Decoding APRS frames finished, started with transmitting frames.
Committer: marcel <marcel@hampi.pe1rxf>
This commit is contained in:
Binary file not shown.
Binary file not shown.
42186
build/src/main.dis
42186
build/src/main.dis
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
6781
build/src/main.hex
6781
build/src/main.hex
File diff suppressed because it is too large
Load Diff
Binary file not shown.
12
src/Config.h
12
src/Config.h
@@ -28,7 +28,7 @@
|
|||||||
int loraPreamble = 8;
|
int loraPreamble = 8;
|
||||||
int loraCodingRate = 5;
|
int loraCodingRate = 5;
|
||||||
int loraTxPower = 17;
|
int loraTxPower = 17;
|
||||||
int LoRaPaSelect = 1;
|
int LoRaPaSelect = 0;
|
||||||
uint32_t loraBandwidth = 125E3;
|
uint32_t loraBandwidth = 125E3;
|
||||||
uint32_t loraFrequency = 433775000;
|
uint32_t loraFrequency = 433775000;
|
||||||
|
|
||||||
@@ -57,4 +57,14 @@
|
|||||||
const uint8_t SIG_SYNCED = 0x02;
|
const uint8_t SIG_SYNCED = 0x02;
|
||||||
const uint8_t RX_ONGOING = 0x04;
|
const uint8_t RX_ONGOING = 0x04;
|
||||||
|
|
||||||
|
struct aprssettings {
|
||||||
|
uint8_t MyCall[10] = { 'P','E','1','R','X','F','-','5', 0} ;
|
||||||
|
uint8_t ServerCall[10] = { 'P','E','1','R','X','F','-','3', 0} ;
|
||||||
|
uint8_t Destination[10] = { 'A','P','Z','M','D','M', 0} ;
|
||||||
|
uint8_t Path1[10] = { 0,'I','D','E','1','-', '1', 0} ;
|
||||||
|
uint8_t Path2[10] = { 0,'I','D','E','2','-', '2', 0} ;
|
||||||
|
|
||||||
|
uint8_t FirmwareVersion[20] = { 'V','1',',','C','o','n','t','r', 'o','l','l','e','r',' ','0','1', 0} ;
|
||||||
|
} AprsSettings;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
246
src/main.cpp
246
src/main.cpp
@@ -7,12 +7,20 @@
|
|||||||
#include "KISS.h"
|
#include "KISS.h"
|
||||||
|
|
||||||
bool startRadio();
|
bool startRadio();
|
||||||
|
bool LoadSettings();
|
||||||
void getPacketData(int packetLength);
|
void getPacketData(int packetLength);
|
||||||
|
int compare_strings(uint8_t a[], uint8_t b[]);
|
||||||
|
bool is_message_for_me (uint8_t data[], uint8_t mycall[]);
|
||||||
|
|
||||||
void encode_kiss ();
|
uint16_t decode_packet ();
|
||||||
|
void ComposeAprsFrame(uint8_t payload[]);
|
||||||
|
|
||||||
|
void transmit();
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
|
uint16_t ServerCommand = 0;
|
||||||
|
|
||||||
/* Among others, this initializes the USB-serial port at 115200bps 8N1 */
|
/* Among others, this initializes the USB-serial port at 115200bps 8N1 */
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
@@ -22,6 +30,8 @@ int main() {
|
|||||||
|
|
||||||
sleep_ms(5000);
|
sleep_ms(5000);
|
||||||
|
|
||||||
|
LoadSettings();
|
||||||
|
|
||||||
startRadio();
|
startRadio();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -40,16 +50,43 @@ int main() {
|
|||||||
}
|
}
|
||||||
rxBuffer[packetSize-3] = 0;
|
rxBuffer[packetSize-3] = 0;
|
||||||
printf("%s\n", rxBuffer);
|
printf("%s\n", rxBuffer);
|
||||||
encode_kiss();
|
ServerCommand = decode_packet();
|
||||||
} else {
|
} else {
|
||||||
printf("ERROR: No or corrupted APRS frame.\n");
|
printf("ERROR: No or corrupted APRS frame.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ServerCommand) {
|
||||||
|
|
||||||
|
if (ServerCommand == 1) {
|
||||||
|
ComposeAprsFrame(AprsSettings.FirmwareVersion);
|
||||||
|
// Wait for 100ms before responding
|
||||||
|
sleep_ms(5000);
|
||||||
|
transmit();
|
||||||
|
sleep_ms(5000);
|
||||||
|
transmit();
|
||||||
|
sleep_ms(5000);
|
||||||
|
transmit();
|
||||||
|
sleep_ms(5000);
|
||||||
|
transmit();
|
||||||
|
}
|
||||||
|
ServerCommand = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load settings from EEPROM
|
||||||
|
*/
|
||||||
|
bool LoadSettings()
|
||||||
|
{
|
||||||
|
printf("APRS settings:\n");
|
||||||
|
printf("My call: %s\n", AprsSettings.MyCall);
|
||||||
|
printf("Server call: %s\n", AprsSettings.ServerCall);
|
||||||
|
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Initializes the LoRa module with the parameters set in config.h
|
* Initializes the LoRa module with the parameters set in config.h
|
||||||
*/
|
*/
|
||||||
@@ -95,8 +132,9 @@ void getPacketData(int packetLength)
|
|||||||
|
|
||||||
/* Encode LoRa APRS frame: extract source call, digipeater path and data field. At the same time, check for data corruption
|
/* Encode LoRa APRS frame: extract source call, digipeater path and data field. At the same time, check for data corruption
|
||||||
*
|
*
|
||||||
|
* If frame is a message from the server it returns the command from this server
|
||||||
*/
|
*/
|
||||||
void encode_kiss ()
|
uint16_t decode_packet ()
|
||||||
{
|
{
|
||||||
int position = 0;
|
int position = 0;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
@@ -106,12 +144,18 @@ void encode_kiss ()
|
|||||||
uint8_t aprs_source_address[10];
|
uint8_t aprs_source_address[10];
|
||||||
uint8_t aprs_digi_path[255];
|
uint8_t aprs_digi_path[255];
|
||||||
uint8_t aprs_data_field[255];
|
uint8_t aprs_data_field[255];
|
||||||
|
uint8_t aprs_message[255];
|
||||||
uint8_t aprs_digis[10][10];
|
uint8_t aprs_digis[10][10];
|
||||||
|
uint8_t aprs_acknowledge_number[255];
|
||||||
|
bool aprs_acknowledge_request = false;
|
||||||
|
uint16_t aprs_server_command = 0;
|
||||||
|
|
||||||
memset(aprs_source_address, 0, sizeof(aprs_source_address));
|
memset(aprs_source_address, 0, sizeof(aprs_source_address));
|
||||||
memset(aprs_digi_path, 0, sizeof(aprs_digi_path));
|
memset(aprs_digi_path, 0, sizeof(aprs_digi_path));
|
||||||
memset(aprs_data_field, 0, sizeof(aprs_data_field));
|
memset(aprs_data_field, 0, sizeof(aprs_data_field));
|
||||||
|
memset(aprs_message, 0, sizeof(aprs_message));
|
||||||
memset(aprs_digis, 0, sizeof(aprs_digis));
|
memset(aprs_digis, 0, sizeof(aprs_digis));
|
||||||
|
memset(aprs_acknowledge_number, 0, sizeof(aprs_acknowledge_number));
|
||||||
|
|
||||||
// Extract from address
|
// Extract from address
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
@@ -184,8 +228,202 @@ void encode_kiss ()
|
|||||||
aprs_digis[number_of_digipeaters][cnt] = 0;
|
aprs_digis[number_of_digipeaters][cnt] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_apsr_data)
|
if (valid_apsr_data) {
|
||||||
|
|
||||||
|
// Check if packet comes from our server and if so, check if it is a message for us.
|
||||||
|
if ( !compare_strings(aprs_source_address, AprsSettings.ServerCall) ) {
|
||||||
|
|
||||||
|
if ( is_message_for_me(aprs_data_field, AprsSettings.MyCall) )
|
||||||
|
{
|
||||||
|
|
||||||
|
// Extract aprs message from data field
|
||||||
|
position=11;
|
||||||
|
while( aprs_data_field[position] != 0 )
|
||||||
|
{
|
||||||
|
aprs_message[position-11] = aprs_data_field[position];
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract command and acknowledge number (if present)
|
||||||
|
cnt = 0;
|
||||||
|
position = 0;
|
||||||
|
while( aprs_message[position] != 0 )
|
||||||
|
{
|
||||||
|
if ( aprs_message[position] == '{' ) {
|
||||||
|
aprs_acknowledge_number[cnt++] = ':';
|
||||||
|
|
||||||
|
while ( AprsSettings.ServerCall[cnt-1] != 0 )
|
||||||
|
{
|
||||||
|
aprs_acknowledge_number[cnt] = AprsSettings.ServerCall[cnt-1];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
//Fill with spaces
|
||||||
|
while ( cnt<10 )
|
||||||
|
{
|
||||||
|
aprs_acknowledge_number[cnt++] = ' ';
|
||||||
|
|
||||||
|
}
|
||||||
|
aprs_acknowledge_number[cnt++] = ':';
|
||||||
|
aprs_acknowledge_number[cnt++] = 'a';
|
||||||
|
aprs_acknowledge_number[cnt++] = 'c';
|
||||||
|
aprs_acknowledge_number[cnt++] = 'k';
|
||||||
|
aprs_acknowledge_request = true;
|
||||||
|
}
|
||||||
|
// Calculate server command
|
||||||
|
if (!aprs_acknowledge_request) {
|
||||||
|
aprs_server_command = 10*aprs_server_command + aprs_message[position]-48;
|
||||||
|
}
|
||||||
|
|
||||||
|
position++;
|
||||||
|
if (aprs_acknowledge_request) {
|
||||||
|
aprs_acknowledge_number[cnt++] = aprs_message[position];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aprs_acknowledge_number[cnt] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
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);
|
||||||
|
if (aprs_message[0])
|
||||||
|
{
|
||||||
|
printf("Message from server: %s (command %u)\n", aprs_message, aprs_server_command);
|
||||||
|
if (aprs_acknowledge_request) {
|
||||||
|
ComposeAprsFrame(aprs_acknowledge_number);
|
||||||
|
// Wait for 100ms before responding with acknowledge
|
||||||
|
sleep_ms(100);
|
||||||
|
transmit();
|
||||||
|
printf("Acknowledge request: %s\n", aprs_acknowledge_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
printf("Error decoding APRS frame.");
|
printf("Error decoding APRS frame.");
|
||||||
|
|
||||||
|
return (aprs_server_command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if aprs datafield contains message and if message is for us
|
||||||
|
*
|
||||||
|
* Returns: 0 if datafield contains no message for us
|
||||||
|
* 1 if datafield contains a message for us
|
||||||
|
*/
|
||||||
|
bool is_message_for_me (uint8_t data[], uint8_t mycall[])
|
||||||
|
{
|
||||||
|
// A variable to iterate through the strings
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
if (data[0] == ':' && data[10] == ':')
|
||||||
|
{
|
||||||
|
while( i<9 && mycall[i] != 0 ) {
|
||||||
|
if (data[i+1] != mycall[i]) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_strings(uint8_t a[], uint8_t b[])
|
||||||
|
{
|
||||||
|
// A variable to iterate through the strings
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (a[i] == b[i])
|
||||||
|
{
|
||||||
|
// If either of the strings reaches the end
|
||||||
|
// we stop the loop
|
||||||
|
if (a[i] == '\0' || b[i] == '\0')
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We check if both the strings have been compared
|
||||||
|
// till the end or not
|
||||||
|
// If the strings are compared till the end they are equal
|
||||||
|
if (a[i] == '\0' && b[i] == '\0')
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(a[i] == '\0')
|
||||||
|
return -1*(b[i]);
|
||||||
|
else if(b[i] == '\0')
|
||||||
|
return a[i];
|
||||||
|
else
|
||||||
|
return (a[i]-b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComposeAprsFrame(uint8_t payload[])
|
||||||
|
{
|
||||||
|
uint16_t BufferPosition = 0;
|
||||||
|
uint16_t cnt = 0;
|
||||||
|
|
||||||
|
// APRS header
|
||||||
|
txBuffer[BufferPosition++] = '<';
|
||||||
|
txBuffer[BufferPosition++] = 0xff;
|
||||||
|
txBuffer[BufferPosition++] = 0x01;
|
||||||
|
|
||||||
|
while ( AprsSettings.MyCall[cnt] != 0 && BufferPosition<MTU )
|
||||||
|
{
|
||||||
|
txBuffer[BufferPosition++] = AprsSettings.MyCall[cnt];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
txBuffer[BufferPosition++] = '>';
|
||||||
|
|
||||||
|
cnt=0;
|
||||||
|
while ( AprsSettings.Destination[cnt] != 0 && BufferPosition<MTU )
|
||||||
|
{
|
||||||
|
txBuffer[BufferPosition++] = AprsSettings.Destination[cnt];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AprsSettings.Path1[0] != 0)
|
||||||
|
txBuffer[BufferPosition++] = ',';
|
||||||
|
|
||||||
|
cnt=0;
|
||||||
|
while ( AprsSettings.Path1[cnt] != 0 && BufferPosition<MTU )
|
||||||
|
{
|
||||||
|
txBuffer[BufferPosition++] = AprsSettings.Path1[cnt];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AprsSettings.Path2[0] != 0)
|
||||||
|
txBuffer[BufferPosition++] = ',';
|
||||||
|
|
||||||
|
cnt=0;
|
||||||
|
while ( AprsSettings.Path2[cnt] != 0 && BufferPosition<MTU )
|
||||||
|
{
|
||||||
|
txBuffer[BufferPosition++] = AprsSettings.Path2[cnt];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
txBuffer[BufferPosition++] = ':';
|
||||||
|
|
||||||
|
cnt=0;
|
||||||
|
while ( payload[cnt] != 0 && BufferPosition<MTU )
|
||||||
|
{
|
||||||
|
txBuffer[BufferPosition++] = payload[cnt];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
printf("%s\n", txBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transmit() {
|
||||||
|
uint16_t position = 0;
|
||||||
|
|
||||||
|
LoRa.beginPacket();
|
||||||
|
while( txBuffer[position] != 0 )
|
||||||
|
{
|
||||||
|
LoRa.write(txBuffer[position]);
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
LoRa.endPacket();
|
||||||
|
|
||||||
|
LoRa.receive();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user