kopia lustrzana https://github.com/sq2ips/m20-custom-firmware
APRS fields implementation.
rodzic
7fb9757665
commit
cdc34b404c
|
|
@ -5,13 +5,20 @@
|
|||
|
||||
#define APRS_CONTROL_FIELD 0x03
|
||||
#define APRS_PROTOCOL_ID 0xf0
|
||||
#define APRS_SPACE_SYMBOL 0x20
|
||||
|
||||
#define APRS_MAX_INFO_LEN 61
|
||||
|
||||
typedef struct TAPRSPacket {
|
||||
uint8_t Hours;
|
||||
uint8_t Minutes;
|
||||
uint8_t Seconds;
|
||||
float Lat;
|
||||
float Lon;
|
||||
uint16_t Alt;
|
||||
uint8_t Speed;
|
||||
} APRSPacket;
|
||||
|
||||
uint16_t encode_APRS_packet(APRSPacket Packet, uint8_t *buff);
|
||||
uint8_t encode_APRS_packet(APRSPacket Packet, uint8_t *buff);
|
||||
|
||||
#endif
|
||||
|
|
@ -31,15 +31,17 @@ const static float QRG_FSK4[] = {435100000}; // Transmitted frequencies array, s
|
|||
#define LED_PERIOD 5 // time between LED lighting
|
||||
#define LED_DISABLE_ALT 1000 // disable led when certain altitude is reached, 0 for always enable
|
||||
|
||||
#define APRS_D_CALL "APRS\x20\x20"
|
||||
#define APRS_D_CALL "APRS"
|
||||
#define APRS_D_CALL_SSID 0
|
||||
|
||||
#define APRS_S_CALL "SQ2IPS"
|
||||
#define APRS_S_CALL_SSID 1
|
||||
|
||||
#define APRS_PATH "WIDE1\x20"
|
||||
#define APRS_PATH "WIDE1"
|
||||
#define APRS_PATH_SSID 1
|
||||
|
||||
#define APRS_SYMBOL "/O" // baloon symbol, all symbols: https://www.aprs.org/symbols.html
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
// the rest of parameters should not be changed normally
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ volatile static uint16_t phase_inc = PHASE_INC_MARC; // current phase increase v
|
|||
volatile static uint16_t phase = 0; // Current phase value, fixed point 9.7
|
||||
volatile static uint16_t sample_in_baud = 0;
|
||||
|
||||
volatile static uint16_t bit_pos = 0;
|
||||
volatile static uint8_t stuffing_cnt = 0;
|
||||
volatile static bool stuff = false;
|
||||
static uint16_t bit_pos = 0;
|
||||
static uint8_t stuffing_cnt = 0;
|
||||
static bool stuff = false;
|
||||
|
||||
bool AFSK_Active = false; // Activity flag
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "aprs.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -27,26 +28,32 @@ static uint16_t calculateFcs(uint8_t *input_data, uint16_t len) {
|
|||
return (~crc);
|
||||
}
|
||||
|
||||
static uint16_t generate_ax25_frame(uint8_t *info_field, uint8_t info_field_size, uint8_t *buff){
|
||||
volatile uint16_t pos = 0;
|
||||
static uint8_t generate_ax25_frame(uint8_t *info_field, uint8_t info_field_size, uint8_t *buff){
|
||||
uint8_t pos = 0;
|
||||
uint8_t d_pos = 0;
|
||||
|
||||
memset(buff, 0, sizeof(250));
|
||||
|
||||
for(; pos<6; pos++){ // Destination adress
|
||||
buff[pos] = APRS_D_CALL[pos]<<1;
|
||||
if(pos >= sizeof(APRS_D_CALL)-1){
|
||||
buff[pos] = APRS_SPACE_SYMBOL<<1;
|
||||
}else buff[pos] = APRS_D_CALL[pos]<<1;
|
||||
}
|
||||
buff[pos++] = (APRS_D_CALL_SSID<<1) | 0b11100000; // Destination adress SSID
|
||||
|
||||
d_pos = pos;
|
||||
for(; pos-d_pos<6; pos++){ // Source adress
|
||||
buff[pos] = APRS_S_CALL[pos-d_pos]<<1;
|
||||
if(pos-d_pos >= sizeof(APRS_S_CALL)-1){
|
||||
buff[pos] = APRS_SPACE_SYMBOL<<1;
|
||||
}else buff[pos] = APRS_S_CALL[pos-d_pos]<<1;
|
||||
}
|
||||
buff[pos++] = (APRS_S_CALL_SSID<<1) | 0b11100000; // Source adress SSID
|
||||
|
||||
d_pos = pos;
|
||||
for(; pos-d_pos<6; pos++){ // Path
|
||||
buff[pos] = APRS_PATH[pos-d_pos]<<1;
|
||||
if(pos-d_pos >= sizeof(APRS_PATH)-1){
|
||||
buff[pos] = APRS_SPACE_SYMBOL<<1;
|
||||
}else buff[pos] = APRS_PATH[pos-d_pos]<<1;
|
||||
}
|
||||
buff[pos++] = (APRS_PATH_SSID<<1) | 0b11100001; // Path SSID (1 at end as last adress)
|
||||
|
||||
|
|
@ -64,7 +71,66 @@ static uint16_t generate_ax25_frame(uint8_t *info_field, uint8_t info_field_size
|
|||
return pos;
|
||||
}
|
||||
|
||||
uint16_t encode_APRS_packet(APRSPacket Packet, uint8_t *buff){
|
||||
uint8_t info[] = "@092345z/:*E\";qZ=OMRC/A=088132Hello World!";
|
||||
return generate_ax25_frame(info, sizeof(info)-1, buff);
|
||||
static uint8_t compress_pos(float lat, float lon, uint8_t *buff){
|
||||
uint32_t lat_base10 = Round(380926 * (90-lat));
|
||||
uint8_t cnt = 0;
|
||||
|
||||
buff[cnt++] = (lat_base10 / 753571) + 33;
|
||||
buff[cnt++] = ((lat_base10 % 753571) / 8281) + 33;
|
||||
buff[cnt++] = ((lat_base10 % 753571) % 8281) / 91 + 33;
|
||||
buff[cnt++] = ((lat_base10 % 753571) % 8281) % 91 + 33;
|
||||
|
||||
|
||||
uint32_t lon_base10 = Round(190463 * (180+lat));
|
||||
buff[cnt++] = (lon_base10 / 753571) + 33;
|
||||
buff[cnt++] = ((lon_base10 % 753571) / 8281) + 33;
|
||||
buff[cnt++] = ((lon_base10 % 753571) % 8281) / 91 + 33;
|
||||
buff[cnt++] = ((lon_base10 % 753571) % 8281) % 91 + 33;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint8_t encode_APRS_packet(APRSPacket Packet, uint8_t *buff){
|
||||
uint8_t info_field[APRS_MAX_INFO_LEN];
|
||||
uint8_t pos = 0;
|
||||
|
||||
info_field[pos++] = '@';
|
||||
|
||||
info_field[pos++] = Packet.Hours%10+'0';
|
||||
info_field[pos++] = Packet.Hours/10+'0';
|
||||
|
||||
info_field[pos++] = Packet.Minutes%10+'0';
|
||||
info_field[pos++] = Packet.Minutes/10+'0';
|
||||
|
||||
info_field[pos++] = Packet.Seconds%10+'0';
|
||||
info_field[pos++] = Packet.Seconds/10+'0';
|
||||
|
||||
info_field[pos++] = 'z';
|
||||
|
||||
info_field[pos++] = APRS_SYMBOL[0];
|
||||
|
||||
pos += compress_pos(Packet.Lat, Packet.Lon, info_field+pos);
|
||||
|
||||
info_field[pos++] = APRS_SYMBOL[1];
|
||||
|
||||
info_field[pos++] = 33; // no course data
|
||||
|
||||
info_field[pos++] = Round((Log(Packet.Speed*0.5399565f+1)/Log(1.08f)))+33;
|
||||
|
||||
info_field[pos++] = 67;
|
||||
|
||||
info_field[pos++] = '/';
|
||||
info_field[pos++] = 'A';
|
||||
info_field[pos++] = '=';
|
||||
uint32_t alt_ft = (uint32_t)(Packet.Alt*3.28084f);
|
||||
uint32_t a = 1000000;
|
||||
for(uint8_t i = 0; i<6; i++){
|
||||
info_field[pos++] = (alt_ft%(a*10))/a;
|
||||
a/=10;
|
||||
}
|
||||
|
||||
memcpy(info_field+pos, "test", 4);
|
||||
pos+=4;
|
||||
|
||||
return generate_ax25_frame(info_field, pos, buff);
|
||||
}
|
||||
|
|
@ -61,8 +61,6 @@ const static uint8_t GPS_airborne[44] = {
|
|||
XMDATA GpsData;
|
||||
#endif
|
||||
|
||||
static uint8_t afsk_buff[] = {0x82, 0xa0, 0xa4, 0xa6, 0x40, 0x40, 0xe0, 0x9c, 0x9e, 0x86, 0x82, 0x98, 0x98, 0xe2, 0xae, 0x92, 0x88, 0x8a, 0x62, 0x40, 0xe3, 0x03, 0xf0, 0x40, 0x30, 0x39, 0x32, 0x33, 0x34, 0x35, 0x7a, 0x2f, 0x3a, 0x2a, 0x45, 0x22, 0x3b, 0x71, 0x5a, 0x3d, 0x4f, 0x4d, 0x52, 0x43, 0x2f, 0x41, 0x3d, 0x30, 0x38, 0x38, 0x31, 0x33, 0x32, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0xa2, 0x48};
|
||||
|
||||
#ifdef GPS_WATCHDOG
|
||||
struct GpsWatchdogStruct {
|
||||
bool PreviousFix;
|
||||
|
|
@ -454,6 +452,14 @@ int main(void)
|
|||
* TIM6 - LED timer: 3
|
||||
* SysTick: 4
|
||||
*/
|
||||
AprsPacket.Alt = 18523;
|
||||
AprsPacket.Lat = 54.123;
|
||||
AprsPacket.Lon = 18.456;
|
||||
AprsPacket.Hours = 12;
|
||||
AprsPacket.Minutes = 34;
|
||||
AprsPacket.Seconds = 56;
|
||||
AprsPacket.Speed = 123;
|
||||
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Infinite loop */
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue