From 96248ed8b857c2c971f1cae8dafb14ba3396098b Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Thu, 2 Apr 2015 11:38:48 +0100 Subject: [PATCH] Working aprs test using square wave on gpio1 and 2gfsk --- firmware/Peripherals.md | 4 +- firmware/inc/aprs.h | 5 +- firmware/inc/ax25.h | 63 +++--- firmware/inc/ax25_sintable.h | 31 --- firmware/inc/telemetry.h | 4 + firmware/src/aprs.c | 46 +++++ firmware/src/ax25.c | 390 +++++++++++++++++++++++++++++------ firmware/src/ax25_sintable.c | 94 --------- firmware/src/main.c | 6 +- firmware/src/si_trx.c | 2 +- firmware/src/telemetry.c | 49 +++-- firmware/src/xosc.c | 10 +- 12 files changed, 451 insertions(+), 253 deletions(-) delete mode 100644 firmware/inc/ax25_sintable.h create mode 100644 firmware/src/aprs.c delete mode 100644 firmware/src/ax25_sintable.c diff --git a/firmware/Peripherals.md b/firmware/Peripherals.md index 3504b29..a214494 100644 --- a/firmware/Peripherals.md +++ b/firmware/Peripherals.md @@ -4,7 +4,9 @@ | --- | --- | --- | --- |*GLCK*| ||gclk0|main clock, internal osc8m|4 MHz -||gclk1|tcxo clock, fed from xosc +||gclk1|tcxo clock, fed from xosc OR osc8m +| +||gclk7|aprs clock, fed from gclk1, div 6 / 11 |*TC*|| ||tc0|telemetry tick timer. 32-bit diff --git a/firmware/inc/aprs.h b/firmware/inc/aprs.h index 898b06b..53cfca7 100644 --- a/firmware/inc/aprs.h +++ b/firmware/inc/aprs.h @@ -1,5 +1,5 @@ /* - * Outputs aprs to the si_trx + * Outputs aprs uisng ax25 * Copyright (C) 2015 Richard Meadows * * Permission is hereby granted, free of charge, to any person obtaining @@ -25,6 +25,7 @@ #ifndef APRS_H #define APRS_H - +void aprs_init(void); +void aprs_tick(void); #endif /* APRS_H */ diff --git a/firmware/inc/ax25.h b/firmware/inc/ax25.h index 0c86de6..dddb910 100644 --- a/firmware/inc/ax25.h +++ b/firmware/inc/ax25.h @@ -25,53 +25,56 @@ #ifndef AX25_H #define AX25_H -#include "ax25_sintable.h" - -/** - * Parameters based on the size of the sintable - */ -#define AX25_SINTABLE_SIZE (AX25_SINTABLE_LENGTH*4) -#define AX25_SINTABLE_LUMASK (AX25_SINTABLE_LENGTH-1) -#define AX25_SINTABLE_MASK (AX25_SINTABLE_SIZE-1) -#define AX25_SINTABLE_PART(phase) ((phase >> AX25_SINTABLE_ORDER) & 3) /** * Bell-202 */ -#define AX25_BAUD 2200 -#define AX25_MARKFREQ 1 -#define AX25_SPACEFREQ 2 +#define AX25_BAUD 1200 +#define AX25_MARK_FREQ 1200 +#define AX25_SPACE_FREQ 2200 +/** + * How often our handler gets called + */ +#define AX25_TICK_RATE AX25_BAUD + +/** + * AX25 packet parameters + */ #define AX25_BITSTUFFINGCOUNT 5 - - +#define AX25_PREAMBLE_FLAGS 15 /* 100 ms of flags */ +#define AX25_POSTAMBLE_FLAGS 1 +#define AX25_MAX_FRAME_LEN 0x100 /** - * How many points we output in a single symbol-time + * Hard-coded AX25 words */ -#define AX25_OVERSAMPLING 2 -#define AX25_TICK_RATE (AX25_BAUD * AX25_OVERSAMPLING) - -/** - * Define the phase velocities for mark and space - * - * This is how many entries in the sin table we step by - */ -#define AX25_MARKPHASEVELOCITY (AX25_SINTABLE_SIZE/AX25_OVERSAMPLING) -#define AX25_SPACEPHASEVELOCITY (AX25_MARKPHASEVELOCITY*(2.2f/1.2f)) -// TODO ^^ - - - +#define AX25_CONTROL_WORD 0x03 /* Use Unnumbered Information (UI) frames */ +#define AX25_PROTOCOL_ID 0xF0 /* No third level protocol */ enum ax25_symbol_t { AX25_MARK, AX25_SPACE, }; +struct ax25_byte_t { + uint8_t val; + uint8_t stuff; +}; + +/** + * State machine + */ +enum ax25_state_t { + AX25_PREAMBLE, + AX25_FRAME, + AX25_POSTAMBLE, + AX25_IDLE, +}; -void ax25_start(); +void ax25_start(char* addresses, uint32_t addresses_len, + char* information, uint32_t information_len); uint8_t ax25_tick(void); #endif /* AX25_H */ diff --git a/firmware/inc/ax25_sintable.h b/firmware/inc/ax25_sintable.h deleted file mode 100644 index 52c378e..0000000 --- a/firmware/inc/ax25_sintable.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Autogenerated sine tables. See tools/ax25_lookup/ax25_lookup.py - */ - -#ifndef AX25_SINTABLE_H -#define AX25_SINTABLE_H - - -#include "samd20.h" - -#define AX25_SINTABLE_ORDER 9 -#define AX25_SINTABLE_LENGTH 512 - - -/** - * 1st quadrant sin lookup table for 1.5kHz deviation - * - * Length: 512 - * Frequency Resolution: 7.805 Hz - */ -uint16_t sintable_512_1500hz[512]; - -/** - * 1st quadrant sin lookup table for 2.5kHz deviation - * - * Length: 512 - * Frequency Resolution: 7.805 Hz - */ -uint16_t sintable_512_2500hz[512]; - -#endif /* AX25_SINTABLE_H */ diff --git a/firmware/inc/telemetry.h b/firmware/inc/telemetry.h index 342268c..be8bafa 100644 --- a/firmware/inc/telemetry.h +++ b/firmware/inc/telemetry.h @@ -53,8 +53,12 @@ float telemetry_si_temperature(void); float timer0_tick_init(float frequency); uint32_t timer0_tick_frequency(float frequency); void timer0_tick_deinit(); + void telemetry_gpio1_pwm_init(void); void telemetry_gpio1_pwm_duty(float duty_cycle); void telemetry_gpio1_pwm_deinit(void); +void telemetry_gpio1_init(void); +void telemetry_gpio1_set(uint8_t value); + #endif /* TELEMETRY_H */ diff --git a/firmware/src/aprs.c b/firmware/src/aprs.c new file mode 100644 index 0000000..642fff3 --- /dev/null +++ b/firmware/src/aprs.c @@ -0,0 +1,46 @@ +/* + * Outputs aprs uisng ax25 + * 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 +#include + +#include "samd20.h" +#include "ax25.h" + +char addresses[50]; + +void aprs_start(void) +{ + sprintf(addresses, "%-6s%c%-6s%c%-6s%c", + "APRS", 0, + "M0SBU", 0, + "WIDE1", 1); + + ax25_start(addresses, 21, 0, 0); +} + +void aprs_tick(void) +{ + ax25_tick(); +} diff --git a/firmware/src/ax25.c b/firmware/src/ax25.c index 583ec5e..2dc524c 100644 --- a/firmware/src/ax25.c +++ b/firmware/src/ax25.c @@ -23,89 +23,345 @@ */ #include "samd20.h" +#include "system/gclk.h" +#include "system/pinmux.h" +#include "tc/tc_driver.h" +#include "hw_config.h" #include "ax25.h" -#include "ax25_sintable.h" +#include "telemetry.h" #include "si_trx.h" -#define AX25_MARKSINTABLE sintable_512_1500hz -#define AX25_SPACESINTABLE sintable_512_2500hz +enum ax25_symbol_t next_symbol; +uint8_t bit_index; +struct ax25_byte_t current_byte; +uint8_t current_bit; +uint8_t one_count; +uint32_t byte_index; + +enum ax25_state_t ax25_state; +//uint8_t ax25_frame[AX25_MAX_FRAME_LEN]; +uint32_t ax25_index, ax25_frame_length; -uint32_t ax25_phase; -uint32_t ax25_phasevelocity; -uint32_t ax25_oversampling_count; +uint8_t ax25_frame[29] = {0x86, 0xA2, 0x40, 0x40, 0x40, 0x40, 0x60, 0xAE, 0x64, 0x8C, 0xA6, + 0x40, 0x40, 0x68, 0xA4, 0x8A, 0x98, 0x82, 0xB2, 0x40, 0x61, 0x03, + 0xF0, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00 }; -uint16_t* ax25_sintable; - -void ax25_start() -{ - /* Init */ - ax25_phase = 0; - ax25_phasevelocity = AX25_MARKPHASEVELOCITY; - ax25_sintable = AX25_MARKSINTABLE; - ax25_oversampling_count = -1LL; -} - - -uint32_t toggle = 0; -enum ax25_symbol_t ax25_get_next_symbol(void) { - return (toggle++ & 1) ? AX25_MARK : AX25_SPACE; -} - - -void telemetry_gpio1_pwm_duty(float duty_cycle); +void ax25_gpio1_pwm_init(void); /** - * Called at our tick rate, outputs tones + * Frame Check Sequence (FCS) + * ============================================================================= + */ + +/** + * CRC Function for the XMODEM protocol. + * http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#gaca726c22a1900f9bad52594c8846115f + */ +uint16_t crc_update(uint16_t crc, uint8_t data) +{ + int i; + +// crc = crc ^ ((uint16_t)data << 8); + + + for (i = 0; i < 8; i++) { + + if ((crc & 1) != (data & 1)) { + + crc = (crc >> 1) ^ 0x8408; + data = data >> 1; + + } else { + crc = crc >> 1; + data = data >> 1; + } + } + + return crc; +} + +uint16_t +crc_ccitt_update (uint16_t crc, uint8_t data) +{ + data ^= (crc & 0xff); + data ^= data << 4; + return ((((uint16_t)data << 8) | ((crc >> 8) & 0xff)) ^ (uint8_t)(data >> 4) + ^ ((uint16_t)data << 3)); +} + +/** + * Calculates the Frame Check Sequence (FCS) using the CRC algorithm + */ +uint16_t crc_fcs(uint8_t *string, uint32_t length) +{ + size_t i; + uint16_t crc; + uint8_t c; + + crc = 0xFFFF; + + for (i = 0; i < length; i++) { + c = string[i]; + crc = crc_ccitt_update(crc, c); + } + + return crc ^ 0xFFFF; +} + + + + + +/** + * Starts the transmission of an ax25 frame + */ +void ax25_start(char* addresses, uint32_t addresses_len, + char* information, uint32_t information_len) +{ + uint32_t i, j; + uint16_t fcs; + + /* /\* Process addresses *\/ */ + /* for (i = 0; i < addresses_len; i++) { */ + + /* if ((i % 7) == 6) { /\* Secondary Station ID *\/ */ + /* ax25_frame[i] = ((addresses[i] << 1) & 0x1F) | 0x60; */ + /* } else { */ + /* ax25_frame[i] = (addresses[i] << 1); */ + /* } */ + /* } */ + /* ax25_frame[i-1] |= 0x1; /\* Set HLDC bit *\/ */ + + /* ax25_frame[i++] = AX25_CONTROL_WORD; */ + /* ax25_frame[i++] = AX25_PROTOCOL_ID; */ + + /* /\* Process information *\/ */ + /* for (j = 0; j < information_len; j++) { */ + /* ax25_frame[i++] = information[j]; */ + /* } */ + + /* Frame Check Sequence (FCS) */ + fcs = crc_fcs(ax25_frame, 27); + ax25_frame[27] = (fcs >> 0) & 0xFF; + ax25_frame[28] = (fcs >> 8) & 0xFF; + + fcs = crc_fcs("data", 4); + + /* Length */ + ax25_frame_length = 29; + + /* Init */ + next_symbol = AX25_MARK; + bit_index = 8; + current_bit = 1; + one_count = 0; + + ax25_state = AX25_PREAMBLE; + ax25_index = 0; + + /* Hardware init */ + ax25_gpio1_pwm_init(); +} + + + + + + + + + +/** + * Sets up gpio1 for the afsk pwm output. Uses gclk 7 + */ +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; + uint32_t capture = top >> 1; /* 50% duty cycle */ + + if (top > 0xFF) while (1); // It's only an 8-bit counter + + /* Setup GCLK genertor 7 */ + system_gclk_gen_set_config(GCLK_GENERATOR_7, + GCLK_SOURCE_GCLKGEN1, /* Source */ + false, /* High When Disabled */ + 11, /* Division Factor */// TODO + false, /* Run in standby */ + false); /* Output Pin Enable */ + system_gclk_gen_enable(GCLK_GENERATOR_7); + + /* Configure timer */ + bool capture_channel_enables[] = {false, true}; + uint32_t compare_channel_values[] = {0x0000, capture}; + + tc_init(TC5, + GCLK_GENERATOR_7, + TC_COUNTER_SIZE_8BIT, + TC_CLOCK_PRESCALER_DIV4, + TC_WAVE_GENERATION_NORMAL_PWM, + TC_RELOAD_ACTION_GCLK, + TC_COUNT_DIRECTION_UP, + TC_WAVEFORM_INVERT_OUTPUT_NONE, + false, /* Oneshot = false */ + false, /* Run in standby = false */ + 0x0000, /* Initial value */ + top, /* Top value */ + capture_channel_enables, /* Capture Channel Enables */ + compare_channel_values); /* Compare Channels Values */ + + + /* Enable the output pin */ + system_pinmux_pin_set_config(SI406X_GPIO1_PINMUX >> 16, /* GPIO Pin */ + SI406X_GPIO1_PINMUX & 0xFFFF, /* Mux Position */ + SYSTEM_PINMUX_PIN_DIR_INPUT, /* Direction */ + SYSTEM_PINMUX_PIN_PULL_NONE, /* Pull */ + false); /* Powersave */ + + tc_enable(TC5); + tc_start_counter(TC5); +} + + +/** + * Returns the packet to transmit + */ +struct ax25_byte_t ax25_get_next_byte(void) { + + struct ax25_byte_t next = { .stuff = 0 }; + + switch (ax25_state) { + case AX25_PREAMBLE: /* Preamble */ + /* Return flag */ + next.val = 0x7E; + + /* Check for next state */ + ax25_index++; + if (ax25_index >= AX25_PREAMBLE_FLAGS) { + /* Next state */ + ax25_state = AX25_FRAME; + ax25_index = 0; + } + break; + + + case AX25_FRAME: /* Frame */ + /* Return data */ + next.val = ax25_frame[ax25_index]; + next.stuff = 1; + + /* Check for next state */ + ax25_index++; + if (ax25_index >= ax25_frame_length) { + /* Next state */ + ax25_state = AX25_POSTAMBLE; + ax25_index = 0; + } + break; + + + case AX25_POSTAMBLE: /* Postamble */ + /* Return flag */ + next.val = 0x7E; + + /* Check for next state */ + ax25_index++; + if (ax25_index >= AX25_POSTAMBLE_FLAGS) { + /* Next state */ + ax25_state = AX25_PREAMBLE; + ax25_index = 0; + } + break; + + + default: + break; + } + + return next; +} + + +//uint32_t toggle = 0; + +/** + * Returns the next symbol to transmit + */ +enum ax25_symbol_t ax25_get_next_symbol(void) { + + uint8_t bit; + + if (bit_index >= 8) { + current_byte = ax25_get_next_byte(); + bit_index = 0; + } + + /* transmit bits lsb first */ + bit = current_byte.val & 0x01; + + if (bit) { /* One */ + + one_count++; + + /* Check if we need to stuff this bit */ + if (one_count >= AX25_BITSTUFFINGCOUNT && current_byte.stuff) { + current_byte.val &= ~0x01;/* Next bit is zero */ + one_count = 0; + + } else { + current_byte.val >>= 1; /* Move along one bit */ + bit_index++; + } + } else { /* Zero */ + + one_count = 0; /* Clear concecutive ones */ + current_byte.val >>= 1; /* Move along one bit */ + bit_index++; + + /* NRZI encoding */ + current_bit ^= 0x01; + } + + return current_bit; + + +// return (toggle++ & 1) ? AX25_MARK : AX25_SPACE; +} + + +/** + * Called at our tick rate, controls the pwm gclk * * Returns 1 when more work todo, 0 when finished */ uint8_t ax25_tick(void) { - int16_t deviation; - uint32_t sintable_phase = ax25_phase & AX25_SINTABLE_LUMASK; - /* Set the instantaneous fm deviation based on the current phase */ - switch (AX25_SINTABLE_PART(ax25_phase)) { - case 0: /* 0° - 90° */ - deviation = ax25_sintable[sintable_phase]; - break; - case 1: /* 90° - 180° */ - deviation = ax25_sintable[AX25_SINTABLE_LUMASK - sintable_phase]; - break; - case 2: /* 180° - 270° */ - deviation = -ax25_sintable[sintable_phase]; - break; - case 3: /* 270° - 360° */ - deviation = -ax25_sintable[AX25_SINTABLE_LUMASK - sintable_phase]; - break; - default: - deviation = 0; + if (next_symbol == AX25_SPACE) { + + + system_gclk_gen_set_config(GCLK_GENERATOR_7, + GCLK_SOURCE_GCLKGEN1, /* Source */ + false, /* High When Disabled */ + 6, /* Division Factor */// TODO + false, /* Run in standby */ + false); /* Output Pin Enable */ + + } else { + + + system_gclk_gen_set_config(GCLK_GENERATOR_7, + GCLK_SOURCE_GCLKGEN1, /* Source */ + false, /* High When Disabled */ + 11, /* Division Factor */// TODO + false, /* Run in standby */ + false); /* Output Pin Enable */ + } -// si_trx_switch_channel(deviation); - -// float duty = 0.5 + ((float)deviation/192.0) / 2.0; - float duty = (ax25_get_next_symbol() == AX25_SPACE) ? 1.0 : 0.0; - - telemetry_gpio1_pwm_duty(duty); - - /* Update with next bit */ - if (ax25_oversampling_count++ >= AX25_OVERSAMPLING) { - ax25_oversampling_count = 0; - - /* Set phase velocity for next symbol */ - if (0) {//ax25_get_next_symbol() == AX25_SPACE) { - ax25_phasevelocity = AX25_SPACEPHASEVELOCITY; - ax25_sintable = AX25_SPACESINTABLE; - } else { - ax25_phasevelocity = AX25_MARKPHASEVELOCITY; - ax25_sintable = AX25_MARKSINTABLE; - } - } - /* Update phase */ - ax25_phase += ax25_phasevelocity; - + next_symbol = ax25_get_next_symbol(); return 1; } diff --git a/firmware/src/ax25_sintable.c b/firmware/src/ax25_sintable.c deleted file mode 100644 index 5ef7968..0000000 --- a/firmware/src/ax25_sintable.c +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Autogenerated sine tables. See tools/ax25_lookup/ax25_lookup.py - */ - -#include "samd20.h" - -/** - * 1st quadrant sin lookup table for 1.5kHz deviation - * - * Length: 512 - * Frequency Resolution: 7.805 Hz - */ -uint16_t sintable_512_1500hz[] = { - 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, - 9, 9, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 16, 17, - 18, 18, 19, 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, - 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 32, 33, 33, 34, 35, - 35, 36, 36, 37, 37, 38, 39, 39, 40, 40, 41, 42, 42, 43, 43, - 44, 44, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 51, 51, 52, - 52, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 59, 59, 60, 60, - 61, 61, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 68, 68, 69, - 69, 70, 70, 71, 71, 72, 72, 73, 74, 74, 75, 75, 76, 76, 77, - 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, - 85, 86, 86, 87, 87, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, - 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, - 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, - 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 114, 115, - 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 121, 122, - 122, 123, 123, 124, 124, 125, 125, 126, 126, 126, 127, 127, 128, 128, 129, - 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 133, 134, 134, 135, 135, - 135, 136, 136, 137, 137, 138, 138, 138, 139, 139, 140, 140, 140, 141, 141, - 142, 142, 142, 143, 143, 144, 144, 144, 145, 145, 146, 146, 146, 147, 147, - 147, 148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 152, 152, 152, 153, - 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, - 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, - 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 167, 167, 167, - 167, 168, 168, 168, 169, 169, 169, 169, 170, 170, 170, 171, 171, 171, 171, - 172, 172, 172, 172, 173, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, - 175, 176, 176, 176, 176, 177, 177, 177, 177, 178, 178, 178, 178, 178, 179, - 179, 179, 179, 180, 180, 180, 180, 180, 181, 181, 181, 181, 181, 182, 182, - 182, 182, 182, 182, 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, 184, - 185, 185, 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 187, 187, - 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 188, 188, 188, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192 -}; - -/** - * 1st quadrant sin lookup table for 2.5kHz deviation - * - * Length: 512 - * Frequency Resolution: 7.805 Hz - */ -uint16_t sintable_512_2500hz[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, 152, 153, 154, 154, - 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 165, 166, 166, 167, - 168, 169, 170, 171, 171, 172, 173, 174, 175, 175, 176, 177, 178, 179, 180, - 180, 181, 182, 183, 184, 184, 185, 186, 187, 188, 188, 189, 190, 191, 192, - 192, 193, 194, 195, 196, 196, 197, 198, 199, 199, 200, 201, 202, 202, 203, - 204, 205, 205, 206, 207, 208, 208, 209, 210, 211, 211, 212, 213, 214, 214, - 215, 216, 217, 217, 218, 219, 219, 220, 221, 222, 222, 223, 224, 224, 225, - 226, 226, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235, 235, - 236, 237, 237, 238, 239, 239, 240, 241, 241, 242, 243, 243, 244, 244, 245, - 246, 246, 247, 248, 248, 249, 249, 250, 251, 251, 252, 253, 253, 254, 254, - 255, 255, 256, 257, 257, 258, 258, 259, 260, 260, 261, 261, 262, 262, 263, - 264, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 270, 270, 271, 271, - 272, 272, 273, 273, 274, 274, 275, 275, 276, 276, 277, 277, 278, 278, 279, - 279, 280, 280, 281, 281, 282, 282, 282, 283, 283, 284, 284, 285, 285, 286, - 286, 287, 287, 287, 288, 288, 289, 289, 290, 290, 290, 291, 291, 292, 292, - 292, 293, 293, 294, 294, 294, 295, 295, 296, 296, 296, 297, 297, 297, 298, - 298, 298, 299, 299, 300, 300, 300, 301, 301, 301, 302, 302, 302, 303, 303, - 303, 304, 304, 304, 304, 305, 305, 305, 306, 306, 306, 307, 307, 307, 307, - 308, 308, 308, 308, 309, 309, 309, 309, 310, 310, 310, 310, 311, 311, 311, - 311, 312, 312, 312, 312, 313, 313, 313, 313, 313, 314, 314, 314, 314, 314, - 315, 315, 315, 315, 315, 315, 316, 316, 316, 316, 316, 316, 317, 317, 317, - 317, 317, 317, 317, 318, 318, 318, 318, 318, 318, 318, 318, 318, 319, 319, - 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 320, 320, 320, 320, 320, - 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, - 320, 320 -}; - diff --git a/firmware/src/main.c b/firmware/src/main.c index e6d647b..7e9a34f 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -255,8 +255,8 @@ void init(void) /* Clock up to 14MHz with 0 wait states */ system_flash_set_waitstates(SYSTEM_WAIT_STATE_1_8V_14MHZ); - /* Up the clock rate to 4MHz */ - system_clock_source_osc8m_set_config(SYSTEM_OSC8M_DIV_2, /* Prescaler */ + /* Up the clock rate to 8MHz */ + system_clock_source_osc8m_set_config(SYSTEM_OSC8M_DIV_1, /* Prescaler */ false, /* Run in Standby */ false); /* Run on Demand */ @@ -285,9 +285,7 @@ void init(void) //wdt_reset_count(); /* Enables the xosc on gclk1 */ -#ifdef USE_XOSC xosc_init(); -#endif led_init(); gps_init(); diff --git a/firmware/src/si_trx.c b/firmware/src/si_trx.c index 6da520d..ecb3bf6 100644 --- a/firmware/src/si_trx.c +++ b/firmware/src/si_trx.c @@ -430,7 +430,7 @@ void si_trx_reset(uint8_t modulation_type, uint16_t deviation) si_trx_set_frequency(RADIO_FREQUENCY, deviation); si_trx_set_tx_power(RADIO_POWER); - si_trx_modem_set_tx_datarate(2200); + si_trx_modem_set_tx_datarate(3000); /* RTTY from GPIO1 */ si_trx_modem_set_modulation(SI_MODEM_MOD_DIRECT_MODE_SYNC, // ASYNC diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index 1bf2760..e5d4a01 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -30,6 +30,7 @@ #include "rtty.h" #include "contestia.h" #include "rsid.h" +#include "aprs.h" #include "ax25.h" #include "pips.h" #include "si_trx.h" @@ -37,6 +38,7 @@ #include "system/gclk.h" #include "system/interrupt.h" #include "system/pinmux.h" +#include "system/port.h" #include "tc/tc_driver.h" #include "hw_config.h" @@ -305,17 +307,13 @@ void telemetry_tick(void) { case TELEMETRY_APRS: /* ---- ---- APRS */ if (!radio_on) { - /* ARPS: We use the modem offset to modulate */ - - telemetry_gpio1_pwm_init(); - //telemetry_gpio1_pwm_duty(0.5); - - si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 400); + /* APRS: We use pwm to control gpio1 */ + aprs_start(); + si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 200); radio_on = 1; - ax25_start(); } - ax25_tick(); + aprs_tick(); break; @@ -351,13 +349,8 @@ void telemetry_tick(void) { */ float timer0_tick_init(float frequency) { -#ifdef USE_XOSC const enum gclk_generator tick_gclk_gen = GCLK_GENERATOR_1; const uint8_t tick_gclk_gen_num = 1; -#else - const enum gclk_generator tick_gclk_gen = GCLK_GENERATOR_0; - const uint8_t tick_gclk_gen_num = 0; -#endif /* Calculate the wrap value for the given frequency */ float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num); @@ -439,22 +432,37 @@ void TC0_Handler(void) -#define GPIO1_PWM_STEPS 208 // // ~ 2kHz on a 4 MHz clock +#define GPIO1_PWM_STEPS 200 // ~ 2kHz on a 4 MHz clock /** * Initialised PWM at the given duty cycle on the GPIO1 pin of the radio */ void telemetry_gpio1_pwm_init(void) { - bool capture_channel_enables[] = {false, true}; - uint32_t compare_channel_values[] = {0x0000, 0x0000}; // Set duty cycle at 0% by default + float gclk1_frequency = (float)system_gclk_gen_get_hz(1); - //float gclk_frequency = (float)system_gclk_gen_get_hz(0); + uint32_t top = 38;//(uint32_t)(gclk1_frequency / 13200.0*4);// & ~0x1; + uint32_t capture = top >> 1; /* 50% duty cycle */ + + if (top > 0xFF) while (1); // It's only an 8-bit counter + + /* Setup GCLK genertor 7 */ + system_gclk_gen_set_config(GCLK_GENERATOR_7, + GCLK_SOURCE_GCLKGEN1, /* Source */ + false, /* High When Disabled */ + 11, /* Division Factor */// TODO + false, /* Run in standby */ + false); /* Output Pin Enable */ + system_gclk_gen_enable(GCLK_GENERATOR_7); + + /* Configure timer */ + bool capture_channel_enables[] = {false, true}; + uint32_t compare_channel_values[] = {0x0000, capture}; tc_init(TC5, - GCLK_GENERATOR_0, + GCLK_GENERATOR_7, TC_COUNTER_SIZE_8BIT, - TC_CLOCK_PRESCALER_DIV16, + TC_CLOCK_PRESCALER_DIV4, TC_WAVE_GENERATION_NORMAL_PWM, TC_RELOAD_ACTION_GCLK, TC_COUNT_DIRECTION_UP, @@ -462,7 +470,7 @@ void telemetry_gpio1_pwm_init(void) false, /* Oneshot = false */ false, /* Run in standby = false */ 0x0000, /* Initial value */ - GPIO1_PWM_STEPS, /* Top value */ + top, /* Top value */ capture_channel_enables, /* Capture Channel Enables */ compare_channel_values); /* Compare Channels Values */ @@ -476,7 +484,6 @@ void telemetry_gpio1_pwm_init(void) tc_enable(TC5); tc_start_counter(TC5); - } /** * Sets duty cycle on PWM pin diff --git a/firmware/src/xosc.c b/firmware/src/xosc.c index ed55de2..78c57ea 100644 --- a/firmware/src/xosc.c +++ b/firmware/src/xosc.c @@ -48,6 +48,7 @@ measurement_result_t _callback; * connects it to GLCK1. */ void xosc_init(void) { +#ifdef USE_XOSC system_clock_source_xosc_set_config(SYSTEM_CLOCK_EXTERNAL_CLOCK, SYSTEM_XOSC_STARTUP_1, true, @@ -57,12 +58,17 @@ void xosc_init(void) { system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC); while (!system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_XOSC)); +#endif /* Configure GCLK1 to XOSC */ system_gclk_gen_set_config(GCLK_GENERATOR_1, - GCLK_SOURCE_XOSC, /* Source */ +#ifdef USE_XOSC + GCLK_SOURCE_XOSC, /* Source */ +#else + GCLK_SOURCE_OSC8M, /* Source */ +#endif false, /* High When Disabled */ - XOSC_GCLK1_DIVIDE,/* Division Factor */ + XOSC_GCLK1_DIVIDE, /* Division Factor */ false, /* Run in standby */ false); /* Output Pin Enable */