diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fsm/cw.c | 66 | ||||
-rw-r--r-- | src/fsm/cw.h | 68 | ||||
-rw-r--r-- | src/fsm/gps.c | 2 | ||||
-rw-r--r-- | src/fsm/main.c | 43 | ||||
-rw-r--r-- | src/fsm/psk31.c | 194 | ||||
-rw-r--r-- | src/fsm/psk31.h | 136 |
6 files changed, 277 insertions, 232 deletions
diff --git a/src/fsm/cw.c b/src/fsm/cw.c index 96c510a..ee0ba77 100644 --- a/src/fsm/cw.c +++ b/src/fsm/cw.c @@ -47,6 +47,69 @@ #define ON_BUFFER_SIZE 1024 +const uint8_t cw_mapping[60] = { // {{{ + // Read bits from right to left + + 0b110101, //+ ASCII 43 + 0b110101, //, ASCII 44 + 0b1011110, //- ASCII 45 + + 0b1010101, //., ASCII 46 + 0b110110, // / ASCII 47 + + 0b100000, // 0, ASCII 48 + 0b100001, // 1 + 0b100011, + 0b100111, + 0b101111, + 0b111111, + 0b111110, + 0b111100, + 0b111000, + 0b110000, // 9, ASCII 57 + + // The following are mostly invalid, but + // required to fill the gap in ASCII between + // numerals and capital letters + 0b10, // : + 0b10, // ; + 0b10, // < + 0b10, // = + 0b10, // > + 0b1110011, // ? + 0b1101001, //@ + + 0b101, // A ASCII 65 + 0b11110, + 0b11010, + 0b1110, + 0b11, + 0b11011, + 0b1100, + 0b11111, + 0b111, + 0b10001, + 0b1010, + 0b11101, + 0b100, //M + 0b110, + 0b1000, + 0b11001, + 0b10100, + 0b1101, + 0b1111, + 0b10, + 0b1011, + 0b10111, + 0b1001, + 0b10110, + 0b10010, + 0b11100, // Z + + 0b101010, //Start, ASCII [ + 0b1010111, // SK , ASCII '\' +}; //}}} + struct cw_out_message_s { // Contains a sequence of ones and zeros corresponding to // TX on/TX off CW data to be sent @@ -173,10 +236,9 @@ size_t cw_fill_buffer(int16_t *buf, size_t bufsize) } static int16_t cw_audio_buf[AUDIO_BUF_LEN]; +static struct cw_out_message_s cw_fill_msg_current; static void cw_task(void *pvParameters) { - struct cw_out_message_s cw_fill_msg_current; - float nco_phase = 0.0f; float ampl = 0.0f; diff --git a/src/fsm/cw.h b/src/fsm/cw.h index 3c09441..0cbb29c 100644 --- a/src/fsm/cw.h +++ b/src/fsm/cw.h @@ -22,6 +22,9 @@ * SOFTWARE. */ +#ifndef __CW_H_ +#define __CW_H_ + #include <stdint.h> #include <stddef.h> @@ -37,69 +40,8 @@ void cw_push_message(const char* text, int dit_duration, int frequency); // Write the waveform into the buffer (stereo) size_t cw_fill_buffer(int16_t *buf, size_t bufsize); -// Return 1 if the CW generator has completed transmission +// Return 1 if the CW generator is running int cw_busy(void); -const uint8_t cw_mapping[60] = { // {{{ - // Read bits from right to left - - 0b110101, //+ ASCII 43 - 0b110101, //, ASCII 44 - 0b1011110, //- ASCII 45 - - 0b1010101, //., ASCII 46 - 0b110110, // / ASCII 47 - - 0b100000, // 0, ASCII 48 - 0b100001, // 1 - 0b100011, - 0b100111, - 0b101111, - 0b111111, - 0b111110, - 0b111100, - 0b111000, - 0b110000, // 9, ASCII 57 - - // The following are mostly invalid, but - // required to fill the gap in ASCII between - // numerals and capital letters - 0b10, // : - 0b10, // ; - 0b10, // < - 0b10, // = - 0b10, // > - 0b1110011, // ? - 0b1101001, //@ - - 0b101, // A ASCII 65 - 0b11110, - 0b11010, - 0b1110, - 0b11, - 0b11011, - 0b1100, - 0b11111, - 0b111, - 0b10001, - 0b1010, - 0b11101, - 0b100, //M - 0b110, - 0b1000, - 0b11001, - 0b10100, - 0b1101, - 0b1111, - 0b10, - 0b1011, - 0b10111, - 0b1001, - 0b10110, - 0b10010, - 0b11100, // Z - - 0b101010, //Start, ASCII [ - 0b1010111, // SK , ASCII '\' -}; //}}} +#endif // __CW_H_ diff --git a/src/fsm/gps.c b/src/fsm/gps.c index 9ebd0b8..2b6d058 100644 --- a/src/fsm/gps.c +++ b/src/fsm/gps.c @@ -82,7 +82,7 @@ static void gps_task(void *pvParameters) if (minmea_parse_rmc(&frame, rxbuf)) { xSemaphoreTake(timeutc_semaphore, portMAX_DELAY); gps_timeutc_last_updated = xTaskGetTickCount(); - gps_timeutc.year = frame.date.year; + gps_timeutc.year = 2000 + frame.date.year; gps_timeutc.month = frame.date.month; gps_timeutc.day = frame.date.day; gps_timeutc.hour = frame.time.hours; diff --git a/src/fsm/main.c b/src/fsm/main.c index 9ae21fa..0dc2ffc 100644 --- a/src/fsm/main.c +++ b/src/fsm/main.c @@ -35,6 +35,7 @@ #include "timers.h" #include "semphr.h" #include "cw.h" +#include "psk31.h" #include "pio.h" #include "i2c.h" #include "gps.h" @@ -101,6 +102,7 @@ int main(void) { static void launcher_task(void *pvParameters) { cw_init(16000); + psk31_init(16000); pio_init(); i2c_init(); common_init(); @@ -134,7 +136,7 @@ static void launcher_task(void *pvParameters) xTaskCreate( gps_monit_task, "TaskGPSMonit", - 4*configMINIMAL_STACK_SIZE, + 6*configMINIMAL_STACK_SIZE, (void*) NULL, tskIDLE_PRIORITY + 2UL, &task_handle); @@ -161,8 +163,6 @@ static void launcher_task(void *pvParameters) static void detect_button_press(void *pvParameters) { - GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN); - while (1) { if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)>0) { @@ -171,14 +171,12 @@ static void detect_button_press(void *pvParameters) } tm_trigger = 1; - GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN); while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0) { vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */ } tm_trigger = 0; - GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_GREEN); } taskYIELD(); } @@ -200,7 +198,11 @@ static void audio_callback(void* context, int select_buffer) select_buffer = 0; } - size_t samples_len = cw_fill_buffer(samples, AUDIO_BUF_LEN); + size_t samples_len = psk31_fill_buffer(samples, AUDIO_BUF_LEN); + + if (samples_len == 0) { + samples_len = cw_fill_buffer(samples, AUDIO_BUF_LEN); + } if (samples_len == 0) { for (int i = 0; i < AUDIO_BUF_LEN; i++) { @@ -214,11 +216,15 @@ static void audio_callback(void* context, int select_buffer) } +static char psk31_msg[256]; static struct gps_time_s gps_time; static void gps_monit_task(void *pvParameters) { GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_BLUE); + int trigger_psk31 = 0; + int last_trigger_psk31 = 0; + while (1) { if (gps_locked()) { @@ -230,7 +236,32 @@ static void gps_monit_task(void *pvParameters) else { GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_BLUE); } + + if (gps_time.sec == 0 || gps_time.sec == 20 || gps_time.sec == 40) { + trigger_psk31 = 1; + } + else { + trigger_psk31 = 0; + } + + } + + if (trigger_psk31 && !last_trigger_psk31) { + snprintf(psk31_msg, 255, "Hello PSK31\nDate: %4d-%02d-%02d %02d:%02d:%02d\n73!", + gps_time.year, gps_time.month, gps_time.day, + gps_time.hour, gps_time.min, gps_time.sec); + + psk31_push_message(psk31_msg, 400); } + last_trigger_psk31 = trigger_psk31; + + if (psk31_busy()) { + GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN); + } + else { + GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_GREEN); + } + taskYIELD(); } } diff --git a/src/fsm/psk31.c b/src/fsm/psk31.c index 6eafa53..a4e770a 100644 --- a/src/fsm/psk31.c +++ b/src/fsm/psk31.c @@ -53,12 +53,148 @@ * The psk31_fill_buffer() function can be called to fetch audio from the audio_queue */ -#define PSK31_MAX_MESSAGE_LEN 10240 +/* + * PSK31 Varicode + * http://aintel.bi.ehu.es/psk31.html + */ +const char *psk31_varicode[] = { // {{{ + "1010101011", + "1011011011", + "1011101101", + "1101110111", + "1011101011", + "1101011111", + "1011101111", + "1011111101", + "1011111111", + "11101111", + "11101", + "1101101111", + "1011011101", + "11111", + "1101110101", + "1110101011", + "1011110111", + "1011110101", + "1110101101", + "1110101111", + "1101011011", + "1101101011", + "1101101101", + "1101010111", + "1101111011", + "1101111101", + "1110110111", + "1101010101", + "1101011101", + "1110111011", + "1011111011", + "1101111111", + "1", + "111111111", + "101011111", + "111110101", + "111011011", + "1011010101", + "1010111011", + "101111111", + "11111011", + "11110111", + "101101111", + "111011111", + "1110101", + "110101", + "1010111", + "110101111", + "10110111", + "10111101", + "11101101", + "11111111", + "101110111", + "101011011", + "101101011", + "110101101", + "110101011", + "110110111", + "11110101", + "110111101", + "111101101", + "1010101", + "111010111", + "1010101111", + "1010111101", + "1111101", + "11101011", + "10101101", + "10110101", + "1110111", + "11011011", + "11111101", + "101010101", + "1111111", + "111111101", + "101111101", + "11010111", + "10111011", + "11011101", + "10101011", + "11010101", + "111011101", + "10101111", + "1101111", + "1101101", + "101010111", + "110110101", + "101011101", + "101110101", + "101111011", + "1010101101", + "111110111", + "111101111", + "111111011", + "1010111111", + "101101101", + "1011011111", + "1011", + "1011111", + "101111", + "101101", + "11", + "111101", + "1011011", + "101011", + "1101", + "111101011", + "10111111", + "11011", + "111011", + "1111", + "111", + "111111", + "110111111", + "10101", + "10111", + "101", + "110111", + "1111011", + "1101011", + "11011111", + "1011101", + "111010101", + "1010110111", + "110111011", + "1010110101", + "1011010111", + "1110110101", +}; //}}} + + +#define PSK31_MAX_MESSAGE_LEN 4096 #define PHASE_BUFFER_SIZE (20 + PSK31_MAX_MESSAGE_LEN + 20) struct psk31_out_message_s { - // Contains a sequence of ones and zeros corresponding to - // the BPSK31 phase + // Contains a string sequence of '0' and '1' corresponding to + // the BPSK31 phase. Is terminated with '\0' char phase_buffer[PHASE_BUFFER_SIZE]; size_t phase_buffer_end; @@ -75,7 +211,7 @@ static int psk31_samplerate; static int psk31_transmit_ongoing; static void psk31_task(void *pvParameters); -static void psk31_str_to_bits(const char* instr, char* outbits); +static int psk31_str_to_bits(const char* instr, char* outbits); void psk31_init(unsigned int samplerate) @@ -83,20 +219,20 @@ void psk31_init(unsigned int samplerate) psk31_samplerate = samplerate; psk31_transmit_ongoing = 0; - psk31_msg_queue = xQueueCreate(15, sizeof(struct psk31_out_message_s)); + psk31_msg_queue = xQueueCreate(1, sizeof(struct psk31_out_message_s)); if (psk31_msg_queue == 0) { while(1); /* fatal error */ } - psk31_audio_queue = xQueueCreate(2, AUDIO_BUF_LEN * sizeof(int16_t)); + psk31_audio_queue = xQueueCreate(1, AUDIO_BUF_LEN * sizeof(int16_t)); if (psk31_audio_queue == 0) { while(1); /* fatal error */ } xTaskCreate( psk31_task, - "TaskPSK31", - 8*configMINIMAL_STACK_SIZE, + "TaskPSK", + 5*configMINIMAL_STACK_SIZE, (void*) NULL, tskIDLE_PRIORITY + 2UL, NULL); @@ -112,7 +248,7 @@ int psk31_push_message(const char* text, int frequency) msg.phase_buffer_end = 0; msg.freq = frequency; - psk31_str_to_bits(text, msg.phase_buffer); + msg.phase_buffer_end = psk31_str_to_bits(text, msg.phase_buffer); xQueueSendToBack(psk31_msg_queue, &msg, portMAX_DELAY); @@ -120,16 +256,25 @@ int psk31_push_message(const char* text, int frequency) } // Write the waveform into the buffer (stereo) -size_t psk31_fill_buffer(int16_t *buf, size_t bufsize); +size_t psk31_fill_buffer(int16_t *buf, size_t bufsize) +{ + if (xQueueReceiveFromISR(psk31_audio_queue, buf, NULL)) { + return bufsize; + } + else { + return 0; + } +} -// Return 1 if the psk31 generator has completed transmission -int psk31_busy(void); +int psk31_busy(void) +{ + return psk31_transmit_ongoing; +} static int16_t psk31_audio_buf[AUDIO_BUF_LEN]; +static struct psk31_out_message_s psk31_fill_msg_current; static void psk31_task(void *pvParameters) { - struct psk31_out_message_s psk31_fill_msg_current; - float nco_phase = 0.0f; float ampl = 0.0f; @@ -141,6 +286,8 @@ static void psk31_task(void *pvParameters) psk31_transmit_ongoing = 1; + const float base_ampl = 20000.0f; + /* BPSK31 is at 31.25 symbols per second. */ const int samples_per_symbol = psk31_samplerate * 100 / 3125; @@ -148,20 +295,17 @@ static void psk31_task(void *pvParameters) const float omega = 2.0f * FLOAT_PI * psk31_fill_msg_current.freq / (float)psk31_samplerate; - int current_psk_phase = 0; + int current_psk_phase = 1; for (int i = 0; i < psk31_fill_msg_current.phase_buffer_end; i++) { for (int t = 0; t < samples_per_symbol; t++) { int16_t s = 0; - if (psk31_fill_msg_current.phase_buffer[i]) { - ampl = 32000.0f; + if (psk31_fill_msg_current.phase_buffer[i] == '1') { + ampl = base_ampl; } else { - ampl = - (float)current_psk_phase * - 32000.0f * - arm_cos_f32( + ampl = base_ampl * arm_cos_f32( FLOAT_PI*(float)t/(float)samples_per_symbol); } @@ -170,7 +314,8 @@ static void psk31_task(void *pvParameters) nco_phase -= 2.0f * FLOAT_PI; } - s = ampl * arm_sin_f32(nco_phase); + s = ampl * arm_sin_f32(nco_phase + + (current_psk_phase == 1 ? 0.0f : FLOAT_PI)); if (buf_pos == AUDIO_BUF_LEN) { xQueueSendToBack(psk31_audio_queue, &psk31_audio_buf, portMAX_DELAY); @@ -187,7 +332,7 @@ static void psk31_task(void *pvParameters) } - if (! psk31_fill_msg_current.phase_buffer[i]) { + if (psk31_fill_msg_current.phase_buffer[i] == '0') { current_psk_phase *= -1; } } @@ -206,7 +351,7 @@ static void psk31_task(void *pvParameters) * outstr must be at least size 20 + strlen(instr)*12 + 20 to accomodate * the header and tail */ -static void psk31_str_to_bits(const char* instr, char* outbits) +static int psk31_str_to_bits(const char* instr, char* outbits) { int i=0, j, k; @@ -232,6 +377,7 @@ static void psk31_str_to_bits(const char* instr, char* outbits) /* NULL terminate */ outbits[i] = 0; + return i; } #if 0 diff --git a/src/fsm/psk31.h b/src/fsm/psk31.h index 3e47f4c..3f08ecf 100644 --- a/src/fsm/psk31.h +++ b/src/fsm/psk31.h @@ -44,141 +44,5 @@ size_t psk31_fill_buffer(int16_t *buf, size_t bufsize); // Return 1 if the psk31 generator has completed transmission int psk31_busy(void); - -/* - * PSK31 Varicode - * http://aintel.bi.ehu.es/psk31.html - */ -const char *psk31_varicode[] = { - "1010101011", - "1011011011", - "1011101101", - "1101110111", - "1011101011", - "1101011111", - "1011101111", - "1011111101", - "1011111111", - "11101111", - "11101", - "1101101111", - "1011011101", - "11111", - "1101110101", - "1110101011", - "1011110111", - "1011110101", - "1110101101", - "1110101111", - "1101011011", - "1101101011", - "1101101101", - "1101010111", - "1101111011", - "1101111101", - "1110110111", - "1101010101", - "1101011101", - "1110111011", - "1011111011", - "1101111111", - "1", - "111111111", - "101011111", - "111110101", - "111011011", - "1011010101", - "1010111011", - "101111111", - "11111011", - "11110111", - "101101111", - "111011111", - "1110101", - "110101", - "1010111", - "110101111", - "10110111", - "10111101", - "11101101", - "11111111", - "101110111", - "101011011", - "101101011", - "110101101", - "110101011", - "110110111", - "11110101", - "110111101", - "111101101", - "1010101", - "111010111", - "1010101111", - "1010111101", - "1111101", - "11101011", - "10101101", - "10110101", - "1110111", - "11011011", - "11111101", - "101010101", - "1111111", - "111111101", - "101111101", - "11010111", - "10111011", - "11011101", - "10101011", - "11010101", - "111011101", - "10101111", - "1101111", - "1101101", - "101010111", - "110110101", - "101011101", - "101110101", - "101111011", - "1010101101", - "111110111", - "111101111", - "111111011", - "1010111111", - "101101101", - "1011011111", - "1011", - "1011111", - "101111", - "101101", - "11", - "111101", - "1011011", - "101011", - "1101", - "111101011", - "10111111", - "11011", - "111011", - "1111", - "111", - "111111", - "110111111", - "10101", - "10111", - "101", - "110111", - "1111011", - "1101011", - "11011111", - "1011101", - "111010101", - "1010110111", - "110111011", - "1010110101", - "1011010111", - "1110110101", -}; - #endif // __PSK_31_H_ |