Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions variants/solarxiao/SolarXiaoBoard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifdef SOLARXIAO

#include <Arduino.h>
#include <Wire.h>

#include "SolarXiaoBoard.h"

#ifdef NRF52_POWER_MANAGEMENT
// Static configuration for power management
// Values set in variant.h defines
const PowerMgtConfig power_config = {
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
};

void SolarXiaoBoard::initiateShutdown(uint8_t reason) {
bool enable_lpcomp = (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
reason == SHUTDOWN_REASON_BOOT_PROTECT);

pinMode(VBAT_ENABLE, OUTPUT);
digitalWrite(VBAT_ENABLE, enable_lpcomp ? LOW : HIGH);

if (enable_lpcomp) {
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
}

enterSystemOff(reason);
}
#endif // NRF52_POWER_MANAGEMENT

void SolarXiaoBoard::begin() {
NRF52BoardDCDC::begin();

// Configure battery voltage ADC
pinMode(PIN_VBAT, INPUT);
pinMode(VBAT_ENABLE, OUTPUT);
digitalWrite(VBAT_ENABLE, LOW); // Enable VBAT divider for reading
analogReadResolution(12);
analogReference(AR_INTERNAL_3_0);
delay(50); // Allow ADC to settle

#ifdef PIN_USER_BTN
pinMode(PIN_USER_BTN, INPUT_PULLUP);
#endif

#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
#endif

Wire.begin();

#ifdef P_LORA_TX_LED
pinMode(P_LORA_TX_LED, OUTPUT);
digitalWrite(P_LORA_TX_LED, HIGH);
#endif

#ifdef NRF52_POWER_MANAGEMENT
// Boot voltage protection check (may not return if voltage too low)
checkBootVoltage(&power_config);
#endif

delay(10); // Give sx1262 some time to power up
}

uint16_t SolarXiaoBoard::getBattMilliVolts() {
// https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging
// VBAT_ENABLE must be LOW to read battery voltage
digitalWrite(VBAT_ENABLE, LOW);
int adcvalue = analogRead(PIN_VBAT);
return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
}

#endif
53 changes: 53 additions & 0 deletions variants/solarxiao/SolarXiaoBoard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#ifdef SOLARXIAO

class SolarXiaoBoard : public NRF52BoardDCDC {
protected:
#if NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif

public:
SolarXiaoBoard() : NRF52Board("XIAO_NRF52_OTA") {}
void begin();

#if defined(P_LORA_TX_LED)
void onBeforeTransmit() override {
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on
}
void onAfterTransmit() override {
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off
}
#endif

uint16_t getBattMilliVolts() override;

const char* getManufacturerName() const override {
return "Seeed Xiao-nrf52";
}

void powerOff() override {
// set led on and wait for button release before poweroff
digitalWrite(PIN_LED, LOW);
#ifdef PIN_USER_BTN
while(digitalRead(PIN_USER_BTN) == LOW);
#endif
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
digitalWrite(PIN_LED, HIGH);

#ifdef PIN_USER_BTN
// configure button press to wake up when in powered off state
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_USER_BTN]), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
#endif

sd_power_system_off();
}
};

#endif
169 changes: 169 additions & 0 deletions variants/solarxiao/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
[solarxiao]
extends = nrf52_base
board = seeed-xiao-afruitnrf52-nrf52840
board_build.ldscript = boards/nrf52840_s140_v7.ld
build_flags = ${nrf52_base.build_flags}
${sensor_base.build_flags}
-I lib/nrf52/s140_nrf52_7.3.0_API/include
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
-I variants/solarxiao
-D NRF52_PLATFORM
-D NRF52_POWER_MANAGEMENT
-D SOLARXIAO
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_TX_LED=11
-D P_LORA_DIO_1=D1
-D P_LORA_RESET=D2
-D P_LORA_BUSY=D3
-D P_LORA_NSS=D4
-D SX126X_RXEN=D5
-D SX126X_TXEN=RADIOLIB_NC
-D SX126X_DIO2_AS_RF_SWITCH=1
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_WIRE_SCL=D6
-D PIN_WIRE_SDA=D7
-D PIN_USER_BTN=PIN_BUTTON1
-D QSPIFLASH=1
-D DISPLAY_CLASS=NullDisplayDriver
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/sensors>
+<../variants/solarxiao>
+<helpers/ui/NullDisplayDriver.cpp>
debug_tool = jlink
upload_protocol = nrfutil
lib_deps = ${nrf52_base.lib_deps}
${sensor_base.lib_deps}

[env:solarxiao_30S_companion_radio_ble]
extends = solarxiao
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
board_upload.maximum_size = 708608
build_flags =
${solarxiao.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${solarxiao.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-orig/*.cpp>
lib_deps =
${solarxiao.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:solarxiao_33S_companion_radio_ble]
extends = env:solarxiao_30S_companion_radio_ble
build_flags =
${env:solarxiao_30S_companion_radio_ble.build_flags}
-D LORA_TX_POWER=9

[env:solarxiao_30S_companion_radio_usb]
extends = solarxiao
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
board_upload.maximum_size = 708608
build_flags =
${solarxiao.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D QSPIFLASH=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${solarxiao.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-orig/*.cpp>
lib_deps =
${solarxiao.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:solarxiao_33S_companion_radio_usb]
extends = env:solarxiao_30S_companion_radio_usb
build_flags =
${env:solarxiao_30S_companion_radio_usb.build_flags}
-D LORA_TX_POWER=9


[env:solarxiao_30S_repeater]
extends = solarxiao
build_flags =
${solarxiao.build_flags}
-D ADVERT_NAME='"SolarXiao 30S Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${solarxiao.build_src_filter}
+<../examples/simple_repeater/*.cpp>

[env:solarxiao_33S_repeater]
extends = env:solarxiao_30S_repeater
build_flags =
${env:solarxiao_30S_repeater.build_flags}
-D LORA_TX_POWER=9
-D ADVERT_NAME='"SolarXiao 33S Repeater"'


[env:solarxiao_30S_repeater_bridge_rs232]
extends = env:solarxiao_30S_repeater
${env:solarxiao_30S_repeater.build_flags}
-D ADVERT_NAME='"SolarXiao 30S RS232"'
-UENV_INCLUDE_GPS
-D WITH_RS232_BRIDGE=Serial1
-D WITH_RS232_BRIDGE_RX=PIN_SERIAL1_RX
-D WITH_RS232_BRIDGE_TX=PIN_SERIAL1_TX
-D BRIDGE_MAX_BAUD=500000

[env:solarxiao_33S_repeater_bridge_rs232]
extends = env:solarxiao_30S_repeater_bridge_rs232
build_flags =
${env:solarxiao_30S_repeater_bridge_rs232.build_flags}
-D LORA_TX_POWER=9
-D ADVERT_NAME='"SolarXiao 33S RS232"'

[env:solarxiao_30S_room_server]
extends = solarxiao
build_flags =
${solarxiao.build_flags}
-D ADVERT_NAME='"SolarXiao 30S Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${solarxiao.build_src_filter}
+<../examples/simple_room_server/*.cpp>

[env:solarxiao_33S_room_server]
extends = env:solarxiao_30S_room_server
build_flags =
${env:solarxiao_30S_room_server.build_flags}
-D LORA_TX_POWER=9
-D ADVERT_NAME='"SolarXiao 33S Room"'

[env:solarxiao_30S_kiss_modem]
extends = solarxiao
build_flags =
${solarxiao.build_flags}
build_src_filter = ${solarxiao.build_src_filter}
+<../examples/kiss_modem/*.cpp>
lib_deps =
${solarxiao.lib_deps}

[env:solarxiao_33S_kiss_modem]
extends = solarxiao_30S_kiss_modem
build_flags =
${env:solarxiao_30S_kiss_modem.build_flags}
-D LORA_TX_POWER=9
50 changes: 50 additions & 0 deletions variants/solarxiao/target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>

#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
#endif

SolarXiaoBoard 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);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#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
}
26 changes: 26 additions & 0 deletions variants/solarxiao/target.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <SolarXiaoBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/EnvironmentSensorManager.h>

#ifdef DISPLAY_CLASS
#include <helpers/ui/NullDisplayDriver.h>
extern DISPLAY_CLASS display;
#endif

extern SolarXiaoBoard board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;

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();
Loading