Răsfoiți Sursa

initial t-echo card support

taco 3 luni în urmă
părinte
comite
1e740d30f2

+ 85 - 0
variants/lilygo_techo_card/TechoCardBoard.cpp

@@ -0,0 +1,85 @@
+#include <Arduino.h>
+#include <Wire.h>
+
+
+#include "TechoCardBoard.h"
+
+#ifdef LILYGO_TECHO_CARD
+
+Adafruit_NeoPixel Led_A(1, WS2812_DATA_2, NEO_GRB + NEO_KHZ800);
+Adafruit_NeoPixel Led_B(1, WS2812_DATA_3, NEO_GRB + NEO_KHZ800);
+Adafruit_NeoPixel Led_C(1, WS2812_DATA_1, NEO_GRB + NEO_KHZ800);
+
+Adafruit_NeoPixel *Led[] =
+    {
+        &Led_A,
+        &Led_B,
+        &Led_C,
+};
+
+
+void TechoCardBoard::begin() {
+    NRF52BoardDCDC::begin();
+    Wire.begin();
+
+    for (uint8_t i = 0; i < sizeof(Led) / sizeof(*Led); i++)
+    {
+        Led[i]->begin();
+        delay(3); // allow the LEDs to initialise, otherwise they can get stuck
+        Led[i]->setPixelColor(0, Led[i]->Color(0, 0, 0));
+        Led[i]->show();
+    }
+    
+    // put IMU20948 to sleep
+    // see https://product.tdk.com/system/files/dam/doc/product/sensor/mortion-inertial/imu/data_sheet/ds-000189-icm-20948-v1.5.pdf
+    Wire.beginTransmission(0x68);
+    Wire.write(0x06);   // PWR_MGMT_1 register
+    Wire.write(0x40);   // set SLEEP bit
+    Wire.endTransmission();
+
+}
+
+uint16_t TechoCardBoard::getBattMilliVolts() {
+  int adcvalue = 0;
+
+  analogReference(AR_INTERNAL_3_0);
+  analogReadResolution(12);
+  
+  digitalWrite(PIN_BAT_CTL, HIGH); // enable vbat vdiv
+  delay(10);
+
+  // ADC range is 0..3000mV and resolution is 12-bit (0..4095)
+  adcvalue = analogRead(PIN_VBAT_READ);
+  digitalWrite(PIN_BAT_CTL, LOW);
+
+  // Convert the raw value to compensated mv, taking the resistor-
+  // divider into account (providing the actual LIPO voltage)
+  return (uint16_t)((float)adcvalue * REAL_VBAT_MV_PER_LSB);
+}
+
+void TechoCardBoard::onBeforeTransmit() {
+    Led_A.setPixelColor(0, 20, 20, 20);   // turn TX LED on
+    Led_A.show();
+}
+
+void TechoCardBoard::onAfterTransmit() {
+    Led_A.setPixelColor(0, 0, 0, 0);   // turn TX LED off
+    Led_A.show();
+}
+
+void TechoCardBoard::turnOffLeds() {
+    for (uint8_t i = 0; i < sizeof(Led) / sizeof(*Led); i++)
+    {
+        Led[i]->setPixelColor(0, 0, 0, 0);
+        Led[i]->show();
+    }
+}
+
+void TechoCardBoard::powerOff() {
+  nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);\
+  turnOffLeds();
+  digitalWrite(PIN_PWR_EN, LOW);
+  sd_power_system_off();
+}
+
+#endif

+ 34 - 0
variants/lilygo_techo_card/TechoCardBoard.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#include <MeshCore.h>
+#include <Arduino.h>
+#include <helpers/NRF52Board.h>
+#include <Adafruit_Neopixel.h>
+
+// built-ins
+#define VBAT_MV_PER_LSB   (0.73242188F)   // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
+
+#define VBAT_DIVIDER      (0.5F)          // Even voltage divider on VBAT
+#define VBAT_DIVIDER_COMP (2.0F)          // Compensation factor for the VBAT divider
+
+#define PIN_VBAT_READ     (2)
+#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
+
+class TechoCardBoard : public NRF52BoardDCDC {
+public:
+  TechoCardBoard() : NRF52Board("TECHO_OTA") {}
+  void begin();
+  uint16_t getBattMilliVolts() override;
+  void onBeforeTransmit(void) override;
+  void onAfterTransmit(void) override;
+
+
+  const char* getManufacturerName() const override {
+    return "LilyGo T-Echo Card";
+  }
+
+  void powerOff() override;
+
+  void turnOffLeds();
+  
+};

+ 118 - 0
variants/lilygo_techo_card/platformio.ini

@@ -0,0 +1,118 @@
+[LilyGo_T-Echo_Card]
+extends = nrf52_base
+board = t-echo
+board_build.ldscript = boards/nrf52840_s140_v6.ld
+build_flags = ${nrf52_base.build_flags}
+  -I variants/lilygo_techo_card
+  -I src/helpers/nrf52
+  -I lib/nrf52/s140_nrf52_6.1.1_API/include
+  -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
+  -D LILYGO_TECHO_CARD
+  -D RADIO_CLASS=CustomSX1262
+  -D WRAPPER_CLASS=CustomSX1262Wrapper
+  -D LORA_TX_POWER=22
+  -D SX126X_CURRENT_LIMIT=140
+  -D SX126X_RX_BOOSTED_GAIN=1
+  -D HAS_NEOPIXEL=1
+  ; -D DISABLE_DIAGNOSTIC_OUTPUT
+  -D ENV_INCLUDE_GPS=1
+  -D DISPLAY_CLASS=SSD1306Display
+  -D PIN_OLED_RESET=-1
+build_src_filter = ${nrf52_base.build_src_filter}
+  +<helpers/*.cpp>
+  +<TechoCardBoard.cpp>
+  +<helpers/sensors/EnvironmentSensorManager.cpp>
+  +<helpers/ui/SSD1306Display.cpp>
+  +<helpers/ui/MomentaryButton.cpp>
+  +<../variants/lilygo_techo_card>
+lib_deps =
+  ${nrf52_base.lib_deps}
+  stevemarple/MicroNMEA @ ^2.0.6
+  adafruit/Adafruit SSD1306 @ ^2.5.13
+  adafruit/Adafruit NeoPixel@^1.10.0
+  bakercp/CRC32 @ ^2.0.0
+debug_tool = jlink
+upload_protocol = nrfutil
+
+[env:LilyGo_T-Echo_Card_repeater]
+extends = LilyGo_T-Echo_Card
+build_src_filter = ${LilyGo_T-Echo_Card.build_src_filter}
+  +<../examples/simple_repeater>
+build_flags =
+  ${LilyGo_T-Echo_Card.build_flags}
+  -D ADVERT_NAME='"T-Echo Card Repeater"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+  -D MAX_NEIGHBOURS=50
+  ; -D MESH_PACKET_LOGGING=1
+  ; -D MESH_DEBUG=1
+
+[env:LilyGo_T-Echo_Card_room_server]
+extends = LilyGo_T-Echo_Card
+build_src_filter = ${LilyGo_T-Echo_Card.build_src_filter}
+  +<../examples/simple_room_server>
+build_flags =
+  ${LilyGo_T-Echo_Card.build_flags}
+  -D ADVERT_NAME='"T-Echo Card Room"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+  ; -D MESH_PACKET_LOGGING=1
+  ; -D MESH_DEBUG=1
+
+[env:LilyGo_T-Echo_Card_companion_radio_ble]
+extends = LilyGo_T-Echo_Card
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
+build_flags =
+  ${LilyGo_T-Echo_Card.build_flags}
+  -I src/helpers/ui
+  -I examples/companion_radio/ui-new
+  -D PIN_BUZZER=38
+  -D QSPIFLASH=1
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+  -D BLE_PIN_CODE=123456
+  ; -D BLE_DEBUG_LOGGING=1
+  -D OFFLINE_QUEUE_SIZE=256
+  -D UI_RECENT_LIST_SIZE=3
+  -D UI_GPS_PAGE=1
+  ; -D MESH_PACKET_LOGGING=1
+  ; -D MESH_DEBUG=1
+  -D AUTO_SHUTDOWN_MILLIVOLTS=3300
+build_src_filter = ${LilyGo_T-Echo_Card.build_src_filter}
+  +<helpers/nrf52/SerialBLEInterface.cpp>
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+  +<helpers/ui/buzzer.cpp>
+lib_deps =
+  ${LilyGo_T-Echo_Card.lib_deps}
+  end2endzone/NonBlockingRTTTL@^1.3.0
+  densaugeo/base64 @ ~1.4.0
+
+[env:LilyGo_T-Echo_Card_companion_radio_usb]
+extends = LilyGo_T-Echo_Card
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
+build_flags =
+  ${LilyGo_T-Echo_Card.build_flags}
+  -I src/helpers/ui
+  -I examples/companion_radio/ui-new
+  -D PIN_BUZZER=38
+  -D QSPIFLASH=1
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+  -D OFFLINE_QUEUE_SIZE=256
+  -D UI_RECENT_LIST_SIZE=3
+  -D UI_GPS_PAGE=1
+  ; -D MESH_PACKET_LOGGING=1
+  ; -D MESH_DEBUG=1
+  -D AUTO_SHUTDOWN_MILLIVOLTS=3300
+build_src_filter = ${LilyGo_T-Echo_Card.build_src_filter}
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+lib_deps =
+  ${LilyGo_T-Echo_Card.lib_deps}
+  end2endzone/NonBlockingRTTTL@^1.3.0
+  densaugeo/base64 @ ~1.4.0

+ 54 - 0
variants/lilygo_techo_card/target.cpp

@@ -0,0 +1,54 @@
+#include <Arduino.h>
+#include "target.h"
+#include <helpers/ArduinoHelpers.h>
+#include <helpers/sensors/MicroNMEALocationProvider.h>
+
+TechoCardBoard board;
+
+RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
+
+WRAPPER_CLASS radio_driver(radio, board);
+
+VolatileRTCClock fallback_clock;
+AutoDiscoverRTCClock rtc_clock(fallback_clock);
+
+#ifdef ENV_INCLUDE_GPS
+MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
+EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
+#else
+EnvironmentSensorManager sensors = EnvironmentSensorManager();
+#endif
+
+
+#ifdef DISPLAY_CLASS
+  DISPLAY_CLASS display;
+  MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
+#endif
+
+bool radio_init() {
+  rtc_clock.begin(Wire);
+  
+  return radio.std_init(&SPI);
+}
+
+uint32_t radio_get_rng_seed() {
+  return radio.random(0x7FFFFFFF);
+}
+
+void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
+  radio.setFrequency(freq);
+  radio.setSpreadingFactor(sf);
+  radio.setBandwidth(bw);
+  radio.setCodingRate(cr);
+}
+
+void radio_set_tx_power(int8_t dbm) {
+  radio.setOutputPower(dbm);
+}
+
+mesh::LocalIdentity radio_new_identity() {
+  RadioNoiseListener rng(radio);
+  return mesh::LocalIdentity(&rng);  // create new random identity
+}
+
+

+ 32 - 0
variants/lilygo_techo_card/target.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#define RADIOLIB_STATIC_ONLY 1
+#include <RadioLib.h>
+#include <helpers/radiolib/RadioLibWrappers.h>
+#include <TechoCardBoard.h>
+#include <helpers/radiolib/CustomSX1262Wrapper.h>
+#include <helpers/AutoDiscoverRTCClock.h>
+#include <helpers/SensorManager.h>
+#include <helpers/sensors/EnvironmentSensorManager.h>
+#include <helpers/sensors/LocationProvider.h>
+#ifdef DISPLAY_CLASS
+  #include <helpers/ui/SSD1306Display.h>
+  #include <helpers/ui/MomentaryButton.h>
+#endif
+
+extern TechoCardBoard board;
+extern WRAPPER_CLASS radio_driver;
+extern AutoDiscoverRTCClock rtc_clock;
+extern EnvironmentSensorManager sensors;
+
+#ifdef DISPLAY_CLASS
+  extern DISPLAY_CLASS display;
+  extern MomentaryButton user_btn;
+#endif
+
+bool radio_init();
+uint32_t radio_get_rng_seed();
+void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
+void radio_set_tx_power(int8_t dbm);
+mesh::LocalIdentity radio_new_identity();
+

+ 45 - 0
variants/lilygo_techo_card/variant.cpp

@@ -0,0 +1,45 @@
+#include "variant.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+#include "Adafruit_NeoPixel.h"
+
+const int MISO = PIN_SPI_MISO;
+const int MOSI = PIN_SPI_MOSI;
+const int SCK = PIN_SPI_SCK;
+
+
+
+const uint32_t g_ADigitalPinMap[] = {
+  0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+  27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+  40, 41, 42, 43, 44, 45, 46, 47
+};
+
+void initVariant() {
+  // turn on 3v3 rail
+  pinMode(PIN_PWR_EN, OUTPUT);
+  digitalWrite(PIN_PWR_EN, HIGH);
+
+  // VDIV enable
+  pinMode(PIN_BAT_CTL, OUTPUT);
+
+  // buttons
+  pinMode(PIN_BUTTON1, INPUT_PULLUP);
+  pinMode(PIN_BUTTON2, INPUT_PULLUP);
+
+  // speaker
+  pinMode(SPEAKER_EN, OUTPUT);
+  digitalWrite(SPEAKER_EN, LOW);
+  pinMode(SPEAKER_EN_2, OUTPUT);
+  digitalWrite(SPEAKER_EN_2, LOW);
+
+  // gps
+  pinMode(PIN_GPS_STANDBY, OUTPUT);
+  digitalWrite(PIN_GPS_STANDBY, HIGH);
+  pinMode(PIN_GPS_EN, OUTPUT);
+  digitalWrite(PIN_GPS_EN, HIGH);
+  pinMode(PIN_GPS_RESET, OUTPUT);
+  digitalWrite(PIN_GPS_RESET, HIGH);
+
+}

+ 144 - 0
variants/lilygo_techo_card/variant.h

@@ -0,0 +1,144 @@
+/*
+ * variant.h
+ *
+ * MIT License
+ */
+
+#pragma once
+
+#include "WVariant.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Low frequency clock source
+
+#define USE_LFXO    // 32.768 kHz crystal oscillator
+#define VARIANT_MCK (64000000ul)
+
+#define WIRE_INTERFACES_COUNT   (1)
+////////////////////////////////////////////////////////////////////////////////
+// Power
+
+#define PIN_PWR_EN              (30)  // RT9080 LDO enable pin for 3v3 rail
+
+#define PIN_BAT_CTL             (31)  // vdiv enable
+#define PIN_VBAT_READ           (2)
+#define ADC_MULTIPLIER          (4.90F)
+
+#define ADC_RESOLUTION          (14)
+#define BATTERY_SENSE_RES       (12)
+#define AREF_VOLTAGE            (3.0)
+
+////////////////////////////////////////////////////////////////////////////////
+// Number of pins
+
+#define PINS_COUNT              (48)
+#define NUM_DIGITAL_PINS        (48)
+#define NUM_ANALOG_INPUTS       (1)
+#define NUM_ANALOG_OUTPUTS      (0)
+
+////////////////////////////////////////////////////////////////////////////////
+// UART pin definition
+
+#define PIN_SERIAL1_RX          PIN_GPS_TX
+#define PIN_SERIAL1_TX          PIN_GPS_RX
+////////////////////////////////////////////////////////////////////////////////
+// I2C pin definition
+
+#define PIN_WIRE_SDA            (36)  // P1.04
+#define PIN_WIRE_SCL            (34)  // P1.02
+#define I2C_NO_RESCAN
+#define DISABLE_DS3231_PROBE    // DS3231 lives at 0x68 but this board has ICM20948 at that address, causing broken clock.
+
+////////////////////////////////////////////////////////////////////////////////
+// SPI pin definition
+
+#define SPI_INTERFACES_COUNT    (1)
+
+#define PIN_SPI_MISO            (17)
+#define PIN_SPI_MOSI            (15)
+#define PIN_SPI_SCK             (13)
+
+////////////////////////////////////////////////////////////////////////////////
+// QSPI FLASH
+
+#define PIN_QSPI_SCK            (4)
+#define PIN_QSPI_CS             (12)
+#define PIN_QSPI_IO0            (6)
+#define PIN_QSPI_IO1            (8)
+#define PIN_QSPI_IO2            (41)  // P1.09
+#define PIN_QSPI_IO3            (26)
+
+#define EXTERNAL_FLASH_DEVICES ZD25WQ32CEIGR
+#define EXTERNAL_FLASH_USE_QSPI
+
+////////////////////////////////////////////////////////////////////////////////
+// Builtin LEDs (only WS2812, no traditional LEDs available)
+
+// WS1812 data lines
+#define WS2812_DATA_1           (39)  // P1.07
+#define WS2812_DATA_2           (44)  // P1.12
+#define WS2812_DATA_3           (28)  // P0.28
+
+#define LED_BLUE                (-1)
+#define LED_BUILTIN             (-1)
+#define LED_PIN                 LED_BUILTIN
+#define LED_STATE_ON            LOW
+
+////////////////////////////////////////////////////////////////////////////////
+// Builtin buttons
+
+#define PIN_BUTTON1             (42)  // P1.10
+#define BUTTON_PIN              PIN_BUTTON1 // BUTTON A
+#define PIN_USER_BTN            BUTTON_PIN
+
+#define PIN_BUTTON2             (24)
+#define BUTTON_PIN2             PIN_BUTTON2 // BUTTON C
+
+////////////////////////////////////////////////////////////////////////////////
+// Lora (Acsip S62F) 
+
+#define  USE_SX1262
+#define  P_LORA_SCLK               PIN_SPI_SCK
+#define  P_LORA_MISO               PIN_SPI_MISO
+#define  P_LORA_MOSI               PIN_SPI_MOSI
+#define  P_LORA_DIO_1              (40)  // P1.08
+#define  P_LORA_RESET              (7)   // P0.07
+#define  P_LORA_BUSY               (14)  // P0.14
+#define  P_LORA_NSS                (11)  // P0.11
+#define  SX126X_RXEN               (33)  // P1.01
+#define  SX126X_TXEN               (27)  // P0.27
+#define  SX126X_DIO3_TCXO_VOLTAGE  (1.8f)
+
+
+////////////////////////////////////////////////////////////////////////////////
+// GPS
+
+// NOTE: these pins are defined differently to how lilygo does them but they
+// seem to work properly for how EnvironmentSensorManager operates.
+// TODO: MAYBE? migrate to board based sensor manager / add GPS_WAKE_UP to ESM
+
+#define PIN_GPS_RX              (21) // GPS_UART_RX in lilygo pin defs
+#define PIN_GPS_TX              (19) // GPS_UART_TX in lilygo pin defs
+#define PIN_GPS_EN              (25) // GPS_WAKE_UP in lilygo pin defs
+#define PIN_GPS_RESET           (47) // GPS_EN      in lilygo pin defs
+#define PIN_GPS_STANDBY         (29) // GPS_RF_EN   in lilygo pin defs
+#define PIN_GPS_PPS             (23) // GPS_1PPS    in lilygo pin defs
+
+// buzzer - enabled in platformio.ini so it can be easily turned off if not wanted.
+// #define PIN_BUZZER              (38) // P1.06
+
+// microphone
+#define MICROPHONE_SCLK         (35) // P1.03
+#define MICROPHONE_DATA         (37) // P1.05
+
+// speaker
+#define SPEAKER_EN              (43) // P1.11
+#define SPEAKER_EN_2            (3)  // P0.03
+#define SPEAKER_BCLK            (16) // P0.16
+#define SPEAKER_DATA            (20) // P0.20
+#define SPEAKER_WS_LRCK         (22) // P0.22
+
+// ICM20948 9dof motion sensor (accelerometer and magnetometer)
+#define ICM20948_SDA PIN_WIRE_SDA    // P1.4
+#define ICM20948_SCL PIN_WIRE_SCL    // P1.2
+#define ICM20948_ADDRESS 0x68