diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2015-12-12 10:13:32 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2015-12-12 10:13:32 +0100 |
commit | aebb7e588e73bd4123be7a540bcad8596b4351d6 (patch) | |
tree | 50a65853cca8075af8250fc36e073e7e0590925e /src/fsm | |
parent | 66e49ea68509fd0c7c9cc218068bb288d1d29582 (diff) | |
download | glutte-o-matic-aebb7e588e73bd4123be7a540bcad8596b4351d6.tar.gz glutte-o-matic-aebb7e588e73bd4123be7a540bcad8596b4351d6.tar.bz2 glutte-o-matic-aebb7e588e73bd4123be7a540bcad8596b4351d6.zip |
Add external pins to exercise FSM, timestamp and random_bool
Diffstat (limited to 'src/fsm')
-rw-r--r-- | src/fsm/common.c | 74 | ||||
-rw-r--r-- | src/fsm/common.h | 6 | ||||
-rw-r--r-- | src/fsm/cw.c | 12 | ||||
-rw-r--r-- | src/fsm/cw.h | 3 | ||||
-rw-r--r-- | src/fsm/fsm.c | 53 | ||||
-rw-r--r-- | src/fsm/fsm.h | 9 | ||||
-rw-r--r-- | src/fsm/main.c | 102 | ||||
-rw-r--r-- | src/fsm/pio.c | 113 | ||||
-rw-r--r-- | src/fsm/pio.h | 71 |
9 files changed, 395 insertions, 48 deletions
diff --git a/src/fsm/common.c b/src/fsm/common.c new file mode 100644 index 0000000..6e00740 --- /dev/null +++ b/src/fsm/common.c @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Matthias P. Braendli + * + * 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 "common.h" +#include "FreeRTOS.h" +#include "timers.h" + +static uint64_t common_timestamp = 0; // milliseconds since startup +static TimerHandle_t common_timer; + +// The LFSR is used as random number generator +static const uint16_t lfsr_start_state = 0x12ABu; +static uint16_t lfsr; + +static void common_increase_timestamp(TimerHandle_t t); + +void common_init(void) +{ + common_timer = xTimerCreate("Timer", + portTICK_PERIOD_MS, + pdTRUE, // Auto-reload + NULL, // No unique id + common_increase_timestamp + ); + + xTimerStart(common_timer, 0); + + lfsr = lfsr_start_state; +} + +static void common_increase_timestamp(TimerHandle_t t) +{ + common_timestamp++; +} + +uint64_t timestamp_now(void) +{ + return common_timestamp; +} + +// Return either 0 or 1, somewhat randomly +int random_bool(void) +{ + uint16_t bit; + + /* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */ + bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1; + lfsr = (lfsr >> 1) | (bit << 15); + + return bit; +} + + diff --git a/src/fsm/common.h b/src/fsm/common.h index 45ba854..1bd3b96 100644 --- a/src/fsm/common.h +++ b/src/fsm/common.h @@ -22,11 +22,17 @@ * SOFTWARE. */ +/* A set of common routines for internal timekeeping and a LFSR to generate + * a random number + */ + #include <stdint.h> #ifndef _COMMON_H_ #define _COMMON_H_ +void common_init(void); + // Return the current timestamp in milliseconds. Timestamps are monotonic, and not // wall clock time. uint64_t timestamp_now(void); diff --git a/src/fsm/cw.c b/src/fsm/cw.c index a54a3ea..da83383 100644 --- a/src/fsm/cw.c +++ b/src/fsm/cw.c @@ -63,11 +63,14 @@ QueueHandle_t cw_msg_queue; QueueHandle_t cw_audio_queue; static int cw_samplerate; +static int cw_transmit_ongoing; + static void cw_task(void *pvParameters); void cw_init(unsigned int samplerate) { cw_samplerate = samplerate; + cw_transmit_ongoing = 0; cw_msg_queue = xQueueCreate(15, sizeof(struct cw_out_message_s)); if (cw_msg_queue == 0) { @@ -245,6 +248,8 @@ static void cw_task(void *pvParameters) int status = xQueueReceive(cw_msg_queue, &cw_fill_msg_current, portMAX_DELAY); if (status == pdTRUE) { + cw_transmit_ongoing = 1; + const int samples_per_dit = (cw_samplerate * 10) / cw_fill_msg_current.dit_duration; @@ -288,7 +293,14 @@ static void cw_task(void *pvParameters) } // We have completed this message + + cw_transmit_ongoing = 0; } } } +int cw_busy(void) +{ + return cw_transmit_ongoing; +} + diff --git a/src/fsm/cw.h b/src/fsm/cw.h index b090a04..31db269 100644 --- a/src/fsm/cw.h +++ b/src/fsm/cw.h @@ -39,3 +39,6 @@ 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 +int cw_busy(void); + diff --git a/src/fsm/fsm.c b/src/fsm/fsm.c index ca6a753..d8a3a5c 100644 --- a/src/fsm/fsm.c +++ b/src/fsm/fsm.c @@ -57,12 +57,12 @@ uint64_t fsm_current_state_time_s(void) { // Between turns in a QSO, the repeater sends a letter in CW, // different messages are possible. They are sorted here from // low to high priority. -const char* letter_all_ok = "k"; -const char* letter_sstv = "s"; -const char* letter_qrp = "g"; -const char* letter_freq_high = "u"; -const char* letter_freq_low = "d"; -const char* letter_swr_high = "r"; +const char* letter_all_ok = "K"; +const char* letter_sstv = "S"; +const char* letter_qrp = "G"; +const char* letter_freq_high = "U"; +const char* letter_freq_low = "D"; +const char* letter_swr_high = "R"; const char* fsm_select_letter(void) { if (fsm_in.swr_high) { @@ -93,7 +93,7 @@ void fsm_update() { fsm_out.modulation = 0; fsm_out.cw_trigger = 0; fsm_out.cw_speed = 23; - fsm_out.cw_frequency = 300; + fsm_out.cw_frequency = 500; // other output signals keep their value switch (current_state) { @@ -200,7 +200,7 @@ void fsm_update() { case FSM_ANTI_BAVARD: fsm_out.tx_on = 1; // No modulation! - fsm_out.cw_msg = "hi hi"; + fsm_out.cw_msg = "HI HI"; fsm_out.cw_trigger = 1; if (fsm_in.cw_done) { @@ -231,7 +231,7 @@ void fsm_update() { case FSM_TEXTE_HB9G: fsm_out.tx_on = 1; fsm_out.modulation = 1; - fsm_out.cw_msg = "hb9g"; + fsm_out.cw_msg = "HB9G"; fsm_out.cw_trigger = 1; if (fsm_in.sq) { @@ -247,10 +247,10 @@ void fsm_update() { fsm_out.modulation = 1; if (random_bool()) { - fsm_out.cw_msg = "hb9g 1628m"; + fsm_out.cw_msg = "HB9G 1628M"; } else { - fsm_out.cw_msg = "hb9g jn36bk"; + fsm_out.cw_msg = "HB9G JN36BK"; } fsm_out.cw_trigger = 1; @@ -268,13 +268,13 @@ void fsm_update() { // TODO transmit humidity // TODO read voltage if (fsm_in.wind_generator_ok) { - fsm_out.cw_msg = "hb9g jn36bk 1628m u 10v5 = T 11 73"; + fsm_out.cw_msg = "HB9G JN36BK 1628M U 10V5 = T 11 73"; // = means same voltage as previous // + means higher // - means lower } else { - fsm_out.cw_msg = "hb9g jn36bk 1628m u 10v5 = T 11 #"; + fsm_out.cw_msg = "HB9G JN36BK 1628M U 10V5 = T 11 #"; // The # is the SK digraph } fsm_out.cw_trigger = 1; @@ -291,10 +291,10 @@ void fsm_update() { fsm_out.tx_on = 1; // TODO read voltage if (fsm_in.wind_generator_ok) { - fsm_out.cw_msg = "hb9g u 10v5 73"; + fsm_out.cw_msg = "HB9G U 10V5 73"; } else { - fsm_out.cw_msg = "hb9g u 10v5 #"; // The # is the SK digraph + fsm_out.cw_msg = "HB9G U 10V5 #"; // The # is the SK digraph } fsm_out.cw_trigger = 1; @@ -313,16 +313,16 @@ void fsm_update() { int rand = random_bool() * 2 + random_bool(); if (rand == 0) { - fsm_out.cw_msg = "hb9g"; + fsm_out.cw_msg = "HB9G"; } else if (rand == 1) { - fsm_out.cw_msg = "hb9g jn36bk"; + fsm_out.cw_msg = "HB9G JN36BK"; } else if (rand == 2) { - fsm_out.cw_msg = "hb9g 1628m"; + fsm_out.cw_msg = "HB9G 1628M"; } else { - fsm_out.cw_msg = "hb9g jn36bk 1628m"; + fsm_out.cw_msg = "HB9G JN36BK 1628M"; } } fsm_out.cw_trigger = 1; @@ -340,7 +340,20 @@ void fsm_update() { break; } + if (next_state != current_state) { + timestamp_state[next_state] = timestamp_now(); + } current_state = next_state; - timestamp_state[next_state] = timestamp_now(); } +void fsm_update_inputs(struct fsm_input_signals_t* inputs) +{ + fsm_in = *inputs; +} + +void fsm_get_outputs(struct fsm_output_signals_t* out) +{ + *out = fsm_out; +} + + diff --git a/src/fsm/fsm.h b/src/fsm/fsm.h index db37fd2..62f86a7 100644 --- a/src/fsm/fsm.h +++ b/src/fsm/fsm.h @@ -87,5 +87,14 @@ struct fsm_output_signals_t { // Initialise local structures void fsm_init(); +// Call the FSM once and update the internal state +void fsm_update(); + +// Setter for inputs +void fsm_update_inputs(struct fsm_input_signals_t* inputs); + +// Getter for outputs +void fsm_get_outputs(struct fsm_output_signals_t* out); + #endif // _FSM_H_ diff --git a/src/fsm/main.c b/src/fsm/main.c index ba0e9c0..15fe4cb 100644 --- a/src/fsm/main.c +++ b/src/fsm/main.c @@ -10,17 +10,23 @@ #include "task.h" #include "timers.h" #include "semphr.h" - #include "cw.h" +#include "pio.h" +#include "fsm.h" +#include "common.h" // Private variables volatile uint32_t time_var1, time_var2; +static int tm_trigger = 0; + + // Private function prototypes void init(); // Tasks static void detect_button_press(void *pvParameters); +static void exercise_fsm(void *pvParameters); static void audio_task(void *pvParameters); struct cw_msg_s { @@ -40,8 +46,12 @@ int main(void) { cw_init(16000); + pio_init(); + + common_init(); + InitializeAudio(Audio16000HzSettings); - SetAudioVolume(128); + SetAudioVolume(164); xTaskCreate( detect_button_press, @@ -52,6 +62,14 @@ int main(void) { NULL); xTaskCreate( + exercise_fsm, + "TaskFSM", + 4*configMINIMAL_STACK_SIZE, + (void*) NULL, + tskIDLE_PRIORITY + 2UL, + NULL); + + xTaskCreate( audio_task, "TaskAudio", configMINIMAL_STACK_SIZE, @@ -66,14 +84,9 @@ int main(void) { while(1); } - +// disabled static void detect_button_press(void *pvParameters) { - int message_select = 0; - struct cw_msg_s msg1 = { "HB9G 1628M", 400, 100 }; - struct cw_msg_s msg2 = { "HB9G JN36BK", 500, 100 }; - struct cw_msg_s msg3 = { "HB9G U 12.5 73", 400, 130 }; - GPIO_SetBits(GPIOD, GPIO_Pin_12); while (1) { @@ -83,26 +96,15 @@ static void detect_button_press(void *pvParameters) vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */ } - if (message_select == 0) { - GPIO_ResetBits(GPIOD, GPIO_Pin_12); - GPIO_SetBits(GPIOD, GPIO_Pin_15); - cw_push_message(msg1.msg, msg1.dit_duration, msg1.freq); - message_select++; - } - else if (message_select == 1) { - GPIO_SetBits(GPIOD, GPIO_Pin_12); - cw_push_message(msg2.msg, msg2.dit_duration, msg2.freq); - message_select++; - } - else if (message_select == 2) { - GPIO_ResetBits(GPIOD, GPIO_Pin_15); - cw_push_message(msg3.msg, msg3.dit_duration, msg3.freq); - message_select = 0; - } + tm_trigger = 1; + GPIO_SetBits(GPIOD, GPIO_Pin_12); while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0) { vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */ } + + tm_trigger = 0; + GPIO_ResetBits(GPIOD, GPIO_Pin_12); } taskYIELD(); } @@ -116,13 +118,11 @@ static void audio_callback(void* context, int select_buffer) if (select_buffer == 0) { samples = audio_buffer0; - GPIO_SetBits(GPIOD, GPIO_Pin_13); GPIO_ResetBits(GPIOD, GPIO_Pin_14); select_buffer = 1; } else { samples = audio_buffer1; GPIO_SetBits(GPIOD, GPIO_Pin_14); - GPIO_ResetBits(GPIOD, GPIO_Pin_13); select_buffer = 0; } @@ -141,8 +141,6 @@ static void audio_callback(void* context, int select_buffer) static void audio_task(void *pvParameters) { - int select_buffer = 0; - PlayAudioWithCallback(audio_callback, NULL); while (1) { @@ -150,6 +148,54 @@ static void audio_task(void *pvParameters) } } +static struct fsm_input_signals_t fsm_input; +static void exercise_fsm(void *pvParameters) +{ + int cw_last_trigger = 0; + + fsm_input.humidity = 0; + fsm_input.temp = 15; + fsm_input.swr_high = 0; + fsm_input.sstv_mode = 0; + fsm_input.wind_generator_ok = 1; + while (1) { + pio_set_fsm_signals(&fsm_input); + fsm_input.start_tm = tm_trigger; // user button + if (fsm_input.start_tm) { + GPIO_SetBits(GPIOD, GPIO_Pin_15); + } + else { + GPIO_ResetBits(GPIOD, GPIO_Pin_15); + } + fsm_input.sq = fsm_input.carrier; // TODO clarify + fsm_input.cw_done = !cw_busy(); + + if (fsm_input.cw_done) { + GPIO_ResetBits(GPIOD, GPIO_Pin_13); + } + else { + GPIO_SetBits(GPIOD, GPIO_Pin_13); + } + + fsm_update_inputs(&fsm_input); + fsm_update(); + + struct fsm_output_signals_t fsm_out; + fsm_get_outputs(&fsm_out); + + pio_set_led_red(fsm_out.tx_on); + pio_set_led_yel(fsm_out.modulation); + pio_set_led_grn(fsm_input.carrier); + + // Add message to CW generator only on rising edge of trigger + if (fsm_out.cw_trigger && !cw_last_trigger) { + cw_push_message(fsm_out.cw_msg, 140 /*fsm_out.cw_speed*/, fsm_out.cw_frequency); + } + + cw_last_trigger = fsm_out.cw_trigger; + } +} + void init() { GPIO_InitTypeDef GPIO_InitStructure; diff --git a/src/fsm/pio.c b/src/fsm/pio.c new file mode 100644 index 0000000..4a83e8d --- /dev/null +++ b/src/fsm/pio.c @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Matthias P. Braendli + * + * 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 "pio.h" +#include "common.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +void read_fsm_input_task(void *pvParameters); + +struct fsm_input_signals_t pio_signals; + +void pio_init() +{ + GPIO_InitTypeDef GPIO_InitStructure; + + // Init pio + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); + + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Pin = PIO_OUTPUT_PINS; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Pin = PIO_INPUT_PINS; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + + xTaskCreate( + read_fsm_input_task, + "TaskPIO", + configMINIMAL_STACK_SIZE, + (void*) NULL, + tskIDLE_PRIORITY + 2UL, + NULL); +} + +void pio_set_fsm_signals(struct fsm_input_signals_t* sig) +{ + *sig = pio_signals; +} + +void read_fsm_input_task(void *pvParameters) +{ + while (1) { + pio_signals.qrp = GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_QRP_n) ? 0 : 1; + pio_signals.tone_1750 = GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_1750) ? 1 : 0; + pio_signals.carrier = GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_RX_n) ? 0 : 1; + pio_signals.discrim_u = GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_U_n) ? 0 : 1; + pio_signals.discrim_d = GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_D_n) ? 0 : 1; + + vTaskDelay(100 / portTICK_RATE_MS); + } +} + +void pio_set_led_red(int on) +{ + if (on) { + GPIO_SetBits(GPIOC, GPIO_PIN_LED_red); + } + else { + GPIO_ResetBits(GPIOC, GPIO_PIN_LED_red); + } +} + +void pio_set_led_grn(int on) +{ + if (on) { + GPIO_SetBits(GPIOC, GPIO_PIN_LED_grn); + } + else { + GPIO_ResetBits(GPIOC, GPIO_PIN_LED_grn); + } +} + +void pio_set_led_yel(int on) +{ + if (on) { + GPIO_SetBits(GPIOC, GPIO_PIN_LED_yel); + } + else { + GPIO_ResetBits(GPIOC, GPIO_PIN_LED_yel); + } +} diff --git a/src/fsm/pio.h b/src/fsm/pio.h new file mode 100644 index 0000000..3209f41 --- /dev/null +++ b/src/fsm/pio.h @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Matthias P. Braendli + * + * 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 _PIO_H_ +#define _PIO_H_ + +#include <stddef.h> +#include <stdint.h> +#include "fsm.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_gpio.h" + +/* +Blue in QRP_n PC1 +Violet out LED red PC2 +Grey in 1750 PC4 +White out LED yel PC5 +Black - GND GND +Brown in RX_n PC6 +Red in U_n PC8 +Orange out LED grn PC9 +Green in D_n PC11 +*/ + +#define GPIO_PIN_QRP_n GPIO_Pin_1 +#define GPIO_PIN_LED_red GPIO_Pin_2 +#define GPIO_PIN_1750 GPIO_Pin_4 +#define GPIO_PIN_LED_yel GPIO_Pin_5 +#define GPIO_PIN_RX_n GPIO_Pin_6 +#define GPIO_PIN_U_n GPIO_Pin_8 +#define GPIO_PIN_LED_grn GPIO_Pin_9 +#define GPIO_PIN_D_n GPIO_Pin_11 + + +#define PIO_OUTPUT_PINS GPIO_Pin_2 | GPIO_Pin_5 | GPIO_Pin_9 + +#define PIO_INPUT_PINS GPIO_Pin_1 | GPIO_Pin_4 | \ + GPIO_Pin_6 | GPIO_Pin_8 | \ + GPIO_Pin_11 + +void pio_init(void); + +void pio_set_led_red(int on); +void pio_set_led_yel(int on); +void pio_set_led_grn(int on); + +void pio_set_fsm_signals(struct fsm_input_signals_t* sig); + +#endif // _PIO_H_ + |