mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-10-05 20:57:37 +00:00
One nRF52840 variant shared across both radios, picked per env: Duo runs the LR1121, Uno the SX1262. Same PCB, only the radio and its DIO1 pin change. SuperIO adds the SH1107 OLED, GPS, buzzer and joystick. GPS is driven by the 3-position mode switch (Mode 2 = on), polled live the way thinknode_m1 does it. Five quick user-button presses power the unit off; a press wakes it back on (arms the button as an nRF52 GPIO SENSE source before SYSTEMOFF). Consolidates #2054 and andyshinn's shared-base/uno work, rebased on dev. Co-authored-by: lbibass <ewdries02@gmail.com> Co-authored-by: Andy Shinn <andys@andyshinn.as>
163 lines
5.0 KiB
C++
163 lines
5.0 KiB
C++
#include <Arduino.h>
|
|
#include <nrf_gpio.h>
|
|
#include "target.h"
|
|
#include "variant.h"
|
|
|
|
muzi_baseBoard 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 <helpers/sensors/MicroNMEALocationProvider.h>
|
|
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
|
MuziBaseSensorManager sensors = MuziBaseSensorManager(nmea);
|
|
#else
|
|
MuziBaseSensorManager sensors;
|
|
#endif
|
|
|
|
// user button for the N-click power-off. single-click mode (multiclick off) so
|
|
// each press is its own CLICK; we count them ourselves. reliable across the
|
|
// idle-sleep loop because it's the same MomentaryButton the UI navigates with.
|
|
static MomentaryButton pwr_btn(PIN_USER_BTN, 0, true, true, false);
|
|
|
|
// power off, arming the user button as a wake source first so a later press
|
|
// turns it back on. wait for the button to release (the 5th click already fires
|
|
// on release, so this returns quickly), then set nRF52 GPIO SENSE (press = LOW);
|
|
// it survives into SYSTEMOFF because shutdownPeripherals() doesn't touch this pin.
|
|
static void muziPowerOff() {
|
|
uint32_t t0 = millis();
|
|
while (digitalRead(PIN_USER_BTN) == USER_BTN_PRESSED && (millis() - t0) < 3000) { delay(5); }
|
|
delay(50); // settle
|
|
nrf_gpio_cfg_sense_input(g_ADigitalPinMap[PIN_USER_BTN], NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
|
|
board.powerOff(); // shutdownPeripherals() + SYSTEMOFF
|
|
}
|
|
|
|
bool MuziBaseSensorManager::begin() {
|
|
pwr_btn.begin();
|
|
bool ok = EnvironmentSensorManager::begin();
|
|
#if ENV_INCLUDE_GPS
|
|
pinMode(PIN_GPS_SWITCH, INPUT);
|
|
_last_gps_sw = digitalRead(PIN_GPS_SWITCH); // initial gps state from the switch
|
|
if (_last_gps_sw == HIGH) start_gps(); else stop_gps();
|
|
#endif
|
|
return ok;
|
|
}
|
|
|
|
void MuziBaseSensorManager::loop() {
|
|
// user button: USER_BTN_POWER_OFF_CLICKS quick clicks -> power off
|
|
if (pwr_btn.check() == BUTTON_EVENT_CLICK) {
|
|
unsigned long t = millis();
|
|
if (t - _pwr_last_click > 2000) _pwr_clicks = 0; // restart if too slow
|
|
_pwr_last_click = t;
|
|
if (++_pwr_clicks >= USER_BTN_POWER_OFF_CLICKS) muziPowerOff();
|
|
}
|
|
#if ENV_INCLUDE_GPS
|
|
unsigned long now = millis();
|
|
if (now > _next_sw_check) { // check the mode switch ~once a sec
|
|
_next_sw_check = now + 1000;
|
|
int sw = digitalRead(PIN_GPS_SWITCH);
|
|
if (sw != _last_gps_sw) {
|
|
_last_gps_sw = sw;
|
|
if (sw == HIGH) start_gps(); else stop_gps();
|
|
}
|
|
}
|
|
#endif
|
|
EnvironmentSensorManager::loop();
|
|
}
|
|
|
|
#ifdef DISPLAY_CLASS
|
|
DISPLAY_CLASS display;
|
|
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
|
|
MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
|
|
MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
|
|
MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
|
|
#endif
|
|
|
|
#if defined(USE_LR1121)
|
|
#ifndef LORA_CR
|
|
#define LORA_CR 5
|
|
#endif
|
|
|
|
#ifdef RF_SWITCH_TABLE
|
|
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
|
|
RADIOLIB_LR11X0_DIO5,
|
|
RADIOLIB_LR11X0_DIO6,
|
|
RADIOLIB_NC
|
|
};
|
|
|
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
|
// mode DIO5 DIO6
|
|
{ LR11x0::MODE_STBY, {LOW, LOW}},
|
|
{ LR11x0::MODE_RX, {HIGH, LOW}},
|
|
{ LR11x0::MODE_TX, {LOW, HIGH}},
|
|
{ LR11x0::MODE_TX_HP, {LOW, HIGH}},
|
|
{ LR11x0::MODE_TX_HF, {LOW, LOW}},
|
|
{ LR11x0::MODE_GNSS, {LOW, LOW}},
|
|
{ LR11x0::MODE_WIFI, {LOW, LOW}},
|
|
END_OF_MODE_TABLE,
|
|
};
|
|
#endif
|
|
#endif // USE_LR1121
|
|
|
|
bool radio_init() {
|
|
//rtc_clock.begin(Wire);
|
|
|
|
#if defined(USE_LR1121)
|
|
#ifdef LR11X0_DIO3_TCXO_VOLTAGE
|
|
float tcxo = LR11X0_DIO3_TCXO_VOLTAGE;
|
|
#else
|
|
float tcxo = 1.6f;
|
|
#endif
|
|
|
|
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
|
|
SPI.begin();
|
|
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
|
if (status != RADIOLIB_ERR_NONE) {
|
|
Serial.print("ERROR: radio init failed: ");
|
|
Serial.println(status);
|
|
return false; // fail
|
|
}
|
|
|
|
radio.setCRC(2);
|
|
radio.explicitHeader();
|
|
|
|
#ifdef RF_SWITCH_TABLE
|
|
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
|
|
#endif
|
|
#ifdef RX_BOOSTED_GAIN
|
|
radio.setRxBoostedGainMode(RX_BOOSTED_GAIN);
|
|
#endif
|
|
|
|
return true; // success
|
|
#else // USE_SX1262
|
|
// CustomSX1262::std_init() configures the SPI pins, runs begin() with the
|
|
// TCXO-voltage fallback, sets CRC, current limit, the DIO2 RF switch, and
|
|
// RX boosted gain from the SX126X_* build flags.
|
|
return radio.std_init(&SPI);
|
|
#endif
|
|
}
|
|
|
|
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
|
|
}
|