Added support for T3S3 SX1280

master
Mark Qvist 2 months ago
parent 4e251cd186
commit 35a4b6ff4e
  1. 448
      sx128x.cpp
  2. 1
      sx128x.h

@ -38,6 +38,7 @@
#define ISR_VECT #define ISR_VECT
#endif #endif
// SX128x registers
#define OP_RF_FREQ_8X 0x86 #define OP_RF_FREQ_8X 0x86
#define OP_SLEEP_8X 0x84 #define OP_SLEEP_8X 0x84
#define OP_STANDBY_8X 0x80 #define OP_STANDBY_8X 0x80
@ -111,34 +112,52 @@ sx128x::sx128x() :
setTimeout(0); setTimeout(0);
} }
void ISR_VECT sx128x::onDio0Rise() { sx128x_modem.handleDio0Rise(); } bool ISR_VECT sx128x::getPacketValidity() {
void sx128x::handleDio0Rise() {
uint8_t buf[2]; uint8_t buf[2];
buf[0] = 0x00; buf[0] = 0x00;
buf[1] = 0x00; buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2); executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2); executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_8X) == 0) { if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_8X) == 0) {
// received a packet return true;
_packetIndex = 0; } else {
return false;
}
}
uint8_t rxbuf[2] = {0}; void ISR_VECT sx128x::onDio0Rise() {
executeOpcodeRead(OP_RX_BUFFER_STATUS_8X, rxbuf, 2); BaseType_t int_status = taskENTER_CRITICAL_FROM_ISR();
if (sx128x_modem.getPacketValidity()) { sx128x_modem.handleDio0Rise(); }
// On the SX1280, there is a bug which can cause the busy line
// to remain high if a high amount of packets are received when
// in continuous RX mode. This is documented as Errata 16.1 in
// the SX1280 datasheet v3.2 (page 149)
// Therefore, the modem is set into receive mode each time a packet is received.
sx128x_modem.receive();
taskEXIT_CRITICAL_FROM_ISR(int_status);
}
_rxPacketLength = rxbuf[0]; void sx128x::handleDio0Rise() {
_fifo_rx_addr_ptr = rxbuf[1]; // received a packet
readBuffer(_packet, _rxPacketLength); _packetIndex = 0;
// On the SX1280, there is a bug which can cause the busy line uint8_t rxbuf[2] = {0};
// to remain high if a high amount of packets are received when executeOpcodeRead(OP_RX_BUFFER_STATUS_8X, rxbuf, 2);
// in continuous RX mode. This is documented as Errata 16.1 in
// the SX1280 datasheet v3.2 (page 149) // If implicit header mode is enabled, read packet length as payload length instead.
// Therefore, the modem is set into receive mode each time a packet is received. // See SX1280 datasheet v3.2, page 92
receive(0); if (_implicitHeaderMode == 0x80) {
_rxPacketLength = _payloadLength;
} else {
_rxPacketLength = rxbuf[0];
}
if (_onReceive) { _onReceive(_rxPacketLength); } if (_onReceive) {
_onReceive(_rxPacketLength);
} }
} }
@ -209,14 +228,24 @@ uint8_t ISR_VECT sx128x::singleTransfer(uint8_t opcode, uint16_t address, uint8_
return response; return response;
} }
void sx128x::rxAntEnable() { void sx128x::rxAntEnable()
if (_txen != -1) { digitalWrite(_txen, LOW); } {
if (_rxen != -1) { digitalWrite(_rxen, HIGH); } if (_txen != -1) {
digitalWrite(_txen, LOW);
}
if (_rxen != -1) {
digitalWrite(_rxen, HIGH);
}
} }
void sx128x::txAntEnable() { void sx128x::txAntEnable()
if (_txen != -1) { digitalWrite(_txen, HIGH); } {
if (_rxen != -1) { digitalWrite(_rxen, LOW); } if (_txen != -1) {
digitalWrite(_txen, HIGH);
}
if (_rxen != -1) {
digitalWrite(_rxen, LOW);
}
} }
void sx128x::loraMode() { void sx128x::loraMode() {
@ -341,29 +370,23 @@ void sx128x::setPacketParams(uint32_t preamble, uint8_t headermode, uint8_t leng
// because there is no access to these registers on the sx1280, we have // because there is no access to these registers on the sx1280, we have
// to set all these parameters at once or not at all. // to set all these parameters at once or not at all.
uint8_t buf[7]; uint8_t buf[7];
// calculate exponent and mantissa values for modem // calculate exponent and mantissa values for modem
// uint8_t e = 1; uint8_t e = 1;
// uint8_t m = 1; uint8_t m = 1;
// uint32_t preamblelen; uint32_t preamblelen;
// while (e <= 15) { while (e <= 15) {
// while (m <= 15) { while (m <= 15) {
// preamblelen = m * (pow(2,e)); preamblelen = m * (pow(2,e));
// if (preamblelen >= preamble) break; if (preamblelen >= preamble) break;
// m++; m++;
// } }
// if (preamblelen >= preamble) break; if (preamblelen >= preamble) break;
// m = 0; m = 0;
// e++; e++;
// } }
// Serial.printf("Calculated preamble: %d\r\n", preamblelen); buf[0] = (e << 4) | m;
// Serial.printf("Reg value: %d\r\n", (e << 4) | m);
// TODO: Remove / clean
//buf[0] = (e << 4) | m;
buf[0] = 0x1C;
buf[1] = headermode; buf[1] = headermode;
buf[2] = length; buf[2] = length;
buf[3] = crc; buf[3] = crc;
@ -402,7 +425,9 @@ int sx128x::begin(unsigned long frequency)
loraMode(); loraMode();
rxAntEnable(); rxAntEnable();
setFrequency(_frequency); Serial.printf("Setting freq to %d\r\n", _frequency);
Serial.printf("Should be %d\r\n", frequency);
setFrequency(frequency);
// set LNA boost // set LNA boost
// todo: implement this // todo: implement this
@ -537,14 +562,6 @@ uint8_t sx128x::packetRssiRaw() {
return buf[0]; return buf[0];
} }
int ISR_VECT sx128x::packetRssi() {
// may need more calculations here
uint8_t buf[5] = {0};
executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
int pkt_rssi = -buf[0] / 2;
return pkt_rssi;
}
int ISR_VECT sx128x::packetRssi(uint8_t pkt_snr_raw) { int ISR_VECT sx128x::packetRssi(uint8_t pkt_snr_raw) {
// may need more calculations here // may need more calculations here
uint8_t buf[5] = {0}; uint8_t buf[5] = {0};
@ -561,7 +578,7 @@ uint8_t ISR_VECT sx128x::packetSnrRaw() {
float ISR_VECT sx128x::packetSnr() { float ISR_VECT sx128x::packetSnr() {
uint8_t buf[5] = {0}; uint8_t buf[5] = {0};
executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 3); executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
return float(buf[1]) * 0.25; return float(buf[1]) * 0.25;
} }
@ -590,17 +607,41 @@ size_t sx128x::write(const uint8_t *buffer, size_t size)
return size; return size;
} }
int ISR_VECT sx128x::available() { return _rxPacketLength - _packetIndex; } int ISR_VECT sx128x::available()
{
return _rxPacketLength - _packetIndex;
}
int ISR_VECT sx128x::read() int ISR_VECT sx128x::read()
{ {
if (!available()) { if (!available()) {
return -1; return -1;
} }
// if received new packet
if (_packetIndex == 0) {
uint8_t rxbuf[2] = {0};
executeOpcodeRead(OP_RX_BUFFER_STATUS_8X, rxbuf, 2);
int size;
// If implicit header mode is enabled, read packet length as payload length instead.
// See SX1280 datasheet v3.2, page 92
if (_implicitHeaderMode == 0x80) {
size = _payloadLength;
} else {
size = rxbuf[0];
}
_fifo_rx_addr_ptr = rxbuf[1];
uint8_t byte = _packet[_packetIndex]; if (size > 255) {
_packetIndex++; size = 255;
return byte; }
readBuffer(_packet, size);
}
uint8_t byte = _packet[_packetIndex];
_packetIndex++;
return byte;
} }
int sx128x::peek() int sx128x::peek()
@ -650,10 +691,9 @@ void sx128x::onReceive(void(*callback)(int)) {
executeOpcode(OP_SET_IRQ_FLAGS_8X, buf, 8); executeOpcode(OP_SET_IRQ_FLAGS_8X, buf, 8);
#ifdef SPI_HAS_NOTUSINGINTERRUPT #ifdef SPI_HAS_NOTUSINGINTERRUPT
_spiModem->usingInterrupt(digitalPinToInterrupt(_dio0)); SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
#endif #endif
// extern void onDio0Rise();
attachInterrupt(digitalPinToInterrupt(_dio0), onDio0Rise, RISING); attachInterrupt(digitalPinToInterrupt(_dio0), onDio0Rise, RISING);
} else { } else {
@ -679,13 +719,13 @@ void sx128x::receive(int size)
rxAntEnable(); rxAntEnable();
// On the SX1280, there is a bug which can cause the busy line // On the SX1280, there is a bug which can cause the busy line
// to remain high if a high amount of packets are received when // to remain high if a high amount of packets are received when
// in continuous RX mode. This is documented as Errata 16.1 in // in continuous RX mode. This is documented as Errata 16.1 in
// the SX1280 datasheet v3.2 (page 149) // the SX1280 datasheet v3.2 (page 149)
// Therefore, the modem is set to single RX mode below instead. // Therefore, the modem is set to single RX mode below instead.
uint8_t mode[3] = {0}; // single RX mode uint8_t mode[3] = {0}; // single RX mode
executeOpcode(OP_RX_8X, mode, 3); executeOpcode(OP_RX_8X, mode, 3);
} }
void sx128x::standby() void sx128x::standby()
@ -726,7 +766,7 @@ void sx128x::setPins(int ss, int reset, int dio0, int busy, int rxen, int txen)
void sx128x::setTxPower(int level, int outputPin) { void sx128x::setTxPower(int level, int outputPin) {
uint8_t tx_buf[2]; uint8_t tx_buf[2];
#if BOARD_VARIANT == MODEL_13 #if BOARD_VARIANT == MODEL_13 || BOARD_VARIANT == MODEL_21
// RAK4631 with WisBlock SX1280 module (LIBSYS002) // RAK4631 with WisBlock SX1280 module (LIBSYS002)
if (level > 27) { if (level > 27) {
level = 27; level = 27;
@ -743,73 +783,73 @@ void sx128x::setTxPower(int level, int outputPin) {
reg_value = -18; reg_value = -18;
break; break;
case 1: case 1:
reg_value = -17; reg_value = -16;
break; break;
case 2: case 2:
reg_value = -16; reg_value = -15;
break; break;
case 3: case 3:
reg_value = -15; reg_value = -14;
break; break;
case 4: case 4:
reg_value = -14; reg_value = -13;
break; break;
case 5: case 5:
reg_value = -13; reg_value = -12;
break; break;
case 6: case 6:
reg_value = -12; reg_value = -11;
break; break;
case 7: case 7:
reg_value = -10; reg_value = -9;
break; break;
case 8: case 8:
reg_value = -9; reg_value = -8;
break; break;
case 9: case 9:
reg_value = -8; reg_value = -7;
break; break;
case 10: case 10:
reg_value = -7; reg_value = -6;
break; break;
case 11: case 11:
reg_value = -6; reg_value = -5;
break; break;
case 12: case 12:
reg_value = -5; reg_value = -4;
break; break;
case 13: case 13:
reg_value = -4; reg_value = -3;
break; break;
case 14: case 14:
reg_value = -3; reg_value = -2;
break; break;
case 15: case 15:
reg_value = -2; reg_value = -1;
break; break;
case 16: case 16:
reg_value = -1; reg_value = 0;
break; break;
case 17: case 17:
reg_value = 0; reg_value = 1;
break; break;
case 18: case 18:
reg_value = 1; reg_value = 2;
break; break;
case 19: case 19:
reg_value = 2; reg_value = 3;
break; break;
case 20: case 20:
reg_value = 3; reg_value = 4;
break; break;
case 21: case 21:
reg_value = 4; reg_value = 5;
break; break;
case 22: case 22:
reg_value = 5; reg_value = 6;
break; break;
case 23: case 23:
reg_value = 6; reg_value = 7;
break; break;
case 24: case 24:
reg_value = 8; reg_value = 8;
@ -828,103 +868,103 @@ void sx128x::setTxPower(int level, int outputPin) {
break; break;
} }
tx_buf[0] = reg_value; 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); executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2);
#elif BOARD_VARIANT == MODEL_AC
// T3S3 SX1280 PA // T3S3 SX1280 PA
#elif BOARD_VARIANT == MODEL_AB if (level > 20) { level = 20; }
if (level > 20) { level = 20; } else if (level < 0) { level = 0; }
else if (level < 0) { level = 0; }
_txp = level;
_txp = level;
int reg_value; int reg_value;
switch (level) { switch (level) {
/*case 0: /*case 0:
reg_value = -18; reg_value = -18;
break; break;
case 1: case 1:
reg_value = -17; reg_value = -17;
break; break;
case 2: case 2:
reg_value = -16; reg_value = -16;
break; break;
case 3: case 3:
reg_value = -15; reg_value = -15;
break; break;
case 4: case 4:
reg_value = -14; reg_value = -14;
break; break;
case 5: case 5:
reg_value = -13; reg_value = -13;
break; break;
case 6: case 6:
reg_value = -12; reg_value = -12;
break; break;
case 7: case 7:
reg_value = -10; reg_value = -10;
break; break;
case 8: case 8:
reg_value = -9; reg_value = -9;
break; break;
case 9: case 9:
reg_value = -8; reg_value = -8;
break; break;
case 10: case 10:
reg_value = -7; reg_value = -7;
break; break;
case 11: case 11:
reg_value = -6; reg_value = -6;
break; break;
case 12: case 12:
reg_value = -5; reg_value = -5;
break; break;
case 13: case 13:
reg_value = -4; reg_value = -4;
break; break;
case 14: case 14:
reg_value = -3; reg_value = -3;
break; break;
case 15: case 15:
reg_value = -2; reg_value = -2;
break; break;
case 16: case 16:
reg_value = -1; reg_value = -1;
break; break;
case 17: case 17:
reg_value = 0; reg_value = 0;
break; break;
case 18: case 18:
reg_value = 1; reg_value = 1;
break; break;
case 19: case 19:
reg_value = 2; reg_value = 2;
break;*/ break;*/
case 20: case 20:
reg_value = 3; reg_value = 3;
break; break;
default: default:
reg_value = 0; reg_value = 0;
break; break;
} }
tx_buf[0] = reg_value;
tx_buf[1] = 0xE0; // ramping time - 20 microseconds
// For SX1280 boards with no specific PA requirements tx_buf[0] = reg_value;
tx_buf[1] = 0xE0; // ramping time - 20 microseconds
#else #else
if (level > 13) { // For SX1280 boards with no specific PA requirements
level = 13; if (level > 13) {
} else if (level < -18) { level = 13;
level = -18; } else if (level < -18) {
} level = -18;
}
_txp = level; _txp = level;
tx_buf[0] = level; tx_buf[0] = level + 18;
tx_buf[1] = 0xE0; // ramping time - 20 microseconds tx_buf[1] = 0xE0; // ramping time - 20 microseconds
#endif #endif
executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2); executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2);
} }
@ -977,13 +1017,16 @@ uint32_t sx128x::getSignalBandwidth() {
return 0; return 0;
} }
// todo: do i need this?? void sx128x::handleLowDataRate(){
void sx128x::handleLowDataRate() { } // todo: do i need this??
}
// todo: check if there's anything the sx1280 can do here void sx128x::optimizeModemSensitivity(){
void sx128x::optimizeModemSensitivity() { } // todo: check if there's anything the sx1280 can do here
}
void sx128x::setSignalBandwidth(uint32_t sbw) { void sx128x::setSignalBandwidth(uint32_t sbw)
{
if (sbw <= 203.125E3) { if (sbw <= 203.125E3) {
_bw = 0x34; _bw = 0x34;
} else if (sbw <= 406.25E3) { } else if (sbw <= 406.25E3) {
@ -1018,9 +1061,13 @@ void sx128x::setCodingRate4(int denominator)
setModulationParams(_sf, _bw, _cr); setModulationParams(_sf, _bw, _cr);
} }
uint8_t sx128x::getCodingRate4() { return _cr + 4; } uint8_t sx128x::getCodingRate4()
{
return _cr + 4;
}
void sx128x::setPreambleLength(long length) { void sx128x::setPreambleLength(long length)
{
_preambleLength = length; _preambleLength = length;
setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode);
} }
@ -1030,21 +1077,21 @@ void sx128x::setSyncWord(int sw)
// not implemented // not implemented
} }
void sx128x::enableCrc() void sx128x::enableCrc() {
{
_crcMode = 0x20; _crcMode = 0x20;
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
} }
void sx128x::disableCrc() void sx128x::disableCrc() {
{
_crcMode = 0; _crcMode = 0;
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
} }
byte sx128x::random() uint8_t sx128x::random() {
{
// todo: implement // todo: implement
return 0x4; //chosen by fair die roll
//guarenteed to be random
//https://xkcd.com/221/
} }
void sx128x::setSPIFrequency(uint32_t frequency) void sx128x::setSPIFrequency(uint32_t frequency)
@ -1075,15 +1122,4 @@ void sx128x::implicitHeaderMode()
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
} }
void sx128x::clearIRQStatus() {
uint8_t buf[2];
buf[0] = 0x00;
buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
}
sx128x sx128x_modem; sx128x sx128x_modem;

@ -106,6 +106,7 @@ private:
void explicitHeaderMode(); void explicitHeaderMode();
void implicitHeaderMode(); void implicitHeaderMode();
bool getPacketValidity();
void handleDio0Rise(); void handleDio0Rise();
uint8_t readRegister(uint16_t address); uint8_t readRegister(uint16_t address);

Loading…
Cancel
Save