aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2015-12-12 10:13:32 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2015-12-12 10:13:32 +0100
commitaebb7e588e73bd4123be7a540bcad8596b4351d6 (patch)
tree50a65853cca8075af8250fc36e073e7e0590925e /src
parent66e49ea68509fd0c7c9cc218068bb288d1d29582 (diff)
downloadglutte-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')
-rw-r--r--src/fsm/common.c74
-rw-r--r--src/fsm/common.h6
-rw-r--r--src/fsm/cw.c12
-rw-r--r--src/fsm/cw.h3
-rw-r--r--src/fsm/fsm.c53
-rw-r--r--src/fsm/fsm.h9
-rw-r--r--src/fsm/main.c102
-rw-r--r--src/fsm/pio.c113
-rw-r--r--src/fsm/pio.h71
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_
+