From 2c9f5fd0704141b3da0e590c535ee04813ef60f6 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 23 Dec 2014 13:50:12 +0100 Subject: [PATCH] Various bugfixes --- LibAPRS/AFSK.cpp | 3 +- LibAPRS/LibAPRS.cpp | 71 ++++++++++---- LibAPRS/LibAPRS.h | 4 +- LibAPRS/examples/Basic_usage/Basic_usage.ino | 97 ++++++++++++++++---- README.md | 6 +- 5 files changed, 139 insertions(+), 42 deletions(-) diff --git a/LibAPRS/AFSK.cpp b/LibAPRS/AFSK.cpp index aa9b75d..5f07619 100644 --- a/LibAPRS/AFSK.cpp +++ b/LibAPRS/AFSK.cpp @@ -1,5 +1,6 @@ #include #include "AFSK.h" +#include "Arduino.h" extern unsigned long custom_preamble; extern unsigned long custom_tail; @@ -465,7 +466,7 @@ ISR(ADC_vect) { } poll_timer++; - if (poll_timer > 4) { + if (poll_timer > 3) { poll_timer = 0; APRS_poll(); } diff --git a/LibAPRS/LibAPRS.cpp b/LibAPRS/LibAPRS.cpp index 83ed9e5..ae29a41 100644 --- a/LibAPRS/LibAPRS.cpp +++ b/LibAPRS/LibAPRS.cpp @@ -58,7 +58,6 @@ void APRS_poll(void) { } void APRS_setCallsign(char *call, int ssid) { - Serial.println("Setting to: "); memset(CALL, 0, 7); int i = 0; while (i < 6 && call[i] != 0) { @@ -171,23 +170,22 @@ void APRS_setDirectivity(int s) { } void APRS_printSettings() { - Serial.println("LibAPRS Settings:"); - Serial.print("Callsign: "); Serial.print(CALL); Serial.print("-"); Serial.println(CALL_SSID); - Serial.print("Destination: "); Serial.print(DST); Serial.print("-"); Serial.println(DST_SSID); - Serial.print("Path1: "); Serial.print(PATH1); Serial.print("-"); Serial.println(PATH1_SSID); - Serial.print("Path2: "); Serial.print(PATH2); Serial.print("-"); Serial.println(PATH2_SSID); - Serial.print("Message dst: "); if (message_recip[0] == 0) { Serial.println("N/A"); } else { Serial.print(message_recip); Serial.print("-"); Serial.println(message_recip_ssid); } - Serial.print("TX Preamble: "); Serial.println(custom_preamble); - Serial.print("TX Tail: "); Serial.println(custom_tail); - Serial.print("Symbol table: "); if (symbolTable = '/') { Serial.println("Normal"); } else { Serial.println("Alternate"); } - Serial.print("Symbol: "); Serial.println(symbol); - Serial.print("Power: "); if (power < 10) { Serial.println(power); } else { Serial.println("N/A"); } - Serial.print("Height: "); if (height < 10) { Serial.println(height); } else { Serial.println("N/A"); } - Serial.print("Gain: "); if (gain < 10) { Serial.println(gain); } else { Serial.println("N/A"); } - Serial.print("Directivity: "); if (directivity < 10) { Serial.println(directivity); } else { Serial.println("N/A"); } - Serial.print("Latitude: "); if (latitude[0] != 0) { Serial.println(latitude); } else { Serial.println("N/A"); } - Serial.print("Longtitude: "); if (longtitude[0] != 0) { Serial.println(longtitude); } else { Serial.println("N/A"); } - + 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) { @@ -214,6 +212,7 @@ void APRS_sendPkt(void *_buffer, size_t length) { 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; @@ -250,6 +249,7 @@ void APRS_sendLoc(void *_buffer, size_t length) { 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; @@ -299,11 +299,44 @@ void APRS_sendMsg(void *_buffer, size_t length) { 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; } \ No newline at end of file diff --git a/LibAPRS/LibAPRS.h b/LibAPRS/LibAPRS.h index d546c92..69a9c11 100644 --- a/LibAPRS/LibAPRS.h +++ b/LibAPRS/LibAPRS.h @@ -34,4 +34,6 @@ void APRS_sendLoc(void *_buffer, size_t length); void APRS_sendMsg(void *_buffer, size_t length); void APRS_msgRetry(); -void APRS_printSettings(); \ No newline at end of file +void APRS_printSettings(); + +int freeMemory(); diff --git a/LibAPRS/examples/Basic_usage/Basic_usage.ino b/LibAPRS/examples/Basic_usage/Basic_usage.ino index 37de64a..5bbcce9 100644 --- a/LibAPRS/examples/Basic_usage/Basic_usage.ino +++ b/LibAPRS/examples/Basic_usage/Basic_usage.ino @@ -18,15 +18,46 @@ // You always need to include this function. It will // get called by the library every time a packet is // received, so you can process incoming packets. +// +// IMPORTANT! This function is called from within an +// interrupt. That means that you should only do things +// here that are FAST. Don't print out info directly +// from this function, instead set a flag and print it +// from your main loop, like this: + +boolean gotPacket = false; +AX25Msg incomingPacket; +uint8_t *packetData; void aprs_msg_callback(struct AX25Msg *msg) { - Serial.print("Received APRS packet. Data: "); - for (int i = 0; i < msg->len; i++) { Serial.write(msg->info[i]); } - Serial.println(""); + // If we already have a packet waiting to be + // processed, we must drop the new one. + if (!gotPacket) { + // Set flag to indicate we got a packet + gotPacket = true; + + // The memory referenced as *msg is volatile + // and we need to copy all the data to a + // local variable for later processing. + memcpy(&incomingPacket, msg, sizeof(AX25Msg)); + + // We need to allocate a new buffer for the + // data payload of the packet. First we check + // if there is enough free RAM. + if (freeMemory() > msg->len) { + packetData = (uint8_t*)malloc(msg->len); + memcpy(packetData, msg->info, msg->len); + incomingPacket.info = packetData; + } else { + // We did not have enough free RAM to receive + // this packet, so we drop it. + gotPacket = false; + } + } } void setup() { // Set up serial port - Serial.begin(9600); + Serial.begin(115200); // Initialise APRS library - This starts the modem APRS_init(); @@ -36,25 +67,26 @@ void setup() { // You don't need to set the destination identifier, but // if you want to, this is how you do it: - APRS_setDestination("APZMDM", 0); + // APRS_setDestination("APZMDM", 0); // Path parameters are set to sensible values by // default, but this is how you can configure them: - APRS_setPath1("WIDE1", 1); - APRS_setPath2("WIDE2", 2); + // APRS_setPath1("WIDE1", 1); + // APRS_setPath2("WIDE2", 2); // You can define preamble and tail like this: - APRS_setPreamble(350); - APRS_setTail(50); + // APRS_setPreamble(350); + // APRS_setTail(50); // You can use the normal or alternate symbol table: - APRS_useAlternateSymbolTable(false); + // APRS_useAlternateSymbolTable(false); // And set what symbol you want to use: - APRS_setSymbol('n'); + // APRS_setSymbol('n'); // We can print out all the settings APRS_printSettings(); + Serial.print(F("Free RAM: ")); Serial.println(freeMemory()); } void locationUpdateExample() { @@ -79,7 +111,7 @@ void locationUpdateExample() { char *comment = "LibAPRS location update"; // And send the update - APRS_sendLoc(comment, sizeof(comment)); + APRS_sendLoc(comment, strlen(comment)); } @@ -88,19 +120,44 @@ void messageExample() { APRS_setMessageDestination("AA3BBB", 0); // And define a string to send - char *message = "Hi there! This is a message"; - APRS_sendMsg(message, sizeof(message)); + char *message = "Hi there! This is a message."; + APRS_sendMsg(message, strlen(message)); } +// Here's a function to process incoming packets +// Remember to call this function often, so you +// won't miss any packets due to one already +// waiting to be processed +void processPacket() { + if (gotPacket) { + gotPacket = false; + Serial.print(F("Received APRS packet. Data: ")); + for (int i = 0; i < incomingPacket.len; i++) { + Serial.write(incomingPacket.info[i]); + } + Serial.println(""); + + // Remeber to free memory for our buffer! + free(packetData); + + // You can print out the amount of free + // RAM to check you don't have any memory + // leaks + // Serial.print(F("Free RAM: ")); Serial.println(freeMemory()); + } +} + +boolean whichExample = false; void loop() { delay(2000); - locationUpdateExample(); - - delay(2000); - messageExample(); - // Just for fun we print out the settings - APRS_printSettings(); + processPacket(); + if (whichExample) { + locationUpdateExample(); + } else { + messageExample(); + } + whichExample ^= true; } \ No newline at end of file diff --git a/README.md b/README.md index 1845ba0..da89cc7 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,8 @@ See the example included in the library for info on how to use it! - Ability to send raw packets - Support for settings APRS symbols - Support for power/height/gain info in location updates -- Can run with open squelch \ No newline at end of file +- Can run with open squelch + +## Installation + +Place the "LibAPRS" folder (the one in the same folder as this readme file) inside your Arduino "libraries" folder. That's all! \ No newline at end of file