From 498b1f12e99f746397326179375f6e54229e5547 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 16:36:24 -0500 Subject: [PATCH 01/19] Get MD5 code building for Linux --- Config.h | 36 +++++++++++++++++++++++++++++++++++- MD5.cpp | 8 +++++++- MD5.h | 10 ++++++++-- Makefile | 13 +++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/Config.h b/Config.h index ad06363..f5d6f38 100644 --- a/Config.h +++ b/Config.h @@ -8,10 +8,12 @@ #define PLATFORM_AVR 0x90 #define PLATFORM_ESP32 0x80 + #define PLATFORM_LINUX 0x70 #define MCU_1284P 0x91 #define MCU_2560 0x92 #define MCU_ESP32 0x81 + #define MCU_LINUX 0x71 #define BOARD_RNODE 0x31 #define BOARD_HMBRW 0x32 @@ -20,6 +22,10 @@ #define BOARD_GENERIC_ESP32 0x35 #define BOARD_LORA32_V2_0 0x36 #define BOARD_LORA32_V2_1 0x37 + #define BOARD_SPIDEV 0x38 + + #define LIBRARY_ARDUINO 0x1 + #define LIBRARY_C 0x2 #define MODE_HOST 0x11 #define MODE_TNC 0x12 @@ -33,6 +39,9 @@ #elif defined(ESP32) #define PLATFORM PLATFORM_ESP32 #define MCU_VARIANT MCU_ESP32 + #elif defined(__unix__) + #define PLATFORM PLATFORM_LINUX + #define MCU_VARIANT MCU_LINUX #else #error "The firmware cannot be compiled for the selected MCU variant" #endif @@ -54,6 +63,7 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_RNODE + #define LIBRARY_TYPE LIBRARY_ARDUINO #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 @@ -70,6 +80,7 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_HMBRW + #define LIBRARY_TYPE LIBRARY_ARDUINO #define CONFIG_UART_BUFFER_SIZE 768 #define CONFIG_QUEUE_SIZE 5120 @@ -130,6 +141,8 @@ #else #error An unsupported board was selected. Cannot compile RNode firmware. #endif + + #define LIBRARY_TYPE LIBRARY_ARDUINO #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 @@ -141,6 +154,22 @@ #define GPS_BAUD_RATE 9600 #define PIN_GPS_TX 12 #define PIN_GPS_RX 34 + #elif MCU_VARIANT == MCU_LINUX + const int pin_cs = -1; + const int pin_reset = -1; + const int pin_dio = -1; + const int pin_led_rx = -1; + const int pin_led_tx = -1; + + #define BOARD_MODEL BOARD_SPIDEV + #define LIBRARY_TYPE LIBRARY_C + + #define CONFIG_UART_BUFFER_SIZE 6144 + #define CONFIG_QUEUE_SIZE 6144 + #define CONFIG_QUEUE_MAX_LENGTH 200 + + #define EEPROM_SIZE 4096 + #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED #endif #if BOARD_MODEL == BOARD_TBEAM @@ -148,7 +177,12 @@ #define I2C_SCL 22 #define PMU_IRQ 35 #endif - + + #if LIBRARY_TYPE == LIBRARY_C + // We need standard int types before we go any further + #include + #endif + #define eeprom_addr(a) (a+EEPROM_OFFSET) // MCU independent configuration parameters diff --git a/MD5.cpp b/MD5.cpp index 56daa77..52317e5 100644 --- a/MD5.cpp +++ b/MD5.cpp @@ -1,5 +1,11 @@ #include "MD5.h" +#if LIBRARY_TYPE == LIBRARY_ARDUINO + #include "Arduino.h" +#elif LIBRARY_TYPE == LIBRARY_C + #include +#endif + MD5::MD5() { //nothing @@ -298,4 +304,4 @@ unsigned char* MD5::make_hash(char *arg,size_t size) MD5Update(&context, arg, size); MD5Final(hash, &context); return hash; -} \ No newline at end of file +} diff --git a/MD5.h b/MD5.h index 3ec8d81..7ca88bd 100644 --- a/MD5.h +++ b/MD5.h @@ -1,7 +1,13 @@ #ifndef MD5_h #define MD5_h -#include "Arduino.h" +#include "Config.h" + +#if LIBRARY_TYPE == LIBRARY_ARDUINO + #include "Arduino.h" +#elif LIBRARY_TYPE == LIBRARY_C + #include +#endif /* * This is an OpenSSL-compatible implementation of the RSA Data Security, @@ -49,4 +55,4 @@ public: static void MD5Update(void *ctxBuf, const void *data, size_t size); }; -#endif \ No newline at end of file +#endif diff --git a/Makefile b/Makefile index 7e3e416..1c2fa08 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ prep-samd: arduino-cli core update-index --config-file arduino-cli.yaml arduino-cli core install adafruit:samd +prep-linux: + mkdir -p bin + mkdir -p obj firmware: @@ -135,3 +138,13 @@ release-mega2560: arduino-cli compile --fqbn arduino:avr:mega -e cp build/arduino.avr.mega/RNode_Firmware.ino.hex Release/rnode_firmware_latest_m2560.hex rm -r build + +.PHONY: clean prep-linux + +clean: + rm -Rf bin + rm -Rf obj + +obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h prep-linux + $(CC) -c -o $@ $< + From e67b38c005241e4a8a5c55a4fac1d0e706c32e31 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 16:58:04 -0500 Subject: [PATCH 02/19] Factor out board config detection --- Config.h | 23 ++++++----------------- LoRa.cpp | 20 +------------------- LoRa.h | 14 +++++++++++--- MD5.cpp | 2 +- Makefile | 5 ++++- Platform.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 Platform.h diff --git a/Config.h b/Config.h index f5d6f38..172f6c9 100644 --- a/Config.h +++ b/Config.h @@ -1,20 +1,13 @@ #include "ROM.h" +#include "Platform.h" + #ifndef CONFIG_H #define CONFIG_H #define MAJ_VERS 0x01 #define MIN_VERS 0x1B - #define PLATFORM_AVR 0x90 - #define PLATFORM_ESP32 0x80 - #define PLATFORM_LINUX 0x70 - - #define MCU_1284P 0x91 - #define MCU_2560 0x92 - #define MCU_ESP32 0x81 - #define MCU_LINUX 0x71 - #define BOARD_RNODE 0x31 #define BOARD_HMBRW 0x32 #define BOARD_TBEAM 0x33 @@ -24,24 +17,25 @@ #define BOARD_LORA32_V2_1 0x37 #define BOARD_SPIDEV 0x38 - #define LIBRARY_ARDUINO 0x1 - #define LIBRARY_C 0x2 - #define MODE_HOST 0x11 #define MODE_TNC 0x12 #if defined(__AVR_ATmega1284P__) #define PLATFORM PLATFORM_AVR #define MCU_VARIANT MCU_1284P + #define LIBRARY_TYPE LIBRARY_ARDUINO #elif defined(__AVR_ATmega2560__) #define PLATFORM PLATFORM_AVR #define MCU_VARIANT MCU_2560 + #define LIBRARY_TYPE LIBRARY_ARDUINO #elif defined(ESP32) #define PLATFORM PLATFORM_ESP32 #define MCU_VARIANT MCU_ESP32 + #define LIBRARY_TYPE LIBRARY_ARDUINO #elif defined(__unix__) #define PLATFORM PLATFORM_LINUX #define MCU_VARIANT MCU_LINUX + #define LIBRARY_TYPE LIBRARY_C #else #error "The firmware cannot be compiled for the selected MCU variant" #endif @@ -63,7 +57,6 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_RNODE - #define LIBRARY_TYPE LIBRARY_ARDUINO #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 @@ -80,7 +73,6 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_HMBRW - #define LIBRARY_TYPE LIBRARY_ARDUINO #define CONFIG_UART_BUFFER_SIZE 768 #define CONFIG_QUEUE_SIZE 5120 @@ -142,8 +134,6 @@ #error An unsupported board was selected. Cannot compile RNode firmware. #endif - #define LIBRARY_TYPE LIBRARY_ARDUINO - #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 #define CONFIG_QUEUE_MAX_LENGTH 200 @@ -162,7 +152,6 @@ const int pin_led_tx = -1; #define BOARD_MODEL BOARD_SPIDEV - #define LIBRARY_TYPE LIBRARY_C #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 diff --git a/LoRa.cpp b/LoRa.cpp index 304e2df..df50cfc 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -6,24 +6,6 @@ #include "LoRa.h" -#define MCU_1284P 0x91 -#define MCU_2560 0x92 -#define MCU_ESP32 0x81 -#if defined(__AVR_ATmega1284P__) - #define PLATFORM PLATFORM_AVR - #define MCU_VARIANT MCU_1284P -#elif defined(__AVR_ATmega2560__) - #define PLATFORM PLATFORM_AVR - #define MCU_VARIANT MCU_2560 -#elif defined(ESP32) - #define PLATFORM PLATFORM_ESP32 - #define MCU_VARIANT MCU_ESP32 -#endif - -#ifndef MCU_VARIANT - #error No MCU variant defined, cannot compile -#endif - #if MCU_VARIANT == MCU_ESP32 #include "soc/rtc_wdt.h" #define ISR_VECT IRAM_ATTR @@ -654,4 +636,4 @@ void ISR_VECT LoRaClass::onDio0Rise() LoRa.handleDio0Rise(); } -LoRaClass LoRa; \ No newline at end of file +LoRaClass LoRa; diff --git a/LoRa.h b/LoRa.h index 09bdc54..42bc116 100644 --- a/LoRa.h +++ b/LoRa.h @@ -7,8 +7,16 @@ #ifndef LORA_H #define LORA_H -#include -#include +#include "Platform.h" + +#if LIBRARY_TYPE == LIBRARY_ARDUINO + #include + #include +#elif LIBRARY_TYPE == LIBRARY_C + #include + #include + #include "ArduinoOnLinux/Stream.h" +#endif #define LORA_DEFAULT_SS_PIN 10 #define LORA_DEFAULT_RESET_PIN 9 @@ -103,4 +111,4 @@ private: extern LoRaClass LoRa; -#endif \ No newline at end of file +#endif diff --git a/MD5.cpp b/MD5.cpp index 52317e5..c04efc1 100644 --- a/MD5.cpp +++ b/MD5.cpp @@ -1,7 +1,7 @@ #include "MD5.h" #if LIBRARY_TYPE == LIBRARY_ARDUINO - #include "Arduino.h" + #include #elif LIBRARY_TYPE == LIBRARY_C #include #endif diff --git a/Makefile b/Makefile index 1c2fa08..fda102b 100644 --- a/Makefile +++ b/Makefile @@ -145,6 +145,9 @@ clean: rm -Rf bin rm -Rf obj -obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h prep-linux +obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h Platform.h prep-linux + $(CC) -c -o $@ $< + +obj/LoRa.o: LoRa.cpp LoRa.h Platform.h prep-linux $(CC) -c -o $@ $< diff --git a/Platform.h b/Platform.h new file mode 100644 index 0000000..5a4c58c --- /dev/null +++ b/Platform.h @@ -0,0 +1,42 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +// Determine the platform, MCU, and C library we are building for. + +#define PLATFORM_AVR 0x90 +#define PLATFORM_ESP32 0x80 +#define PLATFORM_LINUX 0x70 + +#define MCU_1284P 0x91 +#define MCU_2560 0x92 +#define MCU_ESP32 0x81 +#define MCU_LINUX 0x71 + +#define LIBRARY_ARDUINO 0x1 +#define LIBRARY_C 0x2 + +#if defined(__AVR_ATmega1284P__) + #define PLATFORM PLATFORM_AVR + #define MCU_VARIANT MCU_1284P + #define LIBRARY_TYPE LIBRARY_ARDUINO +#elif defined(__AVR_ATmega2560__) + #define PLATFORM PLATFORM_AVR + #define MCU_VARIANT MCU_2560 + #define LIBRARY_TYPE LIBRARY_ARDUINO +#elif defined(ESP32) + #define PLATFORM PLATFORM_ESP32 + #define MCU_VARIANT MCU_ESP32 + #define LIBRARY_TYPE LIBRARY_ARDUINO +#elif defined(__unix__) + #define PLATFORM PLATFORM_LINUX + #define MCU_VARIANT MCU_LINUX + #define LIBRARY_TYPE LIBRARY_C +#else + #error "The firmware cannot be compiled for the selected MCU variant" +#endif + +#ifndef MCU_VARIANT + #error No MCU variant defined, cannot compile +#endif + +#endif From 271ee755843348b28bfe81520dd60b9ddf7b9d83 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 18:19:33 -0500 Subject: [PATCH 03/19] Get LoRa class built for Linux --- LoRa.cpp | 89 ++++++++++++++++++++++++++++++++++++++++------ LoRa.h | 29 +++++++++++++-- RNode_Firmware.ino | 9 +++++ 3 files changed, 115 insertions(+), 12 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index df50cfc..1ce035d 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -6,6 +6,20 @@ #include "LoRa.h" +#if LIBRARY_TYPE == LIBRARY_C + // We need sleep() to use instead of yield() + #include + // And we need to use the filesystem and IOCTLs instead of an SPI global + #include + // And we need to be able to report errors + #include + #include + // And we need IO formatting functions for the C++-stream dumpRegisters() + #include +#endif + + + #if MCU_VARIANT == MCU_ESP32 #include "soc/rtc_wdt.h" #define ISR_VECT IRAM_ATTR @@ -72,18 +86,26 @@ LoRaClass::LoRaClass() : _implicitHeaderMode(0), _onReceive(NULL) { +#if LIBRARY_TYPE == LIBRARY_ARDUINO // overide Stream timeout value setTimeout(0); +#elif LIBRARY_TYPE == LIBRARY_C + _fd = 0; +#endif } int LoRaClass::begin(long frequency) { - // setup pins - pinMode(_ss, OUTPUT); - // set SS high - digitalWrite(_ss, HIGH); + +#if LIBRARY_TYPE == LIBRARY_ARDUINO + // setup pins + pinMode(_ss, OUTPUT); + // set SS high + digitalWrite(_ss, HIGH); +#endif if (_reset != -1) { +#if LIBRARY_TYPE == LIBRARY_ARDUINO pinMode(_reset, OUTPUT); // perform reset @@ -91,11 +113,21 @@ int LoRaClass::begin(long frequency) delay(10); digitalWrite(_reset, HIGH); delay(10); +#endif + // TODO: No reset pin hooked up on BOARD_SPIDEV } +#if LIBRARY_TYPE == LIBRARY_ARDUINO // start SPI SPI.begin(); - +#elif LIBRARY_TYPE == LIBRARY_C + _fd = open("/dev/spidev0.0", O_RDWR); + if (_fd < 0) { + perror("could not open SPI device"); + exit(1); + } +#endif + // check version uint8_t version = readRegister(REG_VERSION); if (version != 0x12) { @@ -103,7 +135,7 @@ int LoRaClass::begin(long frequency) } // put in sleep mode - sleep(); + this->sleep(); // set frequency setFrequency(frequency); @@ -130,10 +162,17 @@ int LoRaClass::begin(long frequency) void LoRaClass::end() { // put in sleep mode - sleep(); + this->sleep(); +#if LIBRARY_TYPE == LIBRARY_ARDUINO // stop SPI SPI.end(); +#elif LIBRARY_TYPE == LIBRARY_C + if (_fd >= 0) { + close(_fd); + _fd = -1; + } +#endif } int LoRaClass::beginPacket(int implicitHeader) @@ -161,7 +200,11 @@ int LoRaClass::endPacket() // wait for TX done while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) { +#if LIBRARY_TYPE == LIBRARY_ARDUINO yield(); +#elif LIBRARY_TYPE == LIBRARY_C + ::sleep(1); +#endif } // clear IRQ's @@ -253,13 +296,13 @@ float ISR_VECT LoRaClass::packetSnr() { long LoRaClass::packetFrequencyError() { int32_t freqError = 0; - freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB) & B111); + freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB) & 0b111); freqError <<= 8L; freqError += static_cast(readRegister(REG_FREQ_ERROR_MID)); freqError <<= 8L; freqError += static_cast(readRegister(REG_FREQ_ERROR_LSB)); - if (readRegister(REG_FREQ_ERROR_MSB) & B1000) { // Sign bit is on + if (readRegister(REG_FREQ_ERROR_MSB) & 0b1000) { // Sign bit is on freqError -= 524288; // B1000'0000'0000'0000'0000 } @@ -337,17 +380,26 @@ void LoRaClass::onReceive(void(*callback)(int)) _onReceive = callback; if (callback) { +#if LIBRARY_TYPE == LIBRARY_ARDUINO pinMode(_dio0, INPUT); +#endif writeRegister(REG_DIO_MAPPING_1, 0x00); + +#if LIBRARY_TYPE == LIBRARY_ARDUINO #ifdef SPI_HAS_NOTUSINGINTERRUPT SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); #endif attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING); +#endif + // TODO: What do we do if we want to use C library with a board that + // actually has dio0 connected? } else { +#if LIBRARY_TYPE == LIBRARY_ARDUINO detachInterrupt(digitalPinToInterrupt(_dio0)); #ifdef SPI_HAS_NOTUSINGINTERRUPT SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0)); +#endif #endif } } @@ -554,6 +606,7 @@ void LoRaClass::setSPIFrequency(uint32_t frequency) _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); } +#if LIBRARY_TYPE == LIBRARY_ARDUINO void LoRaClass::dumpRegisters(Stream& out) { for (int i = 0; i < 128; i++) { @@ -563,6 +616,16 @@ void LoRaClass::dumpRegisters(Stream& out) out.println(readRegister(i), HEX); } } +#elif LIBRARY_TYPE == LIBRARY_C +void LoRaClass::dumpRegisters(std::ostream& out) +{ + for (int i = 0; i < 128; i++) { + out << "0x" << std::hex << i << ": 0x" << std::hex << readRegister(i) << std::endl; + } + out << std::dec; +} +#endif + void LoRaClass::explicitHeaderMode() { @@ -618,7 +681,8 @@ void LoRaClass::writeRegister(uint8_t address, uint8_t value) uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) { uint8_t response; - + +#if LIBRARY_TYPE == LIBRARY_ARDUINO digitalWrite(_ss, LOW); SPI.beginTransaction(_spiSettings); @@ -627,6 +691,11 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) SPI.endTransaction(); digitalWrite(_ss, HIGH); +#elif LIBRARY_TYPE == LIBRARY_C + +#else + #error "SPI transfer not implemented for library type" +#endif return response; } diff --git a/LoRa.h b/LoRa.h index 42bc116..5793337 100644 --- a/LoRa.h +++ b/LoRa.h @@ -15,7 +15,25 @@ #elif LIBRARY_TYPE == LIBRARY_C #include #include - #include "ArduinoOnLinux/Stream.h" + #include + + // Arduino Stream is not available, but not actually needed. + class Stream {}; + + typedef unsigned char byte; + + // Arduino SPI is not available. + #define MSBFIRST 0 + #define SPI_MODE0 0 + class SPISettings { + public: + inline SPISettings(int frequency, int bitness, int mode) : frequency(frequency), bitness(bitness), mode(mode) {}; + SPISettings& operator=(const SPISettings& other) = default; + int frequency; + int bitness; + int mode; + }; + #endif #define LORA_DEFAULT_SS_PIN 10 @@ -81,8 +99,12 @@ public: void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN); void setSPIFrequency(uint32_t frequency); - + +#if LIBRARY_TYPE == LIBRARY_ARDUINO void dumpRegisters(Stream& out); +#elif LIBRARY_TYPE == LIBRARY_C + void dumpRegisters(std::ostream& out); +#endif private: void explicitHeaderMode(); @@ -107,6 +129,9 @@ private: int _packetIndex; int _implicitHeaderMode; void (*_onReceive)(int); + #if LIBRARY_TYPE == LIBRARY_C + int _fd; + #endif }; extern LoRaClass LoRa; diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index ea1c90c..b0b0873 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -864,3 +864,12 @@ void serial_interrupt_init() { buffer_serial(); } #endif + +#if PLATFORM == PLATFORM_LINUX + int main(int argc, char** argv) { + setup(); + while (true) { + loop(); + } + } +#endif From c46ec5778d4d4d7be2b5041c6a83e321406f83c1 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 18:40:30 -0500 Subject: [PATCH 04/19] Actually implement Linux SPI access --- LoRa.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- LoRa.h | 16 ++++++++++------ Makefile | 3 +++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 1ce035d..1b20596 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -11,6 +11,10 @@ #include // And we need to use the filesystem and IOCTLs instead of an SPI global #include + #include + #include + // And to have memset + #include // And we need to be able to report errors #include #include @@ -683,6 +687,7 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) uint8_t response; #if LIBRARY_TYPE == LIBRARY_ARDUINO + // Select chip, send address, and send/read data, the Arduino way digitalWrite(_ss, LOW); SPI.beginTransaction(_spiSettings); @@ -692,7 +697,47 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) digitalWrite(_ss, HIGH); #elif LIBRARY_TYPE == LIBRARY_C - + // Select chip, send address, and send/read data, the Linux way + + // In Linux, chip select is automatically turned off outside of transactions. + + int status; + + // Configure SPI speed and mode to match settings + status = ioctl(_fd, SPI_IOC_WR_MODE, &_spiSettings.mode); + if (status < 0) { + perror("ioctl SPI_IOC_WR_MODE failed"); + exit(1); + } + status = ioctl(_fd, SPI_IOC_WR_LSB_FIRST, &_spiSettings.bitness); + if (status < 0) { + perror("ioctl SPI_IOC_WR_LSB_FIRST failed"); + exit(1); + } + status = ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &_spiSettings.frequency); + if (status < 0) { + perror("ioctl SPI_IOC_WR_MAX_SPEED_HZ failed"); + exit(1); + } + + // We have two transfers: one send-only to send the address, and one + // send/receive, to send the value and get the response. + struct spi_ioc_transfer xfer[2]; + memset(xfer, 0, sizeof xfer); + + xfer[0].tx_buf = (unsigned long) &address; + xfer[0].len = 1; + + xfer[1].tx_buf = (unsigned long) &value; + xfer[1].rx_buf = (unsigned long) &response; + xfer[1].len = 1; + + // Do the transaction + status = ioctl(_fd, SPI_IOC_MESSAGE(2), xfer); + if (status < 0) { + perror("ioctl SPI_IOC_MESSAGE failed"); + exit(1); + } #else #error "SPI transfer not implemented for library type" #endif diff --git a/LoRa.h b/LoRa.h index 5793337..e57543a 100644 --- a/LoRa.h +++ b/LoRa.h @@ -22,16 +22,20 @@ typedef unsigned char byte; - // Arduino SPI is not available. + // Arduino SPI is not available, so make a Linux-ish version of SPISettings #define MSBFIRST 0 - #define SPI_MODE0 0 + #define LSBFIRST 1 + #define SPI_MODE0 SPI_MODE_0 + #define SPI_MODE1 SPI_MODE_1 + #define SPI_MODE2 SPI_MODE_2 + #define SPI_MODE3 SPI_MODE_3 class SPISettings { public: - inline SPISettings(int frequency, int bitness, int mode) : frequency(frequency), bitness(bitness), mode(mode) {}; + inline SPISettings(uint32_t frequency, byte bitness, byte mode) : frequency(frequency), bitness(bitness), mode(mode) {}; SPISettings& operator=(const SPISettings& other) = default; - int frequency; - int bitness; - int mode; + uint32_t frequency; + byte bitness; + byte mode; }; #endif diff --git a/Makefile b/Makefile index fda102b..b66d955 100644 --- a/Makefile +++ b/Makefile @@ -151,3 +151,6 @@ obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h Platform.h prep-linux obj/LoRa.o: LoRa.cpp LoRa.h Platform.h prep-linux $(CC) -c -o $@ $< +obj/RNode_firmware.o: RNode_firmware.ino Utilities.h Config.h LoRa.h ROM.h Framing.h MD5.h Platform.h prep-linux + $(CC) -c -o $@ $< + From d01a4b293f6bcea36ae795532c4ab533c93dfae8 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 20:20:21 -0500 Subject: [PATCH 05/19] Get build building --- Config.h | 28 ++---- LoRa.cpp | 2 +- MD5.h | 8 +- Makefile | 21 ++--- RNode_Firmware.ino | 56 +++++++---- Utilities.h | 229 ++++++++++++++++++++++++++++++++------------- 6 files changed, 223 insertions(+), 121 deletions(-) diff --git a/Config.h b/Config.h index 172f6c9..a88f537 100644 --- a/Config.h +++ b/Config.h @@ -17,29 +17,12 @@ #define BOARD_LORA32_V2_1 0x37 #define BOARD_SPIDEV 0x38 + #define SERIAL_INTERRUPT 0x1 + #define SERIAL_POLLING 0x2 + #define MODE_HOST 0x11 #define MODE_TNC 0x12 - #if defined(__AVR_ATmega1284P__) - #define PLATFORM PLATFORM_AVR - #define MCU_VARIANT MCU_1284P - #define LIBRARY_TYPE LIBRARY_ARDUINO - #elif defined(__AVR_ATmega2560__) - #define PLATFORM PLATFORM_AVR - #define MCU_VARIANT MCU_2560 - #define LIBRARY_TYPE LIBRARY_ARDUINO - #elif defined(ESP32) - #define PLATFORM PLATFORM_ESP32 - #define MCU_VARIANT MCU_ESP32 - #define LIBRARY_TYPE LIBRARY_ARDUINO - #elif defined(__unix__) - #define PLATFORM PLATFORM_LINUX - #define MCU_VARIANT MCU_LINUX - #define LIBRARY_TYPE LIBRARY_C - #else - #error "The firmware cannot be compiled for the selected MCU variant" - #endif - #define MTU 500 #define SINGLE_MTU 255 #define HEADER_L 1 @@ -57,6 +40,7 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_RNODE + #define SERIAL_EVENTS SERIAL_INTERRUPT #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 @@ -73,6 +57,7 @@ const int pin_led_tx = 13; #define BOARD_MODEL BOARD_HMBRW + #define SERIAL_EVENTS SERIAL_INTERRUPT #define CONFIG_UART_BUFFER_SIZE 768 #define CONFIG_QUEUE_SIZE 5120 @@ -134,6 +119,8 @@ #error An unsupported board was selected. Cannot compile RNode firmware. #endif + #define SERIAL_EVENTS SERIAL_POLLING + #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 #define CONFIG_QUEUE_MAX_LENGTH 200 @@ -152,6 +139,7 @@ const int pin_led_tx = -1; #define BOARD_MODEL BOARD_SPIDEV + #define SERIAL_EVENTS SERIAL_POLLING #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 diff --git a/LoRa.cpp b/LoRa.cpp index 1b20596..4788eba 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -207,7 +207,7 @@ int LoRaClass::endPacket() #if LIBRARY_TYPE == LIBRARY_ARDUINO yield(); #elif LIBRARY_TYPE == LIBRARY_C - ::sleep(1); + ::sleep(0); #endif } diff --git a/MD5.h b/MD5.h index 7ca88bd..3c6a5f4 100644 --- a/MD5.h +++ b/MD5.h @@ -1,13 +1,7 @@ #ifndef MD5_h #define MD5_h -#include "Config.h" - -#if LIBRARY_TYPE == LIBRARY_ARDUINO - #include "Arduino.h" -#elif LIBRARY_TYPE == LIBRARY_C - #include -#endif +#include "Platform.h" /* * This is an OpenSSL-compatible implementation of the RSA Data Security, diff --git a/Makefile b/Makefile index b66d955..040edd1 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,6 @@ prep-samd: arduino-cli core update-index --config-file arduino-cli.yaml arduino-cli core install adafruit:samd -prep-linux: - mkdir -p bin - mkdir -p obj - - firmware: arduino-cli compile --fqbn unsignedio:avr:rnode @@ -139,18 +134,22 @@ release-mega2560: cp build/arduino.avr.mega/RNode_Firmware.ino.hex Release/rnode_firmware_latest_m2560.hex rm -r build -.PHONY: clean prep-linux - clean: rm -Rf bin rm -Rf obj -obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h Platform.h prep-linux +obj/MD5.o: MD5.cpp MD5.h Platform.h + mkdir -p obj $(CC) -c -o $@ $< -obj/LoRa.o: LoRa.cpp LoRa.h Platform.h prep-linux +obj/LoRa.o: LoRa.cpp LoRa.h Platform.h + mkdir -p obj $(CC) -c -o $@ $< -obj/RNode_firmware.o: RNode_firmware.ino Utilities.h Config.h LoRa.h ROM.h Framing.h MD5.h Platform.h prep-linux - $(CC) -c -o $@ $< +obj/RNode_Firmware.o: RNode_Firmware.ino Utilities.h Config.h LoRa.h ROM.h Framing.h MD5.h Platform.h + mkdir -p obj + $(CC) -c -o $@ -x c++ $< +bin/rnode: obj/RNode_Firmware.o obj/LoRa.o obj/MD5.o + mkdir -p bin + $(CC) -o $@ $^ -lstdc++ diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index b0b0873..05f8136 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -20,8 +20,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include -#include +#include "Platform.h" + +#if LIBRARY_TYPE == LIBRARY_ARDUINO + #include + #include +#endif #include "Utilities.h" FIFOBuffer serialFIFO; @@ -47,6 +51,16 @@ char sbuf[128]; bool packet_ready = false; #endif +// Arduino C doesn't need pre-declarations to call functions that appear later, +// but standard C does. +void serial_interrupt_init(); +void validateStatus(); +void update_radio_lock(); +void transmit(uint16_t size); +void buffer_serial(); +void serial_poll(); + + void setup() { #if MCU_VARIANT == MCU_ESP32 delay(500); @@ -54,8 +68,10 @@ void setup() { Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE); #endif - // Seed the PRNG - randomSeed(analogRead(0)); + #if LIBRARY_TYPE == LIBRARY_ARDUINO + // Seed the PRNG + randomSeed(analogRead(0)); + #endif // Initialise serial communication memset(serialBuffer, 0, sizeof(serialBuffer)); @@ -66,9 +82,11 @@ void setup() { serial_interrupt_init(); - // Configure input and output pins - pinMode(pin_led_rx, OUTPUT); - pinMode(pin_led_tx, OUTPUT); + #if LIBRARY_TYPE == LIBRARY_ARDUINO + // Configure input and output pins + pinMode(pin_led_rx, OUTPUT); + pinMode(pin_led_tx, OUTPUT); + #endif // Initialise buffers memset(pbuf, 0, sizeof(pbuf)); @@ -318,7 +336,7 @@ void flushQueue(void) { uint16_t processed = 0; - #if MCU_VARIANT == MCU_ESP32 + #if SERIAL_EVENTS == SERIAL_POLLING while (!fifo16_isempty(&packet_starts)) { #else while (!fifo16_isempty_locked(&packet_starts)) { @@ -683,13 +701,19 @@ void validateStatus() { uint8_t F_WDR = WDRF; #elif MCU_VARIANT == MCU_2560 uint8_t boot_flags = OPTIBOOT_MCUSR; - if (boot_flags == 0x00) boot_flags = 0x03; + if (boot_flags == 0x00) boot_flags = START_FROM_BROWNOUT; uint8_t F_POR = PORF; uint8_t F_BOR = BORF; uint8_t F_WDR = WDRF; #elif MCU_VARIANT == MCU_ESP32 // TODO: Get ESP32 boot flags - uint8_t boot_flags = 0x02; + uint8_t boot_flags = START_FROM_POWERON; + uint8_t F_POR = 0x00; + uint8_t F_BOR = 0x00; + uint8_t F_WDR = 0x01; + #elif MCU_VARIANT == MCU_LINUX + // Linux build always works like a clean boot. + uint8_t boot_flags = START_FROM_POWERON; uint8_t F_POR = 0x00; uint8_t F_BOR = 0x00; uint8_t F_WDR = 0x01; @@ -707,7 +731,7 @@ void validateStatus() { } if (boot_vector == START_FROM_BOOTLOADER || boot_vector == START_FROM_POWERON) { - if (eeprom_lock_set()) { + if (eeprom_info_locked()) { if (eeprom_product_valid() && eeprom_model_valid() && eeprom_hwrev_valid()) { if (eeprom_checksum_valid()) { hw_ready = true; @@ -775,7 +799,7 @@ void loop() { } } - #if MCU_VARIANT == MCU_ESP32 + #if SERIAL_EVENTS == SERIAL_POLLING buffer_serial(); if (!fifo_isempty(&serialFIFO)) serial_poll(); #else @@ -787,7 +811,7 @@ volatile bool serial_polling = false; void serial_poll() { serial_polling = true; - #if MCU_VARIANT != MCU_ESP32 + #if SERIAL_EVENTS == SERIAL_INTERRUPT while (!fifo_isempty_locked(&serialFIFO)) { #else while (!fifo_isempty(&serialFIFO)) { @@ -812,7 +836,7 @@ void buffer_serial() { while (c < MAX_CYCLES && Serial.available()) { c++; - #if MCU_VARIANT != MCU_ESP32 + #if SERIAL_EVENTS == SERIAL_INTERRUPT if (!fifo_isfull_locked(&serialFIFO)) { fifo_push_locked(&serialFIFO, Serial.read()); } @@ -853,8 +877,8 @@ void serial_interrupt_init() { TIMSK3 = _BV(ICIE3); - #elif MCU_VARIANT == MCU_ESP32 - // No interrupt-based polling on ESP32 + #else + // No interrupt-based polling on other MCUs. #endif } diff --git a/Utilities.h b/Utilities.h index 5b59364..f150f7a 100644 --- a/Utilities.h +++ b/Utilities.h @@ -1,4 +1,6 @@ -#include +#if LIBRARY_TYPE == LIBRARY_ARDUINO + #include +#endif #include #include "Config.h" #include "LoRa.h" @@ -6,6 +8,81 @@ #include "Framing.h" #include "MD5.h" +#if LIBRARY_TYPE == LIBRARY_C + #include + // We need a delay() + void delay(int ms) { + struct timespec interval; + interval.tv_sec = ms / 1000; + interval.tv_nsec = (ms % 1000) * 1000 * 1000; + // TODO: handle signals interrupting sleep + nanosleep(&interval, NULL); + } + + // And millis() + struct timespec millis_base; + uint32_t millis() { + // Time since first call is close enough. + static bool base_set(false); + if (!base_set) { + if (clock_gettime(CLOCK_MONOTONIC, &millis_base)) { + exit(1); + } + base_set = true; + } + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now)) { + exit(1); + } + return (now.tv_sec - millis_base.tv_sec) * 1000 + (now.tv_nsec - millis_base.tv_nsec)/(1000*1000); + } + + // We also need a Serial + class SerialClass { + public: + const char* fifoPath = "rnode_socket"; + void begin(int baud) { + int status = mkfifo(fifoPath, 0666); + if (status) { + perror("Making fifo failed"); + exit(1); + } + // TODO: Need a bidirectional thing here: openpty??? + _fd = open(fifoPath, O_RDWR); + if (_fd < 0) { + perror("could not open fifo"); + exit(1); + } + } + // Be truthy if connected + operator bool() { + return _fd > 0; + } + void write(int b) { + ssize_t written = ::write(_fd, + } + void write(const char* data) { + throw std::runtime_error("Unimplemented"); + } + bool available() { + throw std::runtime_error("Unimplemented"); + } + uint8_t read() { + throw std::runtime_error("Unimplemented"); + } + protected: + int _fd = -1; + }; + SerialClass Serial; + + // And random(below); + int random(int below) { + return rand() % below; + } + + +#endif + #if MCU_VARIANT == MCU_ESP32 #include "soc/rtc_wdt.h" #define ISR_VECT IRAM_ATTR @@ -68,7 +145,15 @@ uint8_t boot_vector = 0x00; void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } - #endif + #endif +#elif MCU_VARIANT == MCU_LINUX + #if BOARD_MODEL == BOARD_SPIDEV + // No LEDs on this board. SPI only. + void led_rx_on() { } + void led_rx_off() { } + void led_tx_on() { } + void led_tx_off() { } + #endif #endif void hard_reset(void) { @@ -79,23 +164,27 @@ void hard_reset(void) { } #elif MCU_VARIANT == MCU_ESP32 ESP.restart(); + #elif MCU_VARIANT == MCU_LINUX + // TODO: re-exec ourselves? + // For now just quit. + exit(0); #endif } void led_indicate_error(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; - while(cycles > 0) { - digitalWrite(pin_led_rx, HIGH); - digitalWrite(pin_led_tx, LOW); - delay(100); - digitalWrite(pin_led_rx, LOW); - digitalWrite(pin_led_tx, HIGH); - delay(100); - if (!forever) cycles--; - } - led_rx_off(); + while(cycles > 0) { + led_rx_on(); led_tx_off(); + delay(100); + led_rx_off(); + led_tx_on(); + delay(100); + if (!forever) cycles--; + } + led_rx_off(); + led_tx_off(); } void led_indicate_boot_error() { @@ -112,7 +201,7 @@ void led_indicate_boot_error() { void led_indicate_warning(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; - digitalWrite(pin_led_tx, HIGH); + led_tx_on(); while(cycles > 0) { led_tx_off(); delay(100); @@ -123,7 +212,7 @@ void led_indicate_warning(int cycles) { led_tx_off(); } -#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 +#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 || MCU_VARIANT == MCU_LINUX void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; @@ -179,8 +268,9 @@ void led_indicate_warning(int cycles) { #endif #endif - -unsigned long led_standby_ticks = 0; +#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 || MCU_VARIANT == MCU_ESP32 + unsigned long led_standby_ticks = 0; +#endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 uint8_t led_standby_min = 1; uint8_t led_standby_max = 40; @@ -196,8 +286,10 @@ unsigned long led_standby_ticks = 0; unsigned long led_standby_wait = 1768; unsigned long led_notready_wait = 150; #endif -uint8_t led_standby_value = led_standby_min; -int8_t led_standby_direction = 0; +#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 || MCU_VARIANT == MCU_ESP32 + uint8_t led_standby_value = led_standby_min; + int8_t led_standby_direction = 0; +#endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 void led_indicate_standby() { @@ -243,6 +335,9 @@ int8_t led_standby_direction = 0; #endif } } +#elif MCU_VARIANT == MCU_LINUX + // No LEDs available. + void led_indicate_standby() {} #endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 @@ -289,6 +384,9 @@ int8_t led_standby_direction = 0; #endif } } +#elif MCU_VARIANT == MCU_LINUX + // No LEDs available. + void led_indicate_not_ready() {} #endif void escapedSerialWrite(uint8_t byte) { @@ -551,8 +649,16 @@ void promisc_disable() { promisc = false; } +uint8_t eeprom_read(uint8_t addr) { + #if MCU_VARIANT == MCU_LINUX + return 0; + #else + return EEPROM.read(eeprom_addr(addr)); + #endif +} + bool eeprom_info_locked() { - uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)); + uint8_t lock_byte = eeprom_read(ADDR_INFO_LOCK); if (lock_byte == INFO_LOCK_BYTE) { return true; } else { @@ -560,34 +666,6 @@ bool eeprom_info_locked() { } } -void eeprom_dump_info() { - for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) { - uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); - } -} - -void eeprom_dump_config() { - for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) { - uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); - } -} - -void eeprom_dump_all() { - for (int addr = 0; addr < EEPROM_RESERVED; addr++) { - uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); - } -} - -void kiss_dump_eeprom() { - Serial.write(FEND); - Serial.write(CMD_ROM_READ); - eeprom_dump_all(); - Serial.write(FEND); -} - void eeprom_update(int mapped_addr, uint8_t byte) { #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 EEPROM.update(mapped_addr, byte); @@ -597,7 +675,6 @@ void eeprom_update(int mapped_addr, uint8_t byte) { EEPROM.commit(); } #endif - } void eeprom_write(uint8_t addr, uint8_t byte) { @@ -615,16 +692,36 @@ void eeprom_erase() { hard_reset(); } -bool eeprom_lock_set() { - if (EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)) == INFO_LOCK_BYTE) { - return true; - } else { - return false; +void eeprom_dump_info() { + for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) { + uint8_t byte = eeprom_read(addr); + escapedSerialWrite(byte); } } +void eeprom_dump_config() { + for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) { + uint8_t byte = eeprom_read(addr); + escapedSerialWrite(byte); + } +} + +void eeprom_dump_all() { + for (int addr = 0; addr < EEPROM_RESERVED; addr++) { + uint8_t byte = eeprom_read(addr); + escapedSerialWrite(byte); + } +} + +void kiss_dump_eeprom() { + Serial.write(FEND); + Serial.write(CMD_ROM_READ); + eeprom_dump_all(); + Serial.write(FEND); +} + bool eeprom_product_valid() { - uint8_t rval = EEPROM.read(eeprom_addr(ADDR_PRODUCT)); + uint8_t rval = eeprom_read(ADDR_PRODUCT); #if PLATFORM == PLATFORM_AVR if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW) { @@ -640,7 +737,7 @@ bool eeprom_product_valid() { } bool eeprom_model_valid() { - model = EEPROM.read(eeprom_addr(ADDR_MODEL)); + model = eeprom_read(ADDR_MODEL); #if BOARD_MODEL == BOARD_RNODE if (model == MODEL_A4 || model == MODEL_A9) { #elif BOARD_MODEL == BOARD_HMBRW @@ -665,7 +762,7 @@ bool eeprom_model_valid() { } bool eeprom_hwrev_valid() { - hwrev = EEPROM.read(eeprom_addr(ADDR_HW_REV)); + hwrev = eeprom_read(ADDR_HW_REV); if (hwrev != 0x00 && hwrev != 0xFF) { return true; } else { @@ -676,14 +773,14 @@ bool eeprom_hwrev_valid() { bool eeprom_checksum_valid() { char *data = (char*)malloc(CHECKSUMMED_SIZE); for (uint8_t i = 0; i < CHECKSUMMED_SIZE; i++) { - char byte = EEPROM.read(eeprom_addr(i)); + char byte = eeprom_read(i); data[i] = byte; } unsigned char *hash = MD5::make_hash(data, CHECKSUMMED_SIZE); bool checksum_valid = true; for (uint8_t i = 0; i < 16; i++) { - uint8_t stored_chk_byte = EEPROM.read(eeprom_addr(ADDR_CHKSUM+i)); + uint8_t stored_chk_byte = eeprom_read(ADDR_CHKSUM+i); uint8_t calced_chk_byte = (uint8_t)hash[i]; if (stored_chk_byte != calced_chk_byte) { checksum_valid = false; @@ -696,7 +793,7 @@ bool eeprom_checksum_valid() { } bool eeprom_have_conf() { - if (EEPROM.read(eeprom_addr(ADDR_CONF_OK)) == CONF_OK_BYTE) { + if (eeprom_read(ADDR_CONF_OK) == CONF_OK_BYTE) { return true; } else { return false; @@ -705,11 +802,11 @@ bool eeprom_have_conf() { void eeprom_conf_load() { if (eeprom_have_conf()) { - lora_sf = EEPROM.read(eeprom_addr(ADDR_CONF_SF)); - lora_cr = EEPROM.read(eeprom_addr(ADDR_CONF_CR)); - lora_txp = EEPROM.read(eeprom_addr(ADDR_CONF_TXP)); - lora_freq = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x03); - lora_bw = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x03); + lora_sf = eeprom_read(ADDR_CONF_SF); + lora_cr = eeprom_read(ADDR_CONF_CR); + lora_txp = eeprom_read(ADDR_CONF_TXP); + lora_freq = (uint32_t)eeprom_read(ADDR_CONF_FREQ+0x00) << 24 | (uint32_t)eeprom_read(ADDR_CONF_FREQ+0x01) << 16 | (uint32_t)eeprom_read(ADDR_CONF_FREQ+0x02) << 8 | (uint32_t)eeprom_read(ADDR_CONF_FREQ+0x03); + lora_bw = (uint32_t)eeprom_read(ADDR_CONF_BW+0x00) << 24 | (uint32_t)eeprom_read(ADDR_CONF_BW+0x01) << 16 | (uint32_t)eeprom_read(ADDR_CONF_BW+0x02) << 8 | (uint32_t)eeprom_read(ADDR_CONF_BW+0x03); } } @@ -784,7 +881,7 @@ inline void fifo_flush(FIFOBuffer *f) { f->head = f->tail; } -#if MCU_VARIANT != MCU_ESP32 +#if SERIAL_EVENTS == SERIAL_INTERRUPT static inline bool fifo_isempty_locked(const FIFOBuffer *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { @@ -866,7 +963,7 @@ inline void fifo16_flush(FIFOBuffer16 *f) { f->head = f->tail; } -#if MCU_VARIANT != MCU_ESP32 +#if SERIAL_EVENTS == SERIAL_INTERRUPT static inline bool fifo16_isempty_locked(const FIFOBuffer16 *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { From 04c8523619ebac17a96bf6f97c9daaf9567e49cd Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 15 Feb 2022 22:00:13 -0500 Subject: [PATCH 06/19] Implement Serial --- LoRa.cpp | 8 +++++-- Makefile | 2 +- Utilities.h | 63 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 4788eba..8cba9e1 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -125,8 +125,10 @@ int LoRaClass::begin(long frequency) // start SPI SPI.begin(); #elif LIBRARY_TYPE == LIBRARY_C - _fd = open("/dev/spidev0.0", O_RDWR); - if (_fd < 0) { + const char* spi_filename = "/dev/spidev0.0"; + std::cerr << "Opening SPI device " << spi_filename << std::endl; + _fd = open(spi_filename, O_RDWR); + if (_fd <= 0) { perror("could not open SPI device"); exit(1); } @@ -703,6 +705,8 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) int status; + std::cerr << "Access SPI at " << _fd << std::endl; + // Configure SPI speed and mode to match settings status = ioctl(_fd, SPI_IOC_WR_MODE, &_spiSettings.mode); if (status < 0) { diff --git a/Makefile b/Makefile index 040edd1..80e4659 100644 --- a/Makefile +++ b/Makefile @@ -152,4 +152,4 @@ obj/RNode_Firmware.o: RNode_Firmware.ino Utilities.h Config.h LoRa.h ROM.h Frami bin/rnode: obj/RNode_Firmware.o obj/LoRa.o obj/MD5.o mkdir -p bin - $(CC) -o $@ $^ -lstdc++ + $(CC) -o $@ $^ -lstdc++ -lutil diff --git a/Utilities.h b/Utilities.h index f150f7a..3f07bbf 100644 --- a/Utilities.h +++ b/Utilities.h @@ -10,6 +10,9 @@ #if LIBRARY_TYPE == LIBRARY_C #include + #include + #include + #include // We need a delay() void delay(int ms) { struct timespec interval; @@ -40,39 +43,69 @@ // We also need a Serial class SerialClass { public: - const char* fifoPath = "rnode_socket"; void begin(int baud) { - int status = mkfifo(fifoPath, 0666); + int other_end = 0; + int status = openpty(&_fd, &other_end, NULL, NULL, NULL); if (status) { - perror("Making fifo failed"); - exit(1); - } - // TODO: Need a bidirectional thing here: openpty??? - _fd = open(fifoPath, O_RDWR); - if (_fd < 0) { - perror("could not open fifo"); + perror("could not open PTY"); exit(1); } + + std::cout << "Listening on " << ttyname(other_end) << std::endl; } - // Be truthy if connected + operator bool() { return _fd > 0; } void write(int b) { - ssize_t written = ::write(_fd, + uint8_t to_write = b; + ssize_t written = ::write(_fd, &to_write, 1); + while (written != 1) { + if (written < 0) { + perror("could not write to PTY"); + exit(1); + } + written = ::write(_fd, &to_write, 1); + } } void write(const char* data) { - throw std::runtime_error("Unimplemented"); + while(*data) { + write(*data); + ++data; + } } bool available() { - throw std::runtime_error("Unimplemented"); + struct pollfd request; + request.fd = _fd; + request.events = POLLIN; + request.revents = 0; + + int result = poll(&request, 1, 0); + + if (result == -1) { + perror("could not poll"); + exit(1); + } + + return result > 0; } uint8_t read() { - throw std::runtime_error("Unimplemented"); + uint8_t buffer; + ssize_t count = ::read(_fd, &buffer, 1); + while (count != 1) { + if (count < 0) { + perror("could not read from PTY"); + exit(1); + } + count = ::read(_fd, &buffer, 1); + } + return buffer; } protected: - int _fd = -1; + int _fd; }; + + SerialClass Serial; // And random(below); From 910b8b0821768e82d471d8ae7fab5c4baae50179 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Wed, 16 Feb 2022 09:53:56 -0500 Subject: [PATCH 07/19] Don't talk to modem when not begun Indirect debug prints Implement Linux EEPROM from file Make EEPROM-flashable Explain how to flash on startup --- Config.h | 3 +- LoRa.cpp | 32 ++++++--- LoRa.h | 1 + Makefile | 12 ++-- RNode_Firmware.ino | 16 +++-- Utilities.h | 172 +++++++++++++++++++++++++++++++++++++++------ 6 files changed, 196 insertions(+), 40 deletions(-) diff --git a/Config.h b/Config.h index a88f537..262fc6a 100644 --- a/Config.h +++ b/Config.h @@ -15,7 +15,6 @@ #define BOARD_GENERIC_ESP32 0x35 #define BOARD_LORA32_V2_0 0x36 #define BOARD_LORA32_V2_1 0x37 - #define BOARD_SPIDEV 0x38 #define SERIAL_INTERRUPT 0x1 #define SERIAL_POLLING 0x2 @@ -138,7 +137,7 @@ const int pin_led_rx = -1; const int pin_led_tx = -1; - #define BOARD_MODEL BOARD_SPIDEV + #define BOARD_MODEL BOARD_HMBRW #define SERIAL_EVENTS SERIAL_POLLING #define CONFIG_UART_BUFFER_SIZE 6144 diff --git a/LoRa.cpp b/LoRa.cpp index 8cba9e1..c320f00 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -88,7 +88,8 @@ LoRaClass::LoRaClass() : _frequency(0), _packetIndex(0), _implicitHeaderMode(0), - _onReceive(NULL) + _onReceive(NULL), + _spiBegun(false) { #if LIBRARY_TYPE == LIBRARY_ARDUINO // overide Stream timeout value @@ -118,7 +119,7 @@ int LoRaClass::begin(long frequency) digitalWrite(_reset, HIGH); delay(10); #endif - // TODO: No reset pin hooked up on BOARD_SPIDEV + // TODO: No reset pin hooked up on Linux } #if LIBRARY_TYPE == LIBRARY_ARDUINO @@ -126,13 +127,19 @@ int LoRaClass::begin(long frequency) SPI.begin(); #elif LIBRARY_TYPE == LIBRARY_C const char* spi_filename = "/dev/spidev0.0"; - std::cerr << "Opening SPI device " << spi_filename << std::endl; - _fd = open(spi_filename, O_RDWR); + // We need to be re-entrant for restart if (_fd <= 0) { - perror("could not open SPI device"); - exit(1); + std::cerr << "Opening SPI device " << spi_filename << std::endl; + _fd = open(spi_filename, O_RDWR); + if (_fd <= 0) { + perror("could not open SPI device"); + exit(1); + } + } else { + std::cerr << "Skipping LoRa SPI reinitialization" << std::endl; } #endif + _spiBegun = true; // check version uint8_t version = readRegister(REG_VERSION); @@ -167,8 +174,13 @@ int LoRaClass::begin(long frequency) void LoRaClass::end() { - // put in sleep mode - this->sleep(); + // We need to be safe to call when the main loop is shutting down because + // it's in a bad state, even if we ourselves haven't been begun yet. We can't + // safely talk to the modem if the SPI link isn't begun, though. + if (_spiBegun) { + // put in sleep mode + this->sleep(); + } #if LIBRARY_TYPE == LIBRARY_ARDUINO // stop SPI @@ -179,6 +191,7 @@ void LoRaClass::end() _fd = -1; } #endif + _spiBegun = false; } int LoRaClass::beginPacket(int implicitHeader) @@ -706,6 +719,9 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) int status; std::cerr << "Access SPI at " << _fd << std::endl; + if (_fd <= 0) { + throw std::runtime_error("Accessing SPI device without begin()!"); + } // Configure SPI speed and mode to match settings status = ioctl(_fd, SPI_IOC_WR_MODE, &_spiSettings.mode); diff --git a/LoRa.h b/LoRa.h index e57543a..a418efe 100644 --- a/LoRa.h +++ b/LoRa.h @@ -133,6 +133,7 @@ private: int _packetIndex; int _implicitHeaderMode; void (*_onReceive)(int); + bool _spiBegun; #if LIBRARY_TYPE == LIBRARY_C int _fd; #endif diff --git a/Makefile b/Makefile index 80e4659..eebc832 100644 --- a/Makefile +++ b/Makefile @@ -137,19 +137,21 @@ release-mega2560: clean: rm -Rf bin rm -Rf obj - + +CFLAGS += -g + obj/MD5.o: MD5.cpp MD5.h Platform.h mkdir -p obj - $(CC) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< obj/LoRa.o: LoRa.cpp LoRa.h Platform.h mkdir -p obj - $(CC) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< obj/RNode_Firmware.o: RNode_Firmware.ino Utilities.h Config.h LoRa.h ROM.h Framing.h MD5.h Platform.h mkdir -p obj - $(CC) -c -o $@ -x c++ $< + $(CC) $(CFLAGS) -c -o $@ -x c++ $< bin/rnode: obj/RNode_Firmware.o obj/LoRa.o obj/MD5.o mkdir -p bin - $(CC) -o $@ $^ -lstdc++ -lutil + $(CC) $(CFLAGS) -o $@ $^ -lstdc++ -lutil diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 05f8136..5e8af06 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -64,9 +64,8 @@ void serial_poll(); void setup() { #if MCU_VARIANT == MCU_ESP32 delay(500); - EEPROM.begin(EEPROM_SIZE); - Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE); #endif + eeprom_open(EEPROM_SIZE); #if LIBRARY_TYPE == LIBRARY_ARDUINO // Seed the PRNG @@ -79,6 +78,10 @@ void setup() { Serial.begin(serial_baudrate); while (!Serial); + + #if MCU_VARIANT == MCU_ESP32 + Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE); + #endif serial_interrupt_init(); @@ -726,7 +729,7 @@ void validateStatus() { } else if (boot_flags & (1< #include #include + #include + #include + #include // We need a delay() void delay(int ms) { struct timespec interval; @@ -29,29 +32,44 @@ static bool base_set(false); if (!base_set) { if (clock_gettime(CLOCK_MONOTONIC, &millis_base)) { + perror("Could not get time"); exit(1); } base_set = true; } struct timespec now; if (clock_gettime(CLOCK_MONOTONIC, &now)) { + perror("Could not get time"); exit(1); } return (now.tv_sec - millis_base.tv_sec) * 1000 + (now.tv_nsec - millis_base.tv_nsec)/(1000*1000); } + // Serial will want to poll the EEPROM a bit for help text + bool eeprom_info_locked(); + // We also need a Serial class SerialClass { public: void begin(int baud) { - int other_end = 0; - int status = openpty(&_fd, &other_end, NULL, NULL, NULL); - if (status) { - perror("could not open PTY"); - exit(1); + // Need to be rrentrant for restart + if (_fd <= 0) { + int other_end = 0; + int status = openpty(&_fd, &other_end, NULL, NULL, NULL); + if (status) { + perror("could not open PTY"); + exit(1); + } + + std::cerr << "Listening on " << ttyname(other_end) << std::endl; + if (!eeprom_info_locked()) { + std::cerr << "EEPROM configuration is not initialized. You will want to flash it with something like:" << std::endl; + std::cerr << "\trnodeconf --key" << std::endl; + std::cerr << "\trnodeconf --rom --platform " << std::hex << PLATFORM << " --product " << PRODUCT_HMBRW << " --model " << MODEL_FF << std::dec << " --hwrev 1 " << ttyname(other_end) << std::endl; + } + } else { + std::cerr << "Skipping Serial reinitialization" << std::endl; } - - std::cout << "Listening on " << ttyname(other_end) << std::endl; } operator bool() { @@ -116,6 +134,17 @@ #endif +// Log a debug message. Message should have a \r to return the cursor, if +// needed. +void debug(const char* message) { + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << message << std::endl; + #endif + if (Serial) { + Serial.write(message); + } +} + #if MCU_VARIANT == MCU_ESP32 #include "soc/rtc_wdt.h" #define ISR_VECT IRAM_ATTR @@ -180,13 +209,16 @@ uint8_t boot_vector = 0x00; void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #endif #elif MCU_VARIANT == MCU_LINUX - #if BOARD_MODEL == BOARD_SPIDEV - // No LEDs on this board. SPI only. - void led_rx_on() { } - void led_rx_off() { } - void led_tx_on() { } - void led_tx_off() { } - #endif + // No LEDs on Linux, probably. SPI only. + void led_rx_on() { } + void led_rx_off() { } + void led_tx_on() { } + void led_tx_off() { } +#endif + +#if LIBRARY_TYPE == LIBRARY_C + // hard_reset needs a declaration for main + int main(int argc, char** argv); #endif void hard_reset(void) { @@ -199,12 +231,17 @@ void hard_reset(void) { ESP.restart(); #elif MCU_VARIANT == MCU_LINUX // TODO: re-exec ourselves? - // For now just quit. - exit(0); + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Restarting" << std::endl; + exit(main(0, NULL)); + #endif #endif } void led_indicate_error(int cycles) { +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Indicating error" << std::endl; +#endif bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { @@ -221,7 +258,10 @@ void led_indicate_error(int cycles) { } void led_indicate_boot_error() { - while (true) { +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Indicating boot error" << std::endl; +#endif + while (true) { led_tx_on(); led_rx_off(); delay(10); @@ -232,6 +272,9 @@ void led_indicate_boot_error() { } void led_indicate_warning(int cycles) { +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Indicating warning" << std::endl; +#endif bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; led_tx_on(); @@ -287,6 +330,9 @@ void led_indicate_warning(int cycles) { } #else void led_indicate_info(int cycles) { + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Indicating info" << std::endl; + #endif bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { @@ -370,7 +416,15 @@ void led_indicate_warning(int cycles) { } #elif MCU_VARIANT == MCU_LINUX // No LEDs available. - void led_indicate_standby() {} + void led_indicate_standby() { + #if LIBRARY_TYPE == LIBRARY_C + static bool printed = false; + if (!printed) { + std::cerr << "Indicating standby" << std::endl; + printed = true; + } + #endif + } #endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 @@ -419,7 +473,15 @@ void led_indicate_warning(int cycles) { } #elif MCU_VARIANT == MCU_LINUX // No LEDs available. - void led_indicate_not_ready() {} + void led_indicate_not_ready() { + #if LIBRARY_TYPE == LIBRARY_C + static bool printed = false; + if (!printed) { + std::cerr << "Indicating not ready" << std::endl; + printed = true; + } + #endif + } #endif void escapedSerialWrite(uint8_t byte) { @@ -682,15 +744,67 @@ void promisc_disable() { promisc = false; } +#if MCU_VARIANT == MCU_LINUX + // On Linux we always use memory-mapped EEPROM + uint8_t* eeprom_mapping = NULL; +#endif +#if LIBRARY_TYPE == LIBRARY_C + // And when using the C library we set it up from a file descriptor. + int eeprom_fd = 0; +#endif + +void eeprom_open(int size) { + #if MCU_VARIANT == MCU_ESP32 + // This MCU needs EEPROIM to be begun + EEPROM.begin(size); + #elif MCU_VARIANT == MCU_LINUX + // We need to use file-backed EEPROM emulation + #if LIBRARY_TYPE == LIBRARY_C + const char* eeprom_filename = "eeprom.dat"; + // We need to be reentrant for restarts + if (eeprom_fd <= 0) { + eeprom_fd = open(eeprom_filename, O_RDWR | O_CREAT, 0644); + if (eeprom_fd <= 0) { + perror("Could not open EEPROM file"); + exit(1); + } + int status = ftruncate(eeprom_fd, size); + if (status != 0) { + perror("Could not set size of EEPROM file"); + exit(1); + } + // Map EEPROM into RAM + eeprom_mapping = (uint8_t*) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, eeprom_fd, 0); + if (eeprom_mapping == NULL) { + perror("Could not map EEPROM file"); + exit(1); + } + std::cerr << "Mapped " << eeprom_filename << " as FD " << eeprom_fd << " to address " << (void*)eeprom_mapping << " size " << size << std::endl; + } else { + std::cerr << "Skipping EEPROM reinitialization" << std::endl; + } + #endif + #endif +} + uint8_t eeprom_read(uint8_t addr) { #if MCU_VARIANT == MCU_LINUX - return 0; + if (!eeprom_mapping) { + throw std::runtime_error("Tried to read EEPROM before opening it!"); + } + int mapped_address = eeprom_addr(addr); + return eeprom_mapping[mapped_address]; #else return EEPROM.read(eeprom_addr(addr)); #endif } bool eeprom_info_locked() { + #if MCU_VARIANT == MCU_LINUX + if (!eeprom_mapping) { + return false; + } + #endif uint8_t lock_byte = eeprom_read(ADDR_INFO_LOCK); if (lock_byte == INFO_LOCK_BYTE) { return true; @@ -707,6 +821,11 @@ void eeprom_update(int mapped_addr, uint8_t byte) { EEPROM.write(mapped_addr, byte); EEPROM.commit(); } + #elif MCU_VARIANT == MCU_LINUX + if (!eeprom_mapping) { + throw std::runtime_error("Tried to write EEPROM before opening it!"); + } + eeprom_mapping[mapped_addr] = byte; #endif } @@ -760,11 +879,16 @@ bool eeprom_product_valid() { if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW) { #elif PLATFORM == PLATFORM_ESP32 if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21) { - #else + #elif PLATFORM == PLATFORM_LINUX + if (rval == PRODUCT_HMBRW) { + #else if (false) { #endif return true; } else { + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Unacceptable platform: " << std::hex << "0x" << (int)rval << std::dec << std::endl; + #endif return false; } } @@ -790,6 +914,9 @@ bool eeprom_model_valid() { #endif return true; } else { + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Unacceptable model: " << std::hex << "0x" << (int)model << std::dec << std::endl; + #endif return false; } } @@ -799,6 +926,9 @@ bool eeprom_hwrev_valid() { if (hwrev != 0x00 && hwrev != 0xFF) { return true; } else { + #if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Unacceptable revision: " << std::hex << "0x" << (int)hwrev << std::dec << std::endl; + #endif return false; } } From 15d1cdc52677db61eb2806e649f7bc84a39b4287 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Wed, 16 Feb 2022 21:02:49 -0500 Subject: [PATCH 08/19] Poll for packets --- LoRa.cpp | 55 ++++++++++++++++++++++++++++++---------------- LoRa.h | 2 ++ RNode_Firmware.ino | 6 +++++ 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index c320f00..f95a92f 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -394,6 +394,19 @@ void LoRaClass::flush() { } +void LoRaClass::pollReceive() +{ + int irqFlags = readRegister(REG_IRQ_FLAGS); + + // clear IRQ's + writeRegister(REG_IRQ_FLAGS, irqFlags); + + if ((irqFlags & IRQ_RX_DONE_MASK) && !(irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK)) { + // received a packet + handleRx(); + } +} + void LoRaClass::onReceive(void(*callback)(int)) { _onReceive = callback; @@ -404,17 +417,15 @@ void LoRaClass::onReceive(void(*callback)(int)) #endif writeRegister(REG_DIO_MAPPING_1, 0x00); - -#if LIBRARY_TYPE == LIBRARY_ARDUINO + +#if MCU_VARIANT != MCU_LINUX && LIBRARY_TYPE == LIBRARY_ARDUINO #ifdef SPI_HAS_NOTUSINGINTERRUPT SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); #endif attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING); #endif - // TODO: What do we do if we want to use C library with a board that - // actually has dio0 connected? } else { -#if LIBRARY_TYPE == LIBRARY_ARDUINO +#if MCU_VARIANT != MCU_LINUX && LIBRARY_TYPE == LIBRARY_ARDUINO detachInterrupt(digitalPinToInterrupt(_dio0)); #ifdef SPI_HAS_NOTUSINGINTERRUPT SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0)); @@ -670,23 +681,29 @@ void ISR_VECT LoRaClass::handleDio0Rise() if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) { // received a packet - _packetIndex = 0; - - // read packet length - int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES); - - // set FIFO address to current RX address - writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); - - if (_onReceive) { - _onReceive(packetLength); - } - - // reset FIFO address - writeRegister(REG_FIFO_ADDR_PTR, 0); + handleRx(); } } +void ISR_VECT LoRaClass::handleRx() +{ + // received a packet + _packetIndex = 0; + + // read packet length + int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES); + + // set FIFO address to current RX address + writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); + + if (_onReceive) { + _onReceive(packetLength); + } + + // reset FIFO address + writeRegister(REG_FIFO_ADDR_PTR, 0); +} + uint8_t ISR_VECT LoRaClass::readRegister(uint8_t address) { return singleTransfer(address & 0x7f, 0x00); diff --git a/LoRa.h b/LoRa.h index a418efe..b784f27 100644 --- a/LoRa.h +++ b/LoRa.h @@ -76,6 +76,7 @@ public: virtual int peek(); virtual void flush(); + void pollReceive(); void onReceive(void(*callback)(int)); void receive(int size = 0); @@ -115,6 +116,7 @@ private: void implicitHeaderMode(); void handleDio0Rise(); + void handleRx(); uint8_t readRegister(uint8_t address); void writeRegister(uint8_t address, uint8_t value); diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 5e8af06..b444e64 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -778,6 +778,12 @@ void loop() { kiss_write_packet(); } #endif + + #if MCU_VARIANT == MCU_LINUX + // We don't have interrupts, so we need to poll ofr received packets. + // TODO: Is this fast enough? Or do we need threads or something? + LoRa.pollReceive(); + #endif if (queue_height > 0) { if (!dcd_waiting) updateModemStatus(); From ccc83a5c6b45d5842ca3cc9f05e9932d3ba0ad25 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Thu, 17 Feb 2022 10:27:51 -0500 Subject: [PATCH 09/19] Stop spamming console --- LoRa.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/LoRa.cpp b/LoRa.cpp index f95a92f..f07e402 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -735,7 +735,6 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) int status; - std::cerr << "Access SPI at " << _fd << std::endl; if (_fd <= 0) { throw std::runtime_error("Accessing SPI device without begin()!"); } From 8a7621a2f3e44ce42b366a31362d9200d230d50d Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Thu, 17 Feb 2022 16:05:44 +0000 Subject: [PATCH 10/19] Don't close SPI FD when stopping radio --- LoRa.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index f07e402..f14ad14 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -186,10 +186,7 @@ void LoRaClass::end() // stop SPI SPI.end(); #elif LIBRARY_TYPE == LIBRARY_C - if (_fd >= 0) { - close(_fd); - _fd = -1; - } + // Don't do anything. We need to keep things open for restart. #endif _spiBegun = false; } From 49ea5181eede2688425a30c03696c49f53ebfe56 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Thu, 17 Feb 2022 17:26:49 +0000 Subject: [PATCH 11/19] Reset radio registers manually --- LoRa.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index f14ad14..eb97b16 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -38,11 +38,14 @@ #define REG_FRF_MID 0x07 #define REG_FRF_LSB 0x08 #define REG_PA_CONFIG 0x09 +#define REG_PA_RAMP 0x0a +#define REG_OCP 0x0b #define REG_LNA 0x0c #define REG_FIFO_ADDR_PTR 0x0d #define REG_FIFO_TX_BASE_ADDR 0x0e #define REG_FIFO_RX_BASE_ADDR 0x0f #define REG_FIFO_RX_CURRENT_ADDR 0x10 +#define REG_IRQ_FLAGS_MASK 0x11 #define REG_IRQ_FLAGS 0x12 #define REG_RX_NB_BYTES 0x13 #define REG_MODEM_STAT 0x18 @@ -50,17 +53,27 @@ #define REG_PKT_RSSI_VALUE 0x1a #define REG_MODEM_CONFIG_1 0x1d #define REG_MODEM_CONFIG_2 0x1e +#define REG_SYMB_TIMEOUT_LSB 0x1f #define REG_PREAMBLE_MSB 0x20 #define REG_PREAMBLE_LSB 0x21 #define REG_PAYLOAD_LENGTH 0x22 +#define REG_PAYLOAD_MAX_LENGTH 0x23 +#define REG_HOP_PERIOD 0x24 #define REG_MODEM_CONFIG_3 0x26 +#define REG_PPM_CORRECTION 0x27 #define REG_FREQ_ERROR_MSB 0x28 #define REG_FREQ_ERROR_MID 0x29 #define REG_FREQ_ERROR_LSB 0x2a #define REG_RSSI_WIDEBAND 0x2c +#define REG_IF_FREQ_2 0x2f +#define REG_IF_FREQ_1 0x30 #define REG_DETECTION_OPTIMIZE 0x31 +#define REG_INVERT_IQ 0x33 +#define REG_HIGH_BW_OPTIMIZE_1 0x36 #define REG_DETECTION_THRESHOLD 0x37 #define REG_SYNC_WORD 0x39 +#define REG_HIGH_BW_OPTIMIZE_2 0x3a +#define REG_INVERT_IQ_2 0x3b #define REG_DIO_MAPPING_1 0x40 #define REG_VERSION 0x42 @@ -109,19 +122,6 @@ int LoRaClass::begin(long frequency) digitalWrite(_ss, HIGH); #endif - if (_reset != -1) { -#if LIBRARY_TYPE == LIBRARY_ARDUINO - pinMode(_reset, OUTPUT); - - // perform reset - digitalWrite(_reset, LOW); - delay(10); - digitalWrite(_reset, HIGH); - delay(10); -#endif - // TODO: No reset pin hooked up on Linux - } - #if LIBRARY_TYPE == LIBRARY_ARDUINO // start SPI SPI.begin(); @@ -141,6 +141,18 @@ int LoRaClass::begin(long frequency) #endif _spiBegun = true; + #if LIBRARY_TYPE == LIBRARY_ARDUINO + if (_reset != -1) { + pinMode(_reset, OUTPUT); + + // perform reset + digitalWrite(_reset, LOW); + delay(10); + digitalWrite(_reset, HIGH); + delay(10); + } + #endif + // check version uint8_t version = readRegister(REG_VERSION); if (version != 0x12) { @@ -150,6 +162,40 @@ int LoRaClass::begin(long frequency) // put in sleep mode this->sleep(); + #if LIBRARY_TYPE == LIBRARY_ARDUINO + if (_reset == -1) { + #elif LIBRARY_TYPE == LIBRARY_C + if (true) { + #endif + // Manually set important registers to default values because we can't + // reset. We need to make sure our local state agrees with the modem state + // and we don't have a commit-everything function. We also don't have + // bindings for all of these, and we don't want any weird settings set by + // other modem users on Linux. + writeRegister(REG_PA_RAMP, 0x09); + writeRegister(REG_OCP, 0x2b); + writeRegister(REG_LNA, 0x20); + writeRegister(REG_FIFO_ADDR_PTR, 0x00); + writeRegister(REG_IRQ_FLAGS_MASK, 0x00); + writeRegister(REG_MODEM_CONFIG_1, 0x72); + writeRegister(REG_MODEM_CONFIG_2, 0x70); + writeRegister(REG_SYMB_TIMEOUT_LSB, 0x64); + writeRegister(REG_PREAMBLE_MSB, 0x00); + writeRegister(REG_PREAMBLE_LSB, 0x08); + writeRegister(REG_PAYLOAD_LENGTH, 0xff); + writeRegister(REG_HOP_PERIOD, 0x00); + writeRegister(REG_PPM_CORRECTION, 0x00); + writeRegister(REG_IF_FREQ_2, 0x20); + writeRegister(REG_IF_FREQ_1, 0x00); + writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); + writeRegister(REG_INVERT_IQ, 0x13); + writeRegister(REG_HIGH_BW_OPTIMIZE_1, 0x20); + writeRegister(REG_DETECTION_THRESHOLD, 0x0a); + writeRegister(REG_SYNC_WORD, 0x12); + writeRegister(REG_HIGH_BW_OPTIMIZE_2, 0x20); + writeRegister(REG_INVERT_IQ_2, 0x1d); + } + // set frequency setFrequency(frequency); From 3a576b3c4d1d8d84e8870e24a4dab67582ab210e Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Thu, 17 Feb 2022 17:26:57 +0000 Subject: [PATCH 12/19] Log packets --- RNode_Firmware.ino | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index b444e64..aca87b4 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -151,6 +151,9 @@ inline void getPacketData(uint16_t len) { } void ISR_VECT receive_callback(int packet_size) { +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Got packet of " << packet_size << " bytes" << std::endl; +#endif if (!promisc) { // The standard operating mode allows large // packets with a payload up to 500 bytes, @@ -165,6 +168,11 @@ void ISR_VECT receive_callback(int packet_size) { // This is the first part of a split // packet, so we set the seq variable // and add the data to the buffer + +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "\tIs first part of split packet" << std::endl; +#endif + read_len = 0; seq = sequence; @@ -179,7 +187,11 @@ void ISR_VECT receive_callback(int packet_size) { // This is the second part of a split // packet, so we add it to the buffer // and set the ready flag. - + +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "\tIs second part of split packet" << std::endl; +#endif + #if MCU_VARIANT != MCU_ESP32 last_rssi = (last_rssi+LoRa.packetRssi())/2; last_snr_raw = (last_snr_raw+LoRa.packetSnrRaw())/2; @@ -194,6 +206,11 @@ void ISR_VECT receive_callback(int packet_size) { // same sequence id, so we must assume // that we are seeing the first part of // a new split packet. + +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "\tIs first part of a different split packet" << std::endl; +#endif + read_len = 0; seq = sequence; @@ -209,6 +226,10 @@ void ISR_VECT receive_callback(int packet_size) { // just read it and set the ready // flag to true. +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "\tIs complete packet" << std::endl; +#endif + if (seq != SEQ_UNSET) { // If we already had part of a split // packet in the buffer, we clear it. @@ -368,6 +389,9 @@ void flushQueue(void) { void transmit(uint16_t size) { if (radio_online) { if (!promisc) { +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Sending RNode packet(s) of " << size << " bytes" << std::endl; +#endif led_tx_on(); uint16_t written = 0; uint8_t header = random(256) & 0xF0; @@ -400,6 +424,11 @@ void transmit(uint16_t size) { // In promiscuous mode, we only send out // plain raw LoRa packets with a maximum // payload of 255 bytes + +#if LIBRARY_TYPE == LIBRARY_C + std::cerr << "Sending standard packet of " << size << " bytes" << std::endl; +#endif + led_tx_on(); uint16_t written = 0; From f50095f9eb5b591688058b5f54dce0a150a40a8f Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 13:48:53 -0500 Subject: [PATCH 13/19] Define a reset state from a dump --- LoRa.cpp | 137 ++++++++++++++++++++++++++++++++++--------------------- LoRa.h | 2 + 2 files changed, 87 insertions(+), 52 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index eb97b16..5b805e6 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -76,6 +76,13 @@ #define REG_INVERT_IQ_2 0x3b #define REG_DIO_MAPPING_1 0x40 #define REG_VERSION 0x42 +#define REG_TXCO 0x4B +#define REG_PA_DAC 0x4D +#define REG_AGC_REF 0x61 +#define REG_AGC_THRESHOLD_1 0x62 +#define REG_AGC_THRESHOLD_2 0x63 +#define REG_AGC_THRESHOLD_3 0x64 +#define REG_PLL 0x70 // Modes #define MODE_LONG_RANGE_MODE 0x80 @@ -141,61 +148,10 @@ int LoRaClass::begin(long frequency) #endif _spiBegun = true; - #if LIBRARY_TYPE == LIBRARY_ARDUINO - if (_reset != -1) { - pinMode(_reset, OUTPUT); - - // perform reset - digitalWrite(_reset, LOW); - delay(10); - digitalWrite(_reset, HIGH); - delay(10); - } - #endif - - // check version - uint8_t version = readRegister(REG_VERSION); - if (version != 0x12) { + if (!resetModem()) { return 0; } - // put in sleep mode - this->sleep(); - - #if LIBRARY_TYPE == LIBRARY_ARDUINO - if (_reset == -1) { - #elif LIBRARY_TYPE == LIBRARY_C - if (true) { - #endif - // Manually set important registers to default values because we can't - // reset. We need to make sure our local state agrees with the modem state - // and we don't have a commit-everything function. We also don't have - // bindings for all of these, and we don't want any weird settings set by - // other modem users on Linux. - writeRegister(REG_PA_RAMP, 0x09); - writeRegister(REG_OCP, 0x2b); - writeRegister(REG_LNA, 0x20); - writeRegister(REG_FIFO_ADDR_PTR, 0x00); - writeRegister(REG_IRQ_FLAGS_MASK, 0x00); - writeRegister(REG_MODEM_CONFIG_1, 0x72); - writeRegister(REG_MODEM_CONFIG_2, 0x70); - writeRegister(REG_SYMB_TIMEOUT_LSB, 0x64); - writeRegister(REG_PREAMBLE_MSB, 0x00); - writeRegister(REG_PREAMBLE_LSB, 0x08); - writeRegister(REG_PAYLOAD_LENGTH, 0xff); - writeRegister(REG_HOP_PERIOD, 0x00); - writeRegister(REG_PPM_CORRECTION, 0x00); - writeRegister(REG_IF_FREQ_2, 0x20); - writeRegister(REG_IF_FREQ_1, 0x00); - writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); - writeRegister(REG_INVERT_IQ, 0x13); - writeRegister(REG_HIGH_BW_OPTIMIZE_1, 0x20); - writeRegister(REG_DETECTION_THRESHOLD, 0x0a); - writeRegister(REG_SYNC_WORD, 0x12); - writeRegister(REG_HIGH_BW_OPTIMIZE_2, 0x20); - writeRegister(REG_INVERT_IQ_2, 0x1d); - } - // set frequency setFrequency(frequency); @@ -699,6 +655,83 @@ void LoRaClass::dumpRegisters(std::ostream& out) } #endif +bool LoRaClass::resetModem() +{ + // Reset the modem to a known good default state and put it into sleep mode. + // Returns false if the modem doesn't appear to be the right version. + #if LIBRARY_TYPE == LIBRARY_ARDUINO + if (_reset != -1) { + pinMode(_reset, OUTPUT); + + // perform reset + digitalWrite(_reset, LOW); + delay(10); + digitalWrite(_reset, HIGH); + delay(10); + } + #endif + // check version + uint8_t version = readRegister(REG_VERSION); + if (version != 0x12) { + return false; + } + + this->sleep(); + + #if LIBRARY_TYPE == LIBRARY_C + byte CLEAN_STATE[] = { + REG_PA_RAMP, 0x09, + REG_FRF_MSB, 0x6c, + REG_FRF_MID, 0x80, + REG_FRF_LSB, 0x00, + REG_PA_CONFIG, 0x4f, + REG_PA_RAMP, 0x09, + REG_OCP, 0x2b, + REG_LNA, 0x20, + REG_FIFO_ADDR_PTR, 0x00, + REG_FIFO_TX_BASE_ADDR, 0x80, + REG_FIFO_RX_BASE_ADDR, 0x00, + REG_FIFO_RX_CURRENT_ADDR, 0x00, + REG_IRQ_FLAGS_MASK, 0x00, + REG_MODEM_CONFIG_1, 0x72, + REG_MODEM_CONFIG_2, 0x70, + REG_SYMB_TIMEOUT_LSB, 0x64, + REG_PREAMBLE_MSB, 0x00, + REG_PREAMBLE_LSB, 0x08, + REG_PAYLOAD_LENGTH, 0x01, + REG_PAYLOAD_MAX_LENGTH, 0xff, + REG_HOP_PERIOD, 0x00, + REG_MODEM_CONFIG_3, 0x04, + REG_PPM_CORRECTION, 0x00, + REG_DETECTION_OPTIMIZE, 0xc3, // Errata says this needs to be set before REG_IF_FREQ_1 and REG_IF_FREQ_2 + REG_IF_FREQ_2, 0x45, // Datasheet says this defaults to 0x20, but dumping says 0x45. + REG_IF_FREQ_1, 0x55, // Datasheet says this defaults to 0x00, but dumping says 0x55. + REG_INVERT_IQ, 0x27, + REG_HIGH_BW_OPTIMIZE_1, 0x03, + REG_DETECTION_THRESHOLD, 0x0a, + REG_SYNC_WORD, 0x12, + REG_HIGH_BW_OPTIMIZE_2, 0x52, // Datasheet says this defaults to 0x20, but dumping says 0x52. + REG_INVERT_IQ_2, 0x1d, + REG_TXCO, 0x09, + REG_PA_DAC, 0x84, + REG_AGC_REF, 0x1C, // Datasheet says this defaults to 0x13, but dumping says 0x1c. + REG_AGC_THRESHOLD_1, 0x0e, + REG_AGC_THRESHOLD_2, 0x5b, + REG_AGC_THRESHOLD_3, 0xcc, // Datasheet says this defaults to 0xdb, but dumping says 0xcc. + REG_PLL, 0xd0, + 0, 0; + }; + + + // Manually set important registers to default values because we can't + // reset. + for (int i = 0; CLEAN_STATE[i] != 0; i += 2) { + writeRegister(CLEAN_STATE[i], CLEAN_STATE[i + 1]); + } + #endif + + return true; +} void LoRaClass::explicitHeaderMode() { diff --git a/LoRa.h b/LoRa.h index b784f27..f67651e 100644 --- a/LoRa.h +++ b/LoRa.h @@ -112,6 +112,8 @@ public: #endif private: + bool resetModem(); + void explicitHeaderMode(); void implicitHeaderMode(); From 5531120e2f16c5839efdfc56a987b9aeab20f780 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 15:26:14 -0500 Subject: [PATCH 14/19] Drop wayward semicolon --- LoRa.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 5b805e6..8d3022b 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -78,6 +78,8 @@ #define REG_VERSION 0x42 #define REG_TXCO 0x4B #define REG_PA_DAC 0x4D +// These registers have different values in high and low frequency modes (flag 0x08 in mode) +// We always stay in high frequency mode (flag is 0) #define REG_AGC_REF 0x61 #define REG_AGC_THRESHOLD_1 0x62 #define REG_AGC_THRESHOLD_2 0x63 @@ -714,12 +716,13 @@ bool LoRaClass::resetModem() REG_INVERT_IQ_2, 0x1d, REG_TXCO, 0x09, REG_PA_DAC, 0x84, - REG_AGC_REF, 0x1C, // Datasheet says this defaults to 0x13, but dumping says 0x1c. + // These are the high frequency mode (mode flag 0x08 is 0) values + REG_AGC_REF, 0x1C, REG_AGC_THRESHOLD_1, 0x0e, REG_AGC_THRESHOLD_2, 0x5b, - REG_AGC_THRESHOLD_3, 0xcc, // Datasheet says this defaults to 0xdb, but dumping says 0xcc. + REG_AGC_THRESHOLD_3, 0xcc, REG_PLL, 0xd0, - 0, 0; + 0, 0 }; From f7b2a60184073910eb1ee757e2b2fb82b0b62014 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 16:18:04 -0500 Subject: [PATCH 15/19] Dump registers when transmitting --- LoRa.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/LoRa.cpp b/LoRa.cpp index 8d3022b..2a05cb1 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -215,6 +215,13 @@ int LoRaClass::beginPacket(int implicitHeader) int LoRaClass::endPacket() { +#elif LIBRARY_TYPE == LIBRARY_C + std::cerr << "Entering transmit mode" << std::endl; + for (uint8_t i = REG_OP_MODE ; i <= REG_PA_DAC; i++) { + uint8_t val = readRegister(i); + std::cerr << std::hex << "0x" << i << " 0x" << val << std::dec << std::endl; + } +#endif // put in TX mode writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX); From 73e75a19d24a40e7b851f4545deed5d494c092d2 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 21:19:10 +0000 Subject: [PATCH 16/19] Fix build --- LoRa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LoRa.cpp b/LoRa.cpp index 2a05cb1..4219aba 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -215,7 +215,7 @@ int LoRaClass::beginPacket(int implicitHeader) int LoRaClass::endPacket() { -#elif LIBRARY_TYPE == LIBRARY_C +#if LIBRARY_TYPE == LIBRARY_C std::cerr << "Entering transmit mode" << std::endl; for (uint8_t i = REG_OP_MODE ; i <= REG_PA_DAC; i++) { uint8_t val = readRegister(i); From c3e57753ffd7a43b30fc527fc9ea0701e0d7a13b Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 22:04:39 +0000 Subject: [PATCH 17/19] Get tncattach packets visible from loramon --- LoRa.cpp | 8 ++++---- RNode_Firmware.ino | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 4219aba..e39e506 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -219,7 +219,7 @@ int LoRaClass::endPacket() std::cerr << "Entering transmit mode" << std::endl; for (uint8_t i = REG_OP_MODE ; i <= REG_PA_DAC; i++) { uint8_t val = readRegister(i); - std::cerr << std::hex << "0x" << i << " 0x" << val << std::dec << std::endl; + std::cerr << std::hex << "0x" << (int)i << " 0x" << (int)val << std::dec << std::endl; } #endif // put in TX mode @@ -712,9 +712,9 @@ bool LoRaClass::resetModem() REG_HOP_PERIOD, 0x00, REG_MODEM_CONFIG_3, 0x04, REG_PPM_CORRECTION, 0x00, - REG_DETECTION_OPTIMIZE, 0xc3, // Errata says this needs to be set before REG_IF_FREQ_1 and REG_IF_FREQ_2 - REG_IF_FREQ_2, 0x45, // Datasheet says this defaults to 0x20, but dumping says 0x45. - REG_IF_FREQ_1, 0x55, // Datasheet says this defaults to 0x00, but dumping says 0x55. + //REG_DETECTION_OPTIMIZE, 0xc3, // Errata says this needs to be set before REG_IF_FREQ_1 and REG_IF_FREQ_2 + //REG_IF_FREQ_2, 0x45, // Datasheet says this defaults to 0x20, but dumping says 0x45. + //REG_IF_FREQ_1, 0x55, // Datasheet says this defaults to 0x00, but dumping says 0x55. REG_INVERT_IQ, 0x27, REG_HIGH_BW_OPTIMIZE_1, 0x03, REG_DETECTION_THRESHOLD, 0x0a, diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index aca87b4..cac4d1a 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -792,10 +792,21 @@ void validateStatus() { } } +bool started = false; + void loop() { if (radio_online) { checkModemStatus(); + if (!started) { + started = true; + //promisc = true; + tbuf[0] = 'R'; + tbuf[1] = 'N'; + transmit(2); + //promisc = false; + } + #if MCU_VARIANT == MCU_ESP32 if (packet_ready) { portENTER_CRITICAL(&update_lock); From 71df428fa1877fdbfdf4346727136801a33766f0 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 22:11:55 +0000 Subject: [PATCH 18/19] Revert changes that didn't do anything --- LoRa.cpp | 6 +++--- RNode_Firmware.ino | 11 ----------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index e39e506..0849840 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -712,9 +712,9 @@ bool LoRaClass::resetModem() REG_HOP_PERIOD, 0x00, REG_MODEM_CONFIG_3, 0x04, REG_PPM_CORRECTION, 0x00, - //REG_DETECTION_OPTIMIZE, 0xc3, // Errata says this needs to be set before REG_IF_FREQ_1 and REG_IF_FREQ_2 - //REG_IF_FREQ_2, 0x45, // Datasheet says this defaults to 0x20, but dumping says 0x45. - //REG_IF_FREQ_1, 0x55, // Datasheet says this defaults to 0x00, but dumping says 0x55. + REG_DETECTION_OPTIMIZE, 0xc3, // Errata says this needs to be set before REG_IF_FREQ_1 and REG_IF_FREQ_2 + REG_IF_FREQ_2, 0x45, // Datasheet says this defaults to 0x20, but dumping says 0x45. + REG_IF_FREQ_1, 0x55, // Datasheet says this defaults to 0x00, but dumping says 0x55. REG_INVERT_IQ, 0x27, REG_HIGH_BW_OPTIMIZE_1, 0x03, REG_DETECTION_THRESHOLD, 0x0a, diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index cac4d1a..aca87b4 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -792,21 +792,10 @@ void validateStatus() { } } -bool started = false; - void loop() { if (radio_online) { checkModemStatus(); - if (!started) { - started = true; - //promisc = true; - tbuf[0] = 'R'; - tbuf[1] = 'N'; - transmit(2); - //promisc = false; - } - #if MCU_VARIANT == MCU_ESP32 if (packet_ready) { portENTER_CRITICAL(&update_lock); From 840f0a7db6165a26f7288ff561e1e89f31b8090a Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 21 Feb 2022 17:27:46 -0500 Subject: [PATCH 19/19] Stop aggressively logging transmit mode --- LoRa.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 0849840..8d3022b 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -215,13 +215,6 @@ int LoRaClass::beginPacket(int implicitHeader) int LoRaClass::endPacket() { -#if LIBRARY_TYPE == LIBRARY_C - std::cerr << "Entering transmit mode" << std::endl; - for (uint8_t i = REG_OP_MODE ; i <= REG_PA_DAC; i++) { - uint8_t val = readRegister(i); - std::cerr << std::hex << "0x" << (int)i << " 0x" << (int)val << std::dec << std::endl; - } -#endif // put in TX mode writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);