A LoRa APRS node with KISS interface based on a Raspberry Pi Pico
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.

192 lines
5.2 KiB

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "LoRa-RP2040.h"
#include "Config.h"
#include "KISS.h"
bool startRadio();
void getPacketData(int packetLength);
void encode_kiss ();
int main() {
/* Among others, this initializes the USB-serial port at 115200bps 8N1 */
stdio_init_all();
// Buffers
memset(rxBuffer, 0, sizeof(rxBuffer));
memset(txBuffer, 0, sizeof(txBuffer));
sleep_ms(5000);
startRadio();
while (1) {
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
printf("Received packet (RSSI = %idBm)\n",LoRa.packetRssi());
getPacketData(packetSize);
// Check APRS header: must be 0x3C 0xFF 0x01
if (rxBuffer[0] == 0x3C && rxBuffer[1] == 0xFF && rxBuffer[2] == 0x01 ) {
// Shift array three places to left (= remove APRS header)
for (int cnt = 3; cnt < packetSize; cnt++) {
rxBuffer[cnt-3] = rxBuffer[cnt];
}
rxBuffer[packetSize-3] = 0;
printf("%s\n", rxBuffer);
encode_kiss();
} else {
printf("ERROR: No or corrupted APRS frame.\n");
}
}
}
return 0;
}
/*
* Initializes the LoRa module with the parameters set in config.h
*/
bool startRadio()
{
// override the default CS, reset, and IRQ pins (optional)
// LoRa.setPins(7, 6, 1); // set CS, reset, IRQ pin
printf("LoRa settings:\n");
printf("loraFrequency = %u\n", loraFrequency);
printf("loraSpreadingFactor = %i\n", loraSpreadingFactor);
printf("loraPreamble = %i\n", loraPreamble);
printf("loraCodingRate = %i\n", loraCodingRate);
printf("loraTxPower = %i\n", loraTxPower);
printf("LoRaPaSelect = %i\n", LoRaPaSelect);
printf("loraBandwidth = %u\n", loraBandwidth);
printf("Starting LoRa radio");
if (!LoRa.begin(loraFrequency)) {
printf(" [ FAILED ]\n");
while(1);
}
else {
LoRa.setPreambleLength(loraPreamble);
LoRa.setSignalBandwidth(loraBandwidth);
LoRa.setTxPower(loraTxPower,LoRaPaSelect);
LoRa.setSpreadingFactor(loraSpreadingFactor);
LoRa.setCodingRate4(loraCodingRate);
LoRa.enableCrc();
printf(" [ DONE ]\n");
}
}
void getPacketData(int packetLength)
{
int position = 0;
while (packetLength--) {
rxBuffer[position++] = LoRa.read();
}
rxBuffer[position] = 0;
}
/* Encode LoRa APRS frame: extract source call, digipeater path and data field. At the same time, check for data corruption
*
*/
void encode_kiss ()
{
int position = 0;
int cnt = 0;
int number_of_digipeaters = 0;
char valid_apsr_data = false;
uint8_t aprs_source_address[10];
uint8_t aprs_digi_path[255];
uint8_t aprs_data_field[255];
uint8_t aprs_digis[10][10];
memset(aprs_source_address, 0, sizeof(aprs_source_address));
memset(aprs_digi_path, 0, sizeof(aprs_digi_path));
memset(aprs_data_field, 0, sizeof(aprs_data_field));
memset(aprs_digis, 0, sizeof(aprs_digis));
// Extract from address
cnt = 0;
while( rxBuffer[position] != 0 )
{
aprs_source_address[cnt++] = rxBuffer[position];
if ( rxBuffer[position] == '>' && position < 10 ) {
aprs_source_address[cnt-1] = 0;
valid_apsr_data = true;
break;
}
position++;
}
position++;
if (valid_apsr_data == true)
{
// Extract digi path
valid_apsr_data = false;
cnt = 0;
while( rxBuffer[position] != 0 )
{
aprs_digi_path[cnt++] = rxBuffer[position];
if ( rxBuffer[position] == ':' ) {
aprs_digi_path[cnt-1] = 0;
valid_apsr_data = true;
break;
}
position++;
}
}
position++;
if (valid_apsr_data == true)
{
// Extract data field
cnt = 0;
while( rxBuffer[position] != 0 )
{
aprs_data_field[cnt++] = rxBuffer[position];
position++;
}
aprs_data_field[cnt] = 0;
}
if (valid_apsr_data == true)
{
// Extract digis from digi-path
cnt = 0;
position = 0;
number_of_digipeaters = 0;
while( aprs_digi_path[position] != 0 )
{
aprs_digis[number_of_digipeaters][cnt++] = aprs_digi_path[position];
if ( aprs_digi_path[position] == ',' && cnt < 10 ) {
aprs_digis[number_of_digipeaters][cnt-1] = 0;
if (++number_of_digipeaters > 9) {
valid_apsr_data = false;
break;
}
//position++;
cnt = 0;
}
position++;
}
aprs_digis[number_of_digipeaters][cnt] = 0;
}
if (valid_apsr_data)
printf("Source address: %s\nDigipeaters (%u): %s %s %s %s\nData: %s\n", aprs_source_address, number_of_digipeaters+1, aprs_digis[0], aprs_digis[1], aprs_digis[2], aprs_digis[3], aprs_data_field);
else
printf("Error decoding APRS frame.");
}