From cbb004db7eeb9a189946fbb2bd8b5de53b9097a1 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Fri, 27 Feb 2015 10:55:05 +0000 Subject: [PATCH] [New Feature] Contestia Packet output, re-organised telemetry module --- firmware/inc/contestia.h | 38 ++++++++++ firmware/inc/rtty.h | 18 +---- firmware/inc/si_trx.h | 2 + firmware/inc/telemetry.h | 23 ++++++ firmware/src/contestia.c | 72 ++++++++++++++++++ firmware/src/main.c | 126 +++++++------------------------ firmware/src/mfsk.c | 2 +- firmware/src/rtty.c | 111 ++++++++++------------------ firmware/src/telemetry.c | 156 ++++++++++++++++++++++++++++++++++++++- 9 files changed, 353 insertions(+), 195 deletions(-) create mode 100644 firmware/inc/contestia.h create mode 100644 firmware/src/contestia.c diff --git a/firmware/inc/contestia.h b/firmware/inc/contestia.h new file mode 100644 index 0000000..cac6a31 --- /dev/null +++ b/firmware/inc/contestia.h @@ -0,0 +1,38 @@ +/* + * Outputs contestia to the si_trx + * Copyright (C) 2015 Richard Meadows + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef CONTESTIA_H +#define CONTESTIA_H + +/** + * Contestia 32/1000 + */ +#define CONTESTIA_NUMBER_OF_TONES 32 +#define CONTESTIA_CHARACTERS_PER_BLOCK 5 + + +void contestia_start(char* data); +uint8_t contestia_tick(void); + +#endif /* CONTESTIA_H */ diff --git a/firmware/inc/rtty.h b/firmware/inc/rtty.h index 5088927..af6ebd1 100644 --- a/firmware/inc/rtty.h +++ b/firmware/inc/rtty.h @@ -25,21 +25,7 @@ #ifndef RTTY_H #define RTTY_H -#include "util/dbuffer.h" - -/** - * Output String - */ -#define RTTY_STRING_MAX 0x200 -/** - * It's actually a double buffer which we swap for mid-string updates - */ -ARRAY_DBUFFER_T(char, RTTY_STRING_MAX) rtty_dbuffer_string; - -int rtty_active(void); -int rtty_start(void); -int32_t rtty_get_index(void); -void rtty_set_length(int32_t length); -void rtty_tick(void); +void rtty_start(uint8_t data); +uint8_t rtty_tick(void); #endif /* RTTY_H */ diff --git a/firmware/inc/si_trx.h b/firmware/inc/si_trx.h index cfd544d..01f908c 100644 --- a/firmware/inc/si_trx.h +++ b/firmware/inc/si_trx.h @@ -25,6 +25,8 @@ #ifndef SI_TRX_H #define SI_TRX_H +#include "samd20.h" + float si_trx_get_temperature(void); void si_trx_on(uint8_t modulation_type, float channel_spacing); diff --git a/firmware/inc/telemetry.h b/firmware/inc/telemetry.h index 0c075fd..2e98008 100644 --- a/firmware/inc/telemetry.h +++ b/firmware/inc/telemetry.h @@ -26,6 +26,29 @@ #define TELEMETRY_H uint16_t crc_checksum(char *string); + +#include "util/dbuffer.h" + +enum telemetry_t { + TELEMETRY_RTTY, + TELEMETRY_CONTESTIA +}; + +/** + * Output String + */ +#define TELEMETRY_STRING_MAX 0x1F0 +#define TELEMETRY_LARGEST_BLOCK 0x10 +/** + * It's actually a double buffer which we swap for mid-string updates + */ +ARRAY_DBUFFER_T(char, TELEMETRY_STRING_MAX+TELEMETRY_LARGEST_BLOCK) telemetry_dbuffer_string; + +int telemetry_active(void); +int telemetry_start(enum telemetry_t type); +int32_t telemetry_get_index(void); +void telemetry_set_length(int32_t length); + void timer0_tick_init(float frequency); #endif /* TELEMETRY_H */ diff --git a/firmware/src/contestia.c b/firmware/src/contestia.c new file mode 100644 index 0000000..1852c69 --- /dev/null +++ b/firmware/src/contestia.c @@ -0,0 +1,72 @@ +/* + * Outputs contestia to the si_trx + * Copyright (C) 2015 Richard Meadows + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "si_trx.h" +#include "contestia.h" + + +/** + * Current output tones + */ +int8_t contestia_tones[CONTESTIA_NUMBER_OF_TONES]; +/** + * Where we are in the current output tones + */ +uint32_t contestia_tone_index = 0xFFFFFFFE; + +/** + * Starts the transmission of a contestia block + */ +void contestia_start(char* block) { + /* Start transmission */ + contestia_mfsk_encode_block(block, contestia_tones); + contestia_tone_index = 0; +} + +/** + * Called at the baud rate, outputs tones + */ +uint8_t contestia_tick(void) { + + if (contestia_tone_index < CONTESTIA_NUMBER_OF_TONES) { + uint8_t binary_code; + uint8_t grey_code; + + /* Output grey code */ + binary_code = contestia_tones[contestia_tone_index]; + grey_code = (binary_code >> 1) ^ binary_code; + si_trx_switch_channel(grey_code); + + } else { + return 0; + } + + contestia_tone_index++; + + if (contestia_tone_index < CONTESTIA_NUMBER_OF_TONES) { + return 1; + } + + return 0; +} diff --git a/firmware/src/main.c b/firmware/src/main.c index 8b859e1..2102743 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -43,7 +43,6 @@ #include "si_trx_defs.h" #include "analogue.h" #include "spi_bitbang.h" -#include "rtty.h" #include "system/interrupt.h" #define CALLSIGN "UBSEDSx" @@ -155,10 +154,14 @@ void output_telemetry_string(void) uint32_t altitude = 0; /** - * Callsign, Time + * Analogue, Callsign, Time * --------------------------------------------------------------------------- */ + /* Analogue */ + float battery = get_battery(); + float temperature = si_trx_get_temperature(); // REENTRANCY!!!!!! + /* GPS Time */ gps_update_time(); @@ -166,7 +169,7 @@ void output_telemetry_string(void) while (gps_update_time_pending()) { system_sleep(); } - for (int i = 0; i < 100*1000; i++); +// for (int i = 0; i < 100*1000; i++); /* Time */ struct ubx_nav_timeutc time = gps_get_nav_timeutc(); @@ -175,30 +178,31 @@ void output_telemetry_string(void) uint8_t seconds = time.payload.sec; /* init double buffers */ - ARRAY_DBUFFER_INIT(&rtty_dbuffer_string); + ARRAY_DBUFFER_INIT(&telemetry_dbuffer_string); /* sprintf - initial string */ - uint16_t len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string), + uint16_t len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&telemetry_dbuffer_string), "$$%s,%02u:%02u:%02u,", CALLSIGN, hours, minutes, seconds); /* swap buffers */ - ARRAY_DBUFFER_SWAP(&rtty_dbuffer_string); + ARRAY_DBUFFER_SWAP(&telemetry_dbuffer_string); - /* start */ - rtty_start(); + /* start - SI NOW BELONGS TO TELEMETRY, WE CANNOT ACCESS */ +#ifdef RTTY + telemetry_start(TELEMETRY_RTTY); +#endif +#ifdef CONTESTIA + telemetry_start(TELEMETRY_CONTESTIA); +#endif /** - * Position, Status, Analogue, Checksum + * Position, Status, Checksum * --------------------------------------------------------------------------- */ - /* Analogue */ - float battery = get_battery(); - float temperature = si_trx_get_temperature(); - /* Sleep Wait */ - while (rtty_get_index() < (len - 4)) { + while (telemetry_get_index() < (len - 9)) { system_sleep(); } @@ -211,7 +215,7 @@ void output_telemetry_string(void) } /* Wait for the gps update. Move on if it's urgent */ - while (gps_update_position_pending() && rtty_get_index() < (len - 1)) { + while (gps_update_position_pending() && telemetry_get_index() < (len - 6)) { system_sleep(); } @@ -235,18 +239,18 @@ void output_telemetry_string(void) } /* sprintf - full string */ - len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string), + len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&telemetry_dbuffer_string), "$$%s,%02u:%02u:%02u,%02.6f,%03.6f,%ld,%u,%.2f,%.1f", CALLSIGN, hours, minutes, seconds, lat_fmt, lon_fmt, altitude, satillite_count, battery, temperature); /* sprintf - checksum */ - len += sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string) + len, - "*%04X\n", - crc_checksum(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string))); + len += sprintf(ARRAY_DBUFFER_WRITE_PTR(&telemetry_dbuffer_string) + len, + "*%04X\r", + crc_checksum(ARRAY_DBUFFER_WRITE_PTR(&telemetry_dbuffer_string))); /* swap buffers */ - ARRAY_DBUFFER_SWAP(&rtty_dbuffer_string); + ARRAY_DBUFFER_SWAP(&telemetry_dbuffer_string); /** * End @@ -254,27 +258,14 @@ void output_telemetry_string(void) */ /* Set the final length */ - rtty_set_length(len); + telemetry_set_length(len); /* Sleep Wait */ - while (rtty_active()) { + while (telemetry_active()) { system_sleep(); } } -uint8_t started = 0; -/* We transmit 64 tones */ -int8_t tones[] = { - 0x1a, 0x0c, 0x07, 0x1b, 0x00, 0x13, 0x12, 0x0d, - 0x12, 0x0d, 0x1f, 0x11, 0x1c, 0x1b, 0x18, 0x1e, - 0x0e, 0x02, 0x0e, 0x0a, 0x05, 0x08, 0x13, 0x13, - 0x1f, 0x10, 0x09, 0x0d, 0x07, 0x10, 0x1a, 0x1c, - 0x0b, 0x10, 0x01, 0x0e, 0x0f, 0x19, 0x0a, 0x1d, - 0x06, 0x1b, 0x0c, 0x13, 0x02, 0x0f, 0x06, 0x0c, - 0x1d, 0x15, 0x17, 0x09, 0x15, 0x14, 0x1f, 0x00, - 0x08, 0x06, 0x05, 0x09, 0x12, 0x13, 0x1e, 0x0a -}; - /** * MAIN * ============================================================================= @@ -324,27 +315,6 @@ int main(void) /* Initialise Si4060 interface */ si_trx_init(); - /* Start transmitting */ -#ifdef RTTY - /* RTTY Mode: We modulate using the external pin */ - si_trx_on(SI_MODEM_MOD_TYPE_2FSK, 0); -#endif -#ifdef CONTESTIA - /* Contestia: We switch channel to modulate */ - si_trx_on(SI_MODEM_MOD_TYPE_CW, 31.25); -#endif - - - - - /* Prepare a tone sequence */ - char hello[] = "HELLO"; -// olivia_mfsk_encode_block(hello, tones); - contestia_mfsk_encode_block(hello, tones); - - - started = 1; - /* Timer 0 clocks out data */ #ifdef RTTY @@ -364,47 +334,3 @@ int main(void) output_telemetry_string(); } } - -uint32_t tone_index = 0; -uint8_t binary_code; -uint8_t grey_code; - -/** - * Called at the symbol rate - */ -void TC0_Handler(void) -{ - if (tc_get_status(TC0) & TC_STATUS_CHANNEL_0_MATCH) { - tc_clear_status(TC0, TC_STATUS_CHANNEL_0_MATCH); - -#ifdef RTTY - rtty_tick(); -#endif -#ifdef CONTESTIA - if (started) { - if (tone_index < 32) { - - binary_code = tones[tone_index]; - grey_code = (binary_code >> 1) ^ binary_code; - - si_trx_switch_channel(grey_code); - - } else if (tone_index < 64) { - - si_trx_state_ready(); - - /* } else if (tone_index < 96) { */ - - /* si_trx_switch_channel((tone_index & 1) ? 0 : 31); */ - - } - - tone_index++; - if (tone_index >= 64) - { - tone_index = 0; - } - } -#endif - } -} diff --git a/firmware/src/mfsk.c b/firmware/src/mfsk.c index 115d420..b77fe7c 100644 --- a/firmware/src/mfsk.c +++ b/firmware/src/mfsk.c @@ -128,7 +128,7 @@ void contestia_mfsk_encode_block(char* block, int8_t* tones) { size_t bits_per_symbol = 5; /* That is, there are 2^5=32 tones */ - for (uint8_t c_index; c_index < bits_per_symbol; c_index++) { + for (uint8_t c_index = 0; c_index < bits_per_symbol; c_index++) { char character = block[c_index]; /* lowercase => UPPERCASE */ diff --git a/firmware/src/rtty.c b/firmware/src/rtty.c index 1c5ef13..60f5517 100644 --- a/firmware/src/rtty.c +++ b/firmware/src/rtty.c @@ -43,6 +43,10 @@ #define ASCII_BITS 8 #define BITS_PER_CHAR 11 +/** + * Current output data + */ +uint8_t rtty_data; /** * Where we currently are in the rtty output byte * @@ -51,90 +55,49 @@ * 10 = Stop Bit * 11 = Stop Bit */ -uint8_t rtty_phase; -/** - * Where we are in the current output string - */ -int32_t rtty_index; +uint8_t rtty_phase = 0xFE; -/** - * Details of the string that is currently being output - */ -int32_t rtty_string_length = 0; - -/** - * Returns 1 if we're currently outputting. - */ -int rtty_active(void) { - return (rtty_string_length > 0); -} - -/** - * Starts RTTY output - * - * Returns 0 on success, 1 if already active - */ -int rtty_start(void) { - if (!rtty_active()) { - - /* Initialise */ - rtty_string_length = RTTY_STRING_MAX; - rtty_index = 0; - rtty_phase = 0; - - return 0; /* Success */ - } else { - return 1; /* Already active */ - } -} -/** - * Returns the index of the current byte being outputted from the buffer - */ -int32_t rtty_get_index(void) { - return rtty_index; -} -/** - * Sets the final length of the RTTY string - */ -void rtty_set_length(int32_t length) { - if (length <= RTTY_STRING_MAX) { - rtty_string_length = length; - } +void rtty_start(uint8_t data) { + /* Start transmission */ + rtty_phase = 0; + rtty_data = data; } /** * Called at the baud rate, outputs bits of rtty */ -void rtty_tick(void) { - if (rtty_active()) { - RTTY_ACTIVATE(); +uint8_t rtty_tick(void) { - if (rtty_phase == 0) { // Start - // Low - RTTY_SET(0); - } else if (rtty_phase < ASCII_BITS + 1) { - // Data - if ((ARRAY_DBUFFER_READ_PTR(&rtty_dbuffer_string)[rtty_index] >> (rtty_phase - 1)) & 1) { - RTTY_SET(1); - } else { - RTTY_SET(0); - } - } else if (rtty_phase < BITS_PER_CHAR) { // Stop - // High + if (rtty_phase == 0) { /* *** Start *** */ + RTTY_SET(0); + + } else if (rtty_phase < ASCII_BITS + 1) { /* *** Data *** */ + if ((rtty_data >> (rtty_phase - 1)) & 1) { RTTY_SET(1); + } else { + RTTY_SET(0); } - rtty_phase++; + } else if (rtty_phase < BITS_PER_CHAR) { /* *** Stop *** */ + RTTY_SET(1); - if (rtty_phase >= BITS_PER_CHAR) { // Next character - rtty_phase = 0; rtty_index++; RTTY_NEXT(); - - if (rtty_index >= rtty_string_length) { // All done, deactivate - rtty_string_length = 0; // Deactivate - } - } - } else { - RTTY_DEACTIVATE(); + } else { /* *** Not running *** */ + return 0; } -} + rtty_phase++; + + if (rtty_phase < BITS_PER_CHAR) { + return 1; + } + + /* if (rtty_phase >= BITS_PER_CHAR) { // Next character */ + /* rtty_phase = 0; rtty_index++; RTTY_NEXT(); */ + + /* if (rtty_index >= rtty_string_length) { // All done, deactivate */ + /* rtty_string_length = 0; // Deactivate */ + /* } */ + /* } */ + + return 0; +} diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index 66f5bb9..56579da 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -26,12 +26,21 @@ #include #include "samd20.h" +#include "telemetry.h" +#include "rtty.h" +#include "contestia.h" +#include "si_trx.h" +#include "si_trx_defs.h" #include "system/gclk.h" #include "system/interrupt.h" #include "system/pinmux.h" #include "tc/tc_driver.h" #include "hw_config.h" +/** + * CYCLIC REDUNDANCY CHECK (CRC) + * ============================================================================= + */ /** * CRC Function for the XMODEM protocol. @@ -75,12 +84,143 @@ uint16_t crc_checksum(char *string) } +/** + * TELEMETRY OUTPUT + * ============================================================================= + */ + +/** + * The type of telemetry we're currently outputting + */ +enum telemetry_t telemetry_type; +/** + * Current output + */ +int32_t telemetry_string_length = 0; +/** + * Where we are in the current output + */ +int32_t telemetry_index; +/** + * Is the radio currently on? + */ +uint8_t radio_on = 0; + + +/** + * Returns 1 if we're currently outputting. + */ +int telemetry_active(void) { + return (telemetry_string_length > 0); +} + +/** + * Starts telemetry output + * + * Returns 0 on success, 1 if already active + */ +int telemetry_start(enum telemetry_t type) { + if (!telemetry_active()) { + + /* Initialise */ + telemetry_type = type; + telemetry_index = 0; + + /* Initialise first block / character */ + telemetry_string_length = TELEMETRY_STRING_MAX; + return 0; /* Success */ + } else { + return 1; /* Already active */ + } +} +/** + * Returns the index of the current byte being outputted from the buffer + */ +int32_t telemetry_get_index(void) { + return telemetry_index; +} +/** + * Sets the final length of the TELEMETRY string + */ +void telemetry_set_length(int32_t length) { + if (length <= TELEMETRY_STRING_MAX) { + telemetry_string_length = length; + } +} +uint8_t is_telemetry_finished(void) { + if (telemetry_index > telemetry_string_length) { + /* All done, deactivate */ + telemetry_string_length = 0; + + /* Turn radio off */ + si_trx_off(); radio_on = 0; + + return 1; + } + return 0; +} + + +/** + * Called at the telemetry mode's baud rate + */ +void telemetry_tick(void) { + if (telemetry_active()) { + switch (telemetry_type) { + case TELEMETRY_CONTESTIA: /* ---- ---- A block mode */ + + if (!radio_on) { + /* Contestia: We switch channel to modulate */ + si_trx_on(SI_MODEM_MOD_TYPE_CW, 31.25); + radio_on = 1; + } + + if (!contestia_tick()) { + /* Transmission Finished */ + if (is_telemetry_finished()) return; + + /* Let's start again */ + char* block = &ARRAY_DBUFFER_READ_PTR(&telemetry_dbuffer_string)[telemetry_index]; + telemetry_index += CONTESTIA_CHARACTERS_PER_BLOCK; + + contestia_start(block); + } + + break; + case TELEMETRY_RTTY: /* ---- ---- A character mode */ + + if (!radio_on) { + /* RTTY Mode: We modulate using the external pin */ + si_trx_on(SI_MODEM_MOD_TYPE_2FSK, 0); + radio_on = 1; + } + + if (!rtty_tick()) { + /* Transmission Finished */ + if (is_telemetry_finished()) return; + + /* Let's start again */ + uint8_t data = ARRAY_DBUFFER_READ_PTR(&telemetry_dbuffer_string)[telemetry_index]; + telemetry_index++; + + rtty_start(data); + } + + break; + } + } +} + +/** + * CLOCKING + * ============================================================================= + */ void si_gclk_setup(void) { @@ -99,10 +239,6 @@ void si_gclk_setup(void) system_gclk_gen_enable(SI406X_TCXO_GCLK); } - - - - /** * Initialises a timer interupt at the given frequency */ @@ -149,3 +285,15 @@ void timer0_tick_init(float frequency) tc_enable(TC0); tc_start_counter(TC0); } + +/** + * Called at the symbol rate + */ +void TC0_Handler(void) +{ + if (tc_get_status(TC0) & TC_STATUS_CHANNEL_0_MATCH) { + tc_clear_status(TC0, TC_STATUS_CHANNEL_0_MATCH); + + telemetry_tick(); + } +}