|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
#include <stdarg.h> |
|
|
|
|
#include "pico/stdlib.h" |
|
|
|
|
#include "pico/binary_info.h" |
|
|
|
|
#include "hardware/flash.h" |
|
|
|
@ -34,36 +35,88 @@ const uint RelayOnControl = 3; |
|
|
|
|
|
|
|
|
|
const uint8_t *flash_target_contents = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET); |
|
|
|
|
|
|
|
|
|
uint8_t ReadSettingsFromFlash(void) |
|
|
|
|
void log_out(const char *fmt, ...) |
|
|
|
|
{ |
|
|
|
|
char buf[256]; |
|
|
|
|
va_list args; |
|
|
|
|
|
|
|
|
|
if (Status.KissMode == OFF) { |
|
|
|
|
va_start(args, fmt); |
|
|
|
|
|
|
|
|
|
vsnprintf(buf, sizeof buf, fmt, args); |
|
|
|
|
|
|
|
|
|
va_end( args); |
|
|
|
|
|
|
|
|
|
printf("%s", buf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Saves settings in struct AprsSettings to FLASH memory |
|
|
|
|
* Struct AprsSettings should be exactly a multiple of FLASH_PAGE_SIZE in size. |
|
|
|
|
*
|
|
|
|
|
* Returns: 0 when successfull |
|
|
|
|
* 1 when error |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
uint8_t SaveSettingsToFlash(void) |
|
|
|
|
{ |
|
|
|
|
uint32_t ints = save_and_disable_interrupts(); |
|
|
|
|
|
|
|
|
|
// First we erase the FLASH sector we need. After that we can store new values.
|
|
|
|
|
// Note that a whole number of sectors must be erased at a time.
|
|
|
|
|
// Sector size is 4kB, so this is way bigger than the 256 bytes PAGE_SIZE for storing the settings.
|
|
|
|
|
// We can therefore store up to 16 blocks of 256 bytes per sector
|
|
|
|
|
log_out("Erasing FLASH region..."); |
|
|
|
|
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE); |
|
|
|
|
log_out("done\n"); |
|
|
|
|
log_out("Writing settings to FLASH...");
|
|
|
|
|
flash_range_program(FLASH_TARGET_OFFSET, (uint8_t*)&AprsSettings, sizeof(AprsSettings) ); |
|
|
|
|
log_out("done\n"); |
|
|
|
|
restore_interrupts (ints); |
|
|
|
|
|
|
|
|
|
return(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ShowSettings(void) |
|
|
|
|
{ |
|
|
|
|
log_out("LoRa APRS remote switcher with build in KISS TNC.\n");
|
|
|
|
|
log_out(" Firmware version : %s\n",AprsSettings.FirmwareVersion); |
|
|
|
|
log_out(" Size of struct : %u.\n\n", sizeof(AprsSettings)); |
|
|
|
|
|
|
|
|
|
log_out("APRS settings\n"); |
|
|
|
|
log_out(" My call : %s\n", AprsSettings.MyCall); |
|
|
|
|
log_out(" Server call : %s\n", AprsSettings.ServerCall); |
|
|
|
|
log_out(" Destination : %s\n", AprsSettings.Destination); |
|
|
|
|
log_out(" Path 1 : %s\n", AprsSettings.Path1); |
|
|
|
|
log_out(" Path 2 : %s\n\n", AprsSettings.Path2); |
|
|
|
|
|
|
|
|
|
log_out("LoRa settings\n"); |
|
|
|
|
log_out(" Frequency : %u\n", AprsSettings.loraFrequency);
|
|
|
|
|
log_out(" SpreadingFactor : %i\n", AprsSettings.loraSpreadingFactor);
|
|
|
|
|
log_out(" Preamble : %i\n", AprsSettings.loraPreamble);
|
|
|
|
|
log_out(" CodingRate : %i\n", AprsSettings.loraCodingRate);
|
|
|
|
|
log_out(" TxPower : %i\n", AprsSettings.loraTxPower);
|
|
|
|
|
log_out(" PaSelect : %i\n", AprsSettings.loraPaSelect);
|
|
|
|
|
log_out(" Bandwidth : %u\n", AprsSettings.loraBandwidth);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t ReadSettingsFromFlash(void) |
|
|
|
|
{ |
|
|
|
|
// If byte zero of flash contains 0x5A we assume the data to be valid, otherwise we fill the flash with default values.
|
|
|
|
|
if (flash_target_contents[0] != 0x5A) |
|
|
|
|
{ |
|
|
|
|
printf( "No valid data found in FLASH memory.\n" ); |
|
|
|
|
log_out( "No valid data found in FLASH memory. Using default values.\n" ); |
|
|
|
|
memset(AprsSettings.FillerData, 0, sizeof(AprsSettings.FillerData)); |
|
|
|
|
uint32_t ints = save_and_disable_interrupts(); |
|
|
|
|
SaveSettingsToFlash(); |
|
|
|
|
|
|
|
|
|
// First we erase the FLASH sector we need. After that we can store new values.
|
|
|
|
|
// Note that a whole number of sectors must be erased at a time.
|
|
|
|
|
// Sector size is 4kB, so this is way bigger than the needed 256 bytes for storing the settings.
|
|
|
|
|
printf("Erasing FLASH region..."); |
|
|
|
|
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE); |
|
|
|
|
printf("done\n"); |
|
|
|
|
printf("Writing default values to FLASH...");
|
|
|
|
|
flash_range_program(FLASH_TARGET_OFFSET, (uint8_t*)&AprsSettings, FLASH_PAGE_SIZE); |
|
|
|
|
printf("done\n"); |
|
|
|
|
restore_interrupts (ints); |
|
|
|
|
} else { |
|
|
|
|
// Read settings stored in flash memory
|
|
|
|
|
printf("Found valid settings in FLASH memory.\n"); |
|
|
|
|
log_out("Found valid settings in FLASH memory.\n"); |
|
|
|
|
} |
|
|
|
|
memcpy((uint8_t*)&AprsSettings, flash_target_contents, FLASH_PAGE_SIZE); |
|
|
|
|
|
|
|
|
|
printf("APRS settings:\n"); |
|
|
|
|
printf("My call: %s\n", AprsSettings.MyCall); |
|
|
|
|
printf("Server call: %s\n", AprsSettings.ServerCall); |
|
|
|
|
printf("Firmware: %s\n",AprsSettings.FirmwareVersion); |
|
|
|
|
memcpy((uint8_t*)&AprsSettings, flash_target_contents, sizeof(AprsSettings)); |
|
|
|
|
ShowSettings(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void setup(void) |
|
|
|
@ -107,6 +160,191 @@ void setup(void) |
|
|
|
|
startRadio(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print_help(void) |
|
|
|
|
{ |
|
|
|
|
log_out("Unknown command.\n\n"); |
|
|
|
|
log_out("kiss\n"); |
|
|
|
|
log_out(" Enter KISS mode.\n"); |
|
|
|
|
log_out("save\n"); |
|
|
|
|
log_out(" Save settings to flash.\n"); |
|
|
|
|
log_out("read <flash/ram>\n"); |
|
|
|
|
log_out(" Read settings from FLASH or RAM.\n"); |
|
|
|
|
log_out("mycall/servercall/destination/path1/path2\n"); |
|
|
|
|
log_out(" APRS settings.\n"); |
|
|
|
|
log_out("freq/spread/pre/rate/power/pa/band.\n"); |
|
|
|
|
log_out(" LoRa settings.\n"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ProcessSerialInput(char string[]) |
|
|
|
|
{ |
|
|
|
|
uint8_t cnt; |
|
|
|
|
uint8_t position=0; |
|
|
|
|
|
|
|
|
|
char command[100]; |
|
|
|
|
char parameter[100]; |
|
|
|
|
|
|
|
|
|
//log_out("You wrote - %s (%u).\n", string, strlen(string));
|
|
|
|
|
|
|
|
|
|
// Command cannot be any shorter than 3 characters
|
|
|
|
|
if (strlen(string) > 2) { |
|
|
|
|
|
|
|
|
|
// Extract command (part before space)
|
|
|
|
|
cnt = 0;
|
|
|
|
|
while( string[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
command[cnt++] = string[position]; |
|
|
|
|
if ( string[position] == ' ' ) { |
|
|
|
|
command[cnt-1] = 0; // terminate command string
|
|
|
|
|
position++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Extract parameter (part after space)
|
|
|
|
|
cnt = 0;
|
|
|
|
|
while( string[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
parameter[cnt++] = string[position++]; |
|
|
|
|
} |
|
|
|
|
parameter[cnt] = 0; //terminate string
|
|
|
|
|
|
|
|
|
|
//log_out("Command - %s.\n", command);
|
|
|
|
|
//log_out("Parameter - %s.\n", parameter);
|
|
|
|
|
|
|
|
|
|
// Read settings
|
|
|
|
|
if (strcmp(command, "read") == 0) { |
|
|
|
|
if (strcmp(parameter, "flash") == 0) { |
|
|
|
|
ReadSettingsFromFlash(); |
|
|
|
|
} |
|
|
|
|
else if (strcmp(parameter, "ram") == 0) { |
|
|
|
|
ShowSettings(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Save settings to FLASH
|
|
|
|
|
else if (strcmp(command, "save") == 0) |
|
|
|
|
SaveSettingsToFlash(); |
|
|
|
|
|
|
|
|
|
// Enter KISS mode
|
|
|
|
|
else if (strcmp(command, "kiss") == 0) { |
|
|
|
|
log_out("Entering KISS mode.\n"); |
|
|
|
|
log_out("You can exit KISS mode via KISS command <0xC0 0xFF 0xC0>\n"); |
|
|
|
|
Status.KissMode = ON; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set mycall (cannot be longer than 9 characters)
|
|
|
|
|
else if (strcmp(command, "mycall") == 0) { |
|
|
|
|
if (sizeof(AprsSettings.MyCall) > strlen(parameter)) { |
|
|
|
|
position = 0; |
|
|
|
|
while( parameter[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
AprsSettings.MyCall[position] = parameter[position]; |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
AprsSettings.MyCall[position] = 0; |
|
|
|
|
log_out("MyCall set to %s.\n", AprsSettings.MyCall); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Set servercall (cannot be longer than 9 characters)
|
|
|
|
|
else if (strcmp(command, "servercall") == 0) { |
|
|
|
|
if (sizeof(AprsSettings.ServerCall) > strlen(parameter)) { |
|
|
|
|
position = 0; |
|
|
|
|
while( parameter[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
AprsSettings.ServerCall[position] = parameter[position]; |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
AprsSettings.ServerCall[position] = 0; |
|
|
|
|
log_out("ServerCall set to %s.\n", AprsSettings.ServerCall); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Set path 1 (cannot be longer than 9 characters)
|
|
|
|
|
else if (strcmp(command, "path1") == 0) { |
|
|
|
|
// Set path to nothing
|
|
|
|
|
if (parameter[0] == '0') { |
|
|
|
|
AprsSettings.Path1[0] = 0; |
|
|
|
|
log_out("Path1 cleared.\n"); |
|
|
|
|
} |
|
|
|
|
else if (sizeof(AprsSettings.Path1) > strlen(parameter)) { |
|
|
|
|
position = 0; |
|
|
|
|
while( parameter[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
AprsSettings.Path1[position] = parameter[position]; |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
AprsSettings.Path1[position] = 0; |
|
|
|
|
log_out("Path1 set to %s.\n", AprsSettings.Path1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Set path 2 (cannot be longer than 9 characters)
|
|
|
|
|
else if (strcmp(command, "path2") == 0) { |
|
|
|
|
// Set path to nothing
|
|
|
|
|
if (parameter[0] == '0') { |
|
|
|
|
AprsSettings.Path2[0] = 0; |
|
|
|
|
log_out("Path2 cleared.\n"); |
|
|
|
|
} |
|
|
|
|
else if (sizeof(AprsSettings.Path2) > strlen(parameter)) { |
|
|
|
|
position = 0; |
|
|
|
|
while( parameter[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
AprsSettings.Path2[position] = parameter[position]; |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
AprsSettings.Path2[position] = 0; |
|
|
|
|
log_out("Path2 set to %s.\n", AprsSettings.Path2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Set destination (cannot be longer than 9 characters)
|
|
|
|
|
else if (strcmp(command, "dest") == 0) { |
|
|
|
|
if (sizeof(AprsSettings.Destination) > strlen(parameter)) { |
|
|
|
|
position = 0; |
|
|
|
|
while( parameter[position] != 0 ) |
|
|
|
|
{ |
|
|
|
|
AprsSettings.Destination[position] = parameter[position]; |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
AprsSettings.Destination[position] = 0; |
|
|
|
|
log_out("Destination set to %s.\n", AprsSettings.Destination); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
print_help(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
print_help(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void ReadUSBSerial(void) |
|
|
|
|
{ |
|
|
|
|
static char strg[100]; |
|
|
|
|
int chr; |
|
|
|
|
static int lp = 0; |
|
|
|
|
|
|
|
|
|
// Read serial port (USB) - non-blocking!
|
|
|
|
|
chr = getchar_timeout_us(0); |
|
|
|
|
while(chr != PICO_ERROR_TIMEOUT) |
|
|
|
|
{ |
|
|
|
|
log_out("%c", chr); |
|
|
|
|
|
|
|
|
|
strg[lp++] = chr; |
|
|
|
|
if(chr == CR || lp == (sizeof(strg) - 1)) |
|
|
|
|
{ |
|
|
|
|
strg[lp-1] = 0; //terminate string by overwriting <CR> with NULL
|
|
|
|
|
//log_out("You wrote - %s\n", strg);
|
|
|
|
|
lp = 0; //reset string buffer pointer
|
|
|
|
|
|
|
|
|
|
ProcessSerialInput(strg); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
chr = getchar_timeout_us(0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int main() { |
|
|
|
|
|
|
|
|
|
uint16_t ServerCommand = 0; |
|
|
|
@ -118,7 +356,7 @@ int main() { |
|
|
|
|
int packetSize = LoRa.parsePacket(); |
|
|
|
|
if (packetSize) { |
|
|
|
|
// received a packet
|
|
|
|
|
printf("Received packet (RSSI = %idBm)\n",LoRa.packetRssi()); |
|
|
|
|
log_out("Received packet (RSSI = %idBm)\n",LoRa.packetRssi()); |
|
|
|
|
|
|
|
|
|
getPacketData(packetSize); |
|
|
|
|
|
|
|
|
@ -129,10 +367,10 @@ int main() { |
|
|
|
|
rxBuffer[cnt-3] = rxBuffer[cnt]; |
|
|
|
|
} |
|
|
|
|
rxBuffer[packetSize-3] = 0; |
|
|
|
|
printf("%s\n", rxBuffer); |
|
|
|
|
log_out("%s\n", rxBuffer); |
|
|
|
|
ServerCommand = decode_packet(); |
|
|
|
|
} else { |
|
|
|
|
printf("ERROR: No or corrupted APRS frame.\n"); |
|
|
|
|
log_out("ERROR: No or corrupted APRS frame.\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -169,6 +407,10 @@ int main() { |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
// Send description digital outputs
|
|
|
|
|
case 7 : |
|
|
|
|
ComposeAprsFrame(Status.DescriptionString); |
|
|
|
|
|
|
|
|
|
// Switch off 24V power supply
|
|
|
|
|
case 30 : |
|
|
|
|
gpio_put(PowerSupply24VControl, 0); |
|
|
|
@ -235,6 +477,9 @@ int main() { |
|
|
|
|
TransmitRequest = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Read serial input and process it
|
|
|
|
|
ReadUSBSerial(); |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
@ -247,29 +492,19 @@ 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"); |
|
|
|
|
log_out("Starting LoRa radio"); |
|
|
|
|
if (!LoRa.begin(AprsSettings.loraFrequency)) { |
|
|
|
|
log_out(" [ FAILED ]\n"); |
|
|
|
|
while(1); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
LoRa.setPreambleLength(loraPreamble); |
|
|
|
|
LoRa.setSignalBandwidth(loraBandwidth); |
|
|
|
|
LoRa.setTxPower(loraTxPower,LoRaPaSelect); |
|
|
|
|
LoRa.setSpreadingFactor(loraSpreadingFactor); |
|
|
|
|
LoRa.setCodingRate4(loraCodingRate); |
|
|
|
|
LoRa.setPreambleLength(AprsSettings.loraPreamble); |
|
|
|
|
LoRa.setSignalBandwidth(AprsSettings.loraBandwidth); |
|
|
|
|
LoRa.setTxPower(AprsSettings.loraTxPower,AprsSettings.loraPaSelect); |
|
|
|
|
LoRa.setSpreadingFactor(AprsSettings.loraSpreadingFactor); |
|
|
|
|
LoRa.setCodingRate4(AprsSettings.loraCodingRate); |
|
|
|
|
LoRa.enableCrc(); |
|
|
|
|
printf(" [ DONE ]\n"); |
|
|
|
|
log_out(" [ DONE ]\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -318,13 +553,12 @@ uint16_t decode_packet () |
|
|
|
|
if ( rxBuffer[position] == '>' && position < 10 ) { |
|
|
|
|
aprs_source_address[cnt-1] = 0; |
|
|
|
|
valid_apsr_data = true; |
|
|
|
|
position++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
position++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
position++; |
|
|
|
|
|
|
|
|
|
if (valid_apsr_data == true) |
|
|
|
|
{ |
|
|
|
|
// Extract digi path
|
|
|
|
@ -336,6 +570,7 @@ uint16_t decode_packet () |
|
|
|
|
if ( rxBuffer[position] == ':' ) { |
|
|
|
|
aprs_digi_path[cnt-1] = 0; |
|
|
|
|
valid_apsr_data = true; |
|
|
|
|
position++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
position++; |
|
|
|
@ -343,8 +578,6 @@ uint16_t decode_packet () |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
position++; |
|
|
|
|
|
|
|
|
|
if (valid_apsr_data == true) |
|
|
|
|
{ |
|
|
|
|
// Extract data field
|
|
|
|
@ -372,8 +605,6 @@ uint16_t decode_packet () |
|
|
|
|
valid_apsr_data = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//position++;
|
|
|
|
|
cnt = 0; |
|
|
|
|
} |
|
|
|
|
position++; |
|
|
|
@ -424,20 +655,20 @@ uint16_t decode_packet () |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
log_out("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); |
|
|
|
|
log_out("Message from server: %s (command %u)\n", aprs_message, aprs_server_command); |
|
|
|
|
if (aprs_acknowledge_request) { |
|
|
|
|
ComposeAprsFrame(aprs_acknowledge_number); |
|
|
|
|
printf("Acknowledge request: %s\n", aprs_acknowledge_number); |
|
|
|
|
log_out("Acknowledge request: %s\n", aprs_acknowledge_number); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else |
|
|
|
|
printf("Error decoding APRS frame."); |
|
|
|
|
log_out("Error decoding APRS frame."); |
|
|
|
|
|
|
|
|
|
return (aprs_server_command); |
|
|
|
|
} |
|
|
|
@ -570,7 +801,7 @@ void ComposeAprsFrame(uint8_t payload[]) |
|
|
|
|
|
|
|
|
|
// Set variable to indicate a send request
|
|
|
|
|
TransmitRequest = true;
|
|
|
|
|
printf("%s\n", txBuffer); |
|
|
|
|
log_out("%s\n", txBuffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void transmit() { |
|
|
|
|