diff --git a/variants/promicro_washtastic/PromicroBoard.cpp b/variants/promicro_washtastic/PromicroBoard.cpp new file mode 100644 index 0000000000..6de029583c --- /dev/null +++ b/variants/promicro_washtastic/PromicroBoard.cpp @@ -0,0 +1,83 @@ +#include +#include "PromicroBoard.h" + +#include +#include + +static BLEDfu bledfu; + +void PromicroBoard::begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + btn_prev_state = HIGH; + + pinMode(PIN_VBAT_READ, INPUT); + + #ifdef BUTTON_PIN + pinMode(BUTTON_PIN, INPUT_PULLUP); + #endif + + #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) + Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); + #endif + + Wire.begin(); + + pinMode(SX126X_POWER_EN, OUTPUT); + digitalWrite(SX126X_POWER_EN, HIGH); + delay(10); // give sx1262 some time to power up +} + +static void connect_callback(uint16_t conn_handle) { + (void)conn_handle; + MESH_DEBUG_PRINTLN("BLE client connected"); +} + +static void disconnect_callback(uint16_t conn_handle, uint8_t reason) { + (void)conn_handle; + (void)reason; + MESH_DEBUG_PRINTLN("BLE client disconnected"); +} + +bool PromicroBoard::startOTAUpdate(const char* id, char reply[]) { + // Config the peripheral connection with maximum bandwidth + // more SRAM required by SoftDevice + // Note: All config***() function must be called before begin() + Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); + Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16); + + Bluefruit.begin(1, 0); + // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4 + Bluefruit.setTxPower(4); + // Set the BLE device name + Bluefruit.setName("Washtastic_OTA"); + + Bluefruit.Periph.setConnectCallback(connect_callback); + Bluefruit.Periph.setDisconnectCallback(disconnect_callback); + + // To be consistent OTA DFU should be added first if it exists + bledfu.begin(); + + // Set up and start advertising + // Advertising packet + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + Bluefruit.Advertising.addTxPower(); + Bluefruit.Advertising.addName(); + + /* Start Advertising + - Enable auto advertising if disconnected + - Interval: fast mode = 20 ms, slow mode = 152.5 ms + - Timeout for fast mode is 30 seconds + - Start(timeout) with timeout = 0 will advertise forever (until connected) + + For recommended advertising interval + https://developer.apple.com/library/content/qa/qa1931/_index.html + */ + Bluefruit.Advertising.restartOnDisconnect(true); + Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms + Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode + Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds + + strcpy(reply, "OK - started"); + return true; +} diff --git a/variants/promicro_washtastic/PromicroBoard.h b/variants/promicro_washtastic/PromicroBoard.h new file mode 100644 index 0000000000..7a037d48d3 --- /dev/null +++ b/variants/promicro_washtastic/PromicroBoard.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#define P_LORA_NSS 13 //P1.13 45 +#define P_LORA_DIO_1 11 //P0.10 10 +#define P_LORA_RESET 10 //P0.09 9 +#define P_LORA_BUSY 16 //P0.29 29 +#define P_LORA_MISO 15 //P0.02 2 +#define P_LORA_SCLK 12 //P1.11 43 +#define P_LORA_MOSI 14 //P1.15 47 +#define SX126X_POWER_EN 21 //P0.13 13 +#define SX126X_RXEN 2 //P0.17 +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_DIO2_AS_RF_SWITCH true +#define SX126X_DIO3_TCXO_VOLTAGE (1.8f) + +#define PIN_VBAT_READ 17 +#define ADC_MULTIPLIER (1.49753f) // Fine-tuned: base 1.815 * 0.82416 calibration factor for Washtastic variant drift + +class PromicroBoard : public mesh::MainBoard { +protected: + uint8_t startup_reason; + uint8_t btn_prev_state; + +public: + void begin(); + + uint8_t getStartupReason() const override { return startup_reason; } + + #define BATTERY_SAMPLES 8 + + uint16_t getBattMilliVolts() override { + analogReadResolution(12); + + uint32_t raw = 0; + for (int i = 0; i < BATTERY_SAMPLES; i++) { + raw += analogRead(PIN_VBAT_READ); + } + raw = raw / BATTERY_SAMPLES; + return (ADC_MULTIPLIER * raw); + } + + const char* getManufacturerName() const override { + return "Washtastic"; + } + + int buttonStateChanged() { + #ifdef BUTTON_PIN + uint8_t v = digitalRead(BUTTON_PIN); + if (v != btn_prev_state) { + btn_prev_state = v; + return (v == LOW) ? 1 : -1; + } + #endif + return 0; + } + + void reboot() override { + NVIC_SystemReset(); + } + + void powerOff() override { + sd_power_system_off(); + } + + bool startOTAUpdate(const char* id, char reply[]) override; +}; diff --git a/variants/promicro_washtastic/platformio.ini b/variants/promicro_washtastic/platformio.ini new file mode 100644 index 0000000000..af4b34491d --- /dev/null +++ b/variants/promicro_washtastic/platformio.ini @@ -0,0 +1,147 @@ +[Washtastic] +extends = nrf52_base +board = promicro_nrf52840 +build_flags = ${nrf52_base.build_flags} + -I variants/promicro_washtastic + -D WASHTASTIC + -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 PIN_BOARD_SCL=7 + -D PIN_BOARD_SDA=8 + -D PIN_OLED_RESET=-1 + -D PIN_USER_BTN=6 + -D PIN_GPS_RX=3 + -D PIN_GPS_TX=4 + -D PIN_GPS_EN=5 + -D ENV_INCLUDE_GPS=1 + -D ENV_INCLUDE_AHTX0=1 + -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_BMP280=1 + -D ENV_INCLUDE_INA3221=1 + -D ENV_INCLUDE_INA219=1 +build_src_filter = ${nrf52_base.build_src_filter} + + + +<../variants/promicro_washtastic> +lib_deps= ${nrf52_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + adafruit/Adafruit INA3221 Library @ ^1.0.1 + adafruit/Adafruit INA219 @ ^1.2.3 + adafruit/Adafruit AHTX0 @ ^2.0.5 + adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BMP280 Library@^2.6.8 + stevemarple/MicroNMEA @ ^2.0.6 + +[env:Washtastic_repeater] +extends = Washtastic +build_src_filter = ${Washtastic.build_src_filter} + +<../examples/simple_repeater> + + + + +build_flags = + ${Washtastic.build_flags} + -D ADVERT_NAME='"Washtastic Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 + -D DISPLAY_CLASS=SSD1306Display +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = ${Washtastic.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Washtastic_room_server] +extends = Washtastic +build_src_filter = ${Washtastic.build_src_filter} + +<../examples/simple_room_server> + + + + +build_flags = ${Washtastic.build_flags} + -D ADVERT_NAME='"Washtastic Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' + -D DISPLAY_CLASS=SSD1306Display +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = ${Washtastic.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Washtastic_terminal_chat] +extends = Washtastic +build_flags = ${Washtastic.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Washtastic.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = ${Washtastic.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:Washtastic_companion_radio_usb] +extends = Washtastic +board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld +board_upload.maximum_size = 712704 +build_flags = ${Washtastic.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D DISPLAY_CLASS=SSD1306Display +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${Washtastic.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${Washtastic.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:Washtastic_companion_radio_ble] +extends = Washtastic +board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld +board_upload.maximum_size = 712704 +build_flags = ${Washtastic.build_flags} + -I examples/companion_radio/ui-new + -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 DISPLAY_CLASS=SSD1306Display +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${Washtastic.build_src_filter} + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${Washtastic.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:Washtastic_sensor] +extends = Washtastic +build_flags = + ${Washtastic.build_flags} + -D ADVERT_NAME='"Washtastic Sensor"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D DISPLAY_CLASS=SSD1306Display +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Washtastic.build_src_filter} + + + + + +<../examples/simple_sensor> +lib_deps = + ${Washtastic.lib_deps} diff --git a/variants/promicro_washtastic/target.cpp b/variants/promicro_washtastic/target.cpp new file mode 100644 index 0000000000..b26320e472 --- /dev/null +++ b/variants/promicro_washtastic/target.cpp @@ -0,0 +1,51 @@ +#include +#include "target.h" +#include + +PromicroBoard 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); +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, 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(uint8_t dbm) { + radio.setOutputPower(dbm); +} + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); // create new random identity +} + diff --git a/variants/promicro_washtastic/target.h b/variants/promicro_washtastic/target.h new file mode 100644 index 0000000000..38c4b4e883 --- /dev/null +++ b/variants/promicro_washtastic/target.h @@ -0,0 +1,30 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#ifdef DISPLAY_CLASS + #include + #include +#endif + +#include + +extern PromicroBoard 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(uint8_t dbm); +mesh::LocalIdentity radio_new_identity(); diff --git a/variants/promicro_washtastic/variant.cpp b/variants/promicro_washtastic/variant.cpp new file mode 100644 index 0000000000..0a4c3aac5b --- /dev/null +++ b/variants/promicro_washtastic/variant.cpp @@ -0,0 +1,15 @@ +#include "variant.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + 8, 6, 17, 20, 22, 24, 32, 11, 36, 38, + 9, 10, 43, 45, 47, 2, 29, 31, + 33, 34, 37, + 13, 15 +}; + +void initVariant() +{ +} + diff --git a/variants/promicro_washtastic/variant.h b/variants/promicro_washtastic/variant.h new file mode 100644 index 0000000000..98489da193 --- /dev/null +++ b/variants/promicro_washtastic/variant.h @@ -0,0 +1,82 @@ +/* + * variant.h + * Copyright (C) 2023 Seeed K.K. + * MIT License + */ + + #pragma once + + #include "WVariant.h" + + //////////////////////////////////////////////////////////////////////////////// + // Low frequency clock source + +#define VARIANT_MCK (64000000ul) + +//#define USE_LFXO // 32.768 kHz crystal oscillator +#define USE_LFRC // 32.768 kHz RC oscillator + +//////////////////////////////////////////////////////////////////////////////// +// Power + +#define PIN_EXT_VCC (21) +#define EXT_VCC (PIN_EXT_VCC) + +#define BATTERY_PIN (17) +#define ADC_RESOLUTION 12 + +//////////////////////////////////////////////////////////////////////////////// +// Number of pins + +#define PINS_COUNT (23) +#define NUM_DIGITAL_PINS (23) +#define NUM_ANALOG_INPUTS (3) +#define NUM_ANALOG_OUTPUTS (0) + +//////////////////////////////////////////////////////////////////////////////// +// UART pin definition + +#define PIN_SERIAL1_TX (1) +#define PIN_SERIAL1_RX (0) + +//////////////////////////////////////////////////////////////////////////////// +// I2C pin definition + +#define WIRE_INTERFACES_COUNT 2 + +#define PIN_WIRE_SDA (6) +#define PIN_WIRE_SCL (7) +#define PIN_WIRE1_SDA (13) +#define PIN_WIRE1_SCL (14) + +//////////////////////////////////////////////////////////////////////////////// +// SPI pin definition + +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_SCK (2) +#define PIN_SPI_MISO (3) +#define PIN_SPI_MOSI (4) + +#define PIN_SPI_NSS (5) + +#define PIN_SPI1_SCK (18) +#define PIN_SPI1_MISO (19) +#define PIN_SPI1_MOSI (20) + +//////////////////////////////////////////////////////////////////////////////// +// Builtin LEDs + +#define PIN_LED (22) +#define LED_PIN PIN_LED +#define LED_BLUE PIN_LED +#define LED_BUILTIN PIN_LED +#define LED_STATE_ON 1 + +//////////////////////////////////////////////////////////////////////////////// +// Builtin buttons + +#define PIN_BUTTON1 (6) +#define BUTTON_PIN PIN_BUTTON1 + +