From 4f7a173e23340caab082ace6f3aaf3432a588f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Mon, 15 Oct 2018 22:06:29 +0200 Subject: [PATCH] add NEC code controlled power output animations --- application.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 9 deletions(-) diff --git a/application.c b/application.c index e1db3f6..9b0a2fb 100644 --- a/application.c +++ b/application.c @@ -12,8 +12,8 @@ * along with this program. If not, see . * */ -/** STM32F1 application example - * @file application.c +/** STM32F1 application to strobe electricity + * @file * @author King Kévin * @date 2016-2018 */ @@ -43,8 +43,9 @@ #include "usb_cdcacm.h" // USB CDC ACM utilities #include "terminal.h" // handle the terminal interface #include "menu.h" // menu utilities +#include "ir_nec.h" // InfraRed NEC decoding utilities -#define WATCHDOG_PERIOD 10000 /**< watchdog period in ms */ +#define WATCHDOG_PERIOD 20000 /**< watchdog period in ms */ /** @defgroup main_flags flag set in interrupts to be processed in main task * @{ @@ -235,6 +236,94 @@ static void process_command(char* str) } } +#define STROBE_PORT B /**< GPIO port to control strobe light */ +#define STROBE_PIN 6 /**< GPIO pin to control strobe light */ +#define STROBE_ON 0 /**< LED is on when pin is low (open-drain allows 5V on) */ + +/* strobe animations (on + off times in ms) */ +/** single strobe */ +static const uint16_t strobe_single[] = {100, 0}; +/** double strobe */ +static const uint16_t strobe_double[] = {100, 200, 100, 0}; + +/** switch strobe power on */ +static void strobe_on(void) +{ +#if LED_ON + gpio_set(GPIO(STROBE_PORT), GPIO(STROBE_PIN)); +#else + gpio_clear(GPIO(STROBE_PORT), GPIO(STROBE_PIN)); +#endif +} + +/** switch strobe power off */ +static void strobe_off(void) +{ +#if STROBE_ON + gpio_clear(GPIO(STROBE_PORT), GPIO(STROBE_PIN)); +#else + gpio_set(GPIO(STROBE_PORT), GPIO(STROBE_PIN)); +#endif +} + +/** toggle strobe power */ +static void strobe_toggle(void) +{ + gpio_toggle(GPIO(STROBE_PORT), GPIO(STROBE_PIN)); +} + +/** play strobe animation + * @param[in] animation on+off timings (in ms) + * @param[in] length animation length + */ +static void strobe_play(const uint16_t* animation, uint16_t length) +{ + for (uint16_t i = 0; i < length; i++) { + iwdg_reset(); // kick the dog + if (0 == animation[i]) { // skip animation + continue; + } + if (i % 2) { // odd index if encodes off duration + strobe_off(); + } else { + strobe_on(); + } + sleep_ms(animation[i]); // wait for set duration + } + strobe_off(); // switch off at the end +} + +/** perform IR code related action + * @warning the codes need to be adjusted to your remote + * @param[in] code IR code + */ +static void ir_action(const struct ir_nec_code_t* code) +{ + if (code->repeat) { // don't handle long button press repeating the code + return; + } + if (0 != code->address) { // current remote uses this address + return; + } + switch (code->command) { + case 0x30: // power button + strobe_toggle(); + printf("toggle strobe\n"); + break; + case 0x88: // 1 button + strobe_play(strobe_single, LENGTH(strobe_single)); + printf("strobe animation 1\n"); + break; + case 0x48: // 2 button + strobe_play(strobe_double, LENGTH(strobe_double)); + printf("strobe animation 2\n"); + break; + default: + printf("unknown code\n"); + break; + } +} + /** program entry point * this is the firmware function started by the micro-controller */ @@ -258,8 +347,17 @@ void main(void) board_setup(); // setup board uart_setup(); // setup USART (for printing) - usb_cdcacm_setup(); // setup USB CDC ACM (for printing) - printf("\nwelcome to the CuVoodoo STM32F1 example application\n"); // print welcome message + usb_cdcacm_setup(); // setup USB CDC ACM (for printing and DFU) + // setup strobe pin + rcc_periph_clock_enable(RCC_GPIO(STROBE_PORT)); // enable clock for GPIO port peripheral +#if STROBE_ON + gpio_set_mode(GPIO(STROBE_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(STROBE_PIN)); // set pin to output push-pull do drive strobe signal +#else + gpio_set_mode(GPIO(STROBE_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(STROBE_PIN)); // set pin to output open-drain do enable strobe +#endif + strobe_off(); // switch off strobe per defaulf + ir_nec_setup(); // setup ID NEC code decoder + printf("\nwelcome to the CuVoodoo STM32F1 spark strober\n"); // print welcome message #if !(DEBUG) // show watchdog information @@ -290,13 +388,13 @@ void main(void) button_flag = false; // reset button flag while (true) { // infinite loop iwdg_reset(); // kick the dog - while (user_input_available) { // user input is available + if (user_input_available) { // user input is available action = true; // action has been performed led_toggle(); // toggle LED char c = user_input_get(); // store receive character terminal_send(c); // send received character to terminal } - while (button_flag) { // user pressed button + if (button_flag) { // user pressed button action = true; // action has been performed printf("button pressed\n"); led_toggle(); // toggle LED @@ -305,13 +403,22 @@ void main(void) } button_flag = false; // reset flag } - while (rtc_internal_tick_flag) { // the internal RTC ticked + if (rtc_internal_tick_flag) { // the internal RTC ticked rtc_internal_tick_flag = false; // reset flag action = true; // action has been performed #if !defined(BLUE_PILL) // on the blue pill the LED is close to the 32.768 kHz oscillator and heavily influences it - led_toggle(); // toggle LED (good to indicate if main function is stuck) + //led_toggle(); // toggle LED (good to indicate if main function is stuck) #endif } + if (ir_nec_code_received_flag) { // IR code received + ir_nec_code_received_flag = false; // reset flag + led_on(); // notify user we received a code + printf("IR NEC code received: addr=%+02x, cmd=%+02x%s\n", ir_nec_code_received.address, ir_nec_code_received.command, ir_nec_code_received.repeat ? " (repeat)" : ""); + if (!ir_nec_code_received.repeat) { // ignore repeated codes + ir_action(&ir_nec_code_received); // handle IR code + } + led_off(); // notify user we received a code + } if (action) { // go to sleep if nothing had to be done, else recheck for activity action = false; } else {