├── LICENSE ├── README.md ├── grovedupont.jpg ├── image.jpg ├── platformio.ini └── src ├── display.cpp ├── display.h ├── event.cpp ├── event.h ├── input.cpp ├── input.h ├── main.cpp ├── serial.cpp └── serial.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroCOM 2 | 3 | Microcom is a lightweight serial UART communication software for the M5Cardputer. This allows users to configure and manage serial communication with external devices over UART. 4 | 5 | 6 | ![MicroCOM in use](image.jpg) 7 | 8 | 9 | ## Features: 10 | - Easy configuration for baud rate, data bits, parity, stop bits, flow control, and inverted signal settings. 11 | - Send and receive serial data 12 | 13 | ## Installation 14 | - M5Burner : Search into M5CARDPUTER section and simply burn it 15 | - Github : Get the firmware from the latest github release. 16 | 17 | ## Pin Configuration: 18 | The pins used are on the Grove connector: 19 | 20 | - RX Pin: GPIO1 (can be changed in the configuration menu) 21 | - TX Pin: GPIO2 (can be changed in the configuration menu) 22 | 23 | You could use Grove/Dupont connector to interface with the Cardputer: 24 | 25 | ![Grove to Dupont](grovedupont.jpg) 26 | 27 | ## Keybinds: 28 | 29 | - Config: Use `Arrows` and `OK` button to toggle configuration options. 30 | - Terminal: Use `Keys` and `OK` button to send commands 31 | 32 | ## ⚠️ Caution: 33 | 34 | The M5Cardputer operate at 3.3V logic levels. Connecting any UART device that uses a different voltage can damage the device. Always ensure that your connected UART device that uses 3.3V. -------------------------------------------------------------------------------- /grovedupont.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geo-tp/MicroCOM/8b4d10c5c17706dafd29759c3c6e9e7b1733351e/grovedupont.jpg -------------------------------------------------------------------------------- /image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geo-tp/MicroCOM/8b4d10c5c17706dafd29759c3c6e9e7b1733351e/image.jpg -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:m5stack-stamps3] 12 | platform = espressif32 13 | board = m5stack-stamps3 14 | framework = arduino 15 | lib_deps = 16 | m5stack/M5Cardputer@^1.0.3 -------------------------------------------------------------------------------- /src/display.cpp: -------------------------------------------------------------------------------- 1 | #include "display.h" 2 | 3 | void displayInit() { 4 | // Initialize display 5 | M5.Lcd.begin(); 6 | M5.Lcd.setRotation(1); 7 | M5.Lcd.setTextColor(TFT_LIGHTGREY); 8 | } 9 | 10 | void displayWelcome() { 11 | M5.Lcd.fillScreen(BACKGROUND_COLOR); 12 | 13 | // Main title 14 | M5.Lcd.setTextSize(3); 15 | M5.Lcd.setTextColor(PRIMARY_COLOR); 16 | M5.Lcd.setCursor(50, 50); 17 | M5.Lcd.printf("Micro"); 18 | 19 | M5.Lcd.setTextSize(2.5); 20 | M5.Lcd.setTextColor(TEXT_COLOR); 21 | M5.Lcd.setCursor(146, 54); 22 | M5.Lcd.printf("COM"); 23 | 24 | // Sub title 25 | M5.Lcd.setTextSize(1.2); 26 | M5.Lcd.setTextColor(TEXT_COLOR); 27 | M5.Lcd.setCursor(50, 78); 28 | M5.Lcd.printf("Serial"); 29 | 30 | M5.Lcd.setTextSize(1.3); 31 | M5.Lcd.setCursor(98, 78); 32 | M5.Lcd.printf("Communication"); 33 | 34 | }; 35 | 36 | void displayConfig(int baud, uint8_t rx, uint8_t tx, uint8_t dataBits, 37 | std::string parity, uint8_t stopBits, bool flowControl, 38 | bool inverted, uint8_t selectedIndex) { 39 | 40 | std::vector configStrings = { 41 | "Rx Pin: " + std::to_string(rx), 42 | "Tx Pin: " + std::to_string(tx), 43 | "Baud: " + std::to_string(baud), 44 | "Data Bits: " + std::to_string(dataBits), 45 | "Parity: " + parity, 46 | "Stop Bits: " + std::to_string(stopBits), 47 | "Flow Ctrl: " + std::string(flowControl ? "Yes" : "No"), 48 | "Inverted: " + std::string(inverted ? "Yes" : "No") 49 | }; 50 | 51 | uint8_t halfWidth = (M5Cardputer.Display.width() - 20) / 2; // largeur de chaque bloc dans une colonne 52 | uint8_t sizeY = 22; // hauteur de chaque bloc 53 | uint8_t startY = 5; // position de départ en Y pour le premier bloc 54 | uint8_t stepY = 26; // intervalle entre chaque bloc 55 | uint8_t margin = DEFAULT_MARGIN; 56 | uint8_t startText = 13; // position de départ du texte 57 | bool selected; 58 | 59 | displayClearMainView(); 60 | M5.Lcd.setTextSize(1.3); 61 | 62 | for (size_t i = 0; i < configStrings.size(); ++i) { 63 | selected = (i == selectedIndex); 64 | 65 | // Calculer la position en X pour la colonne (gauche ou droite) 66 | uint8_t col = i / 4; // 0 pour la colonne de gauche, 1 pour la colonne de droite 67 | uint8_t xPos = margin + col * (halfWidth + margin); 68 | 69 | // Calculer la position en Y pour chaque ligne 70 | uint8_t yPos = startY + (i % 4) * stepY; 71 | 72 | drawRect(selected, xPos, yPos, halfWidth, sizeY); 73 | 74 | uint8_t marginText = margin + 5; 75 | M5.Lcd.setCursor(xPos + marginText, yPos + startText - startY); 76 | 77 | M5.Lcd.printf(configStrings[i].c_str()); 78 | } 79 | 80 | if (selectedIndex == configStrings.size()) { 81 | displayStart(true); 82 | } else { 83 | displayStart(false); 84 | } 85 | } 86 | 87 | void displayStart(bool selected) { 88 | drawRect(selected, DEFAULT_MARGIN, 110,M5.Lcd.width() - 15, 25); 89 | M5.Lcd.setCursor(79, 118); 90 | M5.Lcd.print("START SERIAL"); 91 | }; 92 | 93 | void displayTerminal(std::string receiveString) { 94 | const uint8_t charsPerLine = 34; 95 | const uint8_t linesPerScreen = 10; 96 | 97 | // Split receiveString by \n and wrap text 98 | std::vector lines; 99 | std::string currentLine; 100 | for (size_t i = 0; i < receiveString.length(); ++i) { 101 | char c = receiveString[i]; 102 | if (c == '\n') { 103 | lines.push_back(currentLine); // Add the current line and reset 104 | currentLine.clear(); 105 | } else { 106 | currentLine += c; 107 | // If the current line exceeds the allowed number of characters per line, wrap it 108 | if (currentLine.length() >= charsPerLine) { 109 | lines.push_back(currentLine); 110 | currentLine.clear(); 111 | } 112 | } 113 | } 114 | // Push the last remaining part of the string (if any) 115 | if (!currentLine.empty()) { 116 | lines.push_back(currentLine); 117 | } 118 | 119 | // Now, calculate the number of lines and only display the last ones that fit on the screen 120 | size_t totalLines = lines.size(); 121 | size_t startLine = 0; 122 | if (totalLines > linesPerScreen) { 123 | startLine = totalLines - linesPerScreen; 124 | } 125 | 126 | // Clear the terminal view before displaying the new content 127 | displayClearTerminalView(); 128 | M5.Lcd.setCursor(0, DEFAULT_MARGIN); 129 | 130 | // Print only the visible portion of the terminal string 131 | for (size_t i = startLine; i < totalLines; ++i) { 132 | M5.Lcd.println(lines[i].c_str()); 133 | } 134 | } 135 | 136 | 137 | void displayPrompt(std::string sendString) { 138 | 139 | if (sendString.length() > 26) { 140 | sendString = sendString.substr(sendString.length() - 26); 141 | } 142 | drawRect(false, DEFAULT_MARGIN, 110,M5.Lcd.width() - 15, 25); 143 | M5.Lcd.setCursor(DEFAULT_MARGIN*2, 118); 144 | M5.Lcd.print(" > "); 145 | M5.Lcd.print(sendString.c_str()); 146 | } 147 | 148 | void drawRect(bool selected, uint8_t margin, uint16_t startY, uint16_t sizeX, uint16_t sizeY) { 149 | // Draw rect 150 | if (selected) { 151 | M5.Lcd.fillRoundRect(margin, startY, sizeX, sizeY, DEFAULT_ROUND_RECT, PRIMARY_COLOR); 152 | M5.Lcd.setTextColor(TEXT_COLOR); 153 | } else { 154 | M5.Lcd.fillRoundRect(margin, startY, sizeX, sizeY, DEFAULT_ROUND_RECT, RECT_COLOR_DARK); 155 | M5.Lcd.drawRoundRect(margin, startY, sizeX, sizeY, DEFAULT_ROUND_RECT, PRIMARY_COLOR); 156 | M5.Lcd.setTextColor(TEXT_COLOR); 157 | } 158 | } 159 | 160 | void displayClearMainView(uint8_t offsetY) { 161 | M5.Lcd.fillRect(0, 0,M5.Lcd.width(),M5.Lcd.height(), BACKGROUND_COLOR); 162 | } 163 | 164 | void displayClearTerminalView() { 165 | M5.Lcd.fillRect(0, 0,M5.Lcd.width(),M5.Lcd.height()-30, BACKGROUND_COLOR); 166 | } 167 | -------------------------------------------------------------------------------- /src/display.h: -------------------------------------------------------------------------------- 1 | #ifndef DISPLAY_H 2 | #define DISPLAY_H 3 | 4 | #include 5 | #include 6 | #include // Assurez-vous que cette bibliothèque est la bonne selon votre matériel (M5Stack, M5Cardputer, etc.) 7 | 8 | #define BACKGROUND_COLOR TFT_BLACK 9 | #define PRIMARY_COLOR 0xfa03 10 | #define RECT_COLOR_DARK 0x0841 11 | #define RECT_COLOR_LIGHT 0xd69a 12 | #define TEXT_COLOR 0xef7d 13 | #define TEXT_COLOR_ALT TFT_DARKGRAY 14 | 15 | #define DEFAULT_MARGIN 5 16 | #define DEFAULT_ROUND_RECT 5 17 | 18 | void displayInit(); 19 | void displayWelcome(); 20 | void displayConfig(int baud, uint8_t rx, uint8_t tx, uint8_t dataBits, 21 | std::string parity, uint8_t stopBits, bool flowControl, 22 | bool inverted, uint8_t selectedIndex); 23 | void displayStart(bool selected); 24 | void displayTerminal(std::string terminalSting); 25 | void displayPrompt(std::string sendString); 26 | void displayClearMainView(uint8_t offsetY=0); 27 | void displayClearTerminalView(); 28 | 29 | // Utility Function (forward declaration if needed) 30 | void drawRect(bool selected, uint8_t margin, uint16_t startY, uint16_t sizeX, uint16_t sizeY); 31 | 32 | #endif // DISPLAY_CONFIG_H 33 | -------------------------------------------------------------------------------- /src/event.cpp: -------------------------------------------------------------------------------- 1 | #include "event.h" 2 | 3 | uint8_t handleIndexSelection(char input, uint8_t currentIndex) { 4 | switch (input) { 5 | case KEY_ARROW_UP: 6 | if (currentIndex == LAUNCH_INDEX) return BITS_INDEX; 7 | if (currentIndex == PARITY_INDEX) return LAUNCH_INDEX; 8 | return currentIndex > 0 ? currentIndex - 1 : LAUNCH_INDEX; 9 | case KEY_ARROW_DOWN: 10 | if (currentIndex == BITS_INDEX) return LAUNCH_INDEX; 11 | return (currentIndex < LAUNCH_INDEX) ? currentIndex + 1 : 0; 12 | case KEY_ARROW_LEFT: 13 | return currentIndex >= 4 ? currentIndex - 4 : currentIndex; 14 | case KEY_ARROW_RIGHT: 15 | return currentIndex < 4 ? currentIndex + 4 : currentIndex; 16 | default: 17 | return currentIndex; 18 | } 19 | } 20 | 21 | void handleConfigSelection(char input, BaudRate &baudRate, uint8_t &rxPin, uint8_t &txPin, 22 | uint8_t &dataBits, ParityType &parity, uint8_t &stopBits, 23 | bool &flowControl, bool &inverted, uint8_t selectedIndex) { 24 | if (input != KEY_OK) return; 25 | 26 | switch (selectedIndex) { 27 | case RXPIN_INDEX: 28 | case TXPIN_INDEX: 29 | rxPin = (rxPin == 1) ? 2 : 1; 30 | txPin = (txPin == 1) ? 2 : 1; 31 | break; 32 | case BAUD_INDEX: 33 | baudRate = static_cast((baudRate == BAUDRATE_COUNT - 1) ? 0 : baudRate + 1); 34 | break; 35 | case BITS_INDEX: 36 | dataBits = (dataBits < 8) ? dataBits + 1 : 5; 37 | break; 38 | case PARITY_INDEX: 39 | parity = static_cast((parity == PARITY_COUNT - 1) ? 0 : parity + 1); 40 | break; 41 | case STOP_BITS_INDEX: 42 | stopBits = (stopBits == 1) ? 2 : 1; 43 | break; 44 | case FLOW_CONTROL_INDEX: 45 | flowControl = !flowControl; 46 | break; 47 | case INVERTED_INDEX: 48 | inverted = !inverted; 49 | break; 50 | default: 51 | break; 52 | } 53 | } 54 | 55 | void handlePrompt(std::atomic &sendDataFlag, std::string &sendString, 56 | std::atomic &running, std::mutex &sendMutex) { 57 | while (running) { 58 | char input = promptInputHandler(); 59 | 60 | switch (input) { 61 | case KEY_NONE: 62 | break; 63 | case KEY_OK: 64 | sendDataFlag = true; 65 | break; 66 | case KEY_DEL: 67 | { 68 | std::lock_guard lock(sendMutex); 69 | if (!sendString.empty()) { 70 | sendString.pop_back(); 71 | } 72 | } 73 | break; 74 | default: 75 | { 76 | std::lock_guard lock(sendMutex); 77 | sendString += input; 78 | } 79 | break; 80 | } 81 | delay(30); 82 | } 83 | } -------------------------------------------------------------------------------- /src/event.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENT_H 2 | #define EVENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "serial.h" 8 | #include "input.h" 9 | 10 | enum ConfigIndex { 11 | RXPIN_INDEX = 0, 12 | TXPIN_INDEX, 13 | BAUD_INDEX, 14 | BITS_INDEX, 15 | PARITY_INDEX, 16 | STOP_BITS_INDEX, 17 | FLOW_CONTROL_INDEX, 18 | INVERTED_INDEX, 19 | LAUNCH_INDEX, 20 | }; 21 | 22 | uint8_t handleIndexSelection(char input, uint8_t currentIndex); 23 | void handleConfigSelection(char input, BaudRate &baudRate, uint8_t &rxPin, uint8_t &txPin, 24 | uint8_t &dataBits, ParityType &parity, uint8_t &stopBits, 25 | bool &flowControl, bool &inverted, uint8_t selectedIndex); 26 | void handlePrompt(std::atomic &sendDataFlag, std::string &sendString, 27 | std::atomic &running, std::mutex &sendMutex); 28 | #endif -------------------------------------------------------------------------------- /src/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | 3 | char configInputHandler() { 4 | // Update keyboard state 5 | M5Cardputer.update(); 6 | 7 | if (M5Cardputer.Keyboard.isChange()) { 8 | 9 | if (M5Cardputer.Keyboard.isPressed()) { 10 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 11 | 12 | if (status.enter) { 13 | return KEY_OK; 14 | } 15 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_LEFT)) { 16 | return KEY_ARROW_LEFT; 17 | } 18 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_RIGHT)) { 19 | return KEY_ARROW_RIGHT; 20 | } 21 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_UP)) { 22 | return KEY_ARROW_UP; 23 | } 24 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_DOWN)) { 25 | return KEY_ARROW_DOWN; 26 | } 27 | } 28 | delay(10); // debounce 29 | } 30 | return KEY_NONE; 31 | } 32 | 33 | char promptInputHandler() { 34 | // Update keyboard state 35 | M5Cardputer.update(); 36 | 37 | // Bouton G0 38 | if (M5Cardputer.BtnA.isPressed()) { 39 | delay(100); // debounce 40 | return KEY_RETURN; 41 | } 42 | 43 | if (M5Cardputer.Keyboard.isChange()) { 44 | 45 | if (M5Cardputer.Keyboard.isPressed()) { 46 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 47 | 48 | if (status.enter) { 49 | return KEY_OK; 50 | } 51 | else if (status.del) { 52 | return KEY_DEL; 53 | } 54 | 55 | for (auto c : status.word) { 56 | return c; // retourner le premier char saisi 57 | } 58 | } 59 | delay(10); // debounce 60 | } 61 | return KEY_NONE; 62 | } -------------------------------------------------------------------------------- /src/input.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUT_H 2 | #define INPUT_H 3 | 4 | #include 5 | 6 | #define KEY_OK '\n' 7 | #define KEY_DEL '\b' 8 | #define KEY_NONE '\0' 9 | #define KEY_RETURN '\r' 10 | #define KEY_ARROW_UP ';' 11 | #define KEY_ARROW_DOWN '.' 12 | #define KEY_ARROW_LEFT ',' 13 | #define KEY_ARROW_RIGHT '/' 14 | 15 | char configInputHandler(); 16 | char promptInputHandler(); 17 | #endif -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "input.h" 6 | #include "display.h" 7 | #include "serial.h" 8 | #include "event.h" 9 | 10 | // Config 11 | BaudRate baudRate = BAUD_9600; 12 | uint8_t rxPin = 1; 13 | uint8_t txPin = 2; 14 | uint8_t dataBits = 8; 15 | ParityType parity = NONE; 16 | uint8_t stopBits = 1; 17 | bool flowControl = false; 18 | bool inverted = false; 19 | uint8_t selectedIndex = LAUNCH_INDEX; 20 | 21 | // Var atomic for input thread 22 | std::atomic sendDataFlag(false); 23 | std::atomic running(true); 24 | 25 | // Strings for serial send/receive 26 | std::string sendString; 27 | std::string receiveString; 28 | 29 | // Lock sendString for thread safe purpose 30 | std::mutex sendMutex; 31 | 32 | void config() { 33 | bool firstRender = true; 34 | while (true) { 35 | char input = configInputHandler(); 36 | selectedIndex = handleIndexSelection(input, selectedIndex); 37 | handleConfigSelection(input, baudRate, rxPin, txPin, dataBits, parity, stopBits, flowControl, inverted, selectedIndex); 38 | 39 | if (input != KEY_NONE || firstRender) { 40 | displayConfig(baudRateToInt(baudRate), rxPin, txPin, dataBits, parityToString(parity), stopBits, flowControl, inverted, selectedIndex); 41 | firstRender = false; 42 | } 43 | 44 | // If user presses the start button, we leave config screen 45 | if (input == KEY_OK && selectedIndex == LAUNCH_INDEX) { 46 | displayClearMainView(); 47 | running = true; 48 | break; 49 | } 50 | } 51 | } 52 | 53 | void terminal() { 54 | int16_t promptSize = -1; 55 | int16_t terminalSize = -1; 56 | 57 | // Limit serial read per iteration 58 | const int maxReadSize = 1024; 59 | char buffer[maxReadSize + 1]; 60 | 61 | while (running) { 62 | 63 | if (Serial1.available()) { 64 | int bytesRead = Serial1.readBytes(buffer, maxReadSize); 65 | buffer[bytesRead] = '\0'; 66 | 67 | if (receiveString.size() > maxReadSize) { 68 | // Only keep last chars 69 | receiveString.erase(0, receiveString.size() - maxReadSize); 70 | terminalSize = -1; // trigger screen render 71 | } 72 | 73 | receiveString += std::string(buffer); 74 | } 75 | 76 | if (sendDataFlag) { 77 | Serial1.println(sendString.c_str()); 78 | sendDataFlag = false; 79 | std::lock_guard lock(sendMutex); 80 | sendString.clear(); 81 | } 82 | 83 | if (terminalSize != receiveString.size()) { 84 | displayTerminal(receiveString); 85 | terminalSize = receiveString.size(); 86 | } 87 | 88 | if (promptSize != sendString.size()) { 89 | displayPrompt(sendString); 90 | promptSize = sendString.size(); 91 | } 92 | } 93 | } 94 | 95 | void setup() { 96 | auto cfg = M5.config(); 97 | M5Cardputer.begin(cfg); 98 | 99 | displayInit(); 100 | displayWelcome(); 101 | delay(2000); 102 | 103 | // Serial config 104 | config(); 105 | auto serialConfig = serialGetConfig(dataBits, parity, stopBits, flowControl); 106 | Serial.begin(9600); // for some reason, we have to init Serial to make Serial1 works 107 | Serial1.begin(baudRateToInt(baudRate), serialConfig, rxPin, txPin); 108 | Serial1.setTimeout(100); // Timeout for readBytes 109 | 110 | // Prompt thread 111 | std::thread inputThread(handlePrompt, std::ref(sendDataFlag), std::ref(sendString), 112 | std::ref(running), std::ref(sendMutex)); 113 | inputThread.detach(); 114 | } 115 | 116 | void loop() { 117 | terminal(); 118 | } -------------------------------------------------------------------------------- /src/serial.cpp: -------------------------------------------------------------------------------- 1 | #include "serial.h" 2 | 3 | std::string parityToString(ParityType parity) { 4 | switch (parity) { 5 | case NONE: 6 | return "None"; 7 | case ODD: 8 | return "Odd"; 9 | case EVEN: 10 | return "Even"; 11 | default: 12 | return "Unknown"; 13 | } 14 | } 15 | 16 | int baudRateToInt(BaudRate baud) { 17 | switch (baud) { 18 | case BAUD_9600: 19 | return 9600; 20 | case BAUD_14400: 21 | return 14400; 22 | case BAUD_19200: 23 | return 19200; 24 | case BAUD_38400: 25 | return 38400; 26 | case BAUD_57600: 27 | return 57600; 28 | case BAUD_115200: 29 | return 115200; 30 | case BAUD_230400: 31 | return 230400; 32 | case BAUD_460800: 33 | return 460800; 34 | case BAUD_921600: 35 | return 921600; 36 | default: 37 | return -1; 38 | } 39 | } 40 | 41 | SerialMode serialGetConfig(uint8_t dataBits, ParityType parity, uint8_t stopBits, bool flowControl) { 42 | SerialMode config = M_SERIAL_8N1; 43 | 44 | // Bits 45 | switch (dataBits) { 46 | case 5: 47 | config = (stopBits == 1) ? M_SERIAL_5N1 : M_SERIAL_5N2; 48 | break; 49 | case 6: 50 | config = (stopBits == 1) ? M_SERIAL_6N1 : M_SERIAL_6N2; 51 | break; 52 | case 7: 53 | config = (stopBits == 1) ? M_SERIAL_7N1 : M_SERIAL_7N2; 54 | break; 55 | case 8: 56 | config = (stopBits == 1) ? M_SERIAL_8N1 : M_SERIAL_8N2; 57 | break; 58 | } 59 | 60 | // Parity 61 | if (parity == ODD) { 62 | config = static_cast(config | 0x1); 63 | } else if (parity == EVEN) { 64 | config = static_cast(config | 0x2); 65 | } 66 | 67 | if (flowControl) { 68 | // TODO: Should we handle this ? 69 | } 70 | 71 | return config; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_H 2 | #define SERIAL_H 3 | 4 | #include 5 | 6 | enum SerialMode { 7 | M_SERIAL_5N1 = 0x8000010, 8 | M_SERIAL_6N1 = 0x8000014, 9 | M_SERIAL_7N1 = 0x8000018, 10 | M_SERIAL_8N1 = 0x800001c, 11 | M_SERIAL_5N2 = 0x8000030, 12 | M_SERIAL_6N2 = 0x8000034, 13 | M_SERIAL_7N2 = 0x8000038, 14 | M_SERIAL_8N2 = 0x800003c, 15 | M_SERIAL_5E1 = 0x8000012, 16 | M_SERIAL_6E1 = 0x8000016, 17 | M_SERIAL_7E1 = 0x800001a, 18 | M_SERIAL_8E1 = 0x800001e, 19 | M_SERIAL_5E2 = 0x8000032, 20 | M_SERIAL_6E2 = 0x8000036, 21 | M_SERIAL_7E2 = 0x800003a, 22 | M_SERIAL_8E2 = 0x800003e, 23 | M_SERIAL_5O1 = 0x8000013, 24 | M_SERIAL_6O1 = 0x8000017, 25 | M_SERIAL_7O1 = 0x800001b, 26 | M_SERIAL_8O1 = 0x800001f, 27 | M_SERIAL_5O2 = 0x8000033, 28 | M_SERIAL_6O2 = 0x8000037, 29 | M_SERIAL_7O2 = 0x800003b, 30 | M_SERIAL_8O2 = 0x800003f 31 | }; 32 | 33 | enum ParityType { 34 | NONE, 35 | ODD, 36 | EVEN, 37 | PARITY_COUNT 38 | }; 39 | std::string parityToString(ParityType parity); 40 | 41 | enum BaudRate { 42 | BAUD_9600, 43 | BAUD_14400, 44 | BAUD_19200, 45 | BAUD_38400, 46 | BAUD_57600, 47 | BAUD_115200, 48 | BAUD_230400, 49 | BAUD_460800, 50 | BAUD_921600, 51 | BAUDRATE_COUNT 52 | }; 53 | int baudRateToInt(BaudRate baud); 54 | 55 | SerialMode serialGetConfig(uint8_t dataBits, ParityType parity, uint8_t stopBits, bool flowControl); 56 | 57 | #endif 58 | --------------------------------------------------------------------------------