add NEC code controlled power output animations

This commit is contained in:
King Kévin 2018-10-15 22:06:29 +02:00
parent 10c2973ee7
commit 4f7a173e23
1 changed files with 116 additions and 9 deletions

View File

@ -12,8 +12,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** STM32F1 application example
* @file application.c
/** STM32F1 application to strobe electricity
* @file
* @author King Kévin <kingkevin@cuvoodoo.info>
* @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 {