diff --git a/firmware/Peripherals.md b/firmware/Peripherals.md index a214494..5f0250c 100644 --- a/firmware/Peripherals.md +++ b/firmware/Peripherals.md @@ -5,7 +5,6 @@ |*GLCK*| ||gclk0|main clock, internal osc8m|4 MHz ||gclk1|tcxo clock, fed from xosc OR osc8m -| ||gclk7|aprs clock, fed from gclk1, div 6 / 11 |*TC*|| diff --git a/firmware/inc/aprs.h b/firmware/inc/aprs.h index 53cfca7..8b91f6a 100644 --- a/firmware/inc/aprs.h +++ b/firmware/inc/aprs.h @@ -26,6 +26,6 @@ #define APRS_H void aprs_init(void); -void aprs_tick(void); +uint8_t aprs_tick(void); #endif /* APRS_H */ diff --git a/firmware/inc/ax25.h b/firmware/inc/ax25.h index dddb910..15a2153 100644 --- a/firmware/inc/ax25.h +++ b/firmware/inc/ax25.h @@ -33,6 +33,12 @@ #define AX25_MARK_FREQ 1200 #define AX25_SPACE_FREQ 2200 +/** + * GCLK division factors + */ +#define AX25_DIVISION_MARK 11 +#define AX25_DIVISION_SPACE 6 + /** * How often our handler gets called */ @@ -51,11 +57,12 @@ */ #define AX25_CONTROL_WORD 0x03 /* Use Unnumbered Information (UI) frames */ #define AX25_PROTOCOL_ID 0xF0 /* No third level protocol */ - +#define AX25_HDLC_FLAG 0x7E enum ax25_symbol_t { AX25_MARK, AX25_SPACE, + AX25_NONE, }; struct ax25_byte_t { uint8_t val; diff --git a/firmware/src/aprs.c b/firmware/src/aprs.c index 676f01e..ac48588 100644 --- a/firmware/src/aprs.c +++ b/firmware/src/aprs.c @@ -28,6 +28,14 @@ #include "samd20.h" #include "ax25.h" +/** + * USEFUL RESOURCES + * ============================================================================= + * + * http://www.aprs.org/doc/APRS101.PDF + * http://k9dci.home.comcast.net/~k9dci/APRS%20Beginner%20Guide%20-%20K9DCI%20Ver%205-1.pdf + */ + char addresses[50]; void aprs_start(void) @@ -40,7 +48,7 @@ void aprs_start(void) ax25_start(addresses, 21, "testtest", 8); } -void aprs_tick(void) +uint8_t aprs_tick(void) { - ax25_tick(); + return ax25_tick(); } diff --git a/firmware/src/ax25.c b/firmware/src/ax25.c index 9efedd2..55fc89e 100644 --- a/firmware/src/ax25.c +++ b/firmware/src/ax25.c @@ -23,6 +23,7 @@ */ #include +#include #include "samd20.h" #include "system/gclk.h" @@ -46,6 +47,19 @@ uint32_t ax25_index, ax25_frame_length; void ax25_gpio1_pwm_init(void); + +/** + * USEFUL RESOURCES + * ============================================================================= + * + * http://en.wikipedia.org/wiki/AX.25 + * https://www.tapr.org/pub_ax25.html#2.4.1.2 + * http://owenduffy.net/blog/?p=2101 + * http://n1vg.net/packet/ + */ + + + /** * Frame Check Sequence (FCS) * ============================================================================= @@ -89,7 +103,7 @@ uint16_t crc_fcs(uint8_t *string, uint32_t length) void ax25_start(char* addresses, uint32_t addresses_len, char* information, uint32_t information_len) { - uint32_t i, j; + uint32_t i; uint16_t fcs; /* Process addresses */ @@ -140,7 +154,9 @@ void ax25_gpio1_pwm_init(void) { float gclk1_frequency = (float)system_gclk_gen_get_hz(1); - uint32_t top = 38;//(uint32_t)(gclk1_frequency / 13200.0*4);// & ~0x1; + float divide_needed = round(gclk1_frequency / (13200*4)); + + uint32_t top = (uint32_t)divide_needed & ~0x1; uint32_t capture = top >> 1; /* 50% duty cycle */ if (top > 0xFF) while (1); // It's only an 8-bit counter @@ -149,7 +165,7 @@ void ax25_gpio1_pwm_init(void) system_gclk_gen_set_config(GCLK_GENERATOR_7, GCLK_SOURCE_GCLKGEN1, /* Source */ false, /* High When Disabled */ - 11, /* Division Factor */// TODO + AX25_DIVISION_MARK,/* Division Factor */ false, /* Run in standby */ false); /* Output Pin Enable */ system_gclk_gen_enable(GCLK_GENERATOR_7); @@ -189,14 +205,13 @@ void ax25_gpio1_pwm_init(void) /** * Returns the next byte to transmit */ -struct ax25_byte_t ax25_get_next_byte(void) { - - /* Return HLDC flag by default */ - struct ax25_byte_t next = { .val = 0x7E, .stuff = 0 }; +uint8_t ax25_get_next_byte(struct ax25_byte_t* next) { switch (ax25_state) { case AX25_PREAMBLE: /* Preamble */ - /* Return flag by default*/ + /* Return flag */ + next->val = AX25_HDLC_FLAG; + next->stuff = 0; /* Check for next state */ ax25_index++; @@ -210,8 +225,8 @@ struct ax25_byte_t ax25_get_next_byte(void) { case AX25_FRAME: /* Frame */ /* Return data */ - next.val = ax25_frame[ax25_index]; - next.stuff = 1; + next->val = ax25_frame[ax25_index]; + next->stuff = 1; /* Check for next state */ ax25_index++; @@ -224,7 +239,9 @@ struct ax25_byte_t ax25_get_next_byte(void) { case AX25_POSTAMBLE: /* Postamble */ - /* Return flag by default */ + /* Return flag */ + next->val = AX25_HDLC_FLAG; + next->stuff = 0; /* Check for next state */ ax25_index++; @@ -237,29 +254,31 @@ struct ax25_byte_t ax25_get_next_byte(void) { default: - break; + return 0; } - return next; + return 1; } /** * Returns the next symbol to transmit */ -enum ax25_symbol_t ax25_get_next_symbol(void) { - - uint8_t bit; - +enum ax25_symbol_t ax25_get_next_symbol(void) +{ + /* Get next byte if we need to */ if (bit_index >= 8) { - current_byte = ax25_get_next_byte(); + + /* Attempt to get the next byte */ + if (!ax25_get_next_byte(¤t_byte)) { + return AX25_NONE; /* We're done */ + } bit_index = 0; + } /* transmit bits lsb first */ - bit = current_byte.val & 0x01; - - if (bit) { /* One */ + if (current_byte.val & 0x01) { /* One */ one_count++; @@ -293,30 +312,28 @@ enum ax25_symbol_t ax25_get_next_symbol(void) { */ uint8_t ax25_tick(void) { + if (next_symbol == AX25_NONE) { + return 0; /* We're done */ + } if (next_symbol == AX25_SPACE) { - - + /* Space */ system_gclk_gen_set_config(GCLK_GENERATOR_7, GCLK_SOURCE_GCLKGEN1, /* Source */ false, /* High When Disabled */ - 6, /* Division Factor */// TODO + AX25_DIVISION_SPACE, /* Division Factor */ false, /* Run in standby */ false); /* Output Pin Enable */ - } else { - - + /* Mark */ system_gclk_gen_set_config(GCLK_GENERATOR_7, GCLK_SOURCE_GCLKGEN1, /* Source */ false, /* High When Disabled */ - 11, /* Division Factor */// TODO + AX25_DIVISION_MARK, /* Division Factor */ false, /* Run in standby */ false); /* Output Pin Enable */ - } next_symbol = ax25_get_next_symbol(); - return 1; } diff --git a/firmware/src/main.c b/firmware/src/main.c index 7e9a34f..2594b22 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -323,10 +323,14 @@ int main(void) led_on(); - telemetry_start(TELEMETRY_APRS, 0xFFFF); - while (1) { - system_sleep(); + telemetry_start(TELEMETRY_APRS, 0xFFFF); + + while (telemetry_active()) { + system_sleep(); + } + + for (int i = 0; i < 1000*1000; i++); } diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index e5d4a01..7f65677 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -310,10 +310,15 @@ void telemetry_tick(void) { /* APRS: We use pwm to control gpio1 */ aprs_start(); - si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 200); + si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 400); radio_on = 1; } - aprs_tick(); + + if (!aprs_tick()) { + /* Transmission Finished */ + telemetry_stop(); + if (is_telemetry_finished()) return; + } break;