Compare commits

...

11 Commits

Author SHA1 Message Date
rcarteraz
b28d095096 missed t-rexes 2025-10-01 13:32:44 -05:00
rcarteraz
17afdb9ccf no more t-rex 2025-10-01 13:32:44 -05:00
Jonathan Bennett
d5164b4fbf Check the BUILD_EPOCH if defined 2025-10-01 13:32:44 -05:00
Jonathan Bennett
ad44940732 Put the GPIO in the right state for wake from sleep 2025-10-01 13:32:44 -05:00
Jonathan Bennett
8b466b1db3 T-rex comment cleanup 2025-10-01 13:32:44 -05:00
Jonathan Bennett
f9937967fa Add HardwareModel and correct directories 2025-10-01 13:32:44 -05:00
Jonathan Bennett
4fd568f384 Initial support for T-Rex 2025-10-01 13:32:44 -05:00
github-actions[bot]
b08e4efb78 Update protobufs (#8172)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-09-30 13:34:40 -05:00
Ben Meadors
ee6857511a Fix Heltec V3 missed button presses (#8167) 2025-09-30 08:05:00 -05:00
Clive Blackledge
a1c658a467 Bug / Send upgraded (duplicate) packets to phone if the queue removal failed. (#8148)
* Add seenRecently = true if wasUpgraded is true but unable to remove from queue (i.e. already sent/processed).

* Consistent comment between FloodingRouter and HopRouter
2025-09-28 16:43:51 -05:00
Ben Meadors
a15d654767 Finish deprecating the Repeater role behavior (#8144)
* Finish deprecating the Repeater role behavior

* Validate

* Fixed bad if/else block

* Get your crap together!
2025-09-28 15:30:53 -05:00
33 changed files with 465 additions and 194 deletions

52
boards/r1-neo.json Normal file
View File

@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "Muzi R1 Neo",
"mcu": "nrf52840",
"variant": "r1-neo",
"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",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino", "freertos"],
"name": "WisCore RAK4631 Board",
"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://muzi.works/",
"vendor": "Muzi Works"
}

View File

@@ -76,9 +76,6 @@ const char *DisplayFormatters::getDeviceRole(meshtastic_Config_DeviceConfig_Role
case meshtastic_Config_DeviceConfig_Role_ROUTER_LATE:
return "Router Late";
break;
case meshtastic_Config_DeviceConfig_Role_REPEATER:
return "Repeater";
break;
default:
return "Unknown";
break;

View File

@@ -25,8 +25,8 @@ ScanI2C::FoundDevice ScanI2C::firstScreen() const
ScanI2C::FoundDevice ScanI2C::firstRTC() const
{
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563};
return firstOfOrNONE(2, types);
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563, RTC_RX8130CE};
return firstOfOrNONE(3, types);
}
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const

View File

@@ -14,6 +14,7 @@ class ScanI2C
SCREEN_ST7567,
RTC_RV3028,
RTC_PCF8563,
RTC_RX8130CE,
CARDKB,
TDECKKB,
BBQ10KB,

View File

@@ -197,6 +197,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#ifdef PCF8563_RTC
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563", (uint8_t)addr.address)
#endif
#ifdef RX8130CE_RTC
SCAN_SIMPLE_CASE(RX8130CE_RTC, RTC_RX8130CE, "RX8130CE", (uint8_t)addr.address)
#endif
case CARDKB_ADDR:
// Do we have the RAK14006 instead?

View File

@@ -1104,11 +1104,6 @@ int32_t GPS::runOnce()
publishUpdate();
}
// Repeaters have no need for GPS
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
return disable();
}
if (whileActive()) {
// if we have received valid NMEA claim we are connected
setConnected();

View File

@@ -109,6 +109,35 @@ RTCSetResult readFromRTC()
}
return RTCSetResultSuccess;
}
#elif defined(RX8130CE_RTC)
if (rtc_found.address == RX8130CE_RTC) {
uint32_t now = millis();
ArtronShop_RX8130CE rtc(&Wire);
tm t;
if (rtc.getTime(&t)) {
tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0;
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
LOG_DEBUG("Read RTC time from RX8130CE getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)", t.tm_year + 1900,
t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
#ifdef BUILD_EPOCH
if (tv.tv_sec < BUILD_EPOCH) {
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
lastTimeValidationWarning = millis();
}
return RTCSetResultInvalidTime;
}
#endif
if (currentQuality == RTCQualityNone) {
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
currentQuality = RTCQualityDevice;
}
return RTCSetResultSuccess;
}
}
#else
if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis();
@@ -214,6 +243,17 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
}
#elif defined(RX8130CE_RTC)
if (rtc_found.address == RX8130CE_RTC) {
ArtronShop_RX8130CE rtc(&Wire);
tm *t = gmtime(&tv->tv_sec);
if (rtc.setTime(*t)) {
LOG_DEBUG("RX8130CE setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1,
t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
} else {
LOG_WARN("Failed to set time for RX8130CE");
}
}
#elif defined(ARCH_ESP32)
settimeofday(tv, NULL);
#endif

View File

@@ -4,6 +4,10 @@
#include "sys/time.h"
#include <Arduino.h>
#ifdef RX8130CE_RTC
#include <ArtronShop_RX8130CE.h>
#endif
enum RTCQuality {
/// We haven't had our RTC set yet

View File

@@ -279,7 +279,7 @@ int32_t ButtonThread::runOnce()
if (!userButton.isIdle() || waitingForLongPress) {
return 50;
}
return INT32_MAX;
return 100; // FIXME: Why can't we rely on interrupts and use INT32_MAX here?
}
/*

View File

@@ -297,6 +297,12 @@ void printInfo()
#ifndef PIO_UNIT_TESTING
void setup()
{
#if defined(R1_NEO)
pinMode(DCDC_EN_HOLD, OUTPUT);
digitalWrite(DCDC_EN_HOLD, HIGH);
pinMode(NRF_ON, OUTPUT);
digitalWrite(NRF_ON, HIGH);
#endif
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
@@ -793,14 +799,7 @@ void setup()
}
#endif
// If we're taking on the repeater role, use NextHopRouter and turn off 3V3_S rail because peripherals are not needed
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
router = new NextHopRouter();
#ifdef PIN_3V3_EN
digitalWrite(PIN_3V3_EN, LOW);
#endif
} else
router = new ReliableRouter();
router = new ReliableRouter();
// only play start melody when role is not tracker or sensor
if (config.power.is_power_saving == true &&
@@ -926,8 +925,7 @@ void setup()
if (sensor_detected == false) {
#endif
if (HAS_GPS) {
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
gps = GPS::createGps();
if (gps) {
gpsStatus->observe(&gps->newStatus);

View File

@@ -54,6 +54,10 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
// We already enqueued the improved copy, so make sure the incoming packet stops here.
return true;
}
// No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid
// delivering the same packet to applications/phone twice with different hop limits.
seenRecently = true;
}
if (seenRecently) {
@@ -81,9 +85,8 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
bool FloodingRouter::roleAllowsCancelingDupe(const meshtastic_MeshPacket *p)
{
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) {
// ROUTER, REPEATER, ROUTER_LATE should never cancel relaying a packet (i.e. we should always rebroadcast),
// ROUTER, ROUTER_LATE should never cancel relaying a packet (i.e. we should always rebroadcast),
// even if we've heard another station rebroadcast it already.
return false;
}
@@ -102,7 +105,7 @@ bool FloodingRouter::roleAllowsCancelingDupe(const meshtastic_MeshPacket *p)
void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
{
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA && roleAllowsCancelingDupe(p)) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
// cancel rebroadcast of this message *if* there was already one, unless we're a router!
// But only LoRa packets should be able to trigger this.
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;

View File

@@ -59,7 +59,7 @@ class FloodingRouter : public Router
*/
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;
// Return false for roles like ROUTER or REPEATER which should always rebroadcast even when we've heard another rebroadcast of
// Return false for roles like ROUTER which should always rebroadcast even when we've heard another rebroadcast of
// the same packet
bool roleAllowsCancelingDupe(const meshtastic_MeshPacket *p);

View File

@@ -85,12 +85,11 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
nodeDB->updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
bool isPreferredRebroadcaster =
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER, meshtastic_Config_DeviceConfig_Role_REPEATER);
bool isPreferredRebroadcaster = config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) {
LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo"); // because this potentially a Repeater which will
// ignore our request for its NodeInfo
LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo");
// ignore our request for its NodeInfo
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user &&
nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) {
if (airTime->isTxAllowedChannelUtil(true)) {

View File

@@ -64,6 +64,10 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
// We already enqueued the improved copy, so make sure the incoming packet stops here.
return true;
}
// No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid
// delivering the same packet to applications/phone twice with different hop limits.
seenRecently = true;
}
if (seenRecently) {
@@ -170,7 +174,6 @@ bool NextHopRouter::perhapsRelay(const meshtastic_MeshPacket *p)
*/
uint8_t NextHopRouter::getNextHop(NodeNum to, uint8_t relay_node)
{
// When we're a repeater router->sniffReceived will call NextHopRouter directly without checking for broadcast
if (isBroadcast(to))
return NO_NEXT_HOP_PREFERENCE;
@@ -208,7 +211,7 @@ bool NextHopRouter::roleAllowsCancelingFromTxQueue(const meshtastic_MeshPacket *
{
// Return true if we're allowed to cancel a packet in the txQueue (so we may never transmit it even once)
// Return false for roles like ROUTER, REPEATER, ROUTER_LATE which should always transmit the packet at least once.
// Return false for roles like ROUTER, ROUTER_LATE which should always transmit the packet at least once.
return roleAllowsCancelingDupe(p); // same logic as FloodingRouter::roleAllowsCancelingDupe
}
@@ -221,7 +224,7 @@ bool NextHopRouter::stopRetransmission(GlobalPacketId key)
/* Only when we already transmitted a packet via LoRa, we will cancel the packet in the Tx queue
to avoid canceling a transmission if it was ACKed super fast via MQTT */
if (old->numRetransmissions < NUM_RELIABLE_RETX - 1) {
// We only cancel it if we are the original sender or if we're not a router(_late)/repeater
// We only cancel it if we are the original sender or if we're not a router(_late)
if (isFromUs(p) || roleAllowsCancelingFromTxQueue(p)) {
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
cancelSending(getFrom(p), p->id);

View File

@@ -554,10 +554,9 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#endif
#ifdef USERPREFS_CONFIG_DEVICE_ROLE
// Restrict ROUTER*, LOST AND FOUND, and REPEATER roles for security reasons
// Restrict ROUTER*, LOST AND FOUND roles for security reasons
if (IS_ONE_OF(USERPREFS_CONFIG_DEVICE_ROLE, meshtastic_Config_DeviceConfig_Role_ROUTER,
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_REPEATER,
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) {
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) {
LOG_WARN("ROUTER roles are restricted, falling back to CLIENT role");
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
} else {
@@ -906,11 +905,6 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
moduleConfig.telemetry.device_update_interval = ONE_DAY;
owner.has_is_unmessagable = true;
owner.is_unmessagable = true;
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
owner.has_is_unmessagable = true;
owner.is_unmessagable = true;
config.display.screen_on_secs = 1;
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY;
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
owner.has_is_unmessagable = true;
owner.is_unmessagable = true;

View File

@@ -317,9 +317,8 @@ uint32_t RadioInterface::getTxDelayMsecWeightedWorst(float snr)
/** Returns true if we should rebroadcast early like a ROUTER */
bool RadioInterface::shouldRebroadcastEarlyLikeRouter(meshtastic_MeshPacket *p)
{
// If we are a ROUTER or REPEATER, we always rebroadcast early
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
// If we are a ROUTER, we always rebroadcast early
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
return true;
}

View File

@@ -399,10 +399,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
{
concurrency::LockGuard g(cryptLock);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
return DecodeState::DECODE_FAILURE;
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY &&
(nodeDB->getMeshNode(p->from) == NULL || !nodeDB->getMeshNode(p->from)->has_user)) {
LOG_DEBUG("Node 0x%x not in nodeDB-> Rebroadcast mode KNOWN_ONLY will ignore packet", p->from);

View File

@@ -253,8 +253,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1 = 99,
/* Seeed Tracker L1 EINK driver */
meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK = 100,
/* Reserved ID for future and past use */
meshtastic_HardwareModel_QWANTZ_TINY_ARMS = 101,
/* Muzi Works R1 Neo */
meshtastic_HardwareModel_MUZI_R1_NEO = 101,
/* Lilygo T-Deck Pro */
meshtastic_HardwareModel_T_DECK_PRO = 102,
/* Lilygo TLora Pager */

View File

@@ -611,10 +611,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
}
config.device = c.payload_variant.device;
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_NONE &&
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER,
meshtastic_Config_DeviceConfig_Role_REPEATER)) {
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
const char *warning = "Rebroadcast mode can't be set to NONE for a router or repeater";
const char *warning = "Rebroadcast mode can't be set to NONE for a router";
LOG_WARN(warning);
sendWarning(warning);
}
@@ -627,8 +626,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d", min_node_info_broadcast_secs);
config.device.node_info_broadcast_secs = min_node_info_broadcast_secs;
}
// Router Client is deprecated; Set it to client
if (c.payload_variant.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT) {
// Router Client and Repeater deprecated; Set it to client
if (IS_ONE_OF(c.payload_variant.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT,
meshtastic_Config_DeviceConfig_Role_REPEATER)) {
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
if (moduleConfig.store_forward.enabled && !moduleConfig.store_forward.is_server) {
moduleConfig.store_forward.is_server = true;
@@ -637,10 +637,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
}
}
#if USERPREFS_EVENT_MODE
// If we're in event mode, nobody is a Router or Repeater
// If we're in event mode, nobody is a Router or Router Late
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) {
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
}
#endif

View File

@@ -112,204 +112,191 @@
*/
void setupModules()
{
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
#if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
inputBroker = new InputBroker();
systemCommandsModule = new SystemCommandsModule();
buzzerFeedbackThread = new BuzzerFeedbackThread();
}
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
inputBroker = new InputBroker();
systemCommandsModule = new SystemCommandsModule();
buzzerFeedbackThread = new BuzzerFeedbackThread();
}
#endif
#if !MESHTASTIC_EXCLUDE_ADMIN
adminModule = new AdminModule();
adminModule = new AdminModule();
#endif
#if !MESHTASTIC_EXCLUDE_NODEINFO
nodeInfoModule = new NodeInfoModule();
nodeInfoModule = new NodeInfoModule();
#endif
#if !MESHTASTIC_EXCLUDE_GPS
positionModule = new PositionModule();
positionModule = new PositionModule();
#endif
#if !MESHTASTIC_EXCLUDE_WAYPOINT
waypointModule = new WaypointModule();
waypointModule = new WaypointModule();
#endif
#if !MESHTASTIC_EXCLUDE_TEXTMESSAGE
textMessageModule = new TextMessageModule();
textMessageModule = new TextMessageModule();
#endif
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
traceRouteModule = new TraceRouteModule();
traceRouteModule = new TraceRouteModule();
#endif
#if !MESHTASTIC_EXCLUDE_NEIGHBORINFO
if (moduleConfig.has_neighbor_info && moduleConfig.neighbor_info.enabled) {
neighborInfoModule = new NeighborInfoModule();
}
if (moduleConfig.has_neighbor_info && moduleConfig.neighbor_info.enabled) {
neighborInfoModule = new NeighborInfoModule();
}
#endif
#if !MESHTASTIC_EXCLUDE_DETECTIONSENSOR
if (moduleConfig.has_detection_sensor && moduleConfig.detection_sensor.enabled) {
detectionSensorModule = new DetectionSensorModule();
}
if (moduleConfig.has_detection_sensor && moduleConfig.detection_sensor.enabled) {
detectionSensorModule = new DetectionSensorModule();
}
#endif
#if !MESHTASTIC_EXCLUDE_ATAK
if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TAK,
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)) {
atakPluginModule = new AtakPluginModule();
}
if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TAK, meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)) {
atakPluginModule = new AtakPluginModule();
}
#endif
#if !MESHTASTIC_EXCLUDE_PKI
keyVerificationModule = new KeyVerificationModule();
keyVerificationModule = new KeyVerificationModule();
#endif
#if !MESHTASTIC_EXCLUDE_DROPZONE
dropzoneModule = new DropzoneModule();
dropzoneModule = new DropzoneModule();
#endif
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
new GenericThreadModule();
new GenericThreadModule();
#endif
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
// to a global variable.
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
// to a global variable.
#if !MESHTASTIC_EXCLUDE_REMOTEHARDWARE
new RemoteHardwareModule();
new RemoteHardwareModule();
#endif
#if !MESHTASTIC_EXCLUDE_POWERSTRESS
new PowerStressModule();
new PowerStressModule();
#endif
// Example: Put your module here
// new ReplyModule();
// Example: Put your module here
// new ReplyModule();
#if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
if (!rotaryEncoderInterruptImpl1->init()) {
delete rotaryEncoderInterruptImpl1;
rotaryEncoderInterruptImpl1 = nullptr;
}
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
if (!rotaryEncoderInterruptImpl1->init()) {
delete rotaryEncoderInterruptImpl1;
rotaryEncoderInterruptImpl1 = nullptr;
}
#ifdef T_LORA_PAGER
// use a special FSM based rotary encoder version for T-LoRa Pager
rotaryEncoderImpl = new RotaryEncoderImpl();
if (!rotaryEncoderImpl->init()) {
delete rotaryEncoderImpl;
rotaryEncoderImpl = nullptr;
}
// use a special FSM based rotary encoder version for T-LoRa Pager
rotaryEncoderImpl = new RotaryEncoderImpl();
if (!rotaryEncoderImpl->init()) {
delete rotaryEncoderImpl;
rotaryEncoderImpl = nullptr;
}
#else
upDownInterruptImpl1 = new UpDownInterruptImpl1();
if (!upDownInterruptImpl1->init()) {
delete upDownInterruptImpl1;
upDownInterruptImpl1 = nullptr;
}
upDownInterruptImpl1 = new UpDownInterruptImpl1();
if (!upDownInterruptImpl1->init()) {
delete upDownInterruptImpl1;
upDownInterruptImpl1 = nullptr;
}
#endif
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
#if defined(M5STACK_UNITC6L)
i2cButton = new i2cButtonThread("i2cButtonThread");
i2cButton = new i2cButtonThread("i2cButtonThread");
#endif
#ifdef INPUTBROKER_MATRIX_TYPE
kbMatrixImpl = new KbMatrixImpl();
kbMatrixImpl->init();
kbMatrixImpl = new KbMatrixImpl();
kbMatrixImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE
#ifdef INPUTBROKER_SERIAL_TYPE
aSerialKeyboardImpl = new SerialKeyboardImpl();
aSerialKeyboardImpl->init();
aSerialKeyboardImpl = new SerialKeyboardImpl();
aSerialKeyboardImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE
}
}
#endif // HAS_BUTTON
#if ARCH_PORTDUINO
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
seesawRotary = new SeesawRotary("SeesawRotary");
if (!seesawRotary->init()) {
delete seesawRotary;
seesawRotary = nullptr;
}
aLinuxInputImpl = new LinuxInputImpl();
aLinuxInputImpl->init();
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
seesawRotary = new SeesawRotary("SeesawRotary");
if (!seesawRotary->init()) {
delete seesawRotary;
seesawRotary = nullptr;
}
aLinuxInputImpl = new LinuxInputImpl();
aLinuxInputImpl->init();
}
#endif
#if !MESHTASTIC_EXCLUDE_INPUTBROKER && HAS_TRACKBALL
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
trackballInterruptImpl1 = new TrackballInterruptImpl1();
trackballInterruptImpl1->init(TB_DOWN, TB_UP, TB_LEFT, TB_RIGHT, TB_PRESS);
}
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
trackballInterruptImpl1 = new TrackballInterruptImpl1();
trackballInterruptImpl1->init(TB_DOWN, TB_UP, TB_LEFT, TB_RIGHT, TB_PRESS);
}
#endif
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
expressLRSFiveWayInput = new ExpressLRSFiveWay();
expressLRSFiveWayInput = new ExpressLRSFiveWay();
#endif
#if HAS_SCREEN && !MESHTASTIC_EXCLUDE_CANNEDMESSAGES
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
cannedMessageModule = new CannedMessageModule();
}
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
cannedMessageModule = new CannedMessageModule();
}
#endif
#if ARCH_PORTDUINO
new HostMetricsModule();
new HostMetricsModule();
#endif
#if HAS_TELEMETRY
new DeviceTelemetryModule();
new DeviceTelemetryModule();
#endif
#if HAS_TELEMETRY && HAS_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (moduleConfig.has_telemetry &&
(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
new EnvironmentTelemetryModule();
}
if (moduleConfig.has_telemetry &&
(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
new EnvironmentTelemetryModule();
}
#if __has_include("Adafruit_PM25AQI.h")
if (moduleConfig.has_telemetry && moduleConfig.telemetry.air_quality_enabled &&
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first > 0) {
new AirQualityTelemetryModule();
}
if (moduleConfig.has_telemetry && moduleConfig.telemetry.air_quality_enabled &&
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first > 0) {
new AirQualityTelemetryModule();
}
#endif
#if !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX30102].first > 0 ||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MLX90614].first > 0) {
new HealthTelemetryModule();
}
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX30102].first > 0 ||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MLX90614].first > 0) {
new HealthTelemetryModule();
}
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (moduleConfig.has_telemetry &&
(moduleConfig.telemetry.power_measurement_enabled || moduleConfig.telemetry.power_screen_enabled)) {
new PowerTelemetryModule();
}
if (moduleConfig.has_telemetry &&
(moduleConfig.telemetry.power_measurement_enabled || moduleConfig.telemetry.power_screen_enabled)) {
new PowerTelemetryModule();
}
#endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)) && \
!defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#if !MESHTASTIC_EXCLUDE_SERIAL
if (moduleConfig.has_serial && moduleConfig.serial.enabled &&
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
new SerialModule();
}
if (moduleConfig.has_serial && moduleConfig.serial.enabled &&
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
new SerialModule();
}
#endif
#endif
#ifdef ARCH_ESP32
// Only run on an esp32 based device.
// Only run on an esp32 based device.
#if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO
audioModule = new AudioModule();
audioModule = new AudioModule();
#endif
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
if (moduleConfig.has_paxcounter && moduleConfig.paxcounter.enabled) {
paxcounterModule = new PaxcounterModule();
}
if (moduleConfig.has_paxcounter && moduleConfig.paxcounter.enabled) {
paxcounterModule = new PaxcounterModule();
}
#endif
#endif
#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
if (moduleConfig.has_store_forward && moduleConfig.store_forward.enabled) {
storeForwardModule = new StoreForwardModule();
}
if (moduleConfig.has_store_forward && moduleConfig.store_forward.enabled) {
storeForwardModule = new StoreForwardModule();
}
#endif
#endif
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
externalNotificationModule = new ExternalNotificationModule();
externalNotificationModule = new ExternalNotificationModule();
#endif
#if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS
if (moduleConfig.has_range_test && moduleConfig.range_test.enabled)
new RangeTestModule();
if (moduleConfig.has_range_test && moduleConfig.range_test.enabled)
new RangeTestModule();
#endif
} else {
#if !MESHTASTIC_EXCLUDE_ADMIN
adminModule = new AdminModule();
#endif
#if HAS_TELEMETRY
new DeviceTelemetryModule();
#endif
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
traceRouteModule = new TraceRouteModule();
#endif
}
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
// acks
routingModule = new RoutingModule();

View File

@@ -94,11 +94,6 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply()
u.public_key.bytes[0] = 0;
u.public_key.size = 0;
}
// Coerce unmessagable for Repeater role
if (u.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
u.has_is_unmessagable = true;
u.is_unmessagable = true;
}
LOG_INFO("Send owner %s/%s/%s", u.id, u.long_name, u.short_name);
lastSentToMesh = millis();

View File

@@ -42,8 +42,6 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh
meshtastic_MeshPacket *RoutingModule::allocReply()
{
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
return NULL;
assert(currentRequest);
return NULL;

View File

@@ -26,7 +26,6 @@ int32_t DeviceTelemetryModule::runOnce()
Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.device_update_interval,
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
airTime->isTxAllowedChannelUtil(!isImpoliteRole) && airTime->isTxAllowedAirUtil() &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
sendTelemetry();
lastSentToMesh = uptimeLastMs;
@@ -44,10 +43,6 @@ int32_t DeviceTelemetryModule::runOnce()
bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
{
// Don't worry about storing telemetry in NodeDB if we're a repeater
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
return false;
if (t->which_variant == meshtastic_Telemetry_device_metrics_tag) {
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
const char *sender = getSenderShortName(mp);

View File

@@ -22,10 +22,6 @@ int32_t HostMetricsModule::runOnce()
bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
{
// Don't worry about storing telemetry in NodeDB if we're a repeater
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
return false;
if (t->which_variant == meshtastic_Telemetry_host_metrics_tag) {
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
const char *sender = getSenderShortName(mp);

View File

@@ -335,7 +335,8 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke
meshtastic::BluetoothStatus newStatus(textkey);
bluetoothStatus->updateStatus(&newStatus);
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) // Todo: migrate this display code back into Screen class, and observe bluetoothStatus
#if HAS_SCREEN && \
!defined(MESHTASTIC_EXCLUDE_SCREEN) // Todo: migrate this display code back into Screen class, and observe bluetoothStatus
if (screen) {
screen->startAlert([](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
char btPIN[16] = "888888";

View File

@@ -98,6 +98,8 @@
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK
#elif defined(SEEED_WIO_TRACKER_L1)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
#elif defined(R1_NEO)
#define HW_VENDOR meshtastic_HardwareModel_MUZI_R1_NEO
#elif defined(HELTEC_MESH_SOLAR)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR
#else

View File

@@ -34,6 +34,8 @@
#define OCV_ARRAY 4200, 3876, 3826, 3763, 3713, 3660, 3573, 3485, 3422, 3359, 3300
#elif defined(SEEED_SOLAR_NODE)
#define OCV_ARRAY 4200, 3986, 3922, 3812, 3734, 3645, 3527, 3420, 3281, 3087, 2786
#elif defined(R1_NEO)
#define OCV_ARRAY 4330, 4292, 4254, 4216, 4178, 4140, 4102, 4064, 4026, 3988, 3950
#else // LiIon
#define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
#endif

View File

@@ -532,8 +532,7 @@ void enableModemSleep()
bool shouldLoraWake(uint32_t msecToWake)
{
return msecToWake < portMAX_DELAY && (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER);
return msecToWake < portMAX_DELAY && (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER);
}
void enableLoraInterrupt()

View File

@@ -21,7 +21,7 @@
// "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US",
// "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name",
// "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN",
// "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, LOST AND FOUND, and REPEATER roles are restricted.
// "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, and LOST AND FOUND roles are restricted.
// "USERPREFS_EVENT_MODE": "1",
// "USERPREFS_FIRMWARE_EDITION": "meshtastic_FirmwareEdition_BURNING_MAN",
// "USERPREFS_FIXED_BLUETOOTH": "121212",

View File

@@ -0,0 +1,19 @@
; The R1 Neo board
[env:r1-neo]
extends = nrf52840_base
board = r1-neo
board_check = true
build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/r1-neo
-D R1_NEO
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/r1-neo> +<mesh/api/> +<mqtt/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
artronshop/ArtronShop_RX8130CE@1.0.0

View File

@@ -0,0 +1,45 @@
/*
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()
{
// LED1 & LED2
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
pinMode(PIN_LED2, OUTPUT);
ledOff(PIN_LED2);
// 3V3 Power Rail
// pinMode(PIN_3V3_EN, OUTPUT);
// digitalWrite(PIN_3V3_EN, HIGH);
}

View File

@@ -0,0 +1,149 @@
/*
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
*/
#ifndef _VARIANT_R1NEO_
#define _VARIANT_R1NEO_
#define RAK4630
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// 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)
// LEDs
#define PIN_LED1 (32 + 4) // P1.04 Controls Green LED
#define PIN_LED2 (28) // P0.28 Controls Blue LED
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 1 // State when LED is litted
// Button
#define PIN_BUTTON1 (26)
#define BUTTON_ACTIVE_LOW 0
#define BUTTON_ACTIVE_PULLUP 0
#define BUTTON_SENSE_TYPE INPUT_SENSE_HIGH
#define ADC_RESOLUTION 14
// Serial for GPS
#define PIN_SERIAL1_RX (25)
#define PIN_SERIAL1_TX (24)
// Connected to Jlink CDC
#define PIN_SERIAL2_RX (8)
#define PIN_SERIAL2_TX (6)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (45)
#define PIN_SPI_MOSI (44)
#define PIN_SPI_SCK (43)
static const uint8_t SS = 42;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
// R1 Neo Extras
#define DCDC_EN_HOLD (13) // P0.13 Keeps DCDC alive after user button is pressed
#define NRF_ON (29) // P0.29 Tells IO controller device is on
// RAKRGB
#define HAS_NCP5623
#define HAS_SCREEN 0
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (19) // P0.19 RTC_SDA
#define PIN_WIRE_SCL (20) // P0.20 RTC_SCL
#define PIN_BUZZER (0 + 3) // P0.03
#define USE_SX1262
#define SX126X_CS (42)
#define SX126X_DIO1 (47)
#define SX126X_BUSY (46)
#define SX126X_RESET (38)
#define SX126X_POWER_EN (37)
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Testing USB detection
#define NRF_APM
#define PIN_GPS_EN (32 + 1) // P1.01
#define PIN_GPS_PPS (2) // P0.02 Pulse per second input from the GPS
#define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN PIN_SERIAL1_TX
// Battery
#define BATTERY_PIN (0 + 31) // P0.31 ADC_VBAT
// and has 12 bit resolution
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER 1.73
#define HAS_RTC 1
#define RX8130CE_RTC 0x32
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif