2020-02-07 06:57:58 +00:00
|
|
|
#include "RH_RF95.h"
|
2020-03-24 20:33:24 +00:00
|
|
|
#include "error.h"
|
2020-02-01 19:25:07 +00:00
|
|
|
#include <RHMesh.h>
|
2020-03-19 02:15:51 +00:00
|
|
|
#include <SPI.h>
|
2020-02-01 19:25:07 +00:00
|
|
|
#include <assert.h>
|
2020-02-01 16:59:16 +00:00
|
|
|
|
|
|
|
#include "MeshRadio.h"
|
2020-02-03 17:13:19 +00:00
|
|
|
#include "NodeDB.h"
|
2020-03-19 02:15:51 +00:00
|
|
|
#include "configuration.h"
|
|
|
|
#include <pb_decode.h>
|
|
|
|
#include <pb_encode.h>
|
2020-02-01 16:59:16 +00:00
|
|
|
|
2020-02-11 19:56:48 +00:00
|
|
|
/**
|
|
|
|
* ## LoRaWAN for North America
|
|
|
|
|
|
|
|
LoRaWAN defines 64, 125 kHz channels from 902.3 to 914.9 MHz increments.
|
|
|
|
|
|
|
|
The maximum output power for North America is +30 dBM.
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
The band is from 902 to 928 MHz. It mentions channel number and its respective channel frequency. All the 13 channels are
|
|
|
|
separated by 2.16 MHz with respect to the adjacent channels. Channel zero starts at 903.08 MHz center frequency.
|
2020-02-11 19:56:48 +00:00
|
|
|
*/
|
2020-02-01 16:59:16 +00:00
|
|
|
|
2020-02-24 02:09:40 +00:00
|
|
|
/// Sometimes while debugging it is useful to set this false, to disable rf95 accesses
|
|
|
|
bool useHardware = true;
|
|
|
|
|
2020-04-01 04:56:35 +00:00
|
|
|
MeshRadio::MeshRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest)
|
|
|
|
: radioIf(_pool, _rxDest) // , manager(radioIf)
|
2020-02-02 20:45:32 +00:00
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
myNodeInfo.num_channels = NUM_CHANNELS;
|
|
|
|
|
|
|
|
// Can't print strings this early - serial not setup yet
|
|
|
|
// DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name);
|
2020-02-02 20:45:32 +00:00
|
|
|
}
|
2020-02-01 16:59:16 +00:00
|
|
|
|
2020-02-02 20:45:32 +00:00
|
|
|
bool MeshRadio::init()
|
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
if (!useHardware)
|
|
|
|
return true;
|
2020-02-24 02:09:40 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
DEBUG_MSG("Starting meshradio init...\n");
|
2020-02-12 21:31:09 +00:00
|
|
|
|
2020-02-05 23:37:58 +00:00
|
|
|
#ifdef RESET_GPIO
|
2020-03-19 02:15:51 +00:00
|
|
|
pinMode(RESET_GPIO, OUTPUT); // Deassert reset
|
|
|
|
digitalWrite(RESET_GPIO, HIGH);
|
|
|
|
|
|
|
|
// pulse reset
|
|
|
|
digitalWrite(RESET_GPIO, LOW);
|
|
|
|
delay(10);
|
|
|
|
digitalWrite(RESET_GPIO, HIGH);
|
|
|
|
delay(10);
|
2020-02-05 23:37:58 +00:00
|
|
|
#endif
|
2020-02-02 20:45:32 +00:00
|
|
|
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setThisAddress(
|
2020-03-19 02:15:51 +00:00
|
|
|
nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor time.
|
2020-02-07 00:07:50 +00:00
|
|
|
|
2020-04-01 04:56:35 +00:00
|
|
|
if (!radioIf.init()) {
|
2020-03-19 02:15:51 +00:00
|
|
|
DEBUG_MSG("LoRa radio init failed\n");
|
|
|
|
DEBUG_MSG("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info\n");
|
|
|
|
return false;
|
|
|
|
}
|
2020-02-01 16:59:16 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// not needed - defaults on
|
|
|
|
// rf95.setPayloadCRC(true);
|
2020-02-08 17:39:26 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
reloadConfig();
|
2020-02-07 06:57:58 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
return true;
|
2020-02-07 06:57:58 +00:00
|
|
|
}
|
|
|
|
|
2020-03-16 00:51:57 +00:00
|
|
|
/** hash a string into an integer
|
2020-03-19 02:15:51 +00:00
|
|
|
*
|
2020-03-16 00:51:57 +00:00
|
|
|
* djb2 by Dan Bernstein.
|
|
|
|
* http://www.cse.yorku.ca/~oz/hash.html
|
|
|
|
*/
|
|
|
|
unsigned long hash(char *str)
|
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
unsigned long hash = 5381;
|
|
|
|
int c;
|
2020-03-16 00:51:57 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
while ((c = *str++) != 0)
|
|
|
|
hash = ((hash << 5) + hash) + (unsigned char)c; /* hash * 33 + c */
|
2020-03-16 00:51:57 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
return hash;
|
2020-03-16 00:51:57 +00:00
|
|
|
}
|
|
|
|
|
2020-02-07 06:57:58 +00:00
|
|
|
void MeshRadio::reloadConfig()
|
|
|
|
{
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setModeIdle(); // Need to be idle before doing init
|
2020-03-19 02:15:51 +00:00
|
|
|
|
|
|
|
// Set up default configuration
|
|
|
|
// No Sync Words in LORA mode.
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setModemConfig(
|
2020-03-19 02:15:51 +00:00
|
|
|
(RH_RF95::ModemConfigChoice)channelSettings.modem_config); // Radio default
|
|
|
|
// setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
|
|
|
|
// rf95.setPreambleLength(8); // Default is 8
|
|
|
|
|
|
|
|
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
|
|
|
|
int channel_num = hash(channelSettings.name) % NUM_CHANNELS;
|
|
|
|
float center_freq = CH0 + CH_SPACING * channel_num;
|
2020-04-01 04:56:35 +00:00
|
|
|
if (!radioIf.setFrequency(center_freq)) {
|
2020-03-19 02:15:51 +00:00
|
|
|
DEBUG_MSG("setFrequency failed\n");
|
|
|
|
assert(0); // fixme panic
|
|
|
|
}
|
|
|
|
|
|
|
|
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
|
|
|
|
|
|
|
|
// The default transmitter power is 13dBm, using PA_BOOST.
|
|
|
|
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
|
|
|
|
// you can set transmitter powers from 5 to 23 dBm:
|
|
|
|
// FIXME - can we do this? It seems to be in the Heltec board.
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setTxPower(channelSettings.tx_power, false);
|
2020-03-19 02:15:51 +00:00
|
|
|
|
2020-03-30 23:05:28 +00:00
|
|
|
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, txpower=%d\n", channelSettings.name, channelSettings.modem_config,
|
2020-03-19 02:15:51 +00:00
|
|
|
channel_num, channelSettings.tx_power);
|
|
|
|
|
|
|
|
// Done with init tell radio to start receiving
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setModeRx();
|
2020-02-19 04:06:01 +00:00
|
|
|
}
|
2020-02-12 16:44:31 +00:00
|
|
|
|
2020-02-02 20:45:32 +00:00
|
|
|
ErrorCode MeshRadio::send(MeshPacket *p)
|
|
|
|
{
|
2020-03-24 20:04:28 +00:00
|
|
|
lastTxStart = millis();
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
if (useHardware)
|
2020-04-01 04:56:35 +00:00
|
|
|
return radioIf.send(p);
|
2020-03-19 02:15:51 +00:00
|
|
|
else {
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.pool.release(p);
|
2020-03-19 02:15:51 +00:00
|
|
|
return ERRNO_OK;
|
|
|
|
}
|
2020-02-01 16:59:16 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 20:04:28 +00:00
|
|
|
#define TX_WATCHDOG_TIMEOUT 30 * 1000
|
|
|
|
|
2020-02-02 20:45:32 +00:00
|
|
|
void MeshRadio::loop()
|
2020-02-01 16:59:16 +00:00
|
|
|
{
|
2020-03-25 18:45:18 +00:00
|
|
|
// It should never take us more than 30 secs to send a packet, if it does, we have a bug, FIXME, move most of this
|
|
|
|
// into CustomRF95
|
2020-03-24 20:04:28 +00:00
|
|
|
uint32_t now = millis();
|
2020-04-01 04:56:35 +00:00
|
|
|
if (lastTxStart != 0 && (now - lastTxStart) > TX_WATCHDOG_TIMEOUT && radioIf.mode() == RHGenericDriver::RHModeTx) {
|
2020-03-24 20:04:28 +00:00
|
|
|
DEBUG_MSG("ERROR! Bug! Tx packet took too long to send, forcing radio into rx mode");
|
2020-04-01 04:56:35 +00:00
|
|
|
radioIf.setModeRx();
|
|
|
|
if (radioIf.sendingPacket) { // There was probably a packet we were trying to send, free it
|
|
|
|
radioIf.pool.release(radioIf.sendingPacket);
|
|
|
|
radioIf.sendingPacket = NULL;
|
2020-03-25 18:45:18 +00:00
|
|
|
}
|
2020-03-24 20:33:24 +00:00
|
|
|
recordCriticalError(ErrTxWatchdog);
|
2020-03-24 20:04:28 +00:00
|
|
|
lastTxStart = 0; // Stop checking for now, because we just warned the developer
|
|
|
|
}
|
2020-02-02 21:29:53 +00:00
|
|
|
}
|