From b43c7c0f23690a966c899bb91463861db9b54365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Mon, 3 Jun 2024 23:04:40 +0200 Subject: [PATCH] LR1110 support (#3013) * DOES NOT WORK * trunk * DOES NOT WORK * trunk * DOES NOT WORK * trunk * WIP: LR11x0 non functional interface code. Please don't expect a working firmware out of this! I don't know what i am doing! :-) * trunk fmt * use canon toolchain * update and fix radiolib dependency * Switch Radiolib back to GIT checkout * enable tcxo and fix startReceive * progress * Correct midjudgement on scope of build defines. * - enable peripheral power rail during startup init - fix portduino builds * add tracker pinout variant * update to radiolib 6.6.0 API (aka: godmode is not for mere mortals) * tracker is not so 'extra' any more --------- Co-authored-by: Ben Meadors --- boards/wio-sdk-wm1110.json | 58 ++++ boards/wio-tracker-wm1110.json | 58 ++++ src/detect/LoRaRadioType.h | 13 +- src/main.cpp | 28 ++ src/mesh/InterfacesTemplates.cpp | 4 + src/mesh/LR1110Interface.cpp | 9 + src/mesh/LR1110Interface.h | 13 + src/mesh/LR1120Interface.cpp | 9 + src/mesh/LR1120Interface.h | 13 + src/mesh/LR11x0Interface.cpp | 299 +++++++++++++++++++++ src/mesh/LR11x0Interface.h | 71 +++++ src/platform/nrf52/architecture.h | 2 + variants/wio-sdk-wm1110/platformio.ini | 15 ++ variants/wio-sdk-wm1110/variant.cpp | 45 ++++ variants/wio-sdk-wm1110/variant.h | 111 ++++++++ variants/wio-tracker-wm1110/platformio.ini | 14 + variants/wio-tracker-wm1110/variant.cpp | 45 ++++ variants/wio-tracker-wm1110/variant.h | 111 ++++++++ 18 files changed, 917 insertions(+), 1 deletion(-) create mode 100644 boards/wio-sdk-wm1110.json create mode 100644 boards/wio-tracker-wm1110.json create mode 100644 src/mesh/LR1110Interface.cpp create mode 100644 src/mesh/LR1110Interface.h create mode 100644 src/mesh/LR1120Interface.cpp create mode 100644 src/mesh/LR1120Interface.h create mode 100644 src/mesh/LR11x0Interface.cpp create mode 100644 src/mesh/LR11x0Interface.h create mode 100644 variants/wio-sdk-wm1110/platformio.ini create mode 100644 variants/wio-sdk-wm1110/variant.cpp create mode 100644 variants/wio-sdk-wm1110/variant.h create mode 100644 variants/wio-tracker-wm1110/platformio.ini create mode 100644 variants/wio-tracker-wm1110/variant.cpp create mode 100644 variants/wio-tracker-wm1110/variant.h diff --git a/boards/wio-sdk-wm1110.json b/boards/wio-sdk-wm1110.json new file mode 100644 index 0000000000..029c9c085e --- /dev/null +++ b/boards/wio-sdk-wm1110.json @@ -0,0 +1,58 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x8029"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"], + ["0x239A", "0x802A"] + ], + "usb_product": "WIO-BOOT", + "mcu": "nrf52840", + "variant": "Seeed_WIO_WM1110", + "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" + }, + "frameworks": ["arduino"], + "name": "Seeed WIO WM1110", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/Wio-WM1110-Dev-Kit-p-5677.html", + "vendor": "Seeed Studio" +} diff --git a/boards/wio-tracker-wm1110.json b/boards/wio-tracker-wm1110.json new file mode 100644 index 0000000000..029c9c085e --- /dev/null +++ b/boards/wio-tracker-wm1110.json @@ -0,0 +1,58 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x8029"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"], + ["0x239A", "0x802A"] + ], + "usb_product": "WIO-BOOT", + "mcu": "nrf52840", + "variant": "Seeed_WIO_WM1110", + "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" + }, + "frameworks": ["arduino"], + "name": "Seeed WIO WM1110", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/Wio-WM1110-Dev-Kit-p-5677.html", + "vendor": "Seeed Studio" +} diff --git a/src/detect/LoRaRadioType.h b/src/detect/LoRaRadioType.h index eadd92e644..3975153b5f 100644 --- a/src/detect/LoRaRadioType.h +++ b/src/detect/LoRaRadioType.h @@ -1,5 +1,16 @@ #pragma once -enum LoRaRadioType { NO_RADIO, STM32WLx_RADIO, SIM_RADIO, RF95_RADIO, SX1262_RADIO, SX1268_RADIO, LLCC68_RADIO, SX1280_RADIO }; +enum LoRaRadioType { + NO_RADIO, + STM32WLx_RADIO, + SIM_RADIO, + RF95_RADIO, + SX1262_RADIO, + SX1268_RADIO, + LLCC68_RADIO, + SX1280_RADIO, + LR1110_RADIO, + LR1120_RADIO +}; extern LoRaRadioType radioType; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 3c18936901..52de93e835 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -65,6 +65,8 @@ NRF52Bluetooth *nrf52Bluetooth; #endif #include "LLCC68Interface.h" +#include "LR1110Interface.h" +#include "LR1120Interface.h" #include "RF95Interface.h" #include "SX1262Interface.h" #include "SX1268Interface.h" @@ -882,6 +884,32 @@ void setup() } #endif +#if defined(USE_LR1110) + if (!rIf) { + rIf = new LR1110Interface(RadioLibHAL, LR1110_SPI_NSS_PIN, LR1110_IRQ_PIN, LR1110_NRESER_PIN, LR1110_BUSY_PIN); + if (!rIf->init()) { + LOG_WARN("Failed to find LR1110 radio\n"); + delete rIf; + rIf = NULL; + } else { + LOG_INFO("LR1110 Radio init succeeded, using LR1110 radio\n"); + } + } +#endif + +#if defined(USE_LR1120) + if (!rIf) { + rIf = new LR1120Interface(RadioLibHAL, LR1120_SPI_NSS_PIN, LR1120_IRQ_PIN, LR1120_NRESER_PIN, LR1120_BUSY_PIN); + if (!rIf->init()) { + LOG_WARN("Failed to find LR1120 radio\n"); + delete rIf; + rIf = NULL; + } else { + LOG_INFO("LR1120 Radio init succeeded, using LR1120 radio\n"); + } + } +#endif + #if defined(USE_SX1280) if (!rIf) { rIf = new SX1280Interface(RadioLibHAL, SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY); diff --git a/src/mesh/InterfacesTemplates.cpp b/src/mesh/InterfacesTemplates.cpp index c732829e94..f2cac80287 100644 --- a/src/mesh/InterfacesTemplates.cpp +++ b/src/mesh/InterfacesTemplates.cpp @@ -1,3 +1,5 @@ +#include "LR11x0Interface.cpp" +#include "LR11x0Interface.h" #include "SX126xInterface.cpp" #include "SX126xInterface.h" #include "SX128xInterface.cpp" @@ -10,6 +12,8 @@ template class SX126xInterface; template class SX126xInterface; template class SX126xInterface; template class SX128xInterface; +template class LR11x0Interface; +template class LR11x0Interface; #ifdef ARCH_STM32WL template class SX126xInterface; #endif diff --git a/src/mesh/LR1110Interface.cpp b/src/mesh/LR1110Interface.cpp new file mode 100644 index 0000000000..c000bd8382 --- /dev/null +++ b/src/mesh/LR1110Interface.cpp @@ -0,0 +1,9 @@ +#include "LR1110Interface.h" +#include "configuration.h" +#include "error.h" + +LR1110Interface::LR1110Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy) + : LR11x0Interface(hal, cs, irq, rst, busy) +{ +} \ No newline at end of file diff --git a/src/mesh/LR1110Interface.h b/src/mesh/LR1110Interface.h new file mode 100644 index 0000000000..79e7c36ca7 --- /dev/null +++ b/src/mesh/LR1110Interface.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LR11x0Interface.h" + +/** + * Our adapter for LR1110 radios + */ +class LR1110Interface : public LR11x0Interface +{ + public: + LR1110Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy); +}; \ No newline at end of file diff --git a/src/mesh/LR1120Interface.cpp b/src/mesh/LR1120Interface.cpp new file mode 100644 index 0000000000..94f3568f7a --- /dev/null +++ b/src/mesh/LR1120Interface.cpp @@ -0,0 +1,9 @@ +#include "LR1120Interface.h" +#include "configuration.h" +#include "error.h" + +LR1120Interface::LR1120Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy) + : LR11x0Interface(hal, cs, irq, rst, busy) +{ +} \ No newline at end of file diff --git a/src/mesh/LR1120Interface.h b/src/mesh/LR1120Interface.h new file mode 100644 index 0000000000..fc59293ec7 --- /dev/null +++ b/src/mesh/LR1120Interface.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LR11x0Interface.h" + +/** + * Our adapter for LR1120 wideband radios + */ +class LR1120Interface : public LR11x0Interface +{ + public: + LR1120Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy); +}; \ No newline at end of file diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp new file mode 100644 index 0000000000..bffca0c448 --- /dev/null +++ b/src/mesh/LR11x0Interface.cpp @@ -0,0 +1,299 @@ +#include "LR11x0Interface.h" +#include "configuration.h" +#include "error.h" +#include "mesh/NodeDB.h" +#ifdef ARCH_PORTDUINO +#include "PortduinoGlue.h" +#endif + +// Particular boards might define a different max power based on what their hardware can do, default to max power output if not +// specified (may be dangerous if using external PA and LR11x0 power config forgotten) +#ifndef LR11X0_MAX_POWER +#define LR11X0_MAX_POWER 22 +#endif + +template +LR11x0Interface::LR11x0Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy) + : RadioLibInterface(hal, cs, irq, rst, busy, &lora), lora(&module) +{ + LOG_WARN("LR11x0Interface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy); +} + +/// Initialise the Driver transport hardware and software. +/// Make sure the Driver is properly configured before calling init(). +/// \return true if initialisation succeeded. +template bool LR11x0Interface::init() +{ +#ifdef LR11X0_POWER_EN + pinMode(LR11X0_POWER_EN, OUTPUT); + digitalWrite(LR11X0_POWER_EN, HIGH); +#endif + +// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE +#if !defined(LR11X0_DIO3_TCXO_VOLTAGE) + float tcxoVoltage = + 0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per + // https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/LR11x0/LR11x0.h#L471C26-L471C104 + // (DIO3 is free to be used as an IRQ) + LOG_DEBUG("LR11X0_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n"); +#else + float tcxoVoltage = LR11X0_DIO3_TCXO_VOLTAGE; + LOG_DEBUG("LR11X0_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", LR11X0_DIO3_TCXO_VOLTAGE); + // (DIO3 is not free to be used as an IRQ) +#endif + + RadioLibInterface::init(); + + if (power > LR11X0_MAX_POWER) // Clamp power to maximum defined level + power = LR11X0_MAX_POWER; + + limitPower(); + + // set RF switch configuration for Wio WM1110 + // Wio WM1110 uses DIO5 and DIO6 for RF switching + // NOTE: other boards may be different. If you are + // using a different board, you may need to wrap + // this in a conditional. + + static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, + 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, {HIGH, 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, + }; + +// We need to do this before begin() call +#ifdef LR11X0_DIO_AS_RF_SWITCH + LOG_DEBUG("Setting DIO RF switch\n"); + bool dioAsRfSwitch = true; +#elif defined(ARCH_PORTDUINO) + bool dioAsRfSwitch = false; + if (settingsMap[dio2_as_rf_switch]) { + LOG_DEBUG("Setting DIO RF switch\n"); + dioAsRfSwitch = true; + } +#else + bool dioAsRfSwitch = false; +#endif + + if (dioAsRfSwitch) + lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table); + + int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage); + // \todo Display actual typename of the adapter, not just `LR11x0` + LOG_INFO("LR11x0 init result %d\n", res); + if (res == RADIOLIB_ERR_CHIP_NOT_FOUND) + return false; + + LOG_INFO("Frequency set to %f\n", getFreq()); + LOG_INFO("Bandwidth set to %f\n", bw); + LOG_INFO("Power output set to %d\n", power); + + if (res == RADIOLIB_ERR_NONE) + res = lora.setCRC(2); + + // FIXME: May want to set depending on a definition, currently all LR1110 variant files use the DC-DC regulator option + if (res == RADIOLIB_ERR_NONE) + res = lora.setRegulatorDCDC(); + + if (res == RADIOLIB_ERR_NONE) { + if (config.lora.sx126x_rx_boosted_gain) { // the name is unfortunate but historically accurate + res = lora.setRxBoostedGainMode(true); + LOG_INFO("Set RX gain to boosted mode; result: %d\n", res); + } else { + res = lora.setRxBoostedGainMode(false); + LOG_INFO("Set RX gain to power saving mode (boosted mode off); result: %d\n", res); + } + } + + if (res == RADIOLIB_ERR_NONE) + startReceive(); // start receiving + + return res == RADIOLIB_ERR_NONE; +} + +template bool LR11x0Interface::reconfigure() +{ + RadioLibInterface::reconfigure(); + + // set mode to standby + setStandby(); + + // configure publicly accessible settings + int err = lora.setSpreadingFactor(sf); + if (err != RADIOLIB_ERR_NONE) + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + err = lora.setBandwidth(bw); + if (err != RADIOLIB_ERR_NONE) + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + err = lora.setCodingRate(cr); + if (err != RADIOLIB_ERR_NONE) + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + // Hmm - seems to lower SNR when the signal levels are high. Leaving off for now... + // TODO: Confirm gain registers are okay now + // err = lora.setRxGain(true); + // assert(err == RADIOLIB_ERR_NONE); + + err = lora.setSyncWord(syncWord); + assert(err == RADIOLIB_ERR_NONE); + + err = lora.setPreambleLength(preambleLength); + assert(err == RADIOLIB_ERR_NONE); + + err = lora.setFrequency(getFreq()); + if (err != RADIOLIB_ERR_NONE) + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + if (power > LR11X0_MAX_POWER) // This chip has lower power limits than some + power = LR11X0_MAX_POWER; + + err = lora.setOutputPower(power); + assert(err == RADIOLIB_ERR_NONE); + + startReceive(); // restart receiving + + return RADIOLIB_ERR_NONE; +} + +template void INTERRUPT_ATTR LR11x0Interface::disableInterrupt() +{ + lora.clearIrqAction(); +} + +template void LR11x0Interface::setStandby() +{ + checkNotification(); // handle any pending interrupts before we force standby + + int err = lora.standby(); + + if (err != RADIOLIB_ERR_NONE) { + LOG_DEBUG("LR11x0 standby failed with error %d\n", err); + } + + assert(err == RADIOLIB_ERR_NONE); + + isReceiving = false; // If we were receiving, not any more + activeReceiveStart = 0; + disableInterrupt(); + completeSending(); // If we were sending, not anymore +} + +/** + * Add SNR data to received messages + */ +template void LR11x0Interface::addReceiveMetadata(meshtastic_MeshPacket *mp) +{ + // LOG_DEBUG("PacketStatus %x\n", lora.getPacketStatus()); + mp->rx_snr = lora.getSNR(); + mp->rx_rssi = lround(lora.getRSSI()); +} + +/** We override to turn on transmitter power as needed. + */ +template void LR11x0Interface::configHardwareForSend() +{ + RadioLibInterface::configHardwareForSend(); +} + +// For power draw measurements, helpful to force radio to stay sleeping +// #define SLEEP_ONLY + +template void LR11x0Interface::startReceive() +{ +#ifdef SLEEP_ONLY + sleep(); +#else + + setStandby(); + + lora.setPreambleLength(preambleLength); // Solve RX ack fail after direct message sent. Not sure why this is needed. + + // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. + // Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving + int err = lora.startReceive( + RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_LR11X0_IRQ_RX_DONE, + 0); // only RX_DONE IRQ is needed, we'll check for PREAMBLE_DETECTED and HEADER_VALID in isActivelyReceiving + assert(err == RADIOLIB_ERR_NONE); + + isReceiving = true; + + // Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits + enableInterrupt(isrRxLevel0); +#endif +} + +/** Is the channel currently active? */ +template bool LR11x0Interface::isChannelActive() +{ + // check if we can detect a LoRa preamble on the current channel + int16_t result; + + setStandby(); + result = lora.scanChannel(); + if (result == RADIOLIB_LORA_DETECTED) + return true; + + assert(result != RADIOLIB_ERR_WRONG_MODEM); + + return false; +} + +/** Could we send right now (i.e. either not actively receiving or transmitting)? */ +template bool LR11x0Interface::isActivelyReceiving() +{ + // The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet + // received and handled the interrupt for reading the packet/handling errors. + + uint16_t irq = lora.getIrqStatus(); + bool detected = (irq & (RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED)); + // Handle false detections + if (detected) { + uint32_t now = millis(); + if (!activeReceiveStart) { + activeReceiveStart = now; + } else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID)) { + // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false preamble detection.\n"); + return false; + } else if (now - activeReceiveStart > maxPacketTimeMsec) { + // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false header detection.\n"); + return false; + } + } + + // if (detected) LOG_DEBUG("rx detected\n"); + return detected; +} + +template bool LR11x0Interface::sleep() +{ + // Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet + // \todo Display actual typename of the adapter, not just `LR11x0` + LOG_DEBUG("LR11x0 entering sleep mode (FIXME, don't keep config)\n"); + setStandby(); // Stop any pending operations + + // turn off TCXO if it was powered + // FIXME - this isn't correct + // lora.setTCXO(0); + + // put chipset into sleep mode (we've already disabled interrupts by now) + bool keepConfig = true; + lora.sleep(keepConfig, 0); // Note: we do not keep the config, full reinit will be needed + +#ifdef LR11X0_POWER_EN + digitalWrite(LR11X0_POWER_EN, LOW); +#endif + + return true; +} \ No newline at end of file diff --git a/src/mesh/LR11x0Interface.h b/src/mesh/LR11x0Interface.h new file mode 100644 index 0000000000..11a389d252 --- /dev/null +++ b/src/mesh/LR11x0Interface.h @@ -0,0 +1,71 @@ +#pragma once + +#include "RadioLibInterface.h" + +/** + * \brief Adapter for LR11x0 radio family. Implements common logic for child classes. + * \tparam T RadioLib module type for LR11x0: SX1262, SX1268. + */ +template class LR11x0Interface : public RadioLibInterface +{ + public: + LR11x0Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy); + + /// Initialise the Driver transport hardware and software. + /// Make sure the Driver is properly configured before calling init(). + /// \return true if initialisation succeeded. + virtual bool init() override; + + /// Apply any radio provisioning changes + /// Make sure the Driver is properly configured before calling init(). + /// \return true if initialisation succeeded. + virtual bool reconfigure() override; + + /// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep. + virtual bool sleep() override; + + bool isIRQPending() override { return lora.getIrqStatus() != 0; } + + protected: + /** + * Specific module instance + */ + T lora; + + /** + * Glue functions called from ISR land + */ + virtual void disableInterrupt() override; + + /** + * Enable a particular ISR callback glue function + */ + virtual void enableInterrupt(void (*callback)()) { lora.setIrqAction(callback); } + + /** can we detect a LoRa preamble on the current channel? */ + virtual bool isChannelActive() override; + + /** are we actively receiving a packet (only called during receiving state) */ + virtual bool isActivelyReceiving() override; + + /** + * Start waiting to receive a message + */ + virtual void startReceive() override; + + /** + * We override to turn on transmitter power as needed. + */ + virtual void configHardwareForSend() override; + + /** + * Add SNR data to received messages + */ + virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override; + + virtual void setStandby() override; + + private: + uint32_t activeReceiveStart = 0; +}; diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 68bd878015..b91c57c5ef 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -56,6 +56,8 @@ #define HW_VENDOR meshtastic_HardwareModel_TWC_MESH_V4 #elif defined(NRF52_PROMICRO_DIY) #define HW_VENDOR meshtastic_HardwareModel_NRF52_PROMICRO_DIY +#elif defined(WIO_WM1110) +#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #elif defined(PRIVATE_HW) || defined(FEATHER_DIY) #define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #else diff --git a/variants/wio-sdk-wm1110/platformio.ini b/variants/wio-sdk-wm1110/platformio.ini new file mode 100644 index 0000000000..8b1433dd1f --- /dev/null +++ b/variants/wio-sdk-wm1110/platformio.ini @@ -0,0 +1,15 @@ +; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921 +[env:wio-sdk-wm1110] +extends = nrf52840_base +board = wio-sdk-wm1110 +board_level = extra +; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e +build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-sdk-wm1110 -DWIO_WM1110 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/wio-sdk-wm1110> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +upload_protocol = jlink \ No newline at end of file diff --git a/variants/wio-sdk-wm1110/variant.cpp b/variants/wio-sdk-wm1110/variant.cpp new file mode 100644 index 0000000000..5a35879826 --- /dev/null +++ b/variants/wio-sdk-wm1110/variant.cpp @@ -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); +} \ No newline at end of file diff --git a/variants/wio-sdk-wm1110/variant.h b/variants/wio-sdk-wm1110/variant.h new file mode 100644 index 0000000000..f027b469f3 --- /dev/null +++ b/variants/wio-sdk-wm1110/variant.h @@ -0,0 +1,111 @@ +/* + 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_WIO_SDK_WM1110_ +#define _VARIANT_WIO_SDK_WM1110_ + +/** 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 (6) +#define NUM_ANALOG_OUTPUTS (0) + +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_3V3_EN (0 + 7) // P0.7, Power to Sensors + +#define PIN_WIRE_SDA (0 + 27) // P0.27 +#define PIN_WIRE_SCL (0 + 26) // P0.26 + +#define PIN_LED1 (0 + 13) // P0.13 +#define PIN_LED2 (0 + 14) // P0.14 + +#define LED_BUILTIN PIN_LED1 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 // Actually red + +#define LED_STATE_ON 1 // State when LED is lit + +#define BUTTON_PIN (0 + 23) // P0.23 + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (0 + 22) // P0.22 +#define PIN_SERIAL1_TX (0 + 24) // P0.24 + +#define PIN_SERIAL2_RX (0 + 6) // P0.06 +#define PIN_SERIAL2_TX (0 + 8) // P0.08 + +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (32 + 15) // P1.15 47 +#define PIN_SPI_MOSI (32 + 14) // P1.14 46 +#define PIN_SPI_SCK (32 + 13) // P1.13 45 +#define PIN_SPI_NSS (32 + 12) // P1.12 44 + +#define LORA_RESET (32 + 10) // P1.10 42 // RST +#define LORA_DIO1 (32 + 8) // P1.08 40 // IRQ +#define LORA_DIO2 (32 + 11) // P1.11 43 // BUSY +#define LORA_SCK PIN_SPI_SCK +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_CS PIN_SPI_NSS + +// supported modules list +#define USE_LR1110 + +#define LR1110_IRQ_PIN LORA_DIO1 +#define LR1110_NRESER_PIN LORA_RESET +#define LR1110_BUSY_PIN LORA_DIO2 +#define LR1110_SPI_NSS_PIN LORA_CS +#define LR1110_SPI_SCK_PIN LORA_SCK +#define LR1110_SPI_MOSI_PIN LORA_MOSI +#define LR1110_SPI_MISO_PIN LORA_MISO + +#define LR11X0_DIO3_TCXO_VOLTAGE 1.6 +#define LR11X0_DIO_AS_RF_SWITCH + +#define LR1110_GNSS_ANT_PIN (32 + 5) // P1.05 37 + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif // _VARIANT_WIO_SDK_WM1110_ diff --git a/variants/wio-tracker-wm1110/platformio.ini b/variants/wio-tracker-wm1110/platformio.ini new file mode 100644 index 0000000000..cba1b87414 --- /dev/null +++ b/variants/wio-tracker-wm1110/platformio.ini @@ -0,0 +1,14 @@ +; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921 +[env:wio-tracker-wm1110] +extends = nrf52840_base +board = wio-tracker-wm1110 +; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e +build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-tracker-wm1110 -DWIO_WM1110 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/wio-tracker-wm1110> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +;upload_protocol = jlink \ No newline at end of file diff --git a/variants/wio-tracker-wm1110/variant.cpp b/variants/wio-tracker-wm1110/variant.cpp new file mode 100644 index 0000000000..5a35879826 --- /dev/null +++ b/variants/wio-tracker-wm1110/variant.cpp @@ -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); +} \ No newline at end of file diff --git a/variants/wio-tracker-wm1110/variant.h b/variants/wio-tracker-wm1110/variant.h new file mode 100644 index 0000000000..e929332e6e --- /dev/null +++ b/variants/wio-tracker-wm1110/variant.h @@ -0,0 +1,111 @@ +/* + 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_WIO_TRACKER_WM1110_ +#define _VARIANT_WIO_TRACKER_WM1110_ + +/** 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 (6) +#define NUM_ANALOG_OUTPUTS (0) + +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_3V3_EN (32 + 1) // P1.01, Power to Sensors + +#define PIN_WIRE_SDA (0 + 5) // P0.05 +#define PIN_WIRE_SCL (0 + 4) // P0.04 + +#define PIN_LED1 (0 + 6) // P0.06 +#define PIN_LED2 (PINS_COUNT) // P0.14 + +#define LED_BUILTIN PIN_LED1 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 + +#define LED_STATE_ON 0 + +#define BUTTON_PIN (32 + 2) // P1.02 + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (0 + 24) // P0.24 +#define PIN_SERIAL1_TX (0 + 25) // P0.25 + +#define PIN_SERIAL2_RX (0 + 6) // P0.06 +#define PIN_SERIAL2_TX (0 + 8) // P0.08 + +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (32 + 15) // P1.15 47 +#define PIN_SPI_MOSI (32 + 14) // P1.14 46 +#define PIN_SPI_SCK (32 + 13) // P1.13 45 +#define PIN_SPI_NSS (32 + 12) // P1.12 44 + +#define LORA_RESET (0 + 18) // P0.18 18 // RST +#define LORA_DIO1 (0 + 2) // P0.02 2 // IRQ +#define LORA_DIO2 (32 + 11) // P1.11 43 // BUSY +#define LORA_SCK PIN_SPI_SCK +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_CS PIN_SPI_NSS + +// supported modules list +#define USE_LR1110 + +#define LR1110_IRQ_PIN LORA_DIO1 +#define LR1110_NRESER_PIN LORA_RESET +#define LR1110_BUSY_PIN LORA_DIO2 +#define LR1110_SPI_NSS_PIN LORA_CS +#define LR1110_SPI_SCK_PIN LORA_SCK +#define LR1110_SPI_MOSI_PIN LORA_MOSI +#define LR1110_SPI_MISO_PIN LORA_MISO + +#define LR11X0_DIO3_TCXO_VOLTAGE 1.6 +#define LR11X0_DIO_AS_RF_SWITCH + +#define LR1110_GNSS_ANT_PIN (32 + 5) // P1.05 37 + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif // _VARIANT_WIO_TRACKER_WM1110_