ex1262 receiving kinda works

This commit is contained in:
geeksville 2020-04-30 12:37:58 -07:00
parent 11b79a942d
commit 22720e9f63
7 changed files with 98 additions and 292 deletions

2
proto

@ -1 +1 @@
Subproject commit e570ee9836949d9f420fd19cc59a2595c8669a6e
Subproject commit bd002e5a144f209e42c97b64fea9a05a2e513b28

View File

@ -289,6 +289,8 @@ void NodeDB::updateFrom(const MeshPacket &mp)
info->position.time = mp.rx_time;
}
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
if (p.has_position) {
// we carefully preserve the old time, because we always trust our local timestamps more
uint32_t oldtime = info->position.time;

View File

@ -102,8 +102,7 @@ typedef struct _NodeInfo {
User user;
bool has_position;
Position position;
int32_t snr;
int32_t frequency_error;
float snr;
} NodeInfo;
typedef struct _RadioConfig {
@ -129,8 +128,8 @@ typedef struct _MeshPacket {
bool has_payload;
SubPacket payload;
uint32_t rx_time;
int32_t rx_snr;
uint32_t id;
float rx_snr;
} MeshPacket;
typedef struct _DeviceState {
@ -198,7 +197,7 @@ typedef struct _ToRadio {
#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0}
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0}
#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}, false, MeshPacket_init_default, 0}
#define DebugString_init_default {""}
@ -213,7 +212,7 @@ typedef struct _ToRadio {
#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0}
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0}
#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}, false, MeshPacket_init_zero, 0}
#define DebugString_init_zero {""}
@ -263,8 +262,7 @@ typedef struct _ToRadio {
#define NodeInfo_num_tag 1
#define NodeInfo_user_tag 2
#define NodeInfo_position_tag 3
#define NodeInfo_snr_tag 5
#define NodeInfo_frequency_error_tag 6
#define NodeInfo_snr_tag 7
#define RadioConfig_preferences_tag 1
#define RadioConfig_channel_settings_tag 2
#define SubPacket_position_tag 1
@ -275,8 +273,8 @@ typedef struct _ToRadio {
#define MeshPacket_to_tag 2
#define MeshPacket_payload_tag 3
#define MeshPacket_rx_time_tag 4
#define MeshPacket_rx_snr_tag 5
#define MeshPacket_id_tag 6
#define MeshPacket_rx_snr_tag 7
#define DeviceState_radio_tag 1
#define DeviceState_my_node_tag 2
#define DeviceState_owner_tag 3
@ -342,8 +340,8 @@ X(a, STATIC, SINGULAR, INT32, from, 1) \
X(a, STATIC, SINGULAR, INT32, to, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, payload, 3) \
X(a, STATIC, SINGULAR, UINT32, rx_time, 4) \
X(a, STATIC, SINGULAR, SINT32, rx_snr, 5) \
X(a, STATIC, SINGULAR, UINT32, id, 6)
X(a, STATIC, SINGULAR, UINT32, id, 6) \
X(a, STATIC, SINGULAR, FLOAT, rx_snr, 7)
#define MeshPacket_CALLBACK NULL
#define MeshPacket_DEFAULT NULL
#define MeshPacket_payload_MSGTYPE SubPacket
@ -385,8 +383,7 @@ X(a, STATIC, SINGULAR, BOOL, promiscuous_mode, 101)
X(a, STATIC, SINGULAR, INT32, num, 1) \
X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \
X(a, STATIC, SINGULAR, INT32, snr, 5) \
X(a, STATIC, SINGULAR, INT32, frequency_error, 6)
X(a, STATIC, SINGULAR, FLOAT, snr, 7)
#define NodeInfo_CALLBACK NULL
#define NodeInfo_DEFAULT NULL
#define NodeInfo_user_MSGTYPE User
@ -494,16 +491,16 @@ extern const pb_msgdesc_t ToRadio_msg;
#define User_size 72
/* RouteDiscovery_size depends on runtime parameters */
#define SubPacket_size 383
#define MeshPacket_size 426
#define MeshPacket_size 425
#define ChannelSettings_size 44
#define RadioConfig_size 120
#define RadioConfig_UserPreferences_size 72
#define NodeInfo_size 155
#define NodeInfo_size 138
#define MyNodeInfo_size 85
#define DeviceState_size 19502
#define DeviceState_size 18925
#define DebugString_size 258
#define FromRadio_size 435
#define ToRadio_size 429
#define FromRadio_size 434
#define ToRadio_size 428
#ifdef __cplusplus
} /* extern "C" */

View File

@ -1,5 +1,9 @@
#include "RadioLibInterface.h"
#include "MeshTypes.h"
#include "mesh-pb-constants.h"
#include <configuration.h>
#include <pb_decode.h>
#include <pb_encode.h>
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
@ -100,14 +104,19 @@ void RadioLibInterface::loop()
else
assert(0);
// First send any outgoing packets we have ready
MeshPacket *txp = txQueue.dequeuePtr(0);
if (txp)
startSend(txp);
else {
// Nothing to send, let's switch back to receive mode
// FIXME - RH_RF95::setModeRx();
}
startNextWork();
}
}
void RadioLibInterface::startNextWork()
{
// First send any outgoing packets we have ready
MeshPacket *txp = txQueue.dequeuePtr(0);
if (txp)
startSend(txp);
else {
// Nothing to send, let's switch back to receive mode
startReceive();
}
}
@ -125,69 +134,39 @@ void RadioLibInterface::handleTransmitInterrupt()
void RadioLibInterface::handleReceiveInterrupt()
{
// FIXME
}
// read the number of actually received bytes
size_t length = iface.getPacketLength();
#if 0
// After doing standard behavior, check to see if a new packet arrived or one was sent and start a new send or receive as
// necessary
void CustomRF95::handleInterrupt()
{
RH_RF95::handleInterrupt();
enableInterrupt(); // Let ISR run again
int state = iface.readData(radiobuf, length);
if (state != ERR_NONE) {
DEBUG_MSG("ignoring received packet due to error=%d\n", state);
} else {
// Skip the 4 headers that are at the beginning of the rxBuf
int32_t payloadLen = length - sizeof(PacketHeader);
const uint8_t *payload = radiobuf + sizeof(PacketHeader);
const PacketHeader *h = (PacketHeader *)radiobuf;
if (_mode == RHModeIdle) // We are now done sending or receiving
{
// fixme check for short packets
// If we just finished receiving a packet, forward it into a queue
if (_rxBufValid) {
// We received a packet
MeshPacket *mp = packetPool.allocZeroed();
// Skip the 4 headers that are at the beginning of the rxBuf
size_t payloadLen = _bufLen - RH_RF95_HEADER_LEN;
uint8_t *payload = _buf + RH_RF95_HEADER_LEN;
SubPacket *p = &mp->payload;
// FIXME - throws exception if called in ISR context: frequencyError() - probably the floating point math
int32_t freqerr = -1, snr = lastSNR();
// DEBUG_MSG("Received packet from mesh src=0x%x,dest=0x%x,id=%d,len=%d rxGood=%d,rxBad=%d,freqErr=%d,snr=%d\n",
// srcaddr, destaddr, id, rxlen, rf95.rxGood(), rf95.rxBad(), freqerr, snr);
mp->from = h->from;
mp->to = h->to;
mp->id = h->id;
MeshPacket *mp = packetPool.allocZeroed();
if (!pb_decode_from_bytes(payload, payloadLen, SubPacket_fields, p)) {
DEBUG_MSG("Invalid protobufs in received mesh packet, discarding.\n");
packetPool.release(mp);
} else {
// parsing was successful, queue for our recipient
mp->has_payload = true;
SubPacket *p = &mp->payload;
mp->from = _rxHeaderFrom;
mp->to = _rxHeaderTo;
mp->id = _rxHeaderId;
//_rxHeaderId = _buf[2];
//_rxHeaderFlags = _buf[3];
// If we already have an entry in the DB for this nodenum, goahead and hide the snr/freqerr info there.
// Note: we can't create it at this point, because it might be a bogus User node allocation. But odds are we will
// already have a record we can hide this debugging info in.
NodeInfo *info = nodeDB.getNode(mp->from);
if (info) {
info->snr = snr;
info->frequency_error = freqerr;
}
if (!pb_decode_from_bytes(payload, payloadLen, SubPacket_fields, p)) {
packetPool.release(mp);
} else {
// parsing was successful, queue for our recipient
mp->has_payload = true;
deliverToReceiver(mp);
}
clearRxBuf(); // This message accepted and cleared
deliverToReceiver(mp);
}
handleIdleISR();
}
}
#endif
/** start an immediate transmit */
void RadioLibInterface::startSend(MeshPacket *txp)
@ -201,198 +180,3 @@ void RadioLibInterface::startSend(MeshPacket *txp)
enableInterrupt(isrTxLevel0);
}
/**
*
*
*
// include the library
// save transmission state between loops
int transmissionState = ERR_NONE;
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
// carrier frequency: 434.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 9
// coding rate: 7
// sync word: 0x12 (private network)
// output power: 14 dBm
// current limit: 60 mA
// preamble length: 8 symbols
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
// regulator: DC-DC (set to true to use LDO)
// CRC: enabled
int state = lora.begin();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// set the function that will be called
// when packet transmission is finished
lora.setDio1Action(setFlag);
// start transmitting the first packet
Serial.print(F("[SX1262] Sending first packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
transmissionState = lora.startTransmit("Hello World!");
// you can also transmit byte array up to 256 bytes long
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
state = lora.startTransmit(byteArr, 8);
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// disable interrupt when it's not needed
volatile bool enableInterrupt = true;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void)
{
// check if the interrupt is enabled
if (!enableInterrupt) {
return;
}
// we sent a packet, set the flag
transmittedFlag = true;
}
void loop()
{
// check if the previous transmission finished
if (transmittedFlag) {
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
transmittedFlag = false;
if (transmissionState == ERR_NONE) {
// packet was successfully sent
Serial.println(F("transmission finished!"));
// NOTE: when using interrupt-driven transmit method,
// it is not possible to automatically measure
// transmission data rate using getDataRate()
} else {
Serial.print(F("failed, code "));
Serial.println(transmissionState);
}
// wait a second before transmitting again
delay(1000);
// send another one
Serial.print(F("[SX1262] Sending another packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
transmissionState = lora.startTransmit("Hello World!");
// you can also transmit byte array up to 256 bytes long
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
int state = lora.startTransmit(byteArr, 8);
// we're ready to send more packets,
// enable interrupt service routine
enableInterrupt = true;
}
}
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void)
{
// check if the interrupt is enabled
if (!enableInterrupt) {
return;
}
// we got a packet, set the flag
receivedFlag = true;
}
void loop()
{
// check if the flag is set
if (receivedFlag) {
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
receivedFlag = false;
// you can read received data as an Arduino String
String str;
int state = lora.readData(str);
// you can also read received data as byte array
byte byteArr[8];
int state = lora.readData(byteArr, 8);
if (state == ERR_NONE) {
// packet was successfully received
Serial.println(F("[SX1262] Received packet!"));
// print data of the packet
Serial.print(F("[SX1262] Data:\t\t"));
Serial.println(str);
// print RSSI (Received Signal Strength Indicator)
Serial.print(F("[SX1262] RSSI:\t\t"));
Serial.print(lora.getRSSI());
Serial.println(F(" dBm"));
// print SNR (Signal-to-Noise Ratio)
Serial.print(F("[SX1262] SNR:\t\t"));
Serial.print(lora.getSNR());
Serial.println(F(" dB"));
} else if (state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.println(F("CRC error!"));
} else {
// some other error occurred
Serial.print(F("failed, code "));
Serial.println(state);
}
// put module back to listen mode
lora.startReceive();
// we're ready to receive more packets,
// enable interrupt service routine
enableInterrupt = true;
}
}
*/

View File

@ -26,7 +26,7 @@ class RadioLibInterface : public RadioInterface
/**
* Raw ISR handler that just calls our polymorphic method
*/
static void isrRxLevel0(), isrTxLevel0();
static void isrTxLevel0();
protected:
float bw = 125;
@ -39,7 +39,7 @@ class RadioLibInterface : public RadioInterface
*/
uint8_t syncWord = SX126X_SYNC_WORD_PRIVATE;
float currentLimit = 100; // FIXME
float currentLimit = 100; // FIXME
uint16_t preambleLength = 8; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving
Module module; // The HW interface to the radio
@ -78,13 +78,18 @@ class RadioLibInterface : public RadioInterface
/// \param[in] thisAddress The address of this node.
virtual void setThisAddress(uint8_t thisAddress) {}
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool init() { return true; }
virtual void loop(); // Idle processing
private:
/** start an immediate transmit */
void startSend(MeshPacket *txp);
/** start a queued transmit (if we have one), else start receiving */
void startNextWork();
void handleTransmitInterrupt();
void handleReceiveInterrupt();
protected:
/**
* Convert our modemConfig enum into wf, sf, etc...
@ -94,9 +99,13 @@ class RadioLibInterface : public RadioInterface
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
virtual bool canSendImmediately() = 0;
/** start an immediate transmit */
void startSend(MeshPacket *txp);
/**
* Start waiting to receive a message
*/
virtual void startReceive() = 0;
void handleTransmitInterrupt();
void handleReceiveInterrupt();
/**
* Raw ISR handler that just calls our polymorphic method
*/
static void isrRxLevel0();
};

View File

@ -12,9 +12,6 @@ SX1262Interface::SX1262Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RA
/// \return true if initialisation succeeded.
bool SX1262Interface::init()
{
if (!RadioLibInterface::init())
return false;
// FIXME, move this to main
SPI.begin();
@ -30,7 +27,10 @@ bool SX1262Interface::init()
if (res == ERR_NONE)
res = lora.setCRC(SX126X_LORA_CRC_ON);
return res == ERR_NONE;
if (res == ERR_NONE)
startReceive(); // start receiving
return res;
}
bool SX1262Interface::reconfigure()
@ -68,9 +68,18 @@ bool SX1262Interface::reconfigure()
err = lora.setOutputPower(power);
assert(err == ERR_NONE);
assert(0); // FIXME - set mode back to receive?
startReceive(); // restart receiving
return true;
return ERR_NONE;
}
void SX1262Interface::startReceive()
{
int err = lora.startReceive();
assert(err == ERR_NONE);
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
@ -86,5 +95,5 @@ bool SX1262Interface::canSendImmediately()
DEBUG_MSG("immediate send on mesh fr=0x%x,to=0x%x,id=%d\n (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id,
txGood(), rxGood(), rxBad());
}
#endif
#endif
}

View File

@ -32,4 +32,9 @@ class SX1262Interface : public RadioLibInterface
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
virtual bool canSendImmediately();
/**
* Start waiting to receive a message
*/
virtual void startReceive();
};