You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
4.8 KiB
245 lines
4.8 KiB
3 years ago
|
#include <SPI.h>
|
||
|
#include "LoRa.h"
|
||
|
#include "Config.h"
|
||
|
#include "KISS.h"
|
||
|
|
||
|
|
||
|
void setup() {
|
||
|
// put your setup code here, to run once:
|
||
|
Serial.begin(serialBaudRate);
|
||
|
while (!Serial); // Waiting until LoRa32u4 is ready
|
||
|
|
||
|
// Buffers
|
||
|
memset(rxBuffer, 0, sizeof(rxBuffer));
|
||
|
memset(txBuffer, 0, sizeof(txBuffer));
|
||
|
|
||
|
LoRa.setPins(pinNSS, pinNRST, pinDIO0);
|
||
|
|
||
|
startRadio();
|
||
|
}
|
||
|
|
||
|
bool startRadio() {
|
||
|
if (!LoRa.begin(loraFrequency)) {
|
||
|
kissIndicateError(ERROR_INITRADIO);
|
||
|
Serial.println("FAIL");
|
||
|
while(1);
|
||
|
}
|
||
|
else {
|
||
|
Serial.println("SUCCESS");
|
||
|
LoRa.setSpreadingFactor(loraSpreadingFactor);
|
||
|
LoRa.setCodingRate4(loraCodingRate);
|
||
|
LoRa.enableCrc();
|
||
|
LoRa.onReceive(receiveCallback);
|
||
|
LoRa.receive();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void transmit(size_t size) {
|
||
|
size_t written = 0;
|
||
|
|
||
|
if (size > MTU) {
|
||
|
size = MTU;
|
||
|
}
|
||
|
|
||
|
LoRa.beginPacket();
|
||
|
for (size_t i; i < size; i++) {
|
||
|
LoRa.write(txBuffer[i]);
|
||
|
written++;
|
||
|
}
|
||
|
LoRa.endPacket();
|
||
|
|
||
|
LoRa.receive();
|
||
|
}
|
||
|
|
||
|
void serialCallback(uint8_t txByte) {
|
||
|
if (inFrame && txByte == FEND && command == CMD_DATA) {
|
||
|
inFrame = false;
|
||
|
//Serial.println("FULL_KISS");
|
||
|
if (outboundReady) {
|
||
|
kissIndicateError(ERROR_QUEUE_FULL);
|
||
|
}
|
||
|
else {
|
||
|
outboundReady = true;
|
||
|
//Serial.println("RDY_OUT");
|
||
|
}
|
||
|
}
|
||
|
else if (txByte == FEND) {
|
||
|
//Serial.println("KISS_FLAG");
|
||
|
inFrame = true;
|
||
|
command = CMD_UNKNOWN;
|
||
|
frameLength = 0;
|
||
|
}
|
||
|
else if (inFrame && frameLength < MTU) {
|
||
|
// Get command byte
|
||
|
if (frameLength == 0 && command == CMD_UNKNOWN) {
|
||
|
//Serial.println("ACQ_CMD");
|
||
|
command = txByte;
|
||
|
}
|
||
|
else if (command == CMD_DATA) {
|
||
|
if (txByte == FESC) {
|
||
|
escape = true;
|
||
|
}
|
||
|
else {
|
||
|
if (escape) {
|
||
|
if (txByte == TFEND) {
|
||
|
txByte = FEND;
|
||
|
}
|
||
|
if (txByte == TFESC) {
|
||
|
txByte = FESC;
|
||
|
}
|
||
|
escape = false;
|
||
|
}
|
||
|
else {
|
||
|
txBuffer[frameLength++] = txByte;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updateModemStatus() {
|
||
|
uint8_t status = LoRa.modemStatus();
|
||
|
lastStatusUpdate = millis();
|
||
|
if (status & SIG_DETECT == 0x01) {
|
||
|
statSignalDetected = true;
|
||
|
}
|
||
|
else {
|
||
|
statSignalDetected = false;
|
||
|
}
|
||
|
if (status & SIG_SYNCED == 0x01) {
|
||
|
statSignalSynced = true;
|
||
|
}
|
||
|
else {
|
||
|
statSignalSynced = false;
|
||
|
}
|
||
|
if (status & RX_ONGOING == 0x01) {
|
||
|
statRxOngoing = true;
|
||
|
}
|
||
|
else {
|
||
|
statRxOngoing = false;
|
||
|
}
|
||
|
|
||
|
if (statSignalDetected || statSignalSynced || statRxOngoing) {
|
||
|
if (dcdCount < dcdThreshold) {
|
||
|
dcdCount++;
|
||
|
dcd = true;
|
||
|
}
|
||
|
else {
|
||
|
dcd = true;
|
||
|
dcdLed = true;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (dcdCount > 0) {
|
||
|
dcdCount--;
|
||
|
}
|
||
|
else {
|
||
|
dcdLed = false;
|
||
|
}
|
||
|
dcd = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool isOutboundReady() {
|
||
|
return outboundReady;
|
||
|
}
|
||
|
|
||
|
void checkModemStatus() {
|
||
|
if (millis() - lastStatusUpdate >= statusIntervalms) {
|
||
|
updateModemStatus();
|
||
|
}
|
||
|
}
|
||
|
void receiveCallback(int packetSize) {
|
||
|
readLength = 0;
|
||
|
lastRssi = LoRa.packetRssi();
|
||
|
getPacketData(packetSize);
|
||
|
|
||
|
// Send RSSI
|
||
|
Serial.write(FEND);
|
||
|
Serial.write(HW_RSSI);
|
||
|
Serial.write((uint8_t)(lastRssi-rssiOffset));
|
||
|
Serial.write(FEND);
|
||
|
|
||
|
// And then write the entire packet
|
||
|
Serial.write(FEND);
|
||
|
Serial.write((uint8_t)CMD_DATA);
|
||
|
for (int i = 0; i < readLength; i++) {
|
||
|
uint8_t temp = rxBuffer[i];
|
||
|
if (temp == FEND) {
|
||
|
Serial.write(FESC);
|
||
|
temp = TFEND;
|
||
|
}
|
||
|
if (temp == FESC) {
|
||
|
Serial.write(FESC);
|
||
|
temp = TFESC;
|
||
|
}
|
||
|
Serial.write(temp);
|
||
|
}
|
||
|
Serial.write(FEND);
|
||
|
readLength = 0;
|
||
|
}
|
||
|
|
||
|
void escapedSerialWrite (uint8_t bufferByte) {
|
||
|
switch(bufferByte) {
|
||
|
case FEND:
|
||
|
Serial.write(FESC);
|
||
|
Serial.write(TFEND);
|
||
|
break;
|
||
|
case FESC:
|
||
|
Serial.write(FESC);
|
||
|
Serial.write(TFESC);
|
||
|
break;
|
||
|
default:
|
||
|
Serial.write(bufferByte);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void kissIndicateError(uint8_t errorCode) {
|
||
|
Serial.write(FEND);
|
||
|
Serial.write(CMD_ERROR);
|
||
|
Serial.write(errorCode);
|
||
|
Serial.write(FEND);
|
||
|
}
|
||
|
|
||
|
void getPacketData(int packetLength) {
|
||
|
while (packetLength--) {
|
||
|
rxBuffer[readLength++] = LoRa.read();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void loop() {
|
||
|
// put your main code here, to run repeatedly:
|
||
|
checkModemStatus();
|
||
|
if (isOutboundReady() && !SERIAL_READING) {
|
||
|
if (!dcdWaiting) {
|
||
|
updateModemStatus();
|
||
|
}
|
||
|
if (!dcd && !dcdLed) {
|
||
|
if (dcdWaiting)
|
||
|
delay(loraRxTurnaround);
|
||
|
updateModemStatus();
|
||
|
if (!dcd) {
|
||
|
dcdWaiting = false;
|
||
|
outboundReady = false;
|
||
|
//Serial.println("CLR_TRANSMIT");
|
||
|
transmit(frameLength);
|
||
|
}
|
||
|
else {
|
||
|
dcdWaiting = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (Serial.available()) {
|
||
|
SERIAL_READING = true;
|
||
|
char txByte = Serial.read();
|
||
|
serialCallback(txByte);
|
||
|
lastSerialRead = millis();
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
if (SERIAL_READING && millis() - lastSerialRead >= serialReadTimeout) {
|
||
|
SERIAL_READING = false;
|
||
|
}
|
||
|
}
|
||
|
}
|