diff --git a/boards/hackaday-communicator.json b/boards/hackaday-communicator.json new file mode 100644 index 0000000000..6e6c1ad2d0 --- /dev/null +++ b/boards/hackaday-communicator.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "hackaday-communicator" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "hackaday-communicator (16 MB FLASH, 8 MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "hackaday.com", + "vendor": "hackaday" +} diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index e8c2e4b88e..add4a3c0ac 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -380,7 +380,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O LOG_INFO("SSD1306 init success"); } #elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(HACKADAY_COMMUNICATOR) dispdev = new TFTDisplay(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); #elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY) @@ -655,7 +655,7 @@ void Screen::setup() #else if (!config.display.flip_screen) { #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(HACKADAY_COMMUNICATOR) static_cast(dispdev)->flipScreenVertically(); #elif defined(USE_ST7789) static_cast(dispdev)->flipScreenVertically(); diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index bcb4c4987e..d54fc99582 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -73,7 +73,8 @@ #endif #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \ + defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) // The screen is bigger so use bigger fonts #define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 87593b0d41..4445a7c5ec 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -123,6 +123,11 @@ static void rak14014_tpIntHandle(void) _rak14014_touch_int = true; } +#elif defined(HACKADAY_COMMUNICATOR) +#include +Arduino_DataBus *bus = nullptr; +Arduino_GFX *tft = nullptr; + #elif defined(ST72xx_DE) #include #include @@ -1135,7 +1140,7 @@ static LGFX *tft = nullptr; #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ST7796_CS) || defined(ILI9341_DRIVER) || \ defined(ILI9342_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || \ - (ARCH_PORTDUINO && HAS_SCREEN != 0) + (ARCH_PORTDUINO && HAS_SCREEN != 0) || defined(HACKADAY_COMMUNICATOR) #include "SPILock.h" #include "TFTDisplay.h" #include @@ -1271,12 +1276,15 @@ void TFTDisplay::display(bool fromBlank) x_LastPixelUpdate = x; } } - +#if defined(HACKADAY_COMMUNICATOR) + tft->draw16bitBeRGBBitmap(x_FirstPixelUpdate, y, &linePixelBuffer[x_FirstPixelUpdate], + (x_LastPixelUpdate - x_FirstPixelUpdate + 1), 1); +#else // Step 4: Send the changed pixels on this line to the screen as a single block transfer. // This function accepts pixel data MSB first so it can dump the memory straight out the SPI port. tft->pushRect(x_FirstPixelUpdate, y, (x_LastPixelUpdate - x_FirstPixelUpdate + 1), 1, &linePixelBuffer[x_FirstPixelUpdate]); - +#endif somethingChanged = true; } y++; @@ -1340,6 +1348,8 @@ void TFTDisplay::sendCommand(uint8_t com) display(true); if (portduino_config.displayBacklight.pin > 0) digitalWrite(portduino_config.displayBacklight.pin, TFT_BACKLIGHT_ON); +#elif defined(HACKADAY_COMMUNICATOR) + tft->displayOn(); #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) tft->wakeup(); tft->powerSaveOff(); @@ -1352,7 +1362,8 @@ void TFTDisplay::sendCommand(uint8_t com) unphone.backlight(true); // using unPhone library #endif #ifdef RAK14014 -#elif !defined(M5STACK) && !defined(ST7789_CS) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function +#elif !defined(M5STACK) && !defined(ST7789_CS) && \ + !defined(HACKADAY_COMMUNICATOR) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function tft->setBrightness(172); #endif break; @@ -1364,6 +1375,8 @@ void TFTDisplay::sendCommand(uint8_t com) tft->clear(); if (portduino_config.displayBacklight.pin > 0) digitalWrite(portduino_config.displayBacklight.pin, !TFT_BACKLIGHT_ON); +#elif defined(HACKADAY_COMMUNICATOR) + tft->displayOff(); #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) tft->sleep(); tft->powerSaveOn(); @@ -1376,7 +1389,7 @@ void TFTDisplay::sendCommand(uint8_t com) unphone.backlight(false); // using unPhone library #endif #ifdef RAK14014 -#elif !defined(M5STACK) +#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) tft->setBrightness(0); #endif break; @@ -1392,7 +1405,7 @@ void TFTDisplay::setDisplayBrightness(uint8_t _brightness) { #ifdef RAK14014 // todo -#else +#elif !defined(HACKADAY_COMMUNICATOR) tft->setBrightness(_brightness); LOG_DEBUG("Brightness is set to value: %i ", _brightness); #endif @@ -1410,7 +1423,7 @@ bool TFTDisplay::hasTouch(void) { #ifdef RAK14014 return true; -#elif !defined(M5STACK) +#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) return tft->touch() != nullptr; #else return false; @@ -1429,7 +1442,7 @@ bool TFTDisplay::getTouch(int16_t *x, int16_t *y) } else { return false; } -#elif !defined(M5STACK) +#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) return tft->getTouch(x, y); #else return false; @@ -1448,6 +1461,12 @@ bool TFTDisplay::connect() LOG_INFO("Do TFT init"); #ifdef RAK14014 tft = new TFT_eSPI; +#elif defined(HACKADAY_COMMUNICATOR) + bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, 38 /* SCK */, 21 /* MOSI */, GFX_NOT_DEFINED /* MISO */, HSPI /* spi_num */); + tft = new Arduino_NV3007(bus, 40, 0 /* rotation */, false /* IPS */, 142 /* width */, 428 /* height */, 12 /* col offset 1 */, + 0 /* row offset 1 */, 14 /* col offset 2 */, 0 /* row offset 2 */, nv3007_279_init_operations, + sizeof(nv3007_279_init_operations)); + #else tft = new LGFX; #endif @@ -1458,8 +1477,15 @@ bool TFTDisplay::connect() #ifdef UNPHONE unphone.backlight(true); // using unPhone library #endif - +#ifdef HACKADAY_COMMUNICATOR + bool beginStatus = tft->begin(); + if (beginStatus) + LOG_DEBUG("TFT Success!"); + else + LOG_ERROR("TFT Fail!"); +#else tft->init(); +#endif #if defined(M5STACK) tft->setRotation(0); diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index 6bccb16530..1b3a148d6e 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -97,8 +97,7 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 (storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ - defined(USE_ST7796) || \ - ARCH_PORTDUINO) && \ + defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1); @@ -110,7 +109,8 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 #endif } else { #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ + defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1); @@ -126,8 +126,7 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 // TODO: Raspberry Pi supports more than just the one screen size #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ - defined(USE_ST7796) || \ - ARCH_PORTDUINO) && \ + defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1); diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index bd647c3d84..e90362236b 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -1038,7 +1038,8 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display) bannerOptions.optionsArrayPtr = optionsArray; bannerOptions.optionsCount = 10; bannerOptions.bannerCallback = [display](int selected) -> void { -#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || defined(T_DECK) || defined(T_LORA_PAGER) || HAS_TFT +#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || defined(T_DECK) || defined(T_LORA_PAGER) || \ + HAS_TFT || defined(HACKADAY_COMMUNICATOR) uint8_t TFT_MESH_r = 0; uint8_t TFT_MESH_g = 0; uint8_t TFT_MESH_b = 0; @@ -1338,7 +1339,7 @@ void menuHandler::screenOptionsMenu() static int optionsEnumArray[5] = {Back}; int options = 1; -#if defined(T_DECK) || defined(T_LORA_PAGER) +#if defined(T_DECK) || defined(T_LORA_PAGER) || defined(HACKADAY_COMMUNICATOR) optionsArray[options] = "Show Long/Short Name"; optionsEnumArray[options++] = NodeNameLength; #endif @@ -1350,7 +1351,8 @@ void menuHandler::screenOptionsMenu() } // Only show screen color for TFT displays -#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || defined(T_DECK) || defined(T_LORA_PAGER) || HAS_TFT +#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || defined(T_DECK) || defined(T_LORA_PAGER) || \ + HAS_TFT || defined(HACKADAY_COMMUNICATOR) optionsArray[options] = "Screen Color"; optionsEnumArray[options++] = ScreenColor; #endif diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 3d23acc9f0..1f01640bff 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -257,7 +257,8 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes } #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ + defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) if (isHighResolution) { diff --git a/src/graphics/images.h b/src/graphics/images.h index 998fe8e2a9..c268b3269e 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -27,7 +27,8 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03 0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f}; #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(USE_ST7796) || defined(ST7796_CS) || ARCH_PORTDUINO) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \ + defined(USE_ST7796) || defined(HACKADAY_COMMUNICATOR) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; diff --git a/src/input/HackadayCommunicatorKeyboard.cpp b/src/input/HackadayCommunicatorKeyboard.cpp new file mode 100644 index 0000000000..87c8a24ae9 --- /dev/null +++ b/src/input/HackadayCommunicatorKeyboard.cpp @@ -0,0 +1,217 @@ +#if defined(HACKADAY_COMMUNICATOR) + +#include "HackadayCommunicatorKeyboard.h" +#include "main.h" + +#define _TCA8418_COLS 10 +#define _TCA8418_ROWS 8 +#define _TCA8418_NUM_KEYS 80 + +#define _TCA8418_MULTI_TAP_THRESHOLD 1500 + +using Key = TCA8418KeyboardBase::TCA8418Key; + +constexpr uint8_t modifierRightShiftKey = 30; +constexpr uint8_t modifierRightShift = 0b0001; +constexpr uint8_t modifierLeftShiftKey = 76; // keynum -1 +constexpr uint8_t modifierLeftShift = 0b0001; +// constexpr uint8_t modifierSymKey = 42; +// constexpr uint8_t modifierSym = 0b0010; + +// Num chars per key, Modulus for rotating through characters +static uint8_t HackadayCommunicatorTapMod[_TCA8418_NUM_KEYS] = { + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 0, 0, 0, 2, 1, 2, 2, 0, 1, 1, 0, +}; + +static unsigned char HackadayCommunicatorTapMap[_TCA8418_NUM_KEYS][2] = {{}, + {}, + {'+'}, + {'9'}, + {'8'}, + {'7'}, + {'2'}, + {'3'}, + {'4'}, + {'5'}, + {Key::ESC}, + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'y', 'Y'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {Key::TAB}, + {'a', 'A'}, + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {}, + {'z', 'Z'}, + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', '<'}, + {'.', '>'}, + {}, + {}, + {}, + {'\\'}, + {' '}, + {}, + {Key::RIGHT}, + {Key::DOWN}, + {Key::LEFT}, + {}, + {}, + {}, + {'-'}, + {'6', '^'}, + {'5', '%'}, + {'4', '$'}, + {'[', '{'}, + {']', '}'}, + {'p', 'P'}, + {}, + {}, + {}, + {'*'}, + {'3', '#'}, + {'2', '@'}, + {'1', '!'}, + {Key::SELECT}, + {'\'', '"'}, + {';', ':'}, + {}, + {}, + {}, + {'/', '?'}, + {'='}, + {'.', '>'}, + {'0', ')'}, + {}, + {Key::UP}, + {Key::BSP}, + {}}; + +HackadayCommunicatorKeyboard::HackadayCommunicatorKeyboard() + : TCA8418KeyboardBase(_TCA8418_ROWS, _TCA8418_COLS), modifierFlag(0), last_modifier_time(0), last_key(-1), next_key(-1), + last_tap(0L), char_idx(0), tap_interval(0) +{ + reset(); +} + +void HackadayCommunicatorKeyboard::reset(void) +{ + TCA8418KeyboardBase::reset(); + enableInterrupts(); +} + +// handle multi-key presses (shift and alt) +void HackadayCommunicatorKeyboard::trigger() +{ + uint8_t count = keyCount(); + if (count == 0) + return; + for (uint8_t i = 0; i < count; ++i) { + uint8_t k = readRegister(TCA8418_REG_KEY_EVENT_A + i); + uint8_t key = k & 0x7F; + if (k & 0x80) { + pressed(key); + } else { + released(); + state = Idle; + } + } +} + +void HackadayCommunicatorKeyboard::pressed(uint8_t key) +{ + if (state == Init || state == Busy) { + return; + } + + if (modifierFlag && (millis() - last_modifier_time > _TCA8418_MULTI_TAP_THRESHOLD)) { + modifierFlag = 0; + } + + uint8_t next_key = 0; + int row = (key - 1) / 10; + int col = (key - 1) % 10; + if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) { + return; // Invalid key + } + + next_key = row * _TCA8418_COLS + col; + state = Held; + + uint32_t now = millis(); + tap_interval = now - last_tap; + + updateModifierFlag(next_key); + if (isModifierKey(next_key)) { + last_modifier_time = now; + } + + if (tap_interval < 0) { + last_tap = 0; + state = Busy; + return; + } + + if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) { + char_idx = 0; + } else { + char_idx += 1; + } + + last_key = next_key; + last_tap = now; +} + +void HackadayCommunicatorKeyboard::released() +{ + if (state != Held) { + return; + } + + if (last_key < 0 || last_key >= _TCA8418_NUM_KEYS) { + last_key = -1; + state = Idle; + return; + } + + uint32_t now = millis(); + last_tap = now; + if (HackadayCommunicatorTapMod[last_key]) + queueEvent(HackadayCommunicatorTapMap[last_key][modifierFlag % HackadayCommunicatorTapMod[last_key]]); + if (isModifierKey(last_key) == false) + modifierFlag = 0; +} + +void HackadayCommunicatorKeyboard::updateModifierFlag(uint8_t key) +{ + if (key == modifierRightShiftKey) { + modifierFlag ^= modifierRightShift; + } else if (key == modifierLeftShiftKey) { + modifierFlag ^= modifierLeftShift; + } +} + +bool HackadayCommunicatorKeyboard::isModifierKey(uint8_t key) +{ + return (key == modifierRightShiftKey || key == modifierLeftShiftKey); +} + +#endif \ No newline at end of file diff --git a/src/input/HackadayCommunicatorKeyboard.h b/src/input/HackadayCommunicatorKeyboard.h new file mode 100644 index 0000000000..8316bed723 --- /dev/null +++ b/src/input/HackadayCommunicatorKeyboard.h @@ -0,0 +1,26 @@ +#include "TCA8418KeyboardBase.h" + +class HackadayCommunicatorKeyboard : public TCA8418KeyboardBase +{ + public: + HackadayCommunicatorKeyboard(); + void reset(void); + void trigger(void) override; + virtual ~HackadayCommunicatorKeyboard() {} + + protected: + void pressed(uint8_t key) override; + void released(void) override; + + void updateModifierFlag(uint8_t key); + bool isModifierKey(uint8_t key); + + private: + uint8_t modifierFlag; // Flag to indicate if a modifier key is pressed + uint32_t last_modifier_time; // Timestamp of the last modifier key press + int8_t last_key; + int8_t next_key; + uint32_t last_tap; + uint8_t char_idx; + int32_t tap_interval; +}; diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index 0ed2df116d..0085c806bf 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -7,6 +7,8 @@ #include "TDeckProKeyboard.h" #elif defined(T_LORA_PAGER) #include "TLoraPagerKeyboard.h" +#elif defined(HACKADAY_COMMUNICATOR) +#include "HackadayCommunicatorKeyboard.h" #else #include "TCA8418Keyboard.h" #endif @@ -20,6 +22,8 @@ KbI2cBase::KbI2cBase(const char *name) TCAKeyboard(*(new TDeckProKeyboard())) #elif defined(T_LORA_PAGER) TCAKeyboard(*(new TLoraPagerKeyboard())) +#elif defined(HACKADAY_COMMUNICATOR) + TCAKeyboard(*(new HackadayCommunicatorKeyboard())) #else TCAKeyboard(*(new TCA8418Keyboard())) #endif @@ -328,7 +332,7 @@ int32_t KbI2cBase::runOnce() break; } if (e.inputEvent != INPUT_BROKER_NONE) { - LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar); + // LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar); this->notifyObservers(&e); } TCAKeyboard.trigger(); diff --git a/src/main.cpp b/src/main.cpp index da2e396044..f8d89e1ba2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -394,7 +394,10 @@ void setup() io.pinMode(EXPANDS_GPIO_EN, OUTPUT); io.digitalWrite(EXPANDS_GPIO_EN, HIGH); io.pinMode(EXPANDS_SD_PULLEN, INPUT); +#elif defined(HACKADAY_COMMUNICATOR) + pinMode(KB_INT, INPUT); #endif + concurrency::hasBeenSetup = true; #if ARCH_PORTDUINO SPISettings spiSettings(portduino_config.spiSpeed, MSBFIRST, SPI_MODE0); @@ -877,8 +880,8 @@ void setup() if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ - defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796) || \ - defined(USE_SPISSD1306) + defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ + defined(USE_SPISSD1306) || defined(USE_ST7796) || defined(HACKADAY_COMMUNICATOR) screen = new graphics::Screen(screen_found, screen_model, screen_geometry); #elif defined(ARCH_PORTDUINO) if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) && @@ -1154,8 +1157,8 @@ void setup() // Don't call screen setup until after nodedb is setup (because we need // the current region name) #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ - defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796) || \ - defined(USE_SPISSD1306) + defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ + defined(USE_ST7796) || defined(USE_SPISSD1306) || defined(HACKADAY_COMMUNICATOR) if (screen) screen->setup(); #elif defined(ARCH_PORTDUINO) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 4e99a22efa..d3000c500a 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -664,7 +664,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) config.bluetooth.fixed_pin = defaultBLEPin; #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \ - defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_SPISSD1306) || defined(USE_ST7796) + defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_SPISSD1306) || \ + defined(USE_ST7796) || defined(HACKADAY_COMMUNICATOR) bool hasScreen = true; #ifdef HELTEC_MESH_NODE_T114 uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET); diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 9b5abfba04..085692f96c 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -101,8 +101,6 @@ #define HW_VENDOR meshtastic_HardwareModel_T_WATCH_S3 #elif defined(GENIEBLOCKS) #define HW_VENDOR meshtastic_HardwareModel_GENIEBLOCKS -#elif defined(PRIVATE_HW) -#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #elif defined(NANO_G1) #define HW_VENDOR meshtastic_HardwareModel_NANO_G1 #elif defined(M5STACK) @@ -205,6 +203,8 @@ #define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L #elif defined(HELTEC_WIRELESS_TRACKER_V2) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V2 +#else +#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #endif // ----------------------------------------------------------------------------- diff --git a/variants/esp32s3/hackaday-communicator/pins_arduino.h b/variants/esp32s3/hackaday-communicator/pins_arduino.h new file mode 100644 index 0000000000..65d4e1751e --- /dev/null +++ b/variants/esp32s3/hackaday-communicator/pins_arduino.h @@ -0,0 +1,59 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +// static const uint8_t TX = 43; +// static const uint8_t RX = 44; + +static const uint8_t SDA = 47; +static const uint8_t SCL = 14; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 17; +static const uint8_t MOSI = 3; +static const uint8_t MISO = 9; +static const uint8_t SCK = 8; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +// static const uint8_t BAT_ADC_PIN = 4; + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32s3/hackaday-communicator/platformio.ini b/variants/esp32s3/hackaday-communicator/platformio.ini new file mode 100644 index 0000000000..9702150453 --- /dev/null +++ b/variants/esp32s3/hackaday-communicator/platformio.ini @@ -0,0 +1,15 @@ +; Hackaday Communicator +[env:hackaday-communicator] +extends = esp32s3_base +board = hackaday-communicator +board_check = true +board_build.partitions = default_16MB.csv +upload_protocol = esptool + +build_flags = ${esp32s3_base.build_flags} + -D HACKADAY_COMMUNICATOR + -D BOARD_HAS_PSRAM + -I variants/esp32s3/hackaday-communicator + +lib_deps = ${esp32s3_base.lib_deps} + https://github.com/meshtastic/Arduino_GFX/archive/054e81ffaf23784830a734e3c184346789349406.zip \ No newline at end of file diff --git a/variants/esp32s3/hackaday-communicator/variant.h b/variants/esp32s3/hackaday-communicator/variant.h new file mode 100644 index 0000000000..ccd9d3edbe --- /dev/null +++ b/variants/esp32s3/hackaday-communicator/variant.h @@ -0,0 +1,60 @@ +#define TFT_BL 2 +#define SPI_FREQUENCY 2000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 142 +#define TFT_WIDTH 428 +#define TFT_OFFSET_X 0 +#define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_TRANSITION_FRAMERATE 5 +#define HAS_SCREEN 1 +#define TFT_BLACK 0 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness + +#define USE_POWERSAVE +#define SLEEP_TIME 120 + +#define GPS_DEFAULT_NOT_PRESENT 1 +// #define GPS_RX_PIN 44 +// #define GPS_TX_PIN 43 + +// #define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +// ratio of voltage divider = 2.0 (RD2=100k, RD3=100k) +// #define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +// #define ADC_CHANNEL ADC1_GPIO4_CHANNEL + +// keyboard +#define I2C_SDA 47 // I2C pins for this board +#define I2C_SCL 14 +// #define KB_POWERON -1 // must be set to HIGH +// #define KB_SLAVE_ADDRESS TDECK_KB_ADDR // 0x55 +// #define KB_BL_PIN 46 // not used for now +#define KB_INT 13 +#define CANNED_MESSAGE_MODULE_ENABLE 1 + +#define TFT_DC 39 +#define TFT_CS 41 + +// LoRa +#define USE_SX1262 + +#define LORA_SCK 8 +#define LORA_MISO 9 +#define LORA_MOSI 3 +#define LORA_CS 17 + +// #define LORA_DIO0 -1 // a No connect on the SX1262 module +#define LORA_RESET 18 +#define LORA_DIO1 16 // SX1262 IRQ +#define LORA_DIO2 15 // SX1262 BUSY +// #define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled + +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET + +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// #define LED_PIN 1 \ No newline at end of file