#include "Arduino.h" #include "AFSK.h" #include "AX25.h" // extern "C" { // //#include "user_interface.h" // }uint32_t freemem = system_get_free_heap_size(); Afsk modem; AX25Ctx AX25; extern void aprs_msg_callback(struct AX25Msg *msg); #define countof(a) sizeof(a) / sizeof(a[0]) 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] = "APE32I"; int DST_SSID = 0; char PATH1[7] = "WIDE1"; int PATH1_SSID = 1; char PATH2[7] = "WIDE2"; int PATH2_SSID = 2; AX25Call path[8]; // 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() { 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); } void APRS_sendTNC2Pkt(String raw) { ax25frame frame; // Serial.println(raw); ax25_encode(frame, (char *)raw.c_str(), raw.length()); ax25sendFrame(&AX25, &frame); } // 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); } int freeMemory() { int free_memory = ESP.getFreeHeap(); return free_memory; }