From 7b66a95f6edaee591f9920da9816ae31d9ad3598 Mon Sep 17 00:00:00 2001 From: Rasul Ismailov Date: Sat, 23 May 2026 21:02:58 +0300 Subject: [PATCH] Add Faketec-MiniX board variant NRF52840 ProMicro-based board with SX1262, OLED, GPS, joystick, buzzer and vibration. Includes repeater, room server, companion (USB/BLE), sensor and terminal chat build environments. Co-authored-by: Cursor --- variants/faketec_minix/PromicroBoard.cpp | 35 +++++ variants/faketec_minix/PromicroBoard.h | 79 +++++++++++ variants/faketec_minix/platformio.ini | 166 +++++++++++++++++++++++ variants/faketec_minix/target.cpp | 59 ++++++++ variants/faketec_minix/target.h | 38 ++++++ variants/faketec_minix/variant.cpp | 35 +++++ variants/faketec_minix/variant.h | 95 +++++++++++++ 7 files changed, 507 insertions(+) create mode 100644 variants/faketec_minix/PromicroBoard.cpp create mode 100644 variants/faketec_minix/PromicroBoard.h create mode 100644 variants/faketec_minix/platformio.ini create mode 100644 variants/faketec_minix/target.cpp create mode 100644 variants/faketec_minix/target.h create mode 100644 variants/faketec_minix/variant.cpp create mode 100644 variants/faketec_minix/variant.h diff --git a/variants/faketec_minix/PromicroBoard.cpp b/variants/faketec_minix/PromicroBoard.cpp new file mode 100644 index 0000000000..f580e22dd2 --- /dev/null +++ b/variants/faketec_minix/PromicroBoard.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "PromicroBoard.h" +#include "target.h" + +void PromicroBoard::begin() { + NRF52Board::begin(); + btn_prev_state = HIGH; + + pinMode(PIN_VBAT_READ, INPUT); + + #ifdef UI_HAS_JOYSTICK + pinMode(PIN_BACK_BTN, INPUT_PULLUP); + pinMode(JOYSTICK_LEFT, INPUT_PULLUP); + pinMode(JOYSTICK_RIGHT, INPUT_PULLUP); + pinMode(PIN_USER_BTN, INPUT_PULLUP); + joystick_left.begin(); + joystick_right.begin(); + user_btn.begin(); + back_btn.begin(); + #else if defined (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 +} \ No newline at end of file diff --git a/variants/faketec_minix/PromicroBoard.h b/variants/faketec_minix/PromicroBoard.h new file mode 100644 index 0000000000..2982d8e829 --- /dev/null +++ b/variants/faketec_minix/PromicroBoard.h @@ -0,0 +1,79 @@ +#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 22 //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 PromicroBoard : public NRF52BoardDCDC { +protected: + uint8_t btn_prev_state; + float adc_mult = ADC_MULTIPLIER; + +public: + PromicroBoard() : NRF52Board("ProMicro_OTA") {} + void begin(); + + #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_mult * raw); + } + + bool setAdcMultiplier(float multiplier) override { + if (multiplier == 0.0f) { + adc_mult = ADC_MULTIPLIER;} + else { + adc_mult = multiplier; + } + return true; + } + float getAdcMultiplier() const override { + if (adc_mult == 0.0f) { + return ADC_MULTIPLIER; + } else { + return adc_mult; + } + } + + const char* getManufacturerName() const override { + return "ProMicro DIY"; + } + + 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 powerOff() override { + sd_power_system_off(); + } +}; diff --git a/variants/faketec_minix/platformio.ini b/variants/faketec_minix/platformio.ini new file mode 100644 index 0000000000..eddbf1589c --- /dev/null +++ b/variants/faketec_minix/platformio.ini @@ -0,0 +1,166 @@ +[FaketecMiniX] +extends = nrf52_base +board = promicro_nrf52840 +build_flags = ${nrf52_base.build_flags} + -I variants/faketec_minix + -D PROMICRO + -D USE_SX1262 + -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_OLED_RESET=-1 + -D ENV_INCLUDE_GPS=1 +build_src_filter = ${nrf52_base.build_src_filter} + + + +<../variants/faketec_minix> +lib_deps= ${nrf52_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + stevemarple/MicroNMEA @ ^2.0.6 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:FaketecMiniX_repeater] +extends = FaketecMiniX +build_src_filter = ${FaketecMiniX.build_src_filter} + +<../examples/simple_repeater> + + + + +build_flags = + ${FaketecMiniX.build_flags} + -D ADVERT_NAME='"Faketec-MiniX 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 = ${FaketecMiniX.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:FaketecMiniX_repeater_bridge_rs232_serial1] +extends = FaketecMiniX +build_src_filter = ${FaketecMiniX.build_src_filter} + +<../examples/simple_repeater> + + + + + + +build_flags = + ${FaketecMiniX.build_flags} + -D ADVERT_NAME='"Faketec-MiniX RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 + -D DISPLAY_CLASS=SSD1306Display + -D WITH_RS232_BRIDGE=Serial1 + -D WITH_RS232_BRIDGE_RX=PIN_SERIAL1_RX + -D WITH_RS232_BRIDGE_TX=PIN_SERIAL1_TX + -UENV_INCLUDE_GPS +; -D BRIDGE_DEBUG=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = ${FaketecMiniX.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:FaketecMiniX_room_server] +extends = FaketecMiniX +build_src_filter = ${FaketecMiniX.build_src_filter} + +<../examples/simple_room_server> + + + + +build_flags = ${FaketecMiniX.build_flags} + -D ADVERT_NAME='"Faketec-MiniX 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 = ${FaketecMiniX.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:FaketecMiniX_terminal_chat] +extends = FaketecMiniX +build_flags = ${FaketecMiniX.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${FaketecMiniX.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = ${FaketecMiniX.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:FaketecMiniX_companion_radio_usb] +extends = FaketecMiniX +board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld +board_upload.maximum_size = 712704 +build_flags = ${FaketecMiniX.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D DISPLAY_CLASS=SSD1306Display + -D PIN_BUZZER=0 + -D PIN_VIBRATION=1 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${FaketecMiniX.build_src_filter} + + + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${FaketecMiniX.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:FaketecMiniX_companion_radio_ble] +extends = FaketecMiniX +board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld +board_upload.maximum_size = 712704 +build_flags = ${FaketecMiniX.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 PIN_BUZZER=0 + -D PIN_VIBRATION=1 +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${FaketecMiniX.build_src_filter} + + + + + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${FaketecMiniX.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:FaketecMiniX_sensor] +extends = FaketecMiniX +build_flags = + ${FaketecMiniX.build_flags} + -D ADVERT_NAME='"Faketec-MiniX 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 = ${FaketecMiniX.build_src_filter} + + + + + +<../examples/simple_sensor> +lib_deps = + ${FaketecMiniX.lib_deps} diff --git a/variants/faketec_minix/target.cpp b/variants/faketec_minix/target.cpp new file mode 100644 index 0000000000..264272664a --- /dev/null +++ b/variants/faketec_minix/target.cpp @@ -0,0 +1,59 @@ +#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, &rtc_clock); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; + #ifdef UI_HAS_JOYSTICK + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); + MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, true); + MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, true); + MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, true, true); + #else + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); + #endif +#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 +} + + diff --git a/variants/faketec_minix/target.h b/variants/faketec_minix/target.h new file mode 100644 index 0000000000..cc46f5326c --- /dev/null +++ b/variants/faketec_minix/target.h @@ -0,0 +1,38 @@ +#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; + #ifdef UI_HAS_JOYSTICK + extern MomentaryButton user_btn; + extern MomentaryButton joystick_left; + extern MomentaryButton joystick_right; + extern MomentaryButton back_btn; + #else + extern MomentaryButton user_btn; + #endif +#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(); + diff --git a/variants/faketec_minix/variant.cpp b/variants/faketec_minix/variant.cpp new file mode 100644 index 0000000000..46ec36ae02 --- /dev/null +++ b/variants/faketec_minix/variant.cpp @@ -0,0 +1,35 @@ +#include "variant.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + 8, //P0.08 - D0 + 6, //P0.06 - D1 + 17,//P0.17 - D2 + 20,//P0.20 - D3 + 22,//P0.22 - D4 + 24,//P0.24 - D5 + 32,//P1.00 - D6 + 11,//P0.11 - D7 + 36,//P1.04 - D8 + 38,//P1.06 - D9 + 9, //P0.09 - D10 + 10,//P0.10 - D11 + 43,//P1.11 - D12 + 45,//P1.13 - D13 + 47,//P1.15 - D14 + 2, //P0.02 - D15 + 29,//P0.29 - D16 + 31,//P0.31 - D17 + 33,//P1.01 - 101 - D18 - joystic right + 34,//P1.02 - 102 - D19 - joystic center + 37,//P1.05 - 105 - D20 + 39,//P1.07 - 107 - D21 - joystic left + 13,//P0.13 - D22 - POWER_PIN + 15 //P0.15 - D23 - BLED +}; + +void initVariant() +{ +} + diff --git a/variants/faketec_minix/variant.h b/variants/faketec_minix/variant.h new file mode 100644 index 0000000000..66a6c63ea4 --- /dev/null +++ b/variants/faketec_minix/variant.h @@ -0,0 +1,95 @@ +/* + * 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 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 (4) +#define PIN_SERIAL1_RX (3) +#define PIN_GPS_RX PIN_SERIAL1_RX +#define PIN_GPS_TX PIN_SERIAL1_TX +#define PIN_GPS_EN (5) + +#define PIN_BUZZER (0) // (T2) +#define PIN_VIBRATION (1) // (T3) + +//////////////////////////////////////////////////////////////////////////////// +// I2C pin definition + +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (8) +#define PIN_WIRE_SCL (7) + +//////////////////////////////////////////////////////////////////////////////// +// SPI pin definition + +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_SCK (12) +#define PIN_SPI_MISO (15) +#define PIN_SPI_MOSI (14) + +#define PIN_SPI_NSS (13) + +#define PIN_SPI1_SCK -1//(18) +#define PIN_SPI1_MISO -1//(19) +#define PIN_SPI1_MOSI -1//(20) + +//////////////////////////////////////////////////////////////////////////////// +// Builtin LEDs + +#define PIN_LED (1) +#define LED_PIN PIN_LED +#define LED_BLUE (23) +#define LED_RED LED_BLUE +#define LED_GREEN LED_BLUE +#define LED_BUILTIN PIN_LED +#define LED_STATE_ON 1 +#define PIN_STATUS_LED PIN_LED + +//////////////////////////////////////////////////////////////////////////////// +// Builtin buttons + +#define UI_HAS_JOYSTICK 1 +#define PIN_BUTTON1 (6) +#define PIN_BACK_BTN PIN_BUTTON1 +// #define PIN_USER_BTN PIN_BUTTON1 +#define JOYSTICK_LEFT (21) // encoder left +#define JOYSTICK_RIGHT (18) // encoder right +#define PIN_USER_BTN (19)// encoder press +// #define PIN_USER_BTN PIN_BUTTON1 + +//////////////////////////////////////////////////////////////////////////////// +// Buzzer & Vibro +#define PIN_BUZZER (0) +#define PIN_VIBRATION (1)