APRS settings can be saved in FLASH.
This commit is contained in:
		
							
								
								
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -9,10 +9,16 @@ All notable changes to this project will be documented in this file.
 | 
			
		||||
    Fixed     : for any bug fixes.
 | 
			
		||||
    Security  : in case of vulnerabilities.
 | 
			
		||||
 | 
			
		||||
## [1.0.0] - pre 2022-05-12
 | 
			
		||||
## [1.0.0] - pre 2022-05-10
 | 
			
		||||
First (more or less) working version.
 | 
			
		||||
 | 
			
		||||
## [1.0.1] - 2022-05-12
 | 
			
		||||
## [1.0.1] - 2022-05-10
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
- Support for saving settings to internal FLASH
 | 
			
		||||
 | 
			
		||||
## [1.0.2] - 2022-05-11
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
- APRS settings can now be saved in FLASH
 | 
			
		||||
- logging to serial USB is disabled when in KISS mode (but KISS mode still needs to be implemented)
 | 
			
		||||
 
 | 
			
		||||
@@ -251,6 +251,8 @@ string.h
 | 
			
		||||
-
 | 
			
		||||
time.h
 | 
			
		||||
-
 | 
			
		||||
stdarg.h
 | 
			
		||||
-
 | 
			
		||||
pico/stdlib.h
 | 
			
		||||
/home/marcel/Documents/electronische_projecten/lora_aprs_node_pico/src/pico/stdlib.h
 | 
			
		||||
pico/binary_info.h
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										50017
									
								
								build/src/main.dis
									
									
									
									
									
								
							
							
						
						
									
										50017
									
								
								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
											
										
									
								
							
							
								
								
									
										7974
									
								
								build/src/main.hex
									
									
									
									
									
								
							
							
						
						
									
										7974
									
								
								build/src/main.hex
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										46
									
								
								src/Config.h
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								src/Config.h
									
									
									
									
									
								
							@@ -21,20 +21,13 @@
 | 
			
		||||
  #define OFF 0
 | 
			
		||||
  #define ON 1
 | 
			
		||||
    
 | 
			
		||||
  #define CR		13
 | 
			
		||||
  
 | 
			
		||||
  const long serialBaudRate   = 38400;
 | 
			
		||||
  const int  rssiOffset      = 292;
 | 
			
		||||
 | 
			
		||||
  const int  loraRxTurnaround = 50;
 | 
			
		||||
 | 
			
		||||
  // Default LoRa settings
 | 
			
		||||
  int       loraSpreadingFactor = 12;
 | 
			
		||||
  int       loraPreamble        = 8;
 | 
			
		||||
  int       loraCodingRate      = 5;
 | 
			
		||||
  int       loraTxPower         = 17;
 | 
			
		||||
  int       LoRaPaSelect        = 1;
 | 
			
		||||
  uint32_t  loraBandwidth       = 125E3;
 | 
			
		||||
  uint32_t  loraFrequency       = 433775000;
 | 
			
		||||
 | 
			
		||||
  uint8_t txBuffer[MTU];
 | 
			
		||||
  uint8_t rxBuffer[MTU];
 | 
			
		||||
 | 
			
		||||
@@ -60,18 +53,31 @@
 | 
			
		||||
  const uint8_t SIG_SYNCED = 0x02;
 | 
			
		||||
  const uint8_t RX_ONGOING = 0x04;
 | 
			
		||||
  
 | 
			
		||||
  // The size of this struc should be a exactly 256 bytes, which is the FLASH_PAGE_SIZE of the RPi pico's flash memory
 | 
			
		||||
  // The size of this struc should be a exactly 256 bytes (or a multiple), which is the FLASH_PAGE_SIZE of the RPi pico's flash memory
 | 
			
		||||
  // Struct can not be bigger than 4kbyte
 | 
			
		||||
  struct aprssettings {
 | 
			
		||||
      uint8_t ValidFlashData = 0x5A;  // Indicates flash contains valid data - 1 bytes
 | 
			
		||||
      uint8_t MyCall[10] = { 'N','O','C','A','L','L','-','2', 0} ;      // 10 bytes
 | 
			
		||||
      uint8_t ServerCall[10] = { 'N','O','C','A','L','L','-','1', 0} ;  // 10 bytes
 | 
			
		||||
      uint8_t Destination[10] = { 'A','P','Z','M','D','M', 0} ;         // 10 bytes
 | 
			
		||||
      uint8_t Path1[10] = { 0,'I','D','E','1','-', '1', 0} ;            // 10 bytes
 | 
			
		||||
      uint8_t Path2[10] = { 0,'I','D','E','2','-', '2', 0} ;            // 10 bytes
 | 
			
		||||
      uint8_t MyCall[10] = { 'P','E','1','R','X','F','-','5', 0, 0} ;      // 10 bytes
 | 
			
		||||
      uint8_t ServerCall[10] = { 'P','E','1','R','X','F','-','3', 0, 0} ;  // 10 bytes
 | 
			
		||||
      uint8_t Destination[10] = { 'A','P','Z','M','D','M', 0, 0, 0 ,0} ;   // 10 bytes
 | 
			
		||||
      uint8_t Path1[10] = { 0,'I','D','E','1','-', '1', 0, 0, 0} ;         // 10 bytes
 | 
			
		||||
      uint8_t Path2[10] = { 0,'I','D','E','2','-', '2', 0, 0 ,0} ;         // 10 bytes
 | 
			
		||||
            
 | 
			
		||||
      uint8_t FirmwareVersion[20] = { 'V','1',',','C','o','n','t','r', 'o','l','l','e','r',' ','0','1', 0} ;    // 20 bytes
 | 
			
		||||
                                                                        // 71 bytes total
 | 
			
		||||
      uint8_t FillerData[256-71];
 | 
			
		||||
      uint8_t FirmwareVersion[20] = { 'V','1',',','C','o','n','t','r', 'o','l','l','e','r',' ','0','1', 0, 0, 0, 0} ;
 | 
			
		||||
                                                                        // 20 bytes
 | 
			
		||||
                                                                       
 | 
			
		||||
      // Default LoRa settings
 | 
			
		||||
      uint16_t  loraSpreadingFactor = 12;                               // 2 bytes
 | 
			
		||||
      uint16_t  loraPreamble        = 8;                                // 2 bytes
 | 
			
		||||
      uint16_t  loraCodingRate      = 5;                                // 2 bytes
 | 
			
		||||
      uint16_t  loraTxPower         = 17;                               // 2 bytes
 | 
			
		||||
      uint16_t  loraPaSelect        = 1;                                // 2 bytes
 | 
			
		||||
      uint32_t  loraBandwidth       = 125E3;                            // 4 bytes
 | 
			
		||||
      uint32_t  loraFrequency       = 433775000;                        // 4 bytes
 | 
			
		||||
      
 | 
			
		||||
                                                                // Total 89 bytes
 | 
			
		||||
      
 | 
			
		||||
      uint8_t   FillerData[163];
 | 
			
		||||
  } AprsSettings;
 | 
			
		||||
  
 | 
			
		||||
  struct status {
 | 
			
		||||
@@ -81,6 +87,10 @@
 | 
			
		||||
      bool ControlRelay;
 | 
			
		||||
      
 | 
			
		||||
      uint8_t StatusString[6] = { '0','0','0','0','0',0};
 | 
			
		||||
      
 | 
			
		||||
      uint8_t DescriptionString[20] ={ 'N','C',',','C','n','t','r',',','5','V',',','1','2','V',',','2','4','V',0,0};
 | 
			
		||||
      
 | 
			
		||||
      uint8_t KissMode = OFF;
 | 
			
		||||
  } Status;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										335
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										335
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -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 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" );
 | 
			
		||||
        memset(AprsSettings.FillerData, 0, sizeof(AprsSettings.FillerData));
 | 
			
		||||
        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 needed 256 bytes for storing the settings.
 | 
			
		||||
        printf("Erasing FLASH region...");
 | 
			
		||||
    // 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);
 | 
			
		||||
        printf("done\n");
 | 
			
		||||
        printf("Writing default values to FLASH...");    
 | 
			
		||||
        flash_range_program(FLASH_TARGET_OFFSET, (uint8_t*)&AprsSettings, FLASH_PAGE_SIZE);
 | 
			
		||||
        printf("done\n");
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
        log_out( "No valid data found in FLASH memory. Using default values.\n" );
 | 
			
		||||
        memset(AprsSettings.FillerData, 0, sizeof(AprsSettings.FillerData));
 | 
			
		||||
        SaveSettingsToFlash();
 | 
			
		||||
        
 | 
			
		||||
    } 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() {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user