LibAPRS/src/LibAPRS.cpp

349 wiersze
8.6 KiB
C++

#include "Arduino.h"
#include "AFSK.h"
#include "AX25.h"
Afsk modem;
AX25Ctx AX25;
extern void aprs_msg_callback(struct AX25Msg *msg);
#define countof(a) sizeof(a)/sizeof(a[0])
int LibAPRS_vref = REF_3V3;
bool LibAPRS_open_squelch = false;
unsigned long custom_preamble = 350UL;
unsigned long custom_tail = 50UL;
AX25Call src;
AX25Call dst;
AX25Call path1;
AX25Call path2;
char CALL[7] = "NOCALL";
int CALL_SSID = 0;
char DST[7] = "APZMDM";
int DST_SSID = 0;
char PATH1[7] = "WIDE1";
int PATH1_SSID = 1;
char PATH2[7] = "WIDE2";
int PATH2_SSID = 2;
AX25Call path[4];
// Location packet assembly fields
char latitude[9];
char longtitude[10];
char symbolTable = '/';
char symbol = 'n';
uint8_t power = 10;
uint8_t height = 10;
uint8_t gain = 10;
uint8_t directivity = 10;
/////////////////////////
// Message packet assembly fields
char message_recip[7];
int message_recip_ssid = -1;
int message_seq = 0;
char lastMessage[67];
size_t lastMessageLen;
bool message_autoAck = false;
/////////////////////////
void APRS_init(int reference, bool open_squelch) {
LibAPRS_vref = reference;
LibAPRS_open_squelch = open_squelch;
AFSK_init(&modem);
ax25_init(&AX25, aprs_msg_callback);
}
void APRS_poll(void) {
ax25_poll(&AX25);
}
void APRS_setCallsign(char *call, int ssid) {
memset(CALL, 0, 7);
int i = 0;
while (i < 6 && call[i] != 0) {
CALL[i] = call[i];
i++;
}
CALL_SSID = ssid;
}
void APRS_setDestination(char *call, int ssid) {
memset(DST, 0, 7);
int i = 0;
while (i < 6 && call[i] != 0) {
DST[i] = call[i];
i++;
}
DST_SSID = ssid;
}
void APRS_setPath1(char *call, int ssid) {
memset(PATH1, 0, 7);
int i = 0;
while (i < 6 && call[i] != 0) {
PATH1[i] = call[i];
i++;
}
PATH1_SSID = ssid;
}
void APRS_setPath2(char *call, int ssid) {
memset(PATH2, 0, 7);
int i = 0;
while (i < 6 && call[i] != 0) {
PATH2[i] = call[i];
i++;
}
PATH2_SSID = ssid;
}
void APRS_setMessageDestination(char *call, int ssid) {
memset(message_recip, 0, 7);
int i = 0;
while (i < 6 && call[i] != 0) {
message_recip[i] = call[i];
i++;
}
message_recip_ssid = ssid;
}
void APRS_setPreamble(unsigned long pre) {
custom_preamble = pre;
}
void APRS_setTail(unsigned long tail) {
custom_tail = tail;
}
void APRS_useAlternateSymbolTable(bool use) {
if (use) {
symbolTable = '\\';
} else {
symbolTable = '/';
}
}
void APRS_setSymbol(char sym) {
symbol = sym;
}
void APRS_setLat(char *lat) {
memset(latitude, 0, 9);
int i = 0;
while (i < 8 && lat[i] != 0) {
latitude[i] = lat[i];
i++;
}
}
void APRS_setLon(char *lon) {
memset(longtitude, 0, 10);
int i = 0;
while (i < 9 && lon[i] != 0) {
longtitude[i] = lon[i];
i++;
}
}
void APRS_setPower(int s) {
if (s >= 0 && s < 10) {
power = s;
}
}
void APRS_setHeight(int s) {
if (s >= 0 && s < 10) {
height = s;
}
}
void APRS_setGain(int s) {
if (s >= 0 && s < 10) {
gain = s;
}
}
void APRS_setDirectivity(int s) {
if (s >= 0 && s < 10) {
directivity = s;
}
}
void APRS_printSettings() {
Serial.println(F("LibAPRS Settings:"));
Serial.print(F("Callsign: ")); Serial.print(CALL); Serial.print(F("-")); Serial.println(CALL_SSID);
Serial.print(F("Destination: ")); Serial.print(DST); Serial.print(F("-")); Serial.println(DST_SSID);
Serial.print(F("Path1: ")); Serial.print(PATH1); Serial.print(F("-")); Serial.println(PATH1_SSID);
Serial.print(F("Path2: ")); Serial.print(PATH2); Serial.print(F("-")); Serial.println(PATH2_SSID);
Serial.print(F("Message dst: ")); if (message_recip[0] == 0) { Serial.println(F("N/A")); } else { Serial.print(message_recip); Serial.print(F("-")); Serial.println(message_recip_ssid); }
Serial.print(F("TX Preamble: ")); Serial.println(custom_preamble);
Serial.print(F("TX Tail: ")); Serial.println(custom_tail);
Serial.print(F("Symbol table: ")); if (symbolTable == '/') { Serial.println(F("Normal")); } else { Serial.println(F("Alternate")); }
Serial.print(F("Symbol: ")); Serial.println(symbol);
Serial.print(F("Power: ")); if (power < 10) { Serial.println(power); } else { Serial.println(F("N/A")); }
Serial.print(F("Height: ")); if (height < 10) { Serial.println(height); } else { Serial.println(F("N/A")); }
Serial.print(F("Gain: ")); if (gain < 10) { Serial.println(gain); } else { Serial.println(F("N/A")); }
Serial.print(F("Directivity: ")); if (directivity < 10) { Serial.println(directivity); } else { Serial.println(F("N/A")); }
Serial.print(F("Latitude: ")); if (latitude[0] != 0) { Serial.println(latitude); } else { Serial.println(F("N/A")); }
Serial.print(F("Longtitude: ")); if (longtitude[0] != 0) { Serial.println(longtitude); } else { Serial.println(F("N/A")); }
}
void APRS_sendPkt(void *_buffer, size_t length) {
uint8_t *buffer = (uint8_t *)_buffer;
memcpy(dst.call, DST, 6);
dst.ssid = DST_SSID;
memcpy(src.call, CALL, 6);
src.ssid = CALL_SSID;
memcpy(path1.call, PATH1, 6);
path1.ssid = PATH1_SSID;
memcpy(path2.call, PATH2, 6);
path2.ssid = PATH2_SSID;
path[0] = dst;
path[1] = src;
path[2] = path1;
path[3] = path2;
ax25_sendVia(&AX25, path, countof(path), buffer, length);
}
// Dynamic RAM usage of this function is 30 bytes
void APRS_sendLoc(void *_buffer, size_t length) {
size_t payloadLength = 20+length;
bool usePHG = false;
if (power < 10 && height < 10 && gain < 10 && directivity < 9) {
usePHG = true;
payloadLength += 7;
}
uint8_t *packet = (uint8_t*)malloc(payloadLength);
uint8_t *ptr = packet;
packet[0] = '=';
packet[9] = symbolTable;
packet[19] = symbol;
ptr++;
memcpy(ptr, latitude, 8);
ptr += 9;
memcpy(ptr, longtitude, 9);
ptr += 10;
if (usePHG) {
packet[20] = 'P';
packet[21] = 'H';
packet[22] = 'G';
packet[23] = power+48;
packet[24] = height+48;
packet[25] = gain+48;
packet[26] = directivity+48;
ptr+=7;
}
if (length > 0) {
uint8_t *buffer = (uint8_t *)_buffer;
memcpy(ptr, buffer, length);
}
APRS_sendPkt(packet, payloadLength);
free(packet);
}
// Dynamic RAM usage of this function is 18 bytes
void APRS_sendMsg(void *_buffer, size_t length) {
if (length > 67) length = 67;
size_t payloadLength = 11+length+4;
uint8_t *packet = (uint8_t*)malloc(payloadLength);
uint8_t *ptr = packet;
packet[0] = ':';
int callSize = 6;
int count = 0;
while (callSize--) {
if (message_recip[count] != 0) {
packet[1+count] = message_recip[count];
count++;
}
}
if (message_recip_ssid != -1) {
packet[1+count] = '-'; count++;
if (message_recip_ssid < 10) {
packet[1+count] = message_recip_ssid+48; count++;
} else {
packet[1+count] = 49; count++;
packet[1+count] = message_recip_ssid-10+48; count++;
}
}
while (count < 9) {
packet[1+count] = ' '; count++;
}
packet[1+count] = ':';
ptr += 11;
if (length > 0) {
uint8_t *buffer = (uint8_t *)_buffer;
memcpy(ptr, buffer, length);
memcpy(lastMessage, buffer, length);
lastMessageLen = length;
}
message_seq++;
if (message_seq > 999) message_seq = 0;
packet[11+length] = '{';
int n = message_seq % 10;
int d = ((message_seq % 100) - n)/10;
int h = (message_seq - d - n) / 100;
packet[12+length] = h+48;
packet[13+length] = d+48;
packet[14+length] = n+48;
APRS_sendPkt(packet, payloadLength);
free(packet);
}
void APRS_msgRetry() {
message_seq--;
APRS_sendMsg(lastMessage, lastMessageLen);
}
// For getting free memory, from:
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720/15
extern unsigned int __heap_start;
extern void *__brkval;
struct __freelist {
size_t sz;
struct __freelist *nx;
};
extern struct __freelist *__flp;
int freeListSize() {
struct __freelist* current;
int total = 0;
for (current = __flp; current; current = current->nx) {
total += 2; /* Add two bytes for the memory block's header */
total += (int) current->sz;
}
return total;
}
int freeMemory() {
int free_memory;
if ((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__heap_start);
} else {
free_memory = ((int)&free_memory) - ((int)__brkval);
free_memory += freeListSize();
}
return free_memory;
}