diff --git a/.vscode/settings.json b/.vscode/settings.json index 81deca8f9..5957d463f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,6 @@ }, "[powershell]": { "editor.defaultFormatter": "ms-vscode.powershell" - } + }, + "idf.currentSetup": "C:/Espressif/frameworks/esp-idf-v5.3.1/" } diff --git a/variants/nrf52840/diy/moonshine_NRF52/platformio.ini b/variants/nrf52840/diy/moonshine_NRF52/platformio.ini new file mode 100644 index 000000000..713a14574 --- /dev/null +++ b/variants/nrf52840/diy/moonshine_NRF52/platformio.ini @@ -0,0 +1,9 @@ +; Moonshine NRF52 node - DIY variant based on RF-BM-ND05 nRF52840 module +[env:moonshine_NRF52_node] +extends = nrf52840_base +board = adafruit_feather_nrf52840 +build_flags = ${nrf52840_base.build_flags} + -I variants/nrf52840/diy/moonshine_NRF52 + -D PRIVATE_HW +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/diy/moonshine_NRF52> +debug_tool = jlink diff --git a/variants/nrf52840/diy/moonshine_NRF52/readme.md b/variants/nrf52840/diy/moonshine_NRF52/readme.md new file mode 100644 index 000000000..1070a801b --- /dev/null +++ b/variants/nrf52840/diy/moonshine_NRF52/readme.md @@ -0,0 +1,49 @@ +# Moonshine NRF52 + +DIY Meshtastic node variant based on the RF-BM-ND05 nRF52840 module. + +## Hardware + +- **MCU module**: RF-BM-ND05 (nRF52840, 512 KB flash / 128 KB RAM) +- **LF clock**: 32.768 kHz crystal (`USE_LFXO`) +- **LoRa**: multi-module compatible (SX1262 / SX1268 / RF95 / LLCC68 / LR1121 / LR2021) with TCXO +- **GPS**: u-blox (no EN pin) +- **Battery ADC**: 0.5 voltage divider (equal resistors) + +## Pin map + +| Function | Pin | Notes | +| ------------- | ----- | -------------------------------------- | +| LED | P0.30 | Active high (`LED_STATE_ON = 1`) | +| BUTTON | P0.27 | User button | +| BUZZER | P0.26 | PWM buzzer | +| BATTERY_ADC | P0.05 | 0.5 divider | +| IIC_SDA | P0.09 | | +| IIC_SCL | P0.10 | | +| SPI_MISO | P0.24 | | +| SPI_MOSI | P0.25 | | +| SPI_SCK | P0.28 | | +| LORA_CS | P0.29 | | +| LORA_DIO1 | P0.21 | IRQ | +| LORA_BUSY | P0.22 | | +| LORA_RESET | P0.23 | | +| LORA_RXEN | P0.11 | TXEN tied to DIO2 internally | +| GPS_RX (MCU) | P0.07 | Data from GNSS to MCU | +| GPS_TX (MCU) | P0.08 | Data from MCU to GNSS | +| UART_TX | P0.14 | Serial2 | +| UART_RX | P0.15 | Serial2 | +| UART_RTS | P0.12 | Serial2 flow control | +| UART_CTS | P0.13 | Serial2 flow control | + +Silkscreen GPS_TX/GPS_RX labels are from the GPS module perspective; Meshtastic +macros (`GPS_TX_PIN` / `GPS_RX_PIN`) are from the MCU perspective, so they are +swapped relative to the silkscreen. + +## Build + +```sh +pio run -e moonshine_NRF52_node +``` + +Uses `PRIVATE_HW` (HardwareModel 255) - no protobuf or `architecture.h` changes +required. Flash via SWD (`debug_tool = jlink`). diff --git a/variants/nrf52840/diy/moonshine_NRF52/rfswitch.h b/variants/nrf52840/diy/moonshine_NRF52/rfswitch.h new file mode 100644 index 000000000..92e1b29e0 --- /dev/null +++ b/variants/nrf52840/diy/moonshine_NRF52/rfswitch.h @@ -0,0 +1,52 @@ +#pragma once +#include "RadioLib.h" + +// Keep LR20x0 naming while RadioLib exposes LR2021 symbols. +#ifndef LR20x0 +#define LR20x0 LR2021 +#endif + +// RF switch matrix for LR1121 following the standard Semtech reference topology. +// DIO5 -> antenna path select +// DIO6 -> TX enable / HP PA select +// DIO7 -> GNSS / WiFi select (if supported by the module) +#ifdef USE_LR1121 +static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7, RADIOLIB_NC, + RADIOLIB_NC}; + +static const Module::RfSwitchMode_t rfswitch_table[] = { + // clang-format off + // mode DIO5 DIO6 DIO7 + {LR11x0::MODE_STBY, {LOW, LOW, LOW}}, + {LR11x0::MODE_RX, {HIGH, LOW, LOW}}, + {LR11x0::MODE_TX, {HIGH, HIGH, LOW}}, + {LR11x0::MODE_TX_HP, {LOW, HIGH, LOW}}, + {LR11x0::MODE_TX_HF, {LOW, LOW, LOW}}, + {LR11x0::MODE_GNSS, {LOW, LOW, HIGH}}, + {LR11x0::MODE_WIFI, {LOW, LOW, LOW}}, + END_OF_MODE_TABLE, + // clang-format on +}; +#endif + +// LR2021 RF switch matrix following the standard Semtech / Seeed T1000-E reference topology. +// DIO5 -> antenna path select (HIGH = sub-GHz LF) +// DIO6 -> TX enable / HP PA select +// DIO7 -> not connected (no GNSS on LR2021) +// DIO8 -> RF front-end power enable +#ifdef USE_LR2021 +static const uint32_t lr20x0_rfswitch_dio_pins[] = {RADIOLIB_LR2021_DIO5, RADIOLIB_LR2021_DIO6, RADIOLIB_LR2021_DIO7, + RADIOLIB_LR2021_DIO8, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t lr20x0_rfswitch_table[] = { + // clang-format off + // mode DIO5 DIO6 DIO7 DIO8 + {LR20x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, + {LR20x0::MODE_RX, {HIGH, LOW, LOW, HIGH}}, + {LR20x0::MODE_TX, {HIGH, HIGH, LOW, HIGH}}, + {LR20x0::MODE_RX_HF, {LOW, LOW, LOW, LOW}}, + {LR20x0::MODE_TX_HF, {LOW, LOW, LOW, LOW}}, + END_OF_MODE_TABLE, + // clang-format on +}; +#endif diff --git a/variants/nrf52840/diy/moonshine_NRF52/variant.cpp b/variants/nrf52840/diy/moonshine_NRF52/variant.cpp new file mode 100644 index 000000000..069210f3d --- /dev/null +++ b/variants/nrf52840/diy/moonshine_NRF52/variant.cpp @@ -0,0 +1,43 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + // P0 + 0, 1, 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, + + // P1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; + +void initVariant() +{ + // No dedicated 3V3 enable pin on this board +} + +void variant_shutdown() +{ + nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Enable internal pull-up on the button pin + nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW; // Configure SENSE signal on low edge + nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep +} diff --git a/variants/nrf52840/diy/moonshine_NRF52/variant.h b/variants/nrf52840/diy/moonshine_NRF52/variant.h new file mode 100644 index 000000000..b1616d7c1 --- /dev/null +++ b/variants/nrf52840/diy/moonshine_NRF52/variant.h @@ -0,0 +1,171 @@ +#ifndef _VARIANT_MOONSHINE_NRF52_ +#define _VARIANT_MOONSHINE_NRF52_ + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/* +MOONSHINE NRF52 PIN ASSIGNMENT (RF-BM-ND05) + +| Pin | Function | | Pin | Function | +| ----- | ----------- | ------ | ----- | ----------- | +| P0.05 | VBAT_ADC | | P0.21 | LORA_DIO1 | +| P0.07 | GPS_RX(MCU) | | P0.22 | LORA_BUSY | +| P0.08 | GPS_TX(MCU) | | P0.23 | LORA_RESET | +| P0.09 | IIC_SDA | | P0.24 | SPI_MISO | +| P0.10 | IIC_SCL | | P0.25 | SPI_MOSI | +| P0.11 | LORA_RXEN | | P0.26 | BUZZER | +| P0.12 | UART_RTS | | P0.27 | BUTTON | +| P0.13 | UART_CTS | | P0.28 | SPI_SCK | +| P0.14 | UART_TX | | P0.29 | LORA_CS | +| P0.15 | UART_RX | | P0.30 | LED | +*/ + +// Number of pins defined in PinDescription array +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (1) +#define NUM_ANALOG_OUTPUTS (0) + +// No dedicated 3V3 enable pin on this board +#define PIN_3V3_EN (-1) + +// Analog pins +#define BATTERY_PIN (0 + 5) // P0.05 Battery ADC +#define ADC_RESOLUTION 14 +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 +#define VBAT_MV_PER_LSB (0.73242188F) +// Voltage divider value => equal resistors divider = 0.5 +#define VBAT_DIVIDER (0.5F) +// Compensation factor for the VBAT divider +#define VBAT_DIVIDER_COMP (2.0F) +// Fixed calculation of milliVolt from compensation value +#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 +#define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB +#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x) + +// WIRE IC AND IIC PINS +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (0 + 9) // P0.09 +#define PIN_WIRE_SCL (0 + 10) // P0.10 + +// LED +#define PIN_LED1 (0 + 30) // P0.30 +#define LED_BLUE PIN_LED1 +#define LED_STATE_ON 1 // State when LED is lit (active high) + +// Buzzer +#define PIN_BUZZER (0 + 26) // P0.26 + +// Button +#define BUTTON_PIN (0 + 27) // P0.27 + +// GPS (silkscreen is from GPS module perspective; Meshtastic macros are from MCU perspective) +#define GPS_RX_PIN (0 + 7) // P0.07 - data from GNSS to MCU +#define GPS_TX_PIN (0 + 8) // P0.08 - data from MCU to GNSS +#define GPS_UBLOX +// define GPS_DEBUG + +// UART interfaces +#define PIN_SERIAL1_TX GPS_TX_PIN +#define PIN_SERIAL1_RX GPS_RX_PIN + +// Serial2 (with hardware flow control: P0.12=RTS, P0.13=CTS) +#define PIN_SERIAL2_RX (0 + 15) // P0.15 +#define PIN_SERIAL2_TX (0 + 14) // P0.14 + +// Serial interfaces +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (0 + 24) // P0.24 +#define PIN_SPI_MOSI (0 + 25) // P0.25 +#define PIN_SPI_SCK (0 + 28) // P0.28 + +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_SCK PIN_SPI_SCK +#define LORA_CS (0 + 29) // P0.29 + +// LORA MODULES +#define USE_LLCC68 +#define USE_SX1262 +#define USE_RF95 +#define USE_SX1268 +#define USE_LR1121 +#define USE_LR2021 + +// RF95 CONFIG +#define LORA_DIO0 (0 + 22) // P0.22 BUSY +#define LORA_DIO1 (0 + 21) // P0.21 IRQ +#define LORA_RESET (0 + 23) // P0.23 NRST + +// RX/TX for RFM95/SX127x +#define RF95_RXEN (0 + 11) // P0.11 +#define RF95_TXEN RADIOLIB_NC // Assuming that DIO2 is connected to TXEN pin. If not, TXEN must be connected. + +// SX126X CONFIG +#define SX126X_CS (0 + 29) // P0.29 FIXME - we really should define LORA_CS instead +#define SX126X_DIO1 (0 + 21) // P0.21 IRQ +#define SX126X_DIO2_AS_RF_SWITCH // Note for E22 modules: DIO2 is not attached internally to TXEN for automatic TX/RX switching, + // so it needs connecting externally if it is used in this way +#define SX126X_BUSY (0 + 22) // P0.22 +#define SX126X_RESET (0 + 23) // P0.23 +#define SX126X_RXEN (0 + 11) // P0.11 +#define SX126X_TXEN RADIOLIB_NC // Assuming that DIO2 is connected to TXEN pin. If not, TXEN must be connected. + +// LR1121 +#ifdef USE_LR1121 +#define LR1121_IRQ_PIN (0 + 21) // P0.21 IRQ +#define LR1121_NRESET_PIN LORA_RESET // P0.23 NRST +#define LR1121_BUSY_PIN (0 + 22) // P0.22 BUSY +#define LR1121_SPI_NSS_PIN LORA_CS // P0.29 +#define LR1121_SPI_SCK_PIN LORA_SCK +#define LR1121_SPI_MOSI_PIN LORA_MOSI +#define LR1121_SPI_MISO_PIN LORA_MISO +#define LR11X0_DIO3_TCXO_VOLTAGE 1.8 +#define LR11X0_DIO_AS_RF_SWITCH +#endif + +// LR2021 +#ifdef USE_LR2021 +#define LR2021_IRQ_PIN (0 + 21) // P0.21 IRQ +#define LR2021_NRESET_PIN LORA_RESET // P0.23 NRST +#define LR2021_BUSY_PIN (0 + 22) // P0.22 BUSY +#define LR2021_SPI_NSS_PIN LORA_CS // P0.29 +#define LR2021_DIO3_TCXO_VOLTAGE 1.8 +#define LR2021_DIO_AS_RF_SWITCH +#define LR2021_IRQ_DIO_NUM 9 // DIO9 -> P0.21 +#endif + +// #define SX126X_MAX_POWER 8 set this if using a high-power board! + +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif