diff --git a/sx126x.cpp b/sx126x.cpp index 72b754b..cd74343 100644 --- a/sx126x.cpp +++ b/sx126x.cpp @@ -1,9 +1,6 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist -// Obviously still under the MIT license. - #include "Boards.h" #if MODEM == SX1262 @@ -24,19 +21,19 @@ #define OP_TX_6X 0x83 #define OP_RX_6X 0x82 #define OP_PA_CONFIG_6X 0x95 -#define OP_SET_IRQ_FLAGS_6X 0x08 // also provides info such as - // preamble detection, etc for - // knowing when it's safe to switch - // antenna modes +#define OP_SET_IRQ_FLAGS_6X 0x08 // Also provides info such as + // preamble detection, etc for + // knowing when it's safe to switch + // antenna modes #define OP_CLEAR_IRQ_STATUS_6X 0x02 #define OP_GET_IRQ_STATUS_6X 0x12 #define OP_RX_BUFFER_STATUS_6X 0x13 -#define OP_PACKET_STATUS_6X 0x14 // get snr & rssi of last packet +#define OP_PACKET_STATUS_6X 0x14 // Get snr & rssi of last packet #define OP_CURRENT_RSSI_6X 0x15 -#define OP_MODULATION_PARAMS_6X 0x8B // bw, sf, cr, etc. -#define OP_PACKET_PARAMS_6X 0x8C // crc, preamble, payload length, etc. +#define OP_MODULATION_PARAMS_6X 0x8B // BW, SF, CR, etc. +#define OP_PACKET_PARAMS_6X 0x8C // CRC, preamble, payload length, etc. #define OP_STATUS_6X 0xC0 -#define OP_TX_PARAMS_6X 0x8E // set dbm, etc +#define OP_TX_PARAMS_6X 0x8E // Set dbm, etc #define OP_PACKET_TYPE_6X 0x8A #define OP_BUFFER_BASE_ADDR_6X 0x8F #define OP_READ_REGISTER_6X 0x1D @@ -63,7 +60,7 @@ #define OP_FIFO_WRITE_6X 0x0E #define OP_FIFO_READ_6X 0x1E #define REG_OCP_6X 0x08E7 -#define REG_LNA_6X 0x08AC // no agc in sx1262 +#define REG_LNA_6X 0x08AC // No agc in sx1262 #define REG_SYNC_WORD_MSB_6X 0x0740 #define REG_SYNC_WORD_LSB_6X 0x0741 #define REG_PAYLOAD_LENGTH_6X 0x0702 // https://github.com/beegee-tokyo/SX126x-Arduino/blob/master/src/radio/sx126x/sx126x.h#L98 @@ -87,7 +84,7 @@ #define SYNC_WORD_6X 0x1424 #define XTAL_FREQ_6X (double)32000000 -#define FREQ_DIV_6X (double)pow(2.0, 25.0) +#define FREQ_DIV_6X (double)pow(2.0, 25.0) #define FREQ_STEP_6X (double)(XTAL_FREQ_6X / FREQ_DIV_6X) #if defined(NRF52840_XXAA) @@ -97,7 +94,7 @@ extern SPIClass SPI; -#define MAX_PKT_LENGTH 255 +#define MAX_PKT_LENGTH 255 sx126x::sx126x() : _spiSettings(8E6, MSBFIRST, SPI_MODE0), @@ -118,10 +115,7 @@ sx126x::sx126x() : _packet({0}), _preinit_done(false), _onReceive(NULL) -{ - // overide Stream timeout value - setTimeout(0); -} +{ setTimeout(0); } bool sx126x::preInit() { pinMode(_ss, OUTPUT); @@ -133,7 +127,7 @@ bool sx126x::preInit() { SPI.begin(); #endif - // check version (retry for up to 2 seconds) + // Check version (retry for up to 2 seconds) // TODO: Actually read version registers, not syncwords long start = millis(); uint8_t syncmsb; @@ -154,190 +148,129 @@ bool sx126x::preInit() { return true; } -uint8_t ISR_VECT sx126x::readRegister(uint16_t address) -{ +uint8_t ISR_VECT sx126x::readRegister(uint16_t address) { return singleTransfer(OP_READ_REGISTER_6X, address, 0x00); } -void sx126x::writeRegister(uint16_t address, uint8_t value) -{ - singleTransfer(OP_WRITE_REGISTER_6X, address, value); +void sx126x::writeRegister(uint16_t address, uint8_t value) { + singleTransfer(OP_WRITE_REGISTER_6X, address, value); } -uint8_t ISR_VECT sx126x::singleTransfer(uint8_t opcode, uint16_t address, uint8_t value) -{ - waitOnBusy(); - - uint8_t response; - - digitalWrite(_ss, LOW); - - SPI.beginTransaction(_spiSettings); - SPI.transfer(opcode); - SPI.transfer((address & 0xFF00) >> 8); - SPI.transfer(address & 0x00FF); - if (opcode == OP_READ_REGISTER_6X) { - SPI.transfer(0x00); - } - response = SPI.transfer(value); - SPI.endTransaction(); +uint8_t ISR_VECT sx126x::singleTransfer(uint8_t opcode, uint16_t address, uint8_t value) { + waitOnBusy(); + + uint8_t response; + digitalWrite(_ss, LOW); + SPI.beginTransaction(_spiSettings); + SPI.transfer(opcode); + SPI.transfer((address & 0xFF00) >> 8); + SPI.transfer(address & 0x00FF); + if (opcode == OP_READ_REGISTER_6X) { SPI.transfer(0x00); } + response = SPI.transfer(value); + SPI.endTransaction(); - digitalWrite(_ss, HIGH); + digitalWrite(_ss, HIGH); - return response; + return response; } -void sx126x::rxAntEnable() -{ - if (_rxen != -1) { - digitalWrite(_rxen, HIGH); - } +void sx126x::rxAntEnable() { + if (_rxen != -1) { digitalWrite(_rxen, HIGH); } } void sx126x::loraMode() { - // enable lora mode on the SX1262 chip - uint8_t mode = MODE_LONG_RANGE_MODE_6X; - executeOpcode(OP_PACKET_TYPE_6X, &mode, 1); + // Enable lora mode on the SX1262 chip + uint8_t mode = MODE_LONG_RANGE_MODE_6X; + executeOpcode(OP_PACKET_TYPE_6X, &mode, 1); } void sx126x::waitOnBusy() { - unsigned long time = millis(); - if (_busy != -1) { - while (digitalRead(_busy) == HIGH) - { - if (millis() >= (time + 100)) { - break; - } - // do nothing - } + unsigned long time = millis(); + if (_busy != -1) { + while (digitalRead(_busy) == HIGH) { + if (millis() >= (time + 100)) { break; } } + } } -void sx126x::executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size) -{ - waitOnBusy(); - - digitalWrite(_ss, LOW); - - SPI.beginTransaction(_spiSettings); - SPI.transfer(opcode); - - for (int i = 0; i < size; i++) - { - SPI.transfer(buffer[i]); - } - - SPI.endTransaction(); - - digitalWrite(_ss, HIGH); +void sx126x::executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size) { + waitOnBusy(); + digitalWrite(_ss, LOW); + SPI.beginTransaction(_spiSettings); + SPI.transfer(opcode); + for (int i = 0; i < size; i++) { SPI.transfer(buffer[i]); } + SPI.endTransaction(); + digitalWrite(_ss, HIGH); } -void sx126x::executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size) -{ - waitOnBusy(); - - digitalWrite(_ss, LOW); - - SPI.beginTransaction(_spiSettings); - SPI.transfer(opcode); - SPI.transfer(0x00); - - for (int i = 0; i < size; i++) - { - buffer[i] = SPI.transfer(0x00); - } - - SPI.endTransaction(); - - digitalWrite(_ss, HIGH); +void sx126x::executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size) { + waitOnBusy(); + digitalWrite(_ss, LOW); + SPI.beginTransaction(_spiSettings); + SPI.transfer(opcode); + SPI.transfer(0x00); + for (int i = 0; i < size; i++) { buffer[i] = SPI.transfer(0x00); } + SPI.endTransaction(); + digitalWrite(_ss, HIGH); } -void sx126x::writeBuffer(const uint8_t* buffer, size_t size) -{ - waitOnBusy(); - - digitalWrite(_ss, LOW); - - SPI.beginTransaction(_spiSettings); - SPI.transfer(OP_FIFO_WRITE_6X); - SPI.transfer(_fifo_tx_addr_ptr); - - for (int i = 0; i < size; i++) - { - SPI.transfer(buffer[i]); - _fifo_tx_addr_ptr++; - } - - SPI.endTransaction(); - - digitalWrite(_ss, HIGH); +void sx126x::writeBuffer(const uint8_t* buffer, size_t size) { + waitOnBusy(); + digitalWrite(_ss, LOW); + SPI.beginTransaction(_spiSettings); + SPI.transfer(OP_FIFO_WRITE_6X); + SPI.transfer(_fifo_tx_addr_ptr); + for (int i = 0; i < size; i++) { SPI.transfer(buffer[i]); _fifo_tx_addr_ptr++; } + SPI.endTransaction(); + digitalWrite(_ss, HIGH); } -void sx126x::readBuffer(uint8_t* buffer, size_t size) -{ - waitOnBusy(); - - digitalWrite(_ss, LOW); - - SPI.beginTransaction(_spiSettings); - SPI.transfer(OP_FIFO_READ_6X); - SPI.transfer(_fifo_rx_addr_ptr); - SPI.transfer(0x00); - - for (int i = 0; i < size; i++) - { - buffer[i] = SPI.transfer(0x00); - } - - SPI.endTransaction(); - - digitalWrite(_ss, HIGH); +void sx126x::readBuffer(uint8_t* buffer, size_t size) { + waitOnBusy(); + digitalWrite(_ss, LOW); + SPI.beginTransaction(_spiSettings); + SPI.transfer(OP_FIFO_READ_6X); + SPI.transfer(_fifo_rx_addr_ptr); + SPI.transfer(0x00); + for (int i = 0; i < size; i++) { buffer[i] = SPI.transfer(0x00); } + SPI.endTransaction(); + digitalWrite(_ss, HIGH); } void sx126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro) { - // because there is no access to these registers on the sx1262, we have + // Because there is no access to these registers on the sx1262, we have // to set all these parameters at once or not at all. uint8_t buf[8]; - buf[0] = sf; buf[1] = bw; buf[2] = cr; - // low data rate toggle - buf[3] = ldro; - // unused params in LoRa mode - buf[4] = 0x00; + buf[3] = ldro; // Low data rate toggle + buf[4] = 0x00; // Unused params in LoRa mode buf[5] = 0x00; buf[6] = 0x00; buf[7] = 0x00; - executeOpcode(OP_MODULATION_PARAMS_6X, buf, 8); } void sx126x::setPacketParams(long preamble, uint8_t headermode, uint8_t length, uint8_t crc) { - // because there is no access to these registers on the sx1262, we have + // Because there is no access to these registers on the sx1262, we have // to set all these parameters at once or not at all. uint8_t buf[9]; - buf[0] = uint8_t((preamble & 0xFF00) >> 8); buf[1] = uint8_t((preamble & 0x00FF)); buf[2] = headermode; buf[3] = length; buf[4] = crc; - // standard IQ setting (no inversion) - buf[5] = 0x00; - // unused params - buf[6] = 0x00; + buf[5] = 0x00; // standard IQ setting (no inversion) + buf[6] = 0x00; // unused params buf[7] = 0x00; buf[8] = 0x00; - executeOpcode(OP_PACKET_PARAMS_6X, buf, 9); } void sx126x::reset(void) { if (_reset != -1) { pinMode(_reset, OUTPUT); - - // perform reset digitalWrite(_reset, LOW); delay(10); digitalWrite(_reset, HIGH); @@ -350,7 +283,7 @@ void sx126x::calibrate(void) { uint8_t mode_byte = MODE_STDBY_RC_6X; executeOpcode(OP_STANDBY_6X, &mode_byte, 1); - // calibrate RC64k, RC13M, PLL, ADC and image + // Calibrate RC64k, RC13M, PLL, ADC and image uint8_t calibrate = MASK_CALIBRATE_ALL; executeOpcode(OP_CALIBRATE_6X, &calibrate, 1); @@ -360,55 +293,25 @@ void sx126x::calibrate(void) { void sx126x::calibrate_image(long frequency) { uint8_t image_freq[2] = {0}; - - if (frequency >= 430E6 && frequency <= 440E6) { - image_freq[0] = 0x6B; - image_freq[1] = 0x6F; - } - else if (frequency >= 470E6 && frequency <= 510E6) { - image_freq[0] = 0x75; - image_freq[1] = 0x81; - } - else if (frequency >= 779E6 && frequency <= 787E6) { - image_freq[0] = 0xC1; - image_freq[1] = 0xC5; - } - else if (frequency >= 863E6 && frequency <= 870E6) { - image_freq[0] = 0xD7; - image_freq[1] = 0xDB; - } - else if (frequency >= 902E6 && frequency <= 928E6) { - image_freq[0] = 0xE1; - image_freq[1] = 0xE9; - } - + if (frequency >= 430E6 && frequency <= 440E6) { image_freq[0] = 0x6B; image_freq[1] = 0x6F; } + else if (frequency >= 470E6 && frequency <= 510E6) { image_freq[0] = 0x75; image_freq[1] = 0x81; } + else if (frequency >= 779E6 && frequency <= 787E6) { image_freq[0] = 0xC1; image_freq[1] = 0xC5; } + else if (frequency >= 863E6 && frequency <= 870E6) { image_freq[0] = 0xD7; image_freq[1] = 0xDB; } + else if (frequency >= 902E6 && frequency <= 928E6) { image_freq[0] = 0xE1; image_freq[1] = 0xE9; } executeOpcode(OP_CALIBRATE_IMAGE_6X, image_freq, 2); waitOnBusy(); } -int sx126x::begin(long frequency) -{ +int sx126x::begin(long frequency) { reset(); - - if (_busy != -1) { - pinMode(_busy, INPUT); - } - - if (!_preinit_done) { - if (!preInit()) { - return false; - } - } - - if (_rxen != -1) { - pinMode(_rxen, OUTPUT); - } + + if (_busy != -1) { pinMode(_busy, INPUT); } + if (!_preinit_done) { if (!preInit()) { return false; } } + if (_rxen != -1) { pinMode(_rxen, OUTPUT); } calibrate(); calibrate_image(frequency); - enableTCXO(); - loraMode(); standby(); @@ -422,18 +325,11 @@ int sx126x::begin(long frequency) #endif rxAntEnable(); - setFrequency(frequency); - - // set output power to 2 dBm setTxPower(2); enableCrc(); - - // set LNA boost - writeRegister(REG_LNA_6X, 0x96); - - // set base addresses - uint8_t basebuf[2] = {0}; + writeRegister(REG_LNA_6X, 0x96); // Set LNA boost + uint8_t basebuf[2] = {0}; // Set base addresses executeOpcode(OP_BUFFER_BASE_ADDR_6X, basebuf, 2); setModulationParams(_sf, _bw, _cr, _ldro); @@ -442,26 +338,12 @@ int sx126x::begin(long frequency) return 1; } -void sx126x::end() -{ - // put in sleep mode - sleep(); - - // stop SPI - SPI.end(); +void sx126x::end() { sleep(); SPI.end(); _preinit_done = false; } - _preinit_done = false; -} - -int sx126x::beginPacket(int implicitHeader) -{ +int sx126x::beginPacket(int implicitHeader) { standby(); - - if (implicitHeader) { - implicitHeaderMode(); - } else { - explicitHeaderMode(); - } + if (implicitHeader) { implicitHeaderMode(); } + else { explicitHeaderMode(); } _payloadLength = 0; _fifo_tx_addr_ptr = 0; @@ -470,24 +352,19 @@ int sx126x::beginPacket(int implicitHeader) return 1; } -int sx126x::endPacket() -{ +int sx126x::endPacket() { setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); - - // put in single TX mode - uint8_t timeout[3] = {0}; + uint8_t timeout[3] = {0}; // Put in single TX mode executeOpcode(OP_TX_6X, timeout, 3); uint8_t buf[2]; - buf[0] = 0x00; buf[1] = 0x00; - executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2); + // Wait for TX done bool timed_out = false; uint32_t w_timeout = millis()+LORA_MODEM_TIMEOUT_MS; - // wait for TX done while ((millis() < w_timeout) && ((buf[1] & IRQ_TX_DONE_MASK_6X) == 0)) { buf[0] = 0x00; buf[1] = 0x00; @@ -497,136 +374,110 @@ int sx126x::endPacket() if (!(millis() < w_timeout)) { timed_out = true; } - // clear IRQ's - + // Clear IRQs uint8_t mask[2]; mask[0] = 0x00; mask[1] = IRQ_TX_DONE_MASK_6X; executeOpcode(OP_CLEAR_IRQ_STATUS_6X, mask, 2); - - if (timed_out) { - return 0; - } else { - return 1; - } + if (timed_out) { return 0; } else { return 1; } } uint8_t sx126x::modemStatus() { - // imitate the register status from the sx1276 / 78 - uint8_t buf[2] = {0}; - - executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2); - uint8_t clearbuf[2] = {0}; - uint8_t byte = 0x00; - - if ((buf[1] & IRQ_PREAMBLE_DET_MASK_6X) != 0) { - byte = byte | 0x01 | 0x04; - // clear register after reading - clearbuf[1] = IRQ_PREAMBLE_DET_MASK_6X; - } + // Imitate the register status from the sx1276 / 78 + uint8_t buf[2] = {0}; + executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2); + uint8_t clearbuf[2] = {0}; + uint8_t byte = 0x00; - if ((buf[1] & IRQ_HEADER_DET_MASK_6X) != 0) { - byte = byte | 0x02 | 0x04; - } + if ((buf[1] & IRQ_PREAMBLE_DET_MASK_6X) != 0) { + byte = byte | 0x01 | 0x04; + clearbuf[1] = IRQ_PREAMBLE_DET_MASK_6X; // Clear register after reading + } - executeOpcode(OP_CLEAR_IRQ_STATUS_6X, clearbuf, 2); + if ((buf[1] & IRQ_HEADER_DET_MASK_6X) != 0) { + byte = byte | 0x02 | 0x04; + } - return byte; + executeOpcode(OP_CLEAR_IRQ_STATUS_6X, clearbuf, 2); + return byte; } uint8_t sx126x::currentRssiRaw() { - uint8_t byte = 0; - executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); - return byte; + uint8_t byte = 0; + executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); + return byte; } int ISR_VECT sx126x::currentRssi() { - uint8_t byte = 0; - executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); - int rssi = -(int(byte)) / 2; - return rssi; + uint8_t byte = 0; + executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); + int rssi = -(int(byte)) / 2; + return rssi; } uint8_t sx126x::packetRssiRaw() { - uint8_t buf[3] = {0}; - executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); - return buf[2]; + uint8_t buf[3] = {0}; + executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); + return buf[2]; } int ISR_VECT sx126x::packetRssi() { - // may need more calculations here - uint8_t buf[3] = {0}; - executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); - int pkt_rssi = -buf[0] / 2; - return pkt_rssi; + // TODO: May need more calculations here + uint8_t buf[3] = {0}; + executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); + int pkt_rssi = -buf[0] / 2; + return pkt_rssi; } int ISR_VECT sx126x::packetRssi(uint8_t pkt_snr_raw) { - // may need more calculations here - uint8_t buf[3] = {0}; - executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); - int pkt_rssi = -buf[0] / 2; - return pkt_rssi; + // TODO: May need more calculations here + uint8_t buf[3] = {0}; + executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); + int pkt_rssi = -buf[0] / 2; + return pkt_rssi; } uint8_t ISR_VECT sx126x::packetSnrRaw() { - uint8_t buf[3] = {0}; - executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); - return buf[1]; + uint8_t buf[3] = {0}; + executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); + return buf[1]; } float ISR_VECT sx126x::packetSnr() { - uint8_t buf[3] = {0}; - executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); - return float(buf[1]) * 0.25; -} - -long sx126x::packetFrequencyError() -{ - // todo: implement this, no idea how to check it on the sx1262 - const float fError = 0.0; - return static_cast(fError); + uint8_t buf[3] = {0}; + executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); + return float(buf[1]) * 0.25; } -size_t sx126x::write(uint8_t byte) -{ - return write(&byte, sizeof(byte)); +long sx126x::packetFrequencyError() { + // TODO: Implement this, no idea how to check it on the sx1262 + const float fError = 0.0; + return static_cast(fError); } -size_t sx126x::write(const uint8_t *buffer, size_t size) -{ - if ((_payloadLength + size) > MAX_PKT_LENGTH) { - size = MAX_PKT_LENGTH - _payloadLength; - } - - // write data - writeBuffer(buffer, size); - _payloadLength = _payloadLength + size; - return size; +size_t sx126x::write(uint8_t byte) { return write(&byte, sizeof(byte)); } +size_t sx126x::write(const uint8_t *buffer, size_t size) { + if ((_payloadLength + size) > MAX_PKT_LENGTH) { size = MAX_PKT_LENGTH - _payloadLength; } + writeBuffer(buffer, size); + _payloadLength = _payloadLength + size; + return size; } -int ISR_VECT sx126x::available() -{ - uint8_t buf[2] = {0}; - executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, buf, 2); - return buf[0] - _packetIndex; +int ISR_VECT sx126x::available() { + uint8_t buf[2] = {0}; + executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, buf, 2); + return buf[0] - _packetIndex; } -int ISR_VECT sx126x::read() -{ - if (!available()) { - return -1; - } - - // if received new packet +int ISR_VECT sx126x::read(){ + if (!available()) { return -1; } if (_packetIndex == 0) { - uint8_t rxbuf[2] = {0}; - executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2); - int size = rxbuf[0]; - _fifo_rx_addr_ptr = rxbuf[1]; - - readBuffer(_packet, size); + uint8_t rxbuf[2] = {0}; + executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2); + int size = rxbuf[0]; + _fifo_rx_addr_ptr = rxbuf[1]; + readBuffer(_packet, size); } uint8_t byte = _packet[_packetIndex]; @@ -634,19 +485,13 @@ int ISR_VECT sx126x::read() return byte; } -int sx126x::peek() -{ - if (!available()) { - return -1; - } - - // if received new packet +int sx126x::peek() { + if (!available()) { return -1; } if (_packetIndex == 0) { uint8_t rxbuf[2] = {0}; executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2); int size = rxbuf[0]; _fifo_rx_addr_ptr = rxbuf[1]; - readBuffer(_packet, size); } @@ -654,83 +499,55 @@ int sx126x::peek() return b; } -void sx126x::flush() -{ -} +void sx126x::flush() { } -void sx126x::onReceive(void(*callback)(int)) -{ +void sx126x::onReceive(void(*callback)(int)){ _onReceive = callback; if (callback) { pinMode(_dio0, INPUT); - - // set preamble and header detection irqs, plus dio0 mask - uint8_t buf[8]; - - // set irq masks, enable all - buf[0] = 0xFF; + uint8_t buf[8]; // Set preamble and header detection irqs, plus dio0 mask + buf[0] = 0xFF; // Set irq masks, enable all buf[1] = 0xFF; - - // set dio0 masks - buf[2] = 0x00; + buf[2] = 0x00; // Set dio0 masks buf[3] = IRQ_RX_DONE_MASK_6X; - - // set dio1 masks - buf[4] = 0x00; + buf[4] = 0x00; // Set dio1 masks buf[5] = 0x00; - - // set dio2 masks - buf[6] = 0x00; + buf[6] = 0x00; // Set dio2 masks buf[7] = 0x00; - executeOpcode(OP_SET_IRQ_FLAGS_6X, buf, 8); -#ifdef SPI_HAS_NOTUSINGINTERRUPT - SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); -#endif + + #ifdef SPI_HAS_NOTUSINGINTERRUPT + SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); + #endif attachInterrupt(digitalPinToInterrupt(_dio0), sx126x::onDio0Rise, RISING); + } else { detachInterrupt(digitalPinToInterrupt(_dio0)); -#ifdef SPI_HAS_NOTUSINGINTERRUPT - SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0)); -#endif + #ifdef SPI_HAS_NOTUSINGINTERRUPT + SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0)); + #endif } } -void sx126x::receive(int size) -{ - if (size > 0) { - implicitHeaderMode(); - - // tell radio payload length - _payloadLength = size; - setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); - } else { - explicitHeaderMode(); - } - - if (_rxen != -1) { - rxAntEnable(); - } +void sx126x::receive(int size) { + if (size > 0) { + implicitHeaderMode(); + _payloadLength = size; + setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); + } else { explicitHeaderMode(); } - uint8_t mode[3] = {0xFF, 0xFF, 0xFF}; // continuous mode - executeOpcode(OP_RX_6X, mode, 3); + if (_rxen != -1) { rxAntEnable(); } + uint8_t mode[3] = {0xFF, 0xFF, 0xFF}; // Continuous mode + executeOpcode(OP_RX_6X, mode, 3); } -void sx126x::standby() -{ - // STDBY_XOSC - uint8_t byte = MODE_STDBY_XOSC_6X; - // STDBY_RC - // uint8_t byte = MODE_STDBY_RC_6X; +void sx126x::standby() { + uint8_t byte = MODE_STDBY_XOSC_6X; // STDBY_XOSC executeOpcode(OP_STANDBY_6X, &byte, 1); } -void sx126x::sleep() -{ - uint8_t byte = 0x00; - executeOpcode(OP_SLEEP_6X, &byte, 1); -} +void sx126x::sleep() { uint8_t byte = 0x00; executeOpcode(OP_SLEEP_6X, &byte, 1); } void sx126x::enableTCXO() { #if HAS_TCXO @@ -755,185 +572,123 @@ void sx126x::enableTCXO() { void sx126x::disableTCXO() { } void sx126x::setTxPower(int level, int outputPin) { - // currently no low power mode for SX1262 implemented, assuming PA boost - - // WORKAROUND - Better Resistance of the SX1262 Tx to Antenna Mismatch, see DS_SX1261-2_V1.2 datasheet chapter 15.2 - // RegTxClampConfig = @address 0x08D8 - writeRegister(0x08D8, readRegister(0x08D8) | (0x0F << 1)); - - uint8_t pa_buf[4]; - - pa_buf[0] = 0x04; // PADutyCycle needs to be 0x04 to achieve 22dBm output, but can be lowered for better efficiency at lower outputs - pa_buf[1] = 0x07; // HPMax at 0x07 is maximum supported for SX1262 - pa_buf[2] = 0x00; // DeviceSel 0x00 for SX1262 (0x01 for SX1261) - pa_buf[3] = 0x01; // PALut always 0x01 (reserved according to datasheet) - - executeOpcode(OP_PA_CONFIG_6X, pa_buf, 4); // set pa_config for high power - - if (level > 22) { level = 22; } - else if (level < -9) { level = -9; } + // Currently no low power mode for SX1262 implemented, assuming PA boost + + // WORKAROUND - Better Resistance of the SX1262 Tx to Antenna Mismatch, see DS_SX1261-2_V1.2 datasheet chapter 15.2 + // RegTxClampConfig = @address 0x08D8 + writeRegister(0x08D8, readRegister(0x08D8) | (0x0F << 1)); - writeRegister(REG_OCP_6X, OCP_TUNED); // Use board-specific tuned OCP + uint8_t pa_buf[4]; + pa_buf[0] = 0x04; // PADutyCycle needs to be 0x04 to achieve 22dBm output, but can be lowered for better efficiency at lower outputs + pa_buf[1] = 0x07; // HPMax at 0x07 is maximum supported for SX1262 + pa_buf[2] = 0x00; // DeviceSel 0x00 for SX1262 (0x01 for SX1261) + pa_buf[3] = 0x01; // PALut always 0x01 (reserved according to datasheet) + executeOpcode(OP_PA_CONFIG_6X, pa_buf, 4); // set pa_config for high power - uint8_t tx_buf[2]; + if (level > 22) { level = 22; } + else if (level < -9) { level = -9; } + writeRegister(REG_OCP_6X, OCP_TUNED); // Use board-specific tuned OCP - tx_buf[0] = level; - tx_buf[1] = 0x02; // PA ramping time - 40 microseconds - - executeOpcode(OP_TX_PARAMS_6X, tx_buf, 2); + uint8_t tx_buf[2]; + tx_buf[0] = level; + tx_buf[1] = 0x02; // PA ramping time - 40 microseconds + executeOpcode(OP_TX_PARAMS_6X, tx_buf, 2); - _txp = level; + _txp = level; } -uint8_t sx126x::getTxPower() { - return _txp; -} +uint8_t sx126x::getTxPower() { return _txp; } void sx126x::setFrequency(long frequency) { _frequency = frequency; - uint8_t buf[4]; - uint32_t freq = (uint32_t)((double)frequency / (double)FREQ_STEP_6X); - buf[0] = ((freq >> 24) & 0xFF); buf[1] = ((freq >> 16) & 0xFF); buf[2] = ((freq >> 8) & 0xFF); buf[3] = (freq & 0xFF); - executeOpcode(OP_RF_FREQ_6X, buf, 4); } uint32_t sx126x::getFrequency() { - // we can't read the frequency on the sx1262 / 80 + // We can't read the frequency on the sx1262 / 80 uint32_t frequency = _frequency; - return frequency; } -void sx126x::setSpreadingFactor(int sf) -{ - if (sf < 5) { - sf = 5; - } else if (sf > 12) { - sf = 12; - } - +void sx126x::setSpreadingFactor(int sf) { + if (sf < 5) { sf = 5; } + else if (sf > 12) { sf = 12; } _sf = sf; handleLowDataRate(); setModulationParams(sf, _bw, _cr, _ldro); } -long sx126x::getSignalBandwidth() -{ - int bw = _bw; - switch (bw) { - case 0x00: return 7.8E3; - case 0x01: return 15.6E3; - case 0x02: return 31.25E3; - case 0x03: return 62.5E3; - case 0x04: return 125E3; - case 0x05: return 250E3; - case 0x06: return 500E3; - case 0x08: return 10.4E3; - case 0x09: return 20.8E3; - case 0x0A: return 41.7E3; - } +long sx126x::getSignalBandwidth() { + int bw = _bw; + switch (bw) { + case 0x00: return 7.8E3; + case 0x01: return 15.6E3; + case 0x02: return 31.25E3; + case 0x03: return 62.5E3; + case 0x04: return 125E3; + case 0x05: return 250E3; + case 0x06: return 500E3; + case 0x08: return 10.4E3; + case 0x09: return 20.8E3; + case 0x0A: return 41.7E3; + } return 0; } void sx126x::handleLowDataRate(){ - if ( long( (1<<_sf) / (getSignalBandwidth()/1000)) > 16) { - _ldro = 0x01; - } else { - _ldro = 0x00; - } + if ( long( (1<<_sf) / (getSignalBandwidth()/1000)) > 16) { _ldro = 0x01; } + else { _ldro = 0x00; } } -void sx126x::optimizeModemSensitivity(){ - // todo: check if there's anything the sx1262 can do here -} - -void sx126x::setSignalBandwidth(long sbw) -{ - if (sbw <= 7.8E3) { - _bw = 0x00; - } else if (sbw <= 10.4E3) { - _bw = 0x08; - } else if (sbw <= 15.6E3) { - _bw = 0x01; - } else if (sbw <= 20.8E3) { - _bw = 0x09; - } else if (sbw <= 31.25E3) { - _bw = 0x02; - } else if (sbw <= 41.7E3) { - _bw = 0x0A; - } else if (sbw <= 62.5E3) { - _bw = 0x03; - } else if (sbw <= 125E3) { - _bw = 0x04; - } else if (sbw <= 250E3) { - _bw = 0x05; - } else /*if (sbw <= 250E3)*/ { - _bw = 0x06; - } +// TODO: check if there's anything the sx1262 can do here +void sx126x::optimizeModemSensitivity(){ } + +void sx126x::setSignalBandwidth(long sbw) { + if (sbw <= 7.8E3) { _bw = 0x00; } + else if (sbw <= 10.4E3) { _bw = 0x08; } + else if (sbw <= 15.6E3) { _bw = 0x01; } + else if (sbw <= 20.8E3) { _bw = 0x09; } + else if (sbw <= 31.25E3) { _bw = 0x02; } + else if (sbw <= 41.7E3) { _bw = 0x0A; } + else if (sbw <= 62.5E3) { _bw = 0x03; } + else if (sbw <= 125E3) { _bw = 0x04; } + else if (sbw <= 250E3) { _bw = 0x05; } + else { _bw = 0x06; } handleLowDataRate(); setModulationParams(_sf, _bw, _cr, _ldro); - optimizeModemSensitivity(); } -void sx126x::setCodingRate4(int denominator) -{ - if (denominator < 5) { - denominator = 5; - } else if (denominator > 8) { - denominator = 8; - } - +void sx126x::setCodingRate4(int denominator) { + if (denominator < 5) { denominator = 5; } + else if (denominator > 8) { denominator = 8; } int cr = denominator - 4; - _cr = cr; - setModulationParams(_sf, _bw, cr, _ldro); } -void sx126x::setPreambleLength(long length) -{ +void sx126x::setPreambleLength(long length) { _preambleLength = length; setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode); } -void sx126x::setSyncWord(uint16_t sw) -{ - // TODO: Fix - // writeRegister(REG_SYNC_WORD_MSB_6X, (sw & 0xFF00) >> 8); - // writeRegister(REG_SYNC_WORD_LSB_6X, sw & 0x00FF); - writeRegister(REG_SYNC_WORD_MSB_6X, 0x14); - writeRegister(REG_SYNC_WORD_LSB_6X, 0x24); -} - -void sx126x::enableCrc() -{ - _crcMode = 1; - setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); -} - -void sx126x::disableCrc() -{ - _crcMode = 0; - setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); -} - -byte sx126x::random() -{ - return readRegister(REG_RANDOM_GEN_6X); +void sx126x::setSyncWord(uint16_t sw) { + // TODO: Why was this hardcoded instead of using the config value? + // writeRegister(REG_SYNC_WORD_MSB_6X, (sw & 0xFF00) >> 8); + // writeRegister(REG_SYNC_WORD_LSB_6X, sw & 0x00FF); + writeRegister(REG_SYNC_WORD_MSB_6X, 0x14); + writeRegister(REG_SYNC_WORD_LSB_6X, 0x24); } -void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen) -{ +void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen) { _ss = ss; _reset = reset; _dio0 = dio0; @@ -941,13 +696,7 @@ void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen) _rxen = rxen; } -void sx126x::setSPIFrequency(uint32_t frequency) -{ - _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); -} - -void sx126x::dumpRegisters(Stream& out) -{ +void sx126x::dumpRegisters(Stream& out) { for (int i = 0; i < 128; i++) { out.print("0x"); out.print(i, HEX); @@ -956,49 +705,29 @@ void sx126x::dumpRegisters(Stream& out) } } -void sx126x::explicitHeaderMode() -{ - _implicitHeaderMode = 0; - setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); -} - -void sx126x::implicitHeaderMode() -{ - _implicitHeaderMode = 1; - setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); -} - - -void ISR_VECT sx126x::handleDio0Rise() -{ - uint8_t buf[2]; - - buf[0] = 0x00; - buf[1] = 0x00; - - executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2); - - executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2); - - if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_6X) == 0) { - // received a packet - _packetIndex = 0; - - // read packet length - uint8_t rxbuf[2] = {0}; - executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2); - int packetLength = rxbuf[0]; - - if (_onReceive) { - _onReceive(packetLength); - } - } +void ISR_VECT sx126x::handleDio0Rise() { + uint8_t buf[2]; + buf[0] = 0x00; + buf[1] = 0x00; + executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2); + executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2); + + if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_6X) == 0) { + _packetIndex = 0; + uint8_t rxbuf[2] = {0}; // Read packet length + executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2); + int packetLength = rxbuf[0]; + if (_onReceive) { _onReceive(packetLength); } + } } -void ISR_VECT sx126x::onDio0Rise() -{ - sx126x_modem.handleDio0Rise(); -} +void ISR_VECT sx126x::onDio0Rise() { sx126x_modem.handleDio0Rise(); } +void sx126x::setSPIFrequency(uint32_t frequency) { _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); } +void sx126x::enableCrc() { _crcMode = 1; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } +void sx126x::disableCrc() { _crcMode = 0; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } +void sx126x::explicitHeaderMode() { _implicitHeaderMode = 0; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } +void sx126x::implicitHeaderMode() { _implicitHeaderMode = 1; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } +byte sx126x::random() { return readRegister(REG_RANDOM_GEN_6X); } sx126x sx126x_modem; diff --git a/sx126x.h b/sx126x.h index 488ba49..bec13f8 100644 --- a/sx126x.h +++ b/sx126x.h @@ -1,9 +1,6 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist -// Obviously still under the MIT license. - #ifndef SX126X_H #define SX126X_H diff --git a/sx127x.cpp b/sx127x.cpp index e3a6c49..2d562c2 100644 --- a/sx127x.cpp +++ b/sx127x.cpp @@ -1,9 +1,6 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist -// Obviously still under the MIT license. - #include "Boards.h" #if MODEM == SX1276 @@ -81,10 +78,7 @@ extern SPIClass SPI; sx127x::sx127x() : _spiSettings(8E6, MSBFIRST, SPI_MODE0), _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), - _frequency(0), - _packetIndex(0), - _preinit_done(false), - _onReceive(NULL) { setTimeout(0); } + _frequency(0), _packetIndex(0), _preinit_done(false), _onReceive(NULL) { setTimeout(0); } void sx127x::setSPIFrequency(uint32_t frequency) { _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); } void sx127x::setPins(int ss, int reset, int dio0, int busy) { _ss = ss; _reset = reset; _dio0 = dio0; _busy = busy; } @@ -123,7 +117,6 @@ bool sx127x::preInit() { } if (version != 0x12) { return false; } - _preinit_done = true; return true; } @@ -144,8 +137,6 @@ uint8_t ISR_VECT sx127x::singleTransfer(uint8_t address, uint8_t value) { int sx127x::begin(long frequency) { if (_reset != -1) { pinMode(_reset, OUTPUT); - - // Perform reset digitalWrite(_reset, LOW); delay(10); digitalWrite(_reset, HIGH); @@ -153,19 +144,16 @@ int sx127x::begin(long frequency) { } if (_busy != -1) { pinMode(_busy, INPUT); } - - if (!_preinit_done) { - if (!preInit()) { return false; } - } + if (!_preinit_done) { if (!preInit()) { return false; } } sleep(); setFrequency(frequency); - // set base addresses + // Set base addresses writeRegister(REG_FIFO_TX_BASE_ADDR_7X, 0); writeRegister(REG_FIFO_RX_BASE_ADDR_7X, 0); - // set LNA boost and auto AGC + // Set LNA boost and auto AGC writeRegister(REG_LNA_7X, readRegister(REG_LNA_7X) | 0x03); writeRegister(REG_MODEM_CONFIG_3_7X, 0x04); @@ -178,20 +166,13 @@ int sx127x::begin(long frequency) { return 1; } -void sx127x::end() { - sleep(); - SPI.end(); - _preinit_done = false; -} +void sx127x::end() { sleep(); SPI.end(); _preinit_done = false; } int sx127x::beginPacket(int implicitHeader) { standby(); - if (implicitHeader) { - implicitHeaderMode(); - } else { - explicitHeaderMode(); - } + if (implicitHeader) { implicitHeaderMode(); } + else { explicitHeaderMode(); } // Reset FIFO address and payload length writeRegister(REG_FIFO_ADDR_PTR_7X, 0); @@ -248,30 +229,25 @@ int ISR_VECT sx127x::packetRssi(uint8_t pkt_snr_raw) { } int ISR_VECT sx127x::packetRssi() { - int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE_7X) - RSSI_OFFSET; - int pkt_snr = packetSnr(); - - if (_frequency < 820E6) pkt_rssi -= 7; - - if (pkt_snr < 0) { - pkt_rssi += pkt_snr; - } else { - // Slope correction is (16/15)*pkt_rssi, - // this estimation looses one floating point - // operation, and should be precise enough. - pkt_rssi = (int)(1.066 * pkt_rssi); - } - return pkt_rssi; -} + int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE_7X) - RSSI_OFFSET; + int pkt_snr = packetSnr(); -uint8_t ISR_VECT sx127x::packetSnrRaw() { - return readRegister(REG_PKT_SNR_VALUE_7X); -} + if (_frequency < 820E6) pkt_rssi -= 7; -float ISR_VECT sx127x::packetSnr() { - return ((int8_t)readRegister(REG_PKT_SNR_VALUE_7X)) * 0.25; + if (pkt_snr < 0) { pkt_rssi += pkt_snr; } + else { + // Slope correction is (16/15)*pkt_rssi, + // this estimation looses one floating point + // operation, and should be precise enough. + pkt_rssi = (int)(1.066 * pkt_rssi); + } + return pkt_rssi; } +uint8_t ISR_VECT sx127x::packetSnrRaw() { return readRegister(REG_PKT_SNR_VALUE_7X); } + +float ISR_VECT sx127x::packetSnr() { return ((int8_t)readRegister(REG_PKT_SNR_VALUE_7X)) * 0.25; } + long sx127x::packetFrequencyError() { int32_t freqError = 0; freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB_7X) & B111); @@ -293,17 +269,13 @@ long sx127x::packetFrequencyError() { size_t sx127x::write(uint8_t byte) { return write(&byte, sizeof(byte)); } size_t sx127x::write(const uint8_t *buffer, size_t size) { - int currentLength = readRegister(REG_PAYLOAD_LENGTH_7X); - if ((currentLength + size) > MAX_PKT_LENGTH) { - size = MAX_PKT_LENGTH - currentLength; - } + int currentLength = readRegister(REG_PAYLOAD_LENGTH_7X); + if ((currentLength + size) > MAX_PKT_LENGTH) { size = MAX_PKT_LENGTH - currentLength; } - for (size_t i = 0; i < size; i++) { - writeRegister(REG_FIFO_7X, buffer[i]); - } + for (size_t i = 0; i < size; i++) { writeRegister(REG_FIFO_7X, buffer[i]); } + writeRegister(REG_PAYLOAD_LENGTH_7X, currentLength + size); - writeRegister(REG_PAYLOAD_LENGTH_7X, currentLength + size); - return size; + return size; } int ISR_VECT sx127x::available() { return (readRegister(REG_RX_NB_BYTES_7X) - _packetIndex); } diff --git a/sx127x.h b/sx127x.h index a45817e..56ff889 100644 --- a/sx127x.h +++ b/sx127x.h @@ -1,9 +1,6 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist -// Obviously still under the MIT license. - #ifndef SX1276_H #define SX1276_H diff --git a/sx128x.cpp b/sx128x.cpp index 5b8c81e..34eb14f 100644 --- a/sx128x.cpp +++ b/sx128x.cpp @@ -1,11 +1,10 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist & Jacob Eva -// Obviously still under the MIT license. +#include "Boards.h" +#if MODEM == SX1280 #include "sx128x.h" -#include "Boards.h" #define MCU_1284P 0x91 #define MCU_2560 0x92 @@ -44,19 +43,19 @@ #define OP_STANDBY_8X 0x80 #define OP_TX_8X 0x83 #define OP_RX_8X 0x82 -#define OP_SET_IRQ_FLAGS_8X 0x8D // also provides info such as +#define OP_SET_IRQ_FLAGS_8X 0x8D // Also provides info such as // preamble detection, etc for // knowing when it's safe to switch // antenna modes #define OP_CLEAR_IRQ_STATUS_8X 0x97 #define OP_GET_IRQ_STATUS_8X 0x15 #define OP_RX_BUFFER_STATUS_8X 0x17 -#define OP_PACKET_STATUS_8X 0x1D // get snr & rssi of last packet +#define OP_PACKET_STATUS_8X 0x1D // Get snr & rssi of last packet #define OP_CURRENT_RSSI_8X 0x1F -#define OP_MODULATION_PARAMS_8X 0x8B // bw, sf, cr, etc. -#define OP_PACKET_PARAMS_8X 0x8C // crc, preamble, payload length, etc. +#define OP_MODULATION_PARAMS_8X 0x8B // BW, SF, CR, etc. +#define OP_PACKET_PARAMS_8X 0x8C // CRC, preamble, payload length, etc. #define OP_STATUS_8X 0xC0 -#define OP_TX_PARAMS_8X 0x8E // set dbm, etc +#define OP_TX_PARAMS_8X 0x8E // Set dbm, etc #define OP_PACKET_TYPE_8X 0x8A #define OP_BUFFER_BASE_ADDR_8X 0x8F #define OP_READ_REGISTER_8X 0x19 @@ -73,9 +72,9 @@ #define OP_FIFO_READ_8X 0x1B #define IRQ_PREAMBLE_DET_MASK_8X 0x80 -#define REG_PACKET_SIZE 0x901 -#define REG_FIRM_VER_MSB 0x154 -#define REG_FIRM_VER_LSB 0x153 +#define REG_PACKET_SIZE 0x901 +#define REG_FIRM_VER_MSB 0x154 +#define REG_FIRM_VER_LSB 0x153 #define XTAL_FREQ_8X (double)52000000 #define FREQ_DIV_8X (double)pow(2.0, 18.0) @@ -93,24 +92,8 @@ extern SPIClass SPI; sx128x::sx128x() : _spiSettings(8E6, MSBFIRST, SPI_MODE0), _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _rxen(pin_rxen), _busy(LORA_DEFAULT_BUSY_PIN), _txen(pin_txen), - _frequency(0), - _txp(0), - _sf(0x05), - _bw(0x34), - _cr(0x01), - _packetIndex(0), - _implicitHeaderMode(0), - _payloadLength(255), - _crcMode(0), - _fifo_tx_addr_ptr(0), - _fifo_rx_addr_ptr(0), - _rxPacketLength(0), - _preinit_done(false), - _tcxo(false) -{ - // overide Stream timeout value - setTimeout(0); -} + _frequency(0), _txp(0), _sf(0x05), _bw(0x34), _cr(0x01), _packetIndex(0), _implicitHeaderMode(0), _payloadLength(255), _crcMode(0), _fifo_tx_addr_ptr(0), + _fifo_rx_addr_ptr(0), _rxPacketLength(0), _preinit_done(false), _tcxo(false) { setTimeout(0); } bool ISR_VECT sx128x::getPacketValidity() { uint8_t buf[2]; @@ -472,23 +455,17 @@ float ISR_VECT sx128x::packetSnr() { } long sx128x::packetFrequencyError() { - // TODO: implement this, page 120 of sx1280 datasheet + // TODO: Implement this, page 120 of sx1280 datasheet int32_t freqError = 0; const float fError = 0.0; return static_cast(fError); } void sx128x::flush() { } - int ISR_VECT sx128x::available() { return _rxPacketLength - _packetIndex; } - size_t sx128x::write(uint8_t byte) { return write(&byte, sizeof(byte)); } - size_t sx128x::write(const uint8_t *buffer, size_t size) { - if ((_payloadLength + size) > MAX_PKT_LENGTH) { - size = MAX_PKT_LENGTH - _payloadLength; - } - + if ((_payloadLength + size) > MAX_PKT_LENGTH) { size = MAX_PKT_LENGTH - _payloadLength; } writeBuffer(buffer, size); _payloadLength = _payloadLength + size; return size; @@ -716,7 +693,7 @@ void sx128x::setTxPower(int level, int outputPin) { } tx_buf[0] = reg_value + 18; - tx_buf[1] = 0xE0; // ramping time - 20 microseconds + tx_buf[1] = 0xE0; // Ramping time, 20 microseconds executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2); // T3S3 SX1280 PA @@ -795,7 +772,7 @@ void sx128x::setTxPower(int level, int outputPin) { break; } tx_buf[0] = reg_value; - tx_buf[1] = 0xE0; // ramping time - 20 microseconds + tx_buf[1] = 0xE0; // Ramping time, 20 microseconds // For SX1280 boards with no specific PA requirements #else @@ -803,7 +780,7 @@ void sx128x::setTxPower(int level, int outputPin) { else if (level < -18) { level = -18; } _txp = level; tx_buf[0] = level + 18; - tx_buf[1] = 0xE0; // ramping time - 20 microseconds + tx_buf[1] = 0xE0; // Ramping time, 20 microseconds #endif executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2); @@ -821,7 +798,7 @@ void sx128x::setFrequency(uint32_t frequency) { } uint32_t sx128x::getFrequency() { - // we can't read the frequency on the sx1280 + // We can't read the frequency on the sx1280 uint32_t frequency = _frequency; return frequency; } @@ -847,12 +824,6 @@ uint32_t sx128x::getSignalBandwidth() { return 0; } -// TODO: Is this needed for SX1280? -void sx128x::handleLowDataRate() { } - -// TODO: Check if there's anything the sx1280 can do here -void sx128x::optimizeModemSensitivity() { } - void sx128x::setSignalBandwidth(uint32_t sbw) { if (sbw <= 203.125E3) { _bw = 0x34; } else if (sbw <= 406.25E3) { _bw = 0x26; } @@ -872,40 +843,22 @@ void sx128x::setCodingRate4(int denominator) { setModulationParams(_sf, _bw, _cr); } +void sx128x::handleLowDataRate() { } // TODO: Is this needed for SX1280? +void sx128x::optimizeModemSensitivity() { } // TODO: Check if there's anything the sx1280 can do here uint8_t sx128x::getCodingRate4() { return _cr + 4; } - -void sx128x::setPreambleLength(long length) { - _preambleLength = length; - setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode); -} - -// TODO: Implement -void sx128x::setSyncWord(int sw) { } - -// TODO: need to check how to implement on sx1280 -void sx128x::enableTCXO() { } - -// TODO: need to check how to implement on sx1280 -void sx128x::disableTCXO() { } - +void sx128x::setPreambleLength(long length) { _preambleLength = length; setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode); } +void sx128x::setSyncWord(int sw) { } // TODO: Implement +void sx128x::enableTCXO() { } // TODO: Need to check how to implement on sx1280 +void sx128x::disableTCXO() { } // TODO: Need to check how to implement on sx1280 void sx128x::sleep() { uint8_t byte = 0x00; executeOpcode(OP_SLEEP_8X, &byte, 1); } - uint8_t sx128x::getTxPower() { return _txp; } - uint8_t sx128x::getSpreadingFactor() { return _sf; } - void sx128x::enableCrc() { _crcMode = 0x20; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } - void sx128x::disableCrc() { _crcMode = 0; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } - void sx128x::setSPIFrequency(uint32_t frequency) { _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); } - void sx128x::explicitHeaderMode() { _implicitHeaderMode = 0; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } - void sx128x::implicitHeaderMode() { _implicitHeaderMode = 0x80; setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); } +void sx128x::dumpRegisters(Stream& out) { for (int i = 0; i < 128; i++) { out.print("0x"); out.print(i, HEX); out.print(": 0x"); out.println(readRegister(i), HEX); } } -void sx128x::dumpRegisters(Stream& out) { - for (int i = 0; i < 128; i++) { out.print("0x"); out.print(i, HEX); out.print(": 0x"); out.println(readRegister(i), HEX); } -} - -sx128x sx128x_modem; \ No newline at end of file +sx128x sx128x_modem; +#endif \ No newline at end of file diff --git a/sx128x.h b/sx128x.h index 86f3238..203a265 100644 --- a/sx128x.h +++ b/sx128x.h @@ -1,9 +1,6 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. +// Copyright Sandeep Mistry, Mark Qvist and Jacob Eva. // Licensed under the MIT license. -// Modifications and additions copyright 2024 by Mark Qvist -// Obviously still under the MIT license. - #ifndef SX128X_H #define SX128X_H @@ -11,18 +8,16 @@ #include #include "Modem.h" -#define LORA_DEFAULT_SS_PIN 10 -#define LORA_DEFAULT_RESET_PIN 9 -#define LORA_DEFAULT_DIO0_PIN 2 +#define LORA_DEFAULT_SS_PIN 10 +#define LORA_DEFAULT_RESET_PIN 9 +#define LORA_DEFAULT_DIO0_PIN 2 #define LORA_DEFAULT_RXEN_PIN -1 #define LORA_DEFAULT_TXEN_PIN -1 #define LORA_DEFAULT_BUSY_PIN -1 -#define LORA_MODEM_TIMEOUT_MS 15E3 - -#define PA_OUTPUT_RFO_PIN 0 -#define PA_OUTPUT_PA_BOOST_PIN 1 - -#define RSSI_OFFSET 157 +#define LORA_MODEM_TIMEOUT_MS 15E3 +#define PA_OUTPUT_RFO_PIN 0 +#define PA_OUTPUT_PA_BOOST_PIN 1 +#define RSSI_OFFSET 157 class sx128x : public Stream { public: