kopia lustrzana https://github.com/bristol-seds/pico-tracker
More re-orginisation to telemetry etc, added working RSID demo run
rodzic
7fc4421939
commit
67719ea8b5
|
@ -3,7 +3,7 @@
|
|||
| Type | Peripheral | Function | Notes
|
||||
| --- | --- | --- | ---
|
||||
|*GLCK*|
|
||||
||gclk0|main|
|
||||
||gclk0|main|2MHz??
|
||||
|*TC*||
|
||||
||tc0|
|
||||
||tc1|
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
*/
|
||||
#define CONTESTIA_NUMBER_OF_TONES 32
|
||||
#define CONTESTIA_CHARACTERS_PER_BLOCK 5
|
||||
#define CONTESTIA_CHANNEL_SPACING 4 // Corresponds to 31.22 Hz
|
||||
#define CONTESTIA_SYMBOL_RATE 31.25
|
||||
|
||||
|
||||
void contestia_start(char* data);
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
#define SI406X_SDN_PIN PIN_PA16
|
||||
#define SI406X_GPIO0_PIN PIN_PA27
|
||||
#define SI406X_GPIO1_PIN PIN_PA25
|
||||
#define SI406X_GPIO1_PINMUX PINMUX_PA25F_TC5_WO1
|
||||
|
||||
#define SI406X_TCXO_PIN PIN_PA17
|
||||
#define SI406X_TCXO_PINMUX PINMUX_PA17H_GCLK_IO3
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Reed-Solomon Identification (RSID) functions
|
||||
* Copyright (C) 2014 Richard Meadows <richardeoin>
|
||||
*
|
||||
* 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 RSID_H
|
||||
#define RSID_H
|
||||
|
||||
#define RSID_NSYMBOLS 15
|
||||
#define RSID_SYMBOL_RATE (11025.0 / 1024.0)
|
||||
|
||||
/**
|
||||
* The RSID codes for all supported modes.
|
||||
*
|
||||
* From http://www.w1hkj.com/RSID_description.html
|
||||
*/
|
||||
typedef enum rsid_code_t {
|
||||
RSID_BPSK31 = 1,
|
||||
RSID_QPSK31 = 110,
|
||||
RSID_BPSK63 = 2,
|
||||
RSID_QPSK63 = 3,
|
||||
RSID_BPSK125 = 4,
|
||||
RSID_QPSK125 = 5,
|
||||
RSID_BPSK250 = 126,
|
||||
RSID_QPSK250 = 127,
|
||||
RSID_BPSK500 = 173,
|
||||
RSID_PSK125R = 183,
|
||||
RSID_PSK250R = 186,
|
||||
RSID_PSK500R = 187,
|
||||
RSID_PSKFEC31 = 7,
|
||||
RSID_PSK10 = 8,
|
||||
RSID_MT63_500_LG = 9,
|
||||
RSID_MT63_500_ST = 10,
|
||||
RSID_MT63_500_VST = 11,
|
||||
RSID_MT63_1000_LG = 12,
|
||||
RSID_MT63_1000_ST = 13,
|
||||
RSID_MT63_1000_VST = 14,
|
||||
RSID_MT63_2000_LG = 15,
|
||||
RSID_MT63_2000_ST = 17,
|
||||
RSID_MT63_2000_VST = 18,
|
||||
RSID_PSKAM10 = 19,
|
||||
RSID_PSKAM31 = 20,
|
||||
RSID_PSKAM50 = 21,
|
||||
RSID_PSK63F = 22,
|
||||
RSID_PSK220F = 23,
|
||||
RSID_CHIP64 = 24,
|
||||
RSID_CHIP128 = 25,
|
||||
RSID_CW = 26,
|
||||
RSID_CCW_OOK_12 = 27,
|
||||
RSID_CCW_OOK_24 = 28,
|
||||
RSID_CCW_OOK_48 = 29,
|
||||
RSID_CCW_FSK_12 = 30,
|
||||
RSID_CCW_FSK_24 = 31,
|
||||
RSID_CCW_FSK_48 = 33,
|
||||
RSID_PACTOR1_FEC = 34,
|
||||
RSID_PACKET_110 = 113,
|
||||
RSID_PACKET_300 = 35,
|
||||
RSID_PACKET_1200 = 36,
|
||||
RSID_RTTY_ASCII_7 = 37,
|
||||
RSID_RTTY_ASCII_8 = 38,
|
||||
RSID_RTTY_45 = 39,
|
||||
RSID_RTTY_50 = 40,
|
||||
RSID_RTTY_75 = 41,
|
||||
RSID_AMTOR_FEC = 42,
|
||||
RSID_THROB_1 = 43,
|
||||
RSID_THROB_2 = 44,
|
||||
RSID_THROB_4 = 45,
|
||||
RSID_THROBX_1 = 46,
|
||||
RSID_THROBX_2 = 47,
|
||||
RSID_THROBX_4 = 146,
|
||||
RSID_CONTESTIA_4_125 = 204,
|
||||
RSID_CONTESTIA_4_250 = 55,
|
||||
RSID_CONTESTIA_4_500 = 54,
|
||||
RSID_CONTESTIA_4_1000 = 255,
|
||||
RSID_CONTESTIA_4_2000 = 254,
|
||||
RSID_CONTESTIA_8_125 = 169,
|
||||
RSID_CONTESTIA_8_250 = 49,
|
||||
RSID_CONTESTIA_8_500 = 52,
|
||||
RSID_CONTESTIA_8_1000 = 117,
|
||||
RSID_CONTESTIA_8_2000 = 247,
|
||||
RSID_CONTESTIA_16_500 = 50,
|
||||
RSID_CONTESTIA_16_1000 = 53,
|
||||
RSID_CONTESTIA_16_2000 = 259,
|
||||
RSID_CONTESTIA_32_1000 = 51,
|
||||
RSID_CONTESTIA_32_2000 = 201,
|
||||
RSID_CONTESTIA_64_500 = 194,
|
||||
RSID_CONTESTIA_64_1000 = 193,
|
||||
RSID_CONTESTIA_64_2000 = 191,
|
||||
RSID_VOICE = 56,
|
||||
RSID_MFSK8 = 60,
|
||||
RSID_MFSK16 = 57,
|
||||
RSID_MFSK32 = 147,
|
||||
RSID_MFSK11 = 148,
|
||||
RSID_MFSK22 = 152,
|
||||
RSID_RTTYM_8_250 = 61,
|
||||
RSID_RTTYM_16_500 = 62,
|
||||
RSID_RTTYM_32_1000 = 63,
|
||||
RSID_RTTYM_8_500 = 65,
|
||||
RSID_RTTYM_16_1000 = 66,
|
||||
RSID_RTTYM_4_500 = 67,
|
||||
RSID_RTTYM_4_250 = 68,
|
||||
RSID_RTTYM_8_1000 = 119,
|
||||
RSID_RTTYM_8_125 = 170,
|
||||
RSID_OLIVIA_4_125 = 203,
|
||||
RSID_OLIVIA_4_250 = 75,
|
||||
RSID_OLIVIA_4_500 = 74,
|
||||
RSID_OLIVIA_4_1000 = 229,
|
||||
RSID_OLIVIA_4_2000 = 238,
|
||||
RSID_OLIVIA_8_125 = 163,
|
||||
RSID_OLIVIA_8_250 = 69,
|
||||
RSID_OLIVIA_8_500 = 72,
|
||||
RSID_OLIVIA_8_1000 = 116,
|
||||
RSID_OLIVIA_8_2000 = 214,
|
||||
RSID_OLIVIA_16_500 = 70,
|
||||
RSID_OLIVIA_16_1000 = 73,
|
||||
RSID_OLIVIA_16_2000 = 234,
|
||||
RSID_OLIVIA_32_1000 = 71,
|
||||
RSID_OLIVIA_32_2000 = 221,
|
||||
RSID_OLIVIA_64_2000 = 211,
|
||||
RSID_PAX = 76,
|
||||
RSID_PAX2 = 77,
|
||||
RSID_DOMINOF = 78,
|
||||
RSID_FAX = 79,
|
||||
RSID_SSTV = 81,
|
||||
RSID_DOMINOEX_4 = 84,
|
||||
RSID_DOMINOEX_5 = 85,
|
||||
RSID_DOMINOEX_8 = 86,
|
||||
RSID_DOMINOEX_11 = 87,
|
||||
RSID_DOMINOEX_16 = 88,
|
||||
RSID_DOMINOEX_22 = 90,
|
||||
RSID_DOMINOEX_4_FEC = 92,
|
||||
RSID_DOMINOEX_5_FEC = 93,
|
||||
RSID_DOMINOEX_8_FEC = 97,
|
||||
RSID_DOMINOEX_11_FEC = 98,
|
||||
RSID_DOMINOEX_16_FEC = 99,
|
||||
RSID_DOMINOEX_22_FEC = 101,
|
||||
RSID_FELD_HELL = 104,
|
||||
RSID_PSK_HELL = 105,
|
||||
RSID_HELL_80 = 106,
|
||||
RSID_FM_HELL_105 = 107,
|
||||
RSID_FM_HELL_245 = 108,
|
||||
RSID_MODE_141A = 114,
|
||||
RSID_DTMF = 123,
|
||||
RSID_ALE400 = 125,
|
||||
RSID_FDMDV = 131,
|
||||
RSID_JT65_A = 132,
|
||||
RSID_JT65_B = 134,
|
||||
RSID_JT65_C = 135,
|
||||
RSID_THOR_4 = 136,
|
||||
RSID_THOR_8 = 137,
|
||||
RSID_THOR_16 = 138,
|
||||
RSID_THOR_5 = 139,
|
||||
RSID_THOR_11 = 143,
|
||||
RSID_THOR_22 = 145,
|
||||
RSID_CALL_ID = 153,
|
||||
RSID_PACKET_PSK1200 = 155,
|
||||
RSID_PACKET_PSK250 = 156,
|
||||
RSID_PACKET_PSK63 = 159,
|
||||
RSID_MODE_188_110A_8N1 = 172,
|
||||
} rsid_code_t;
|
||||
|
||||
void rsid_start(rsid_code_t rsid_code);
|
||||
uint8_t rsid_tick(void);
|
||||
|
||||
#endif
|
|
@ -25,6 +25,13 @@
|
|||
#ifndef RTTY_H
|
||||
#define RTTY_H
|
||||
|
||||
/**
|
||||
* 50 baud RTTY
|
||||
*/
|
||||
#define RTTY_BITRATE 50
|
||||
#define RTTY_CHANNEL_SPACING 52 // Corresponds to 405.9Hz spacing
|
||||
|
||||
|
||||
void rtty_start(uint8_t data);
|
||||
uint8_t rtty_tick(void);
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
float si_trx_get_temperature(void);
|
||||
|
||||
void si_trx_on(uint8_t modulation_type, float channel_spacing);
|
||||
void si_trx_on(uint8_t modulation_type);
|
||||
void si_trx_off(void);
|
||||
void si_trx_switch_channel(uint8_t channel);
|
||||
void si_trx_switch_channel(int16_t channel);
|
||||
|
||||
void si_trx_init(void);
|
||||
|
||||
|
|
|
@ -31,7 +31,10 @@ uint16_t crc_checksum(char *string);
|
|||
|
||||
enum telemetry_t {
|
||||
TELEMETRY_RTTY,
|
||||
TELEMETRY_CONTESTIA
|
||||
TELEMETRY_CONTESTIA,
|
||||
TELEMETRY_RSID,
|
||||
TELEMETRY_APRS,
|
||||
TELEMETRY_PIPS,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -49,6 +52,11 @@ 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);
|
||||
|
||||
float timer0_tick_init(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);
|
||||
|
||||
#endif /* TELEMETRY_H */
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "si_trx.h"
|
||||
#include "samd20.h"
|
||||
#include "contestia.h"
|
||||
|
||||
#include "telemetry.h"
|
||||
#include "si_trx.h"
|
||||
#include "mfsk.h"
|
||||
|
||||
/**
|
||||
* Current output tones
|
||||
|
@ -52,11 +54,15 @@ uint8_t contestia_tick(void) {
|
|||
if (contestia_tone_index < CONTESTIA_NUMBER_OF_TONES) {
|
||||
uint8_t binary_code;
|
||||
uint8_t grey_code;
|
||||
int16_t channel;
|
||||
|
||||
/* Output grey code */
|
||||
binary_code = contestia_tones[contestia_tone_index];
|
||||
grey_code = (binary_code >> 1) ^ binary_code;
|
||||
si_trx_switch_channel(grey_code);
|
||||
|
||||
/* Align this to a channel */
|
||||
channel = grey_code - (CONTESTIA_NUMBER_OF_TONES / 2);
|
||||
si_trx_switch_channel(channel * CONTESTIA_CHANNEL_SPACING);
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "system/wdt.h"
|
||||
#include "timepulse.h"
|
||||
#include "telemetry.h"
|
||||
#include "rsid.h"
|
||||
#include "si_trx.h"
|
||||
#include "si_trx_defs.h"
|
||||
#include "analogue.h"
|
||||
|
@ -317,11 +318,19 @@ int main(void)
|
|||
|
||||
led_on();
|
||||
|
||||
|
||||
while (1) {
|
||||
/* Watchdog */
|
||||
//wdt_reset_count();
|
||||
|
||||
/* Send the next packet */
|
||||
output_telemetry_string();
|
||||
//output_telemetry_string();
|
||||
|
||||
telemetry_start_rsid(RSID_CONTESTIA_32_1000);
|
||||
|
||||
/* Sleep Wait */
|
||||
while (telemetry_active()) {
|
||||
system_sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Reed-Solomon Identification (RSID) functions
|
||||
* Copyright (C) 2014 Richard Meadows <richardeoin>
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "samd20.h"
|
||||
#include "rsid.h"
|
||||
#include "telemetry.h"
|
||||
#include "si_trx.h"
|
||||
|
||||
/**
|
||||
* USEFUL RESOURCES ============================================================
|
||||
*
|
||||
* http://www.w1hkj.com/RSID_description.html
|
||||
*
|
||||
* dl-fldigi source:
|
||||
* https://github.com/jamescoxon/dl-fldigi/blob/master/src/rsid/rsid.cxx#L180
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* ENCODING
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Constants used in the Reed-Solomon encoding
|
||||
*/
|
||||
const int rsid_squares[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
|
||||
0, 2, 4, 6, 8,10,12,14, 9,11,13,15, 1, 3, 5, 7,
|
||||
0, 3, 6, 5,12,15,10, 9, 1, 2, 7, 4,13,14,11, 8,
|
||||
0, 4, 8,12, 9,13, 1, 5,11,15, 3, 7, 2, 6,10,14,
|
||||
0, 5,10,15,13, 8, 7, 2, 3, 6, 9,12,14,11, 4, 1,
|
||||
0, 6,12,10, 1, 7,13,11, 2, 4,14, 8, 3, 5,15, 9,
|
||||
0, 7,14, 9, 5, 2,11,12,10,13, 4, 3,15, 8, 1, 6,
|
||||
0, 8, 9, 1,11, 3, 2,10,15, 7, 6,14, 4,12,13, 5,
|
||||
0, 9,11, 2,15, 6, 4,13, 7,14,12, 5, 8, 1, 3,10,
|
||||
0,10,13, 7, 3, 9,14, 4, 6,12,11, 1, 5,15, 8, 2,
|
||||
0,11,15, 4, 7,12, 8, 3,14, 5, 1,10, 9, 2, 6,13,
|
||||
0,12, 1,13, 2,14, 3,15, 4, 8, 5, 9, 6,10, 7,11,
|
||||
0,13, 3,14, 6,11, 5, 8,12, 1,15, 2,10, 7, 9, 4,
|
||||
0,14, 5,11,10, 4,15, 1,13, 3, 8, 6, 7, 9, 2,12,
|
||||
0,15, 7, 8,14, 1, 9, 6, 5,10, 2,13,11, 4,12, 3
|
||||
};
|
||||
const int rsid_indices[] = {
|
||||
2, 4, 8, 9, 11, 15, 7, 14, 5, 10, 13, 3
|
||||
};
|
||||
|
||||
/**
|
||||
* This function populates the RSID_NSYMBOLS tones needed to transmit
|
||||
* a RSID for the given rsid_code
|
||||
*/
|
||||
void rsid_encode(rsid_code_t rsid_code, int8_t* rsid)
|
||||
{
|
||||
memset(rsid, 0, RSID_NSYMBOLS * sizeof(int8_t));
|
||||
|
||||
/* Encode the 12-bit code into the first 3 nibbles */
|
||||
rsid[0] = (rsid_code >> 8) & 0x0F;
|
||||
rsid[1] = (rsid_code >> 4) & 0x0F;
|
||||
rsid[2] = (rsid_code >> 0) & 0x0F;
|
||||
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
for (int j = RSID_NSYMBOLS - 1; j > 0; j--) {
|
||||
rsid[j] = rsid[j - 1] ^ rsid_squares[(rsid[j] << 4) + rsid_indices[i]];
|
||||
}
|
||||
|
||||
rsid[0] = rsid_squares[(rsid[0] << 4) + rsid_indices[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TRANSMISSION
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
uint8_t rsid_index = 0xFE;
|
||||
int8_t rsid[RSID_NSYMBOLS];
|
||||
|
||||
#define MODEM_TONE_SPACING 7.805
|
||||
|
||||
#define RSID_LOOKUP
|
||||
/* Lookup tables designed for a modem tone spacing of 7.805 Hz */
|
||||
int8_t rsid_tones_channels[] = { 0, 1, 3, 4, 6, 7, 8, 10, 11 };
|
||||
float rsid_tones_deviations[] = {
|
||||
0, 0.379, -0.241, 0.138, -0.482, -0.103, 0.276, -0.344, 0.035 };
|
||||
|
||||
|
||||
/**
|
||||
* Setup a rsid transmission
|
||||
*/
|
||||
void rsid_start(rsid_code_t rsid_code)
|
||||
{
|
||||
/* Start transmission */
|
||||
rsid_index = 0;
|
||||
rsid_encode(rsid_code, rsid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs one of the 16 RSID tones
|
||||
*/
|
||||
void rsid_tone(uint8_t tone)
|
||||
{
|
||||
int16_t channel;
|
||||
float deviation;
|
||||
int8_t air_tone = tone - 7;
|
||||
|
||||
#ifdef RSID_LOOKUP
|
||||
if (air_tone >= 0) {
|
||||
channel = rsid_tones_channels[air_tone];
|
||||
deviation = rsid_tones_deviations[air_tone];
|
||||
} else {
|
||||
channel = -rsid_tones_channels[-air_tone];
|
||||
deviation = -rsid_tones_deviations[-air_tone];
|
||||
}
|
||||
#else
|
||||
/* Calcuate the offset of this tone in channels */
|
||||
float tone_offset = ((float)air_tone * (float)RSID_SYMBOL_RATE) / (float)MODEM_TONE_SPACING;
|
||||
/* Centre channel */
|
||||
channel = (int16_t)round(tone_offset);
|
||||
/* And the deviation from this we need, in channels */
|
||||
deviation = tone_offset - (float)channel;
|
||||
#endif
|
||||
|
||||
float duty_cycle = 0.5 + (deviation / 2); // FSK only provides a marginal improvement in performance!
|
||||
|
||||
si_trx_switch_channel(channel);
|
||||
telemetry_gpio1_pwm_duty(duty_cycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at the rsid baud rate
|
||||
*/
|
||||
uint8_t rsid_tick(void)
|
||||
{
|
||||
|
||||
if (rsid_index < RSID_NSYMBOLS) {
|
||||
|
||||
/* Transmit this tone */
|
||||
rsid_tone(rsid[rsid_index]);
|
||||
|
||||
rsid_index++;
|
||||
if (rsid_index < RSID_NSYMBOLS) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -27,15 +27,19 @@
|
|||
#include "samd20.h"
|
||||
#include "rtty.h"
|
||||
#include "hw_config.h"
|
||||
#include "system/port.h"
|
||||
#include "si_trx.h"
|
||||
|
||||
|
||||
/**
|
||||
* Interface to the physical world.
|
||||
*/
|
||||
#define RTTY_ACTIVATE()
|
||||
#define RTTY_DEACTIVATE()
|
||||
#define RTTY_SET(b) port_pin_set_output_level(SI406X_GPIO1_PIN, !b);
|
||||
#define RTTY_NEXT()
|
||||
#define RTTY_CHANNEL_DEVIATION (RTTY_CHANNEL_SPACING / 2)
|
||||
#define RTTY_CHANNEL(b) (b ? RTTY_CHANNEL_DEVIATION : -RTTY_CHANNEL_DEVIATION)
|
||||
#define RTTY_SET(b) si_trx_switch_channel(RTTY_CHANNEL(b))
|
||||
|
||||
//port_pin_set_output_level(SI406X_GPIO1_PIN, !b);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Formatting 8N2
|
||||
|
|
|
@ -35,6 +35,13 @@
|
|||
#define VCXO_FREQUENCY SI406X_TCXO_FREQUENCY
|
||||
#define RF_DEVIATION 200
|
||||
|
||||
/**
|
||||
* The LSB tuning resolution of the frac-n pll as currently
|
||||
* configured.
|
||||
*/
|
||||
float lsb_tuning_resolution = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Generic SPI Send / Receive
|
||||
*/
|
||||
|
@ -223,16 +230,6 @@ static void si_trx_frequency_control_set_divider(uint8_t integer_divider,
|
|||
SI_FREQ_CONTROL_INTE,
|
||||
divider);
|
||||
}
|
||||
/**
|
||||
* Sets the step size between adjacent channels, in units of the
|
||||
* resolution of the frac-n pll synthesiser.
|
||||
*/
|
||||
static void si_trx_frequency_control_set_channel_step_size(uint16_t step_size)
|
||||
{
|
||||
_si_trx_set_property_16(SI_PROPERTY_GROUP_FREQ_CONTROL,
|
||||
SI_FREQ_CONTROL_CHANNEL_STEP_SIZE,
|
||||
step_size);
|
||||
}
|
||||
/**
|
||||
* Sets the output divider of the frac-n pll synthesiser
|
||||
*/
|
||||
|
@ -243,7 +240,11 @@ static void si_trx_frequency_control_set_band(uint8_t band, uint8_t sy_sel)
|
|||
sy_sel | (band & 0x7));
|
||||
}
|
||||
/**
|
||||
* Sets the frequency deviation in the modem
|
||||
* Sets the modem frequency deviation. This is how much the external
|
||||
* pin deviates the synthesiser from the centre frequency. In units of
|
||||
* the resolution of the frac-n pll synthsiser.
|
||||
*
|
||||
* This is an unsigned 17-bit value.
|
||||
*/
|
||||
static void si_trx_modem_set_deviation(uint32_t deviation)
|
||||
{
|
||||
|
@ -251,6 +252,19 @@ static void si_trx_modem_set_deviation(uint32_t deviation)
|
|||
SI_MODEM_FREQ_DEV,
|
||||
deviation);
|
||||
}
|
||||
/**
|
||||
* Sets the modem frequency offset manually. In units of the
|
||||
* resolution of the frac-n pll synthsiser.
|
||||
*
|
||||
* This is a signed 16-bit value.
|
||||
*/
|
||||
static void si_trx_modem_set_offset(int16_t offset)
|
||||
{
|
||||
_si_trx_set_property_16(SI_PROPERTY_GROUP_MODEM,
|
||||
SI_MODEM_FREQ_OFFSET,
|
||||
offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the modulation mode
|
||||
*/
|
||||
|
@ -283,9 +297,11 @@ static void si_trx_set_tx_pa_duty_cycle(uint8_t pa_duty_cycle)
|
|||
|
||||
|
||||
/**
|
||||
* Set the synthesiser to the given frequency
|
||||
* Set the synthesiser to the given frequency.
|
||||
*
|
||||
* Returns the LSB tuning resolution of the frac-n pll synthesiser.
|
||||
*/
|
||||
static void si_trx_set_frequency(uint32_t frequency, float channel_spacing)
|
||||
static float si_trx_set_frequency(uint32_t frequency)
|
||||
{
|
||||
uint8_t outdiv, band, nprescaler;
|
||||
|
||||
|
@ -309,25 +325,19 @@ static void si_trx_set_frequency(uint32_t frequency, float channel_spacing)
|
|||
outdiv = 24; band = SI_MODEM_CLKGEN_FVCO_DIV_24;
|
||||
}
|
||||
|
||||
uint32_t f_pfd = nprescaler * VCXO_FREQUENCY / outdiv;
|
||||
float f_pfd = nprescaler * VCXO_FREQUENCY / outdiv;
|
||||
|
||||
uint16_t n = ((uint16_t)(frequency / f_pfd)) - 1;
|
||||
|
||||
float ratio = (float)frequency / (float)f_pfd;
|
||||
float ratio = (float)frequency / f_pfd;
|
||||
float rest = ratio - (float)n;
|
||||
|
||||
uint32_t m = (uint32_t)(rest * (float)(1 << 19));
|
||||
|
||||
|
||||
/* Check n and m are in valid ranges, halt otherwise */
|
||||
if (n > 0x7f || m > 0xfffff) while (1);
|
||||
|
||||
/* Set the modem deviation, in units of the VCO resolution */
|
||||
float dev_ratio = (float)RF_DEVIATION / (float)f_pfd;
|
||||
uint32_t dev = (uint32_t)(dev_ratio * (float)(1 << 19));
|
||||
|
||||
/* Set the channel spacing, in units of the VCO resolution */
|
||||
float channel_spacing_ratio = channel_spacing / (float)f_pfd;
|
||||
uint32_t channel_step = (uint32_t)(channel_spacing_ratio * (float)(1 << 19));
|
||||
|
||||
/* Set the frac-n PLL output divider */
|
||||
if (nprescaler == 4) { /* Prescaler */
|
||||
|
@ -336,20 +346,21 @@ static void si_trx_set_frequency(uint32_t frequency, float channel_spacing)
|
|||
si_trx_frequency_control_set_band(band, SI_MODEM_CLKGEN_SY_SEL_1);
|
||||
}
|
||||
|
||||
|
||||
/* Set the frac-n PLL divisior */
|
||||
si_trx_frequency_control_set_divider(n, m);
|
||||
|
||||
/* Set the channel step in the PLL */
|
||||
si_trx_frequency_control_set_channel_step_size(channel_step);
|
||||
/* Set the external pin frequency deviation to the LSB tuning resoultion */
|
||||
si_trx_modem_set_deviation(1);
|
||||
|
||||
/* Set the frequency deviation in the modem */
|
||||
si_trx_modem_set_deviation(dev);
|
||||
/* Return the LSB tuning resolution of the frac-n pll synthesiser. */
|
||||
return f_pfd / (float)(1 << 19);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the transceiver
|
||||
*/
|
||||
void si_trx_reset(uint8_t modulation_type, float channel_spacing)
|
||||
void si_trx_reset(uint8_t modulation_type)
|
||||
{
|
||||
_si_trx_sdn_enable(); /* active high shutdown = reset */
|
||||
|
||||
|
@ -376,7 +387,7 @@ void si_trx_reset(uint8_t modulation_type, float channel_spacing)
|
|||
SI_GPIO_PIN_CFG_GPIO_MODE_INPUT | SI_GPIO_PIN_CFG_PULL_ENABLE,
|
||||
SI_GPIO_PIN_CFG_DRV_STRENGTH_LOW);
|
||||
|
||||
si_trx_set_frequency(RADIO_FREQUENCY, channel_spacing);
|
||||
si_trx_set_frequency(RADIO_FREQUENCY);
|
||||
si_trx_set_tx_power(RADIO_POWER);
|
||||
|
||||
/* RTTY from GPIO1 */
|
||||
|
@ -391,10 +402,10 @@ void si_trx_reset(uint8_t modulation_type, float channel_spacing)
|
|||
/**
|
||||
* Enables the radio and starts transmitting
|
||||
*/
|
||||
void si_trx_on(uint8_t modulation_type, float channel_spacing)
|
||||
void si_trx_on(uint8_t modulation_type)
|
||||
{
|
||||
si_trx_reset(modulation_type, channel_spacing);
|
||||
si_trx_start_tx(1);
|
||||
si_trx_reset(modulation_type);
|
||||
si_trx_start_tx(0);
|
||||
}
|
||||
/**
|
||||
* Disables the radio and places it in shutdown
|
||||
|
@ -404,13 +415,13 @@ void si_trx_off(void)
|
|||
si_trx_state_ready();
|
||||
_si_trx_sdn_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the transmittion to the specified channel
|
||||
* Switches the transmission to the specified channel. Signed 16-bit int
|
||||
*/
|
||||
void si_trx_switch_channel(uint8_t channel)
|
||||
void si_trx_switch_channel(int16_t channel)
|
||||
{
|
||||
si_trx_state_ready();
|
||||
si_trx_start_tx(channel);
|
||||
si_trx_modem_set_offset(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "telemetry.h"
|
||||
#include "rtty.h"
|
||||
#include "contestia.h"
|
||||
#include "rsid.h"
|
||||
#include "si_trx.h"
|
||||
#include "si_trx_defs.h"
|
||||
#include "system/gclk.h"
|
||||
|
@ -125,17 +126,15 @@ int telemetry_start(enum telemetry_t type) {
|
|||
/* Initialise */
|
||||
telemetry_type = type;
|
||||
telemetry_index = 0;
|
||||
|
||||
/* Initialise first block / character */
|
||||
telemetry_string_length = TELEMETRY_STRING_MAX;
|
||||
|
||||
/* Setup timer tick */
|
||||
switch(telemetry_type) {
|
||||
case TELEMETRY_CONTESTIA:
|
||||
timer0_tick_init(31.25);
|
||||
timer0_tick_init(CONTESTIA_SYMBOL_RATE);
|
||||
break;
|
||||
case TELEMETRY_RTTY:
|
||||
timer0_tick_init(50);
|
||||
timer0_tick_init(RTTY_BITRATE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -144,6 +143,32 @@ int telemetry_start(enum telemetry_t type) {
|
|||
return 1; /* Already active */
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Start RSID output. Argument: RSID Data
|
||||
*
|
||||
* Returns 0 on success, 1 if already active
|
||||
*/
|
||||
int telemetry_start_rsid(rsid_code_t rsid) {
|
||||
if (!telemetry_active()) {
|
||||
|
||||
/* Initialise */
|
||||
telemetry_type = TELEMETRY_RSID;
|
||||
telemetry_index = 0;
|
||||
telemetry_string_length = 6;
|
||||
|
||||
/* Start RSID */
|
||||
rsid_start(rsid);
|
||||
|
||||
/* Setup timer tick */
|
||||
timer0_tick_init(RSID_SYMBOL_RATE);
|
||||
|
||||
return 0; /* Success */
|
||||
} else {
|
||||
return 1; /* Already active */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the current byte being outputted from the buffer
|
||||
*/
|
||||
|
@ -185,8 +210,8 @@ void telemetry_tick(void) {
|
|||
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);
|
||||
/* Contestia: We use the modem offset to modulate */
|
||||
si_trx_on(SI_MODEM_MOD_TYPE_CW);
|
||||
radio_on = 1;
|
||||
}
|
||||
|
||||
|
@ -205,8 +230,8 @@ void telemetry_tick(void) {
|
|||
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);
|
||||
/* RTTY: We use the modem offset to modulate */
|
||||
si_trx_on(SI_MODEM_MOD_TYPE_CW);
|
||||
radio_on = 1;
|
||||
}
|
||||
|
||||
|
@ -222,10 +247,36 @@ void telemetry_tick(void) {
|
|||
}
|
||||
|
||||
break;
|
||||
|
||||
case TELEMETRY_RSID: /* ---- ---- A block mode */
|
||||
|
||||
/* Wait for 5 bit times of silence */
|
||||
if (telemetry_index < 5) {
|
||||
telemetry_index++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!radio_on) {
|
||||
/* RSID: We PWM frequencies with the external pin */
|
||||
si_trx_on(SI_MODEM_MOD_TYPE_2FSK);
|
||||
telemetry_gpio1_pwm_init();
|
||||
|
||||
radio_on = 1;
|
||||
}
|
||||
|
||||
/* Do Tx */
|
||||
if (!rsid_tick()) {
|
||||
/* Force transmission finished */
|
||||
telemetry_index++;
|
||||
is_telemetry_finished(); // Returns true
|
||||
telemetry_gpio1_pwm_deinit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CLOCKING
|
||||
* =============================================================================
|
||||
|
@ -250,8 +301,10 @@ void si_gclk_setup(void)
|
|||
|
||||
/**
|
||||
* Initialises a timer interupt at the given frequency
|
||||
*
|
||||
* Returns the frequency we actually initialised.
|
||||
*/
|
||||
void timer0_tick_init(float frequency)
|
||||
float timer0_tick_init(float frequency)
|
||||
{
|
||||
//si_gclk_setup();
|
||||
|
||||
|
@ -293,6 +346,9 @@ void timer0_tick_init(float frequency)
|
|||
/* Enable Timer */
|
||||
tc_enable(TC0);
|
||||
tc_start_counter(TC0);
|
||||
|
||||
/* Return the frequency we actually initialised */
|
||||
return gclk_frequency / (float)count;
|
||||
}
|
||||
/**
|
||||
* Disables the timer
|
||||
|
@ -315,3 +371,64 @@ void TC0_Handler(void)
|
|||
telemetry_tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define GPIO1_PWM_STEPS 200 // ~ 20kHz 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 gclk_frequency = (float)system_gclk_chan_get_hz(0);
|
||||
|
||||
tc_init(TC5,
|
||||
GCLK_GENERATOR_0,
|
||||
TC_COUNTER_SIZE_8BIT,
|
||||
TC_CLOCK_PRESCALER_DIV1,
|
||||
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 */
|
||||
GPIO1_PWM_STEPS, /* 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);
|
||||
|
||||
}
|
||||
/**
|
||||
* Sets duty cycle on PWM pin
|
||||
*/
|
||||
void telemetry_gpio1_pwm_duty(float duty_cycle)
|
||||
{
|
||||
uint32_t compare_value = (float)GPIO1_PWM_STEPS * duty_cycle;
|
||||
|
||||
tc_set_compare_value(TC5,
|
||||
TC_COMPARE_CAPTURE_CHANNEL_1,
|
||||
compare_value);
|
||||
}
|
||||
/**
|
||||
* Turn the pwm off again
|
||||
*/
|
||||
void telemetry_gpio1_pwm_deinit(void)
|
||||
{
|
||||
tc_stop_counter(TC5);
|
||||
tc_enable(TC5);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue