diff --git a/platformio.ini b/platformio.ini index bf50b7646..3129decaa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,6 +30,7 @@ default_envs = tbeam ;default_envs = rak4631 ;default_envs = rak4631_eth_gw ;default_envs = rak2560 +;default_envs = rak11310 ;default_envs = rak_wismeshtap ;default_envs = wio-e5 ;default_envs = radiomaster_900_bandit_nano @@ -164,4 +165,4 @@ lib_deps = robtillaart/INA226@0.6.0 ; Health Sensor Libraries - sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 \ No newline at end of file + sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 4cfb8701e..198dcc235 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1015,7 +1015,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil); } else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 || strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 || - strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) { + strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F498") == 0) { display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart); } else { @@ -1506,7 +1506,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O #elif defined(USE_ST7567) dispdev = new ST7567Wire(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); -#elif ARCH_PORTDUINO +#elif ARCH_PORTDUINO && !HAS_TFT if (settingsMap[displayPanel] != no_screen) { LOG_DEBUG("Make TFTDisplay!"); dispdev = new TFTDisplay(address.address, -1, -1, geometry, diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 4f2af670b..c5187cffc 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -352,7 +352,7 @@ static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h class LGFX : public lgfx::LGFX_Device { - lgfx::Panel_LCD *_panel_instance; + lgfx::Panel_Device *_panel_instance; lgfx::Bus_SPI _bus_instance; lgfx::ITouch *_touch_instance; @@ -366,10 +366,21 @@ class LGFX : public lgfx::LGFX_Device _panel_instance = new lgfx::Panel_ST7735; else if (settingsMap[displayPanel] == st7735s) _panel_instance = new lgfx::Panel_ST7735S; + else if (settingsMap[displayPanel] == st7796) + _panel_instance = new lgfx::Panel_ST7796; else if (settingsMap[displayPanel] == ili9341) _panel_instance = new lgfx::Panel_ILI9341; else if (settingsMap[displayPanel] == ili9342) _panel_instance = new lgfx::Panel_ILI9342; + else if (settingsMap[displayPanel] == ili9488) + _panel_instance = new lgfx::Panel_ILI9488; + else if (settingsMap[displayPanel] == hx8357d) + _panel_instance = new lgfx::Panel_HX8357D; + else { + _panel_instance = new lgfx::Panel_NULL; + LOG_ERROR("Unknown display panel configured!"); + } + auto buscfg = _bus_instance.config(); buscfg.spi_mode = 0; buscfg.spi_host = settingsMap[displayspidev]; @@ -383,12 +394,12 @@ class LGFX : public lgfx::LGFX_Device LOG_DEBUG("Height: %d, Width: %d ", settingsMap[displayHeight], settingsMap[displayWidth]); cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable) cfg.pin_rst = settingsMap[displayReset]; - cfg.panel_width = settingsMap[displayWidth]; // actual displayable width - cfg.panel_height = settingsMap[displayHeight]; // actual displayable height - cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction - cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction - cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored) - cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed + cfg.panel_width = settingsMap[displayWidth]; // actual displayable width + cfg.panel_height = settingsMap[displayHeight]; // actual displayable height + cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction + cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction + cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored) + cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed _panel_instance->config(cfg); @@ -410,7 +421,7 @@ class LGFX : public lgfx::LGFX_Device touch_cfg.y_max = settingsMap[displayWidth] - 1; touch_cfg.pin_int = settingsMap[touchscreenIRQ]; touch_cfg.bus_shared = true; - touch_cfg.offset_rotation = 1; + touch_cfg.offset_rotation = settingsMap[touchscreenRotate]; if (settingsMap[touchscreenI2CAddr] != -1) { touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr]; } else { diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9dbe92b7c..bbc9eb1ea 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -409,6 +409,13 @@ bool NodeDB::resetRadioConfig(bool factory_reset) rebootAtMsec = millis() + (5 * 1000); } +#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3)) && defined(HAS_TFT) + // as long as PhoneAPI shares BT and TFT app switch BT off + config.bluetooth.enabled = false; + if (moduleConfig.external_notification.nag_timeout == 60) + moduleConfig.external_notification.nag_timeout = 0; +#endif + return didFactoryReset; } @@ -985,8 +992,11 @@ void NodeDB::loadFromDisk() // Make sure we load hard coded admin keys even when the configuration file has none. // Initialize admin_key_count to zero byte numAdminKeys = 0; +#if defined(USERPREFS_USE_ADMIN_KEY_0) || defined(USERPREFS_USE_ADMIN_KEY_1) || defined(USERPREFS_USE_ADMIN_KEY_2) uint16_t sum = 0; +#endif #ifdef USERPREFS_USE_ADMIN_KEY_0 + for (uint8_t b = 0; b < 32; b++) { sum += config.security.admin_key[0].bytes[b]; } @@ -995,8 +1005,6 @@ void NodeDB::loadFromDisk() LOG_INFO("Admin 0 key zero. Loading hard coded key from user preferences."); memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32); config.security.admin_key[0].size = 32; - config.security.admin_key_count = numAdminKeys; - saveToDisk(SEGMENT_CONFIG); } #endif @@ -1010,8 +1018,6 @@ void NodeDB::loadFromDisk() LOG_INFO("Admin 1 key zero. Loading hard coded key from user preferences."); memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32); config.security.admin_key[1].size = 32; - config.security.admin_key_count = numAdminKeys; - saveToDisk(SEGMENT_CONFIG); } #endif @@ -1025,10 +1031,14 @@ void NodeDB::loadFromDisk() LOG_INFO("Admin 2 key zero. Loading hard coded key from user preferences."); memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32); config.security.admin_key[2].size = 32; + } +#endif + + if (numAdminKeys > 0) { + LOG_INFO("Saving %d hard coded admin keys.", numAdminKeys); config.security.admin_key_count = numAdminKeys; saveToDisk(SEGMENT_CONFIG); } -#endif state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig), &meshtastic_LocalModuleConfig_msg, &moduleConfig); diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp index 3b4d716f5..08ecb7ce8 100644 --- a/src/mesh/eth/ethClient.cpp +++ b/src/mesh/eth/ethClient.cpp @@ -107,6 +107,11 @@ static int32_t reconnectETH() bool initEthernet() { if (config.network.eth_enabled) { +#ifdef PIN_ETH_POWER_EN + pinMode(PIN_ETH_POWER_EN, OUTPUT); + digitalWrite(PIN_ETH_POWER_EN, HIGH); // Power up. + delay(100); +#endif #ifdef PIN_ETHERNET_RESET pinMode(PIN_ETHERNET_RESET, OUTPUT); @@ -115,6 +120,12 @@ bool initEthernet() digitalWrite(PIN_ETHERNET_RESET, HIGH); // Reset Time. #endif +#ifdef RAK11310 // Initialize the SPI port + ETH_SPI_PORT.setSCK(PIN_SPI0_SCK); + ETH_SPI_PORT.setTX(PIN_SPI0_MOSI); + ETH_SPI_PORT.setRX(PIN_SPI0_MISO); + ETH_SPI_PORT.begin(); +#endif Ethernet.init(ETH_SPI_PORT, PIN_ETHERNET_SS); uint8_t mac[6]; diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 2b88702ed..aa8a68f91 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -725,7 +725,6 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res) node["position"] = new JSONValue(position); } - JSONObject user; node["long_name"] = new JSONValue(tempNodeInfo->user.long_name); node["short_name"] = new JSONValue(tempNodeInfo->user.short_name); char macStr[18]; diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index a96fcc080..c20b7b56e 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -982,6 +982,7 @@ bool CannedMessageModule::interceptingKeyboardInput() } } +#if !HAS_TFT void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { char buffer[50]; @@ -1140,6 +1141,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st } } } +#endif //! HAS_TFT ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp) { diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 008da5c71..e72b03bd4 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -64,6 +64,10 @@ CGRadSensSensor cgRadSens; #include "Sensor/T1000xSensor.h" T1000xSensor t1000xSensor; #endif +#ifdef SENSECAP_INDICATOR +#include "Sensor/IndicatorSensor.h" +IndicatorSensor indicatorSensor; +#endif #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true @@ -103,6 +107,9 @@ int32_t EnvironmentTelemetryModule::runOnce() LOG_INFO("Environment Telemetry: init"); // it's possible to have this module enabled, only for displaying values on the screen. // therefore, we should only enable the sensor loop if measurement is also enabled +#ifdef SENSECAP_INDICATOR + result = indicatorSensor.runOnce(); +#endif #ifdef T1000X_SENSOR_EN result = t1000xSensor.runOnce(); #elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL @@ -298,6 +305,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m m->which_variant = meshtastic_Telemetry_environment_metrics_tag; m->variant.environment_metrics = meshtastic_EnvironmentMetrics_init_zero; +#ifdef SENSECAP_INDICATOR + valid = valid && indicatorSensor.getMetrics(m); + hasSensor = true; +#endif #ifdef T1000X_SENSOR_EN // add by WayenWeng valid = valid && t1000xSensor.getMetrics(m); hasSensor = true; @@ -410,7 +421,6 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && cgRadSens.getMetrics(m); hasSensor = true; } - #endif return valid && hasSensor; } diff --git a/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp b/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp index 5e69cc22f..ac5df1b81 100644 --- a/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp +++ b/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp @@ -41,13 +41,12 @@ void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr) float CGRadSensSensor::getStaticRadiation() { // Read a register, following the same pattern as the RCWL9620Sensor - uint32_t data; _wire->beginTransmission(_addr); // Transfer data to addr. _wire->write(0x06); // Radiation intensity (static period T = 500 sec) if (_wire->endTransmission() == 0) { if (_wire->requestFrom(_addr, (uint8_t)3)) { ; // Request 3 bytes - data = _wire->read(); + uint32_t data = _wire->read(); data <<= 8; data |= _wire->read(); data <<= 8; diff --git a/src/modules/Telemetry/Sensor/IndicatorSensor.cpp b/src/modules/Telemetry/Sensor/IndicatorSensor.cpp new file mode 100644 index 000000000..317357137 --- /dev/null +++ b/src/modules/Telemetry/Sensor/IndicatorSensor.cpp @@ -0,0 +1,166 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(SENSECAP_INDICATOR) + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "IndicatorSensor.h" +#include "TelemetrySensor.h" +#include "serialization/cobs.h" +#include +#include + +IndicatorSensor::IndicatorSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "Indicator") {} + +#define SENSOR_BUF_SIZE (512) + +uint8_t buf[SENSOR_BUF_SIZE]; // recv +uint8_t data[SENSOR_BUF_SIZE]; // decode + +#define ACK_PKT_PARA "ACK" + +enum sensor_pkt_type { + PKT_TYPE_ACK = 0x00, // uin32_t + PKT_TYPE_CMD_COLLECT_INTERVAL = 0xA0, // uin32_t + PKT_TYPE_CMD_BEEP_ON = 0xA1, // uin32_t ms: on time + PKT_TYPE_CMD_BEEP_OFF = 0xA2, + PKT_TYPE_CMD_SHUTDOWN = 0xA3, // uin32_t + PKT_TYPE_CMD_POWER_ON = 0xA4, + PKT_TYPE_SENSOR_SCD41_TEMP = 0xB0, // float + PKT_TYPE_SENSOR_SCD41_HUMIDITY = 0xB1, // float + PKT_TYPE_SENSOR_SCD41_CO2 = 0xB2, // float + PKT_TYPE_SENSOR_AHT20_TEMP = 0xB3, // float + PKT_TYPE_SENSOR_AHT20_HUMIDITY = 0xB4, // float + PKT_TYPE_SENSOR_TVOC_INDEX = 0xB5, // float +}; + +static int cmd_send(uint8_t cmd, const char *p_data, uint8_t len) +{ + uint8_t send_buf[32] = {0}; + uint8_t send_data[32] = {0}; + + if (len > 31) { + return -1; + } + + uint8_t index = 1; + + send_data[0] = cmd; + + if (len > 0 && p_data != NULL) { + memcpy(&send_data[1], p_data, len); + index += len; + } + cobs_encode_result ret = cobs_encode(send_buf, sizeof(send_buf), send_data, index); + + // LOG_DEBUG("cobs TX status:%d, len:%d, type 0x%x", ret.status, ret.out_len, cmd); + + if (ret.status == COBS_ENCODE_OK) { + return uart_write_bytes(SENSOR_PORT_NUM, send_buf, ret.out_len + 1); + } + + return -1; +} + +int32_t IndicatorSensor::runOnce() +{ + LOG_INFO("%s: init", sensorName); + setup(); + return 2 * DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; // give it some time to start up +} + +void IndicatorSensor::setup() +{ + uart_config_t uart_config = { + .baud_rate = SENSOR_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_APB, + }; + int intr_alloc_flags = 0; + char buffer[11]; + + uart_driver_install(SENSOR_PORT_NUM, SENSOR_BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags); + uart_param_config(SENSOR_PORT_NUM, &uart_config); + uart_set_pin(SENSOR_PORT_NUM, SENSOR_RP2040_TXD, SENSOR_RP2040_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + cmd_send(PKT_TYPE_CMD_POWER_ON, NULL, 0); + // measure and send only once every minute, for the phone API + const char *interval = ultoa(60000, buffer, 10); + cmd_send(PKT_TYPE_CMD_COLLECT_INTERVAL, interval, strlen(interval) + 1); +} + +bool IndicatorSensor::getMetrics(meshtastic_Telemetry *measurement) +{ + cobs_decode_result ret; + int len = uart_read_bytes(SENSOR_PORT_NUM, buf, (SENSOR_BUF_SIZE - 1), 100 / portTICK_PERIOD_MS); + + float value = 0.0; + uint8_t *p_buf_start = buf; + uint8_t *p_buf_end = buf; + if (len > 0) { + while (p_buf_start < (buf + len)) { + p_buf_end = p_buf_start; + while (p_buf_end < (buf + len)) { + if (*p_buf_end == 0x00) { + break; + } + p_buf_end++; + } + // decode buf + memset(data, 0, sizeof(data)); + ret = cobs_decode(data, sizeof(data), p_buf_start, p_buf_end - p_buf_start); + + // LOG_DEBUG("cobs RX status:%d, len:%d, type:0x%x ", ret.status, ret.out_len, data[0]); + + if (ret.out_len > 1 && ret.status == COBS_DECODE_OK) { + + value = 0.0; + uint8_t pkt_type = data[0]; + switch (pkt_type) { + case PKT_TYPE_SENSOR_SCD41_CO2: { + memcpy(&value, &data[1], sizeof(value)); + // LOG_DEBUG("CO2: %.1f", value); + cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4); + break; + } + + case PKT_TYPE_SENSOR_AHT20_TEMP: { + memcpy(&value, &data[1], sizeof(value)); + // LOG_DEBUG("Temp: %.1f", value); + cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4); + measurement->variant.environment_metrics.has_temperature = true; + measurement->variant.environment_metrics.temperature = value; + break; + } + + case PKT_TYPE_SENSOR_AHT20_HUMIDITY: { + memcpy(&value, &data[1], sizeof(value)); + // LOG_DEBUG("Humidity: %.1f", value); + cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4); + measurement->variant.environment_metrics.has_relative_humidity = true; + measurement->variant.environment_metrics.relative_humidity = value; + break; + } + + case PKT_TYPE_SENSOR_TVOC_INDEX: { + memcpy(&value, &data[1], sizeof(value)); + // LOG_DEBUG("Tvoc: %.1f", value); + cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4); + measurement->variant.environment_metrics.has_iaq = true; + measurement->variant.environment_metrics.iaq = value; + break; + } + default: + break; + } + } + + p_buf_start = p_buf_end + 1; // next message + } + return true; + } + return false; +} + +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/IndicatorSensor.h b/src/modules/Telemetry/Sensor/IndicatorSensor.h new file mode 100644 index 000000000..48ecef8de --- /dev/null +++ b/src/modules/Telemetry/Sensor/IndicatorSensor.h @@ -0,0 +1,19 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" + +class IndicatorSensor : public TelemetrySensor +{ + protected: + virtual void setup() override; + + public: + IndicatorSensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; +}; + +#endif \ No newline at end of file diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index c91252231..4260ae201 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -627,8 +627,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me // mp_decoded will not be decoded when it's PKI encrypted and not directed to us if (mp_decoded.which_payload_variant == meshtastic_MeshPacket_decoded_tag) { // For uplinking other's packets, check if it's not OK to MQTT or if it's an older packet without the bitfield - bool dontUplink = !mp_decoded.decoded.has_bitfield || - (mp_decoded.decoded.has_bitfield && !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK)); + bool dontUplink = !mp_decoded.decoded.has_bitfield || !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK); // check for the lowest bit of the data bitfield set false, and the use of one of the default keys. if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && dontUplink && (ch.settings.psk.size < 2 || (ch.settings.psk.size == 16 && memcmp(ch.settings.psk.bytes, defaultpsk, 16)) || diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 4fadc3ca9..b042510f5 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -90,7 +90,7 @@ void getMacAddr(uint8_t *dmac) if (strlen(optionMac) >= 12) { MAC_from_string(optionMac, dmac); } else { - uint32_t hwId; + uint32_t hwId = {0}; sscanf(optionMac, "%u", &hwId); dmac[0] = 0x80; dmac[1] = 0; @@ -104,7 +104,7 @@ void getMacAddr(uint8_t *dmac) exit; } else { - struct hci_dev_info di; + struct hci_dev_info di = {0}; di.dev_id = 0; bdaddr_t bdaddr; int btsock; @@ -231,6 +231,9 @@ void portduinoSetup() dmac[3] = hash[3]; dmac[4] = hash[4]; dmac[5] = hash[5]; + char macBuf[13] = {0}; + sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); + settingsStrings[mac_address] = macBuf; } } @@ -240,7 +243,7 @@ void portduinoSetup() std::cout << "Please set a MAC Address in config.yaml using either MACAddress or MACAddressSource." << std::endl; exit(EXIT_FAILURE); } - std::cout << "MAC Address: " << std::hex << +dmac[0] << +dmac[1] << +dmac[2] << +dmac[3] << +dmac[4] << +dmac[5] << std::endl; + printf("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\n", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); // Rather important to set this, if not running simulated. randomSeed(time(NULL)); diff --git a/src/platform/portduino/USBHal.h b/src/platform/portduino/USBHal.h index 2b0302ced..064f7ae36 100644 --- a/src/platform/portduino/USBHal.h +++ b/src/platform/portduino/USBHal.h @@ -26,7 +26,7 @@ class Ch341Hal : public RadioLibHal { public: // default constructor - initializes the base HAL and any needed private members - Ch341Hal(uint8_t spiChannel, uint32_t spiSpeed = 2000000, uint8_t spiDevice = 0, uint8_t gpioDevice = 0) + explicit Ch341Hal(uint8_t spiChannel, uint32_t spiSpeed = 2000000, uint8_t spiDevice = 0, uint8_t gpioDevice = 0) : RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, PI_RISING, PI_FALLING) { } diff --git a/src/serialization/MeshPacketSerializer.cpp b/src/serialization/MeshPacketSerializer.cpp index b4603186b..2f0d881f2 100644 --- a/src/serialization/MeshPacketSerializer.cpp +++ b/src/serialization/MeshPacketSerializer.cpp @@ -13,6 +13,8 @@ #include "mesh/generated/meshtastic/remote_hardware.pb.h" #include +static const char *errStr = "Error decoding proto for %s message!"; + std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp, bool shouldLog) { // the created jsonObj is immutable after creation, so diff --git a/src/serialization/MeshPacketSerializer.h b/src/serialization/MeshPacketSerializer.h index 12efccb43..03860ab35 100644 --- a/src/serialization/MeshPacketSerializer.h +++ b/src/serialization/MeshPacketSerializer.h @@ -2,7 +2,6 @@ #include static const char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; -static const char *errStr = "Error decoding proto for %s message!"; class MeshPacketSerializer { diff --git a/src/serialization/cobs.cpp b/src/serialization/cobs.cpp new file mode 100644 index 000000000..afb868f50 --- /dev/null +++ b/src/serialization/cobs.cpp @@ -0,0 +1,129 @@ +#include "cobs.h" +#include + +#ifdef SENSECAP_INDICATOR + +cobs_encode_result cobs_encode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len) +{ + + cobs_encode_result result = {0, COBS_ENCODE_OK}; + + if (!dst_buf_ptr || !src_ptr) { + result.status = COBS_ENCODE_NULL_POINTER; + return result; + } + + const uint8_t *src_read_ptr = src_ptr; + const uint8_t *src_end_ptr = src_read_ptr + src_len; + uint8_t *dst_buf_start_ptr = dst_buf_ptr; + uint8_t *dst_buf_end_ptr = dst_buf_start_ptr + dst_buf_len; + uint8_t *dst_code_write_ptr = dst_buf_ptr; + uint8_t *dst_write_ptr = dst_code_write_ptr + 1; + uint8_t search_len = 1; + + if (src_len != 0) { + for (;;) { + if (dst_write_ptr >= dst_buf_end_ptr) { + result.status = (cobs_encode_status)(result.status | (cobs_encode_status)COBS_ENCODE_OUT_BUFFER_OVERFLOW); + break; + } + + uint8_t src_byte = *src_read_ptr++; + if (src_byte == 0) { + *dst_code_write_ptr = search_len; + dst_code_write_ptr = dst_write_ptr++; + search_len = 1; + if (src_read_ptr >= src_end_ptr) { + break; + } + } else { + *dst_write_ptr++ = src_byte; + search_len++; + if (src_read_ptr >= src_end_ptr) { + break; + } + if (search_len == 0xFF) { + *dst_code_write_ptr = search_len; + dst_code_write_ptr = dst_write_ptr++; + search_len = 1; + } + } + } + } + + if (dst_code_write_ptr >= dst_buf_end_ptr) { + result.status = (cobs_encode_status)(result.status | (cobs_encode_status)COBS_ENCODE_OUT_BUFFER_OVERFLOW); + dst_write_ptr = dst_buf_end_ptr; + } else { + *dst_code_write_ptr = search_len; + } + + result.out_len = dst_write_ptr - dst_buf_start_ptr; + + return result; +} + +cobs_decode_result cobs_decode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len) +{ + cobs_decode_result result = {0, COBS_DECODE_OK}; + + if (!dst_buf_ptr || !src_ptr) { + result.status = COBS_DECODE_NULL_POINTER; + return result; + } + + const uint8_t *src_read_ptr = src_ptr; + const uint8_t *src_end_ptr = src_read_ptr + src_len; + uint8_t *dst_buf_start_ptr = dst_buf_ptr; + const uint8_t *dst_buf_end_ptr = dst_buf_start_ptr + dst_buf_len; + uint8_t *dst_write_ptr = dst_buf_ptr; + + if (src_len != 0) { + for (;;) { + uint8_t len_code = *src_read_ptr++; + if (len_code == 0) { + result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_ZERO_BYTE_IN_INPUT); + break; + } + len_code--; + + size_t remaining_bytes = src_end_ptr - src_read_ptr; + if (len_code > remaining_bytes) { + result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_INPUT_TOO_SHORT); + len_code = remaining_bytes; + } + + remaining_bytes = dst_buf_end_ptr - dst_write_ptr; + if (len_code > remaining_bytes) { + result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_OUT_BUFFER_OVERFLOW); + len_code = remaining_bytes; + } + + for (uint8_t i = len_code; i != 0; i--) { + uint8_t src_byte = *src_read_ptr++; + if (src_byte == 0) { + result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_ZERO_BYTE_IN_INPUT); + } + *dst_write_ptr++ = src_byte; + } + + if (src_read_ptr >= src_end_ptr) { + break; + } + + if (len_code != 0xFE) { + if (dst_write_ptr >= dst_buf_end_ptr) { + result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_OUT_BUFFER_OVERFLOW); + break; + } + *dst_write_ptr++ = 0; + } + } + } + + result.out_len = dst_write_ptr - dst_buf_start_ptr; + + return result; +} + +#endif \ No newline at end of file diff --git a/src/serialization/cobs.h b/src/serialization/cobs.h new file mode 100644 index 000000000..f95e61f62 --- /dev/null +++ b/src/serialization/cobs.h @@ -0,0 +1,75 @@ +#ifndef COBS_H_ +#define COBS_H_ + +#include "configuration.h" + +#ifdef SENSECAP_INDICATOR + +#include +#include + +#define COBS_ENCODE_DST_BUF_LEN_MAX(SRC_LEN) ((SRC_LEN) + (((SRC_LEN) + 253u) / 254u)) +#define COBS_DECODE_DST_BUF_LEN_MAX(SRC_LEN) (((SRC_LEN) == 0) ? 0u : ((SRC_LEN)-1u)) +#define COBS_ENCODE_SRC_OFFSET(SRC_LEN) (((SRC_LEN) + 253u) / 254u) + +typedef enum { + COBS_ENCODE_OK = 0x00, + COBS_ENCODE_NULL_POINTER = 0x01, + COBS_ENCODE_OUT_BUFFER_OVERFLOW = 0x02 +} cobs_encode_status; + +typedef struct { + size_t out_len; + cobs_encode_status status; +} cobs_encode_result; + +typedef enum { + COBS_DECODE_OK = 0x00, + COBS_DECODE_NULL_POINTER = 0x01, + COBS_DECODE_OUT_BUFFER_OVERFLOW = 0x02, + COBS_DECODE_ZERO_BYTE_IN_INPUT = 0x04, + COBS_DECODE_INPUT_TOO_SHORT = 0x08 +} cobs_decode_status; + +typedef struct { + size_t out_len; + cobs_decode_status status; +} cobs_decode_result; + +#ifdef __cplusplus +extern "C" { +#endif + +/* COBS-encode a string of input bytes. + * + * dst_buf_ptr: The buffer into which the result will be written + * dst_buf_len: Length of the buffer into which the result will be written + * src_ptr: The byte string to be encoded + * src_len Length of the byte string to be encoded + * + * returns: A struct containing the success status of the encoding + * operation and the length of the result (that was written to + * dst_buf_ptr) + */ +cobs_encode_result cobs_encode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len); + +/* Decode a COBS byte string. + * + * dst_buf_ptr: The buffer into which the result will be written + * dst_buf_len: Length of the buffer into which the result will be written + * src_ptr: The byte string to be decoded + * src_len Length of the byte string to be decoded + * + * returns: A struct containing the success status of the decoding + * operation and the length of the result (that was written to + * dst_buf_ptr) + */ +cobs_decode_result cobs_decode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SENSECAP_INDICATOR */ + +#endif /* COBS_H_ */ diff --git a/src/sleep.cpp b/src/sleep.cpp index 69eb0349a..161b6e107 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -58,7 +58,7 @@ RTC_DATA_ATTR int bootCount = 0; */ void setCPUFast(bool on) { -#if defined(ARCH_ESP32) && HAS_WIFI +#if defined(ARCH_ESP32) && HAS_WIFI && !HAS_TFT if (isWifiAvailable()) { /* @@ -271,6 +271,12 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN gpio_hold_en((gpio_num_t)BUTTON_PIN); } #endif +#ifdef SENSECAP_INDICATOR + // Portexpander definition does not pass GPIO_IS_VALID_OUTPUT_GPIO + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + gpio_hold_en((gpio_num_t)LORA_CS); +#else if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) { // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep pinMode(LORA_CS, OUTPUT); @@ -278,6 +284,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN gpio_hold_en((gpio_num_t)LORA_CS); } #endif +#endif #ifdef HAS_PMU if (pmu_found && PMU) { @@ -384,6 +391,9 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); #endif +#ifdef INPUTDRIVER_ENCODER_BTN + gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL); +#endif #ifdef T_WATCH_S3 gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif diff --git a/variants/rak11310/pins_arduino.h b/variants/rak11310/pins_arduino.h index 626bed1da..0e2808b19 100644 --- a/variants/rak11310/pins_arduino.h +++ b/variants/rak11310/pins_arduino.h @@ -38,15 +38,15 @@ static const uint8_t A3 = PIN_A3; #define PIN_SERIAL2_RX (5ul) // SPI -#define PIN_SPI0_MISO (12u) -#define PIN_SPI0_MOSI (11u) -#define PIN_SPI0_SCK (10u) -#define PIN_SPI0_SS (13u) +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) -#define PIN_SPI1_MISO (16u) -#define PIN_SPI1_MOSI (19u) -#define PIN_SPI1_SCK (18u) -#define PIN_SPI1_SS (17u) +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) // Wire #define PIN_WIRE0_SDA (2u) @@ -65,4 +65,4 @@ static const uint8_t MISO = PIN_SPI0_MISO; static const uint8_t SCK = PIN_SPI0_SCK; static const uint8_t SDA = PIN_WIRE0_SDA; -static const uint8_t SCL = PIN_WIRE0_SCL; \ No newline at end of file +static const uint8_t SCL = PIN_WIRE0_SCL; diff --git a/variants/rak11310/platformio.ini b/variants/rak11310/platformio.ini index 923cedaa3..0cc60bc7c 100644 --- a/variants/rak11310/platformio.ini +++ b/variants/rak11310/platformio.ini @@ -12,7 +12,10 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/rak11310 -DDEBUG_RP2040_PORT=Serial -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" +build_src_filter = ${rp2040_base.build_src_filter} +<../variants/rak11310> + + + lib_deps = ${rp2040_base.lib_deps} + ${networking_base.lib_deps} + https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2 debug_build_flags = ${rp2040_base.build_flags}, -g -debug_tool = cmsis-dap ; for e.g. Picotool \ No newline at end of file +debug_tool = cmsis-dap ; for e.g. Picotool diff --git a/variants/rak11310/variant.h b/variants/rak11310/variant.h index 54e403ee7..bc8d2d71b 100644 --- a/variants/rak11310/variant.h +++ b/variants/rak11310/variant.h @@ -28,10 +28,10 @@ // RAK BSP somehow uses SPI1 instead of SPI0 #define HW_SPI1_DEVICE -#define LORA_SCK PIN_SPI0_SCK -#define LORA_MOSI PIN_SPI0_MOSI -#define LORA_MISO PIN_SPI0_MISO -#define LORA_CS PIN_SPI0_SS +#define LORA_SCK (10u) +#define LORA_MOSI (11u) +#define LORA_MISO (12u) +#define LORA_CS (13u) #define LORA_DIO0 RADIOLIB_NC #define LORA_RESET 14 @@ -49,3 +49,10 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 #endif + +#define HAS_ETHERNET 1 +#define PIN_ETHERNET_RESET 7 // IO3 +#define PIN_ETHERNET_SS 17 +#define ETH_SPI_PORT SPI + +#define PIN_ETH_POWER_EN 22 diff --git a/variants/seeed-sensecap-indicator/platformio.ini b/variants/seeed-sensecap-indicator/platformio.ini index e6bb2145e..1b64ed6e1 100644 --- a/variants/seeed-sensecap-indicator/platformio.ini +++ b/variants/seeed-sensecap-indicator/platformio.ini @@ -2,7 +2,7 @@ [env:seeed-sensecap-indicator] extends = esp32s3_base platform_packages = - platformio/framework-arduinoespressif32 @ https://github.com/mverch67/arduino-esp32.git#add_tca9535 ; based on 2.0.16 + platformio/framework-arduinoespressif32 @ https://github.com/mverch67/arduino-esp32.git#aef7fef6de3329ed6f75512d46d63bba12b09bb5 ; add_tca9535 (based on 2.0.16) board = seeed-sensecap-indicator board_check = true @@ -24,5 +24,5 @@ build_flags = ${esp32_base.build_flags} lib_deps = ${esp32s3_base.lib_deps} https://github.com/mverch67/LovyanGFX#develop - earlephilhower/ESP8266Audio@^1.9.7 - earlephilhower/ESP8266SAM@^1.0.1 \ No newline at end of file + earlephilhower/ESP8266Audio@^1.9.9 + earlephilhower/ESP8266SAM@^1.0.1 diff --git a/variants/seeed-sensecap-indicator/variant.h b/variants/seeed-sensecap-indicator/variant.h index 6028a3ffa..29d547be3 100644 --- a/variants/seeed-sensecap-indicator/variant.h +++ b/variants/seeed-sensecap-indicator/variant.h @@ -1,6 +1,12 @@ #define I2C_SDA 39 #define I2C_SCL 40 +// This board has a serial coprocessor for sensor readings +#define SENSOR_RP2040_TXD 19 +#define SENSOR_RP2040_RXD 20 +#define SENSOR_PORT_NUM 2 +#define SENSOR_BAUD_RATE 115200 + #define BUTTON_PIN 38 // #define BUTTON_NEED_PULLUP @@ -19,8 +25,7 @@ #define ST7701_BL 45 #define ST7701_SPI_HOST SPI2_HOST #define ST7701_BACKLIGHT_EN 45 -#define SPI_FREQUENCY 20000000 -#define SPI_READ_FREQUENCY 16000000 +#define SPI_FREQUENCY 12000000 #define TFT_HEIGHT 480 #define TFT_WIDTH 480 #define TFT_OFFSET_X 0 diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini index 16769e2f2..d2f09f50b 100644 --- a/variants/t-deck/platformio.ini +++ b/variants/t-deck/platformio.ini @@ -6,7 +6,7 @@ board_check = true upload_protocol = esptool #upload_port = COM29 -build_flags = ${esp32_base.build_flags} +build_flags = ${esp32s3_base.build_flags} -DT_DECK -DBOARD_HAS_PSRAM -DMAX_THREADS=40 @@ -16,4 +16,4 @@ build_flags = ${esp32_base.build_flags} lib_deps = ${esp32s3_base.lib_deps} lovyan03/LovyanGFX@^1.1.9 earlephilhower/ESP8266Audio@^1.9.9 - earlephilhower/ESP8266SAM@^1.0.1 \ No newline at end of file + earlephilhower/ESP8266SAM@^1.0.1 diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 91c12ab3d..4aeeb7ca8 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -27,8 +27,10 @@ #define SLEEP_TIME 120 +#ifndef HAS_TFT #define BUTTON_PIN 0 // #define BUTTON_NEED_PULLUP +#endif #define GPS_DEFAULT_NOT_PRESENT 1 #define GPS_RX_PIN 44 #define GPS_TX_PIN 43 @@ -60,7 +62,7 @@ #define TB_DOWN 15 #define TB_LEFT 1 #define TB_RIGHT 2 -#define TB_PRESS BUTTON_PIN +#define TB_PRESS 0 // BUTTON_PIN // microphone #define ES7210_SCK 47 @@ -98,4 +100,4 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 // Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface -// code) \ No newline at end of file +// code) diff --git a/version.properties b/version.properties index ba7d7fe6f..800529e39 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 5 -build = 18 +build = 19