diff --git a/boards/promicro_nrf52840.json b/boards/promicro_nrf52840.json new file mode 100644 index 00000000..346f0f26 --- /dev/null +++ b/boards/promicro_nrf52840.json @@ -0,0 +1,78 @@ +{ + "build": { + "arduino":{ + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + [ + "0x239A", + "0x00B3" + ], + [ + "0x239A", + "0x8029" + ], + [ + "0x239A", + "0x0029" + ], + [ + "0x239A", + "0x002A" + ], + [ + "0x239A", + "0x802A" + ] + ], + "usb_product": "ProMicro NRF52840", + "mcu": "nrf52840", + "variant": "promicro_nrf52840", + "variants_dir": "variants", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "6.1.1", + "sd_fwid": "0x00B6" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": [ + "bluetooth" + ], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd" + }, + "frameworks": [ + "arduino", + "zephyr" + ], + "name": "ProMicro NRF52840", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.nologo.tech/en/product/otherboard/NRF52840.html", + "vendor": "Nologo" + } \ No newline at end of file diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 3511172d..3411db92 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -96,6 +96,10 @@ #include #include static TechoBoard board; +#elif defined(FAKETEC) + #include + #include + static faketecBoard board; #else #error "need to provide a 'board' object" #endif @@ -1357,6 +1361,13 @@ void setup() { spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); +#if defined(FAKETEC) + if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { + #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); + tcxo = SX126X_DIO3_TCXO_VOLTAGE; + status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + } +#endif if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); Serial.println(status); @@ -1388,7 +1399,9 @@ void setup() { sprintf(dev_name, "%s%s", BLE_NAME_PREFIX, the_mesh.getNodeName()); serial_interface.begin(dev_name, the_mesh.getBLEPin()); #else +#ifdef RAK_4631 pinMode(WB_IO2, OUTPUT); +#endif serial_interface.begin(Serial); #endif the_mesh.startInterface(serial_interface); diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 0ddf4fdf..1bb42bda 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -96,6 +96,10 @@ #include #include static TechoBoard board; +#elif defined(FAKETEC) + #include + #include + static faketecBoard board; #else #error "need to provide a 'board' object" #endif @@ -685,6 +689,13 @@ void setup() { spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); +#if defined(FAKETEC) + if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { + #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); + tcxo = SX126X_DIO3_TCXO_VOLTAGE; + status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + } +#endif if (status != RADIOLIB_ERR_NONE) { delay(5000); Serial.print("ERROR: radio init failed: "); diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 94d1e4fc..e2572613 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -100,6 +100,10 @@ #include #include static TechoBoard board; +#elif defined(FAKETEC) + #include + #include + static faketecBoard board; #else #error "need to provide a 'board' object" #endif @@ -747,6 +751,13 @@ void setup() { spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); +#if defined(FAKETEC) + if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { + #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); + tcxo = SX126X_DIO3_TCXO_VOLTAGE; + status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + } +#endif if (status != RADIOLIB_ERR_NONE) { delay(5000); Serial.print("ERROR: radio init failed: "); diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 3a376e54..248353aa 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -78,6 +78,10 @@ #include #include static T1000eBoard board; +#elif defined(FAKETEC) + #include + #include + static faketecBoard board; #else #error "need to provide a 'board' object" #endif diff --git a/platformio.ini b/platformio.ini index 24056adb..2b118561 100644 --- a/platformio.ini +++ b/platformio.ini @@ -961,3 +961,93 @@ build_src_filter = ${LilyGo_Techo.build_src_filter} lib_deps = ${LilyGo_Techo.lib_deps} densaugeo/base64 @ ~1.4.0 + + +[faketec] +extends = nrf52840_base +board = promicro_nrf52840 +build_src_filter = ${nrf52840_base.build_src_filter} + +build_flags = ${nrf52840_base.build_flags} + -D FAKETEC + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 + +[env:Faketec_Repeater] +extends = faketec +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${faketec.build_flags} + -D ADVERT_NAME="\"Faketec Repeater\"" + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD="\"password\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_room_server] +extends = faketec +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_room_server/main.cpp> +build_flags = + ${faketec.build_flags} + -D ADVERT_NAME="\"Test Room\"" + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD="\"password\"" + -D ROOM_PASSWORD="\"hello\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_terminal_chat] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${faketec.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_companion_radio_usb] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} +<../examples/companion_radio/main.cpp> +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:Faketec_companion_radio_ble] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 + -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} + +<../examples/companion_radio/main.cpp> +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/src/helpers/nrf52/faketecBoard.cpp b/src/helpers/nrf52/faketecBoard.cpp new file mode 100644 index 00000000..6ef294bc --- /dev/null +++ b/src/helpers/nrf52/faketecBoard.cpp @@ -0,0 +1,63 @@ +#include +#include "faketecBoard.h" + +#include +#include + +static BLEDfu bledfu; + +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 faketecBoard::startOTAUpdate() { + // 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("Faketec_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 + + return true; +} diff --git a/src/helpers/nrf52/faketecBoard.h b/src/helpers/nrf52/faketecBoard.h new file mode 100644 index 00000000..b5cebb78 --- /dev/null +++ b/src/helpers/nrf52/faketecBoard.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#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.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking + +class faketecBoard : public mesh::MainBoard { +protected: + uint8_t startup_reason; + +public: + void begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + + pinMode(PIN_VBAT_READ, INPUT); + + #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) + Wire.begin(PIN_BOARD_SDA, PIN_BOARD_SCL); + #else + Wire.begin(); + #endif + + pinMode(SX126X_POWER_EN, OUTPUT); + digitalWrite(SX126X_POWER_EN, HIGH); + delay(10); // give sx1262 some time to power up + } + + 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 "Faketec DIY"; + } + + void reboot() override { + NVIC_SystemReset(); + } + + bool startOTAUpdate() override; +}; diff --git a/variants/promicro_nrf52840/variant.cpp b/variants/promicro_nrf52840/variant.cpp new file mode 100644 index 00000000..0a4c3aac --- /dev/null +++ b/variants/promicro_nrf52840/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_nrf52840/variant.h b/variants/promicro_nrf52840/variant.h new file mode 100644 index 00000000..98489da1 --- /dev/null +++ b/variants/promicro_nrf52840/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 + +