2016-01-17 14:54:54 +01:00
|
|
|
/* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
2016-03-23 07:50:53 +01:00
|
|
|
/** @file main.c
|
2016-03-24 10:37:42 +01:00
|
|
|
@author King Kévin <kingkevin@cuvoodoo.info>
|
|
|
|
@date 2016
|
|
|
|
@brief show the time on a LED strip
|
|
|
|
|
|
|
|
The LED strip consists of 60 WS2812b LEDs.
|
|
|
|
The time is read from a DS1307 RTC module.
|
2016-03-23 07:50:53 +01:00
|
|
|
*/
|
2016-01-17 14:54:54 +01:00
|
|
|
|
|
|
|
/* standard libraries */
|
|
|
|
#include <stdint.h> // standard integer types
|
|
|
|
#include <stdio.h> // standard I/O facilities
|
|
|
|
#include <stdlib.h> // standard utilities
|
|
|
|
#include <unistd.h> // standard streams
|
|
|
|
#include <errno.h> // error number utilities
|
|
|
|
|
|
|
|
/* STM32 (including CM3) libraries */
|
|
|
|
#include <libopencm3/stm32/rcc.h> // real-time control clock library
|
|
|
|
#include <libopencm3/stm32/gpio.h> // general purpose input output library
|
|
|
|
#include <libopencm3/cm3/scb.h> // vector table definition
|
2016-01-18 16:23:35 +01:00
|
|
|
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
2016-01-29 11:25:30 +01:00
|
|
|
#include <libopencm3/cm3/nvic.h> // interrupt utilities
|
|
|
|
#include <libopencm3/stm32/exti.h> // external interrupt utilities
|
2016-01-17 14:54:54 +01:00
|
|
|
|
|
|
|
/* own libraries */
|
2016-01-28 21:21:50 +01:00
|
|
|
#include "global.h" // board definitions
|
2016-01-17 14:54:54 +01:00
|
|
|
#include "usart.h" // USART utilities
|
2016-01-18 16:23:35 +01:00
|
|
|
#include "usb_cdcacm.h" // USB CDC ACM utilities
|
2016-02-18 11:02:28 +01:00
|
|
|
#include "led_ws2812b.h" // WS2812b LEDs utilities
|
2016-03-23 07:50:53 +01:00
|
|
|
#include "rtc_ds1307.h" // Real Time Clock DS1307 utilities
|
2016-01-17 14:54:54 +01:00
|
|
|
|
2016-03-24 10:37:42 +01:00
|
|
|
/** @defgroup main_flags flag set in interrupts to be processed in main task
|
|
|
|
@{
|
|
|
|
*/
|
|
|
|
volatile bool button_flag = false; /**< flag set if board user button has been pressed */
|
|
|
|
/** @} */
|
2016-02-18 11:34:08 +01:00
|
|
|
|
2016-03-23 07:50:53 +01:00
|
|
|
/** the number of ticks in one second
|
|
|
|
* @note the other values are derived from this value @ref main_ticks
|
|
|
|
*/
|
2016-02-19 11:31:30 +01:00
|
|
|
#define TICKS_PER_SECOND 255
|
2016-03-23 07:50:53 +01:00
|
|
|
/** @defgroup main_ticks ticks per time units
|
|
|
|
* @note I have to use type variables because defines would be stored in signed integers, leading to an overflow it later calculations
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
/** number of ticks in one second */
|
|
|
|
const uint32_t ticks_second = TICKS_PER_SECOND;
|
|
|
|
/** number of ticks in one minute */
|
|
|
|
const uint32_t ticks_minute = 60*TICKS_PER_SECOND;
|
|
|
|
/** number of ticks in one hour */
|
|
|
|
const uint32_t ticks_hour = 60*60*TICKS_PER_SECOND;
|
|
|
|
/** number of ticks in one midday (12 hours) */
|
|
|
|
const uint32_t ticks_midday = 12*60*60*TICKS_PER_SECOND;
|
|
|
|
/** @} */
|
2016-02-19 11:31:30 +01:00
|
|
|
|
2016-03-24 10:37:42 +01:00
|
|
|
/** RGB values for the WS2812b clock LEDs */
|
|
|
|
uint8_t clock_leds[WS2812B_LEDS*3] = {0};
|
2016-02-18 10:39:08 +01:00
|
|
|
|
2016-01-17 14:54:54 +01:00
|
|
|
int _write(int file, char *ptr, int len)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (ptr[i] == '\n') { // add carrier return before line feed. this is recommended for most UART terminals
|
|
|
|
usart_putchar_nonblocking('\r'); // a second line feed doesn't break the display
|
2016-01-18 16:23:35 +01:00
|
|
|
cdcacm_putchar('\r'); // a second line feed doesn't break the display
|
2016-01-17 14:54:54 +01:00
|
|
|
}
|
|
|
|
usart_putchar_nonblocking(ptr[i]); // send byte over USART
|
2016-01-18 16:23:35 +01:00
|
|
|
cdcacm_putchar(ptr[i]); // send byte over USB
|
2016-01-17 14:54:54 +01:00
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
errno = EIO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-01-29 00:24:49 +01:00
|
|
|
void led_on(void)
|
2016-01-17 14:54:54 +01:00
|
|
|
{
|
2016-01-29 00:24:49 +01:00
|
|
|
#ifdef SYSTEM_BOARD
|
|
|
|
gpio_clear(LED_PORT, LED_PIN);
|
|
|
|
#elif MAPLE_MINI
|
|
|
|
gpio_set(LED_PORT, LED_PIN);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void led_off(void)
|
|
|
|
{
|
|
|
|
#ifdef SYSTEM_BOARD
|
|
|
|
gpio_set(LED_PORT, LED_PIN);
|
|
|
|
#elif MAPLE_MINI
|
|
|
|
gpio_clear(LED_PORT, LED_PIN);
|
|
|
|
#endif
|
2016-01-17 14:54:54 +01:00
|
|
|
}
|
|
|
|
|
2016-01-29 00:24:49 +01:00
|
|
|
void led_toggle(void)
|
2016-01-17 14:54:54 +01:00
|
|
|
{
|
2016-01-29 00:24:49 +01:00
|
|
|
gpio_toggle(LED_PORT, LED_PIN);
|
2016-01-17 14:54:54 +01:00
|
|
|
}
|
|
|
|
|
2016-03-25 11:42:41 +01:00
|
|
|
/** @brief switch off all clock LEDs
|
|
|
|
* @note LEDs need to be set separately
|
|
|
|
*/
|
2016-02-19 11:31:30 +01:00
|
|
|
static void clock_clear(void)
|
2016-02-18 11:34:08 +01:00
|
|
|
{
|
|
|
|
// set all colors of all LEDs to 0
|
|
|
|
for (uint16_t i=0; i<LENGTH(clock_leds); i++) {
|
|
|
|
clock_leds[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-25 11:42:41 +01:00
|
|
|
/** @brief set hours mark on clock LEDs
|
|
|
|
* @note LEDs need to be set separately
|
|
|
|
*/
|
2016-02-19 11:31:30 +01:00
|
|
|
static void clock_hours(void)
|
2016-02-18 11:34:08 +01:00
|
|
|
{
|
|
|
|
for (uint8_t hour=0; hour<12; hour++) {
|
2016-02-19 11:31:30 +01:00
|
|
|
uint16_t led = WS2812B_LEDS/12*hour;
|
2016-02-18 11:34:08 +01:00
|
|
|
clock_leds[led*3+0] = 0xff;
|
|
|
|
clock_leds[led*3+1] = 0xff;
|
|
|
|
clock_leds[led*3+2] = 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-25 11:42:41 +01:00
|
|
|
/** @brief show time on LED clock
|
|
|
|
* @param[in] time in ticks to show
|
|
|
|
* @details show hours and minutes progress as full arcs, show second position as marker. the brightness of the LED shows the progress of the unit. hours are blue, minutes green, seconds red
|
|
|
|
* @note LEDs need to be set separately
|
|
|
|
*/
|
2016-02-24 10:33:21 +01:00
|
|
|
static void clock_show_time(uint32_t time)
|
2016-02-19 11:31:30 +01:00
|
|
|
{
|
2016-02-23 21:52:00 +01:00
|
|
|
uint32_t led_hour = (WS2812B_LEDS*(255*(uint64_t)(time%ticks_midday)))/ticks_midday; // scale to LED brightnesses for hours
|
|
|
|
uint32_t led_minute = (WS2812B_LEDS*(255*(uint64_t)(time%ticks_hour)))/ticks_hour; // scale to LED brightnesses for minutes
|
|
|
|
if (led_hour>=WS2812B_LEDS*255 || led_minute>=WS2812B_LEDS*255) { // a calculation error occurred
|
2016-02-23 20:28:55 +01:00
|
|
|
return;
|
2016-02-19 11:31:30 +01:00
|
|
|
}
|
2016-02-23 23:38:08 +01:00
|
|
|
// show hours and minutes on LEDs
|
2016-02-23 22:03:52 +01:00
|
|
|
if (led_hour>led_minute) {
|
|
|
|
// show hours in blue (and clear other LEDs)
|
|
|
|
for (uint16_t led=0; led<WS2812B_LEDS; led++) {
|
|
|
|
clock_leds[led*3+0] = 0;
|
|
|
|
clock_leds[led*3+1] = 0;
|
|
|
|
if (led_hour>=0xff) { // full hours
|
|
|
|
clock_leds[led*3+2] = 0xff;
|
|
|
|
} else { // running hours
|
|
|
|
clock_leds[led*3+2] = led_hour;
|
|
|
|
}
|
|
|
|
led_hour -= clock_leds[led*3+2];
|
|
|
|
}
|
|
|
|
// show minutes in green (override hours)
|
2016-02-23 23:38:08 +01:00
|
|
|
for (uint16_t led=0; led<WS2812B_LEDS && led_minute>0; led++) {
|
2016-02-23 21:52:00 +01:00
|
|
|
clock_leds[led*3+0] = 0;
|
|
|
|
if (led_minute>=0xff) { // full minutes
|
|
|
|
clock_leds[led*3+1] = 0xff;
|
|
|
|
} else { // running minutes
|
|
|
|
clock_leds[led*3+1] = led_minute;
|
|
|
|
}
|
|
|
|
led_minute -= clock_leds[led*3+1];
|
2016-02-23 22:03:52 +01:00
|
|
|
clock_leds[led*3+2] = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// show minutes in green (and clear other LEDs)
|
|
|
|
for (uint16_t led=0; led<WS2812B_LEDS; led++) {
|
2016-02-23 21:52:00 +01:00
|
|
|
clock_leds[led*3+0] = 0;
|
2016-02-23 22:03:52 +01:00
|
|
|
if (led_minute>=0xff) { // full minutes
|
|
|
|
clock_leds[led*3+1] = 0xff;
|
|
|
|
} else { // running minutes
|
|
|
|
clock_leds[led*3+1] = led_minute;
|
2016-02-23 21:52:00 +01:00
|
|
|
}
|
2016-02-23 22:03:52 +01:00
|
|
|
led_minute -= clock_leds[led*3+1];
|
|
|
|
clock_leds[led*3+2] = 0;
|
|
|
|
}
|
|
|
|
// show hours in blue (override minutes)
|
2016-02-23 23:38:08 +01:00
|
|
|
for (uint16_t led=0; led<WS2812B_LEDS && led_hour>0; led++) {
|
2016-02-23 22:03:52 +01:00
|
|
|
clock_leds[led*3+0] = 0;
|
|
|
|
clock_leds[led*3+1] = 0;
|
2016-02-23 21:52:00 +01:00
|
|
|
if (led_hour>=0xff) { // full hours
|
|
|
|
clock_leds[led*3+2] = 0xff;
|
|
|
|
} else { // running hours
|
|
|
|
clock_leds[led*3+2] = led_hour;
|
|
|
|
}
|
|
|
|
led_hour -= clock_leds[led*3+2];
|
2016-02-23 20:28:55 +01:00
|
|
|
}
|
2016-02-23 22:03:52 +01:00
|
|
|
}
|
2016-02-24 10:33:21 +01:00
|
|
|
// don't show seconds on full minute (better for first time setting, barely visible else)
|
|
|
|
if (time%ticks_minute==0) {
|
|
|
|
return;
|
|
|
|
}
|
2016-02-23 23:56:04 +01:00
|
|
|
uint16_t led_second = (WS2812B_LEDS*(time%ticks_minute))/ticks_minute; // get LED for seconds
|
|
|
|
uint8_t brightness_second = (255*(time%ticks_second))/ticks_second; // get brightness for seconds
|
|
|
|
// set second LED
|
|
|
|
clock_leds[led_second*3+0] = brightness_second;
|
|
|
|
clock_leds[led_second*3+1] = 0;
|
|
|
|
clock_leds[led_second*3+2] = 0;
|
|
|
|
// set previous LED
|
|
|
|
clock_leds[((led_second-1)%WS2812B_LEDS)*3+0] = 0xff-brightness_second;
|
|
|
|
clock_leds[((led_second-1)%WS2812B_LEDS)*3+1] = 0;
|
|
|
|
clock_leds[((led_second-1)%WS2812B_LEDS)*3+2] = 0;
|
2016-02-19 11:31:30 +01:00
|
|
|
}
|
|
|
|
|
2016-03-25 11:42:41 +01:00
|
|
|
/** @brief set the LEDs
|
|
|
|
* @details set the LED colors on WS2812b LEDs
|
|
|
|
* @note WS2812b LED color values need to be transmitted separately
|
|
|
|
*/
|
2016-02-18 11:34:08 +01:00
|
|
|
static void leds_set(void)
|
|
|
|
{
|
|
|
|
for (uint16_t i=0; i<LENGTH(clock_leds)/3; i++) {
|
|
|
|
ws2812b_set_rgb(i,clock_leds[i*3+0],clock_leds[i*3+1],clock_leds[i*3+2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-24 10:37:42 +01:00
|
|
|
/** @brief program entry point
|
|
|
|
* this is the firmware function started by the micro-controller
|
|
|
|
*/
|
2016-01-17 14:54:54 +01:00
|
|
|
int main(void)
|
2016-01-17 15:03:10 +01:00
|
|
|
{
|
2016-01-17 14:54:54 +01:00
|
|
|
SCB_VTOR = (uint32_t) 0x08002000; // relocate vector table because of the bootloader
|
|
|
|
|
2016-01-29 00:24:49 +01:00
|
|
|
rcc_clock_setup_in_hse_8mhz_out_72mhz(); // use 8 MHz high speed external clock to generate 72 MHz internal clock
|
2016-01-29 11:25:30 +01:00
|
|
|
usart_setup(); // setup USART (for printing)
|
|
|
|
cdcacm_setup(); // setup USB CDC ACM (for printing)
|
|
|
|
setbuf(stdout, NULL); // set standard out buffer to NULL to immediately print
|
|
|
|
setbuf(stderr, NULL); // set standard error buffer to NULL to immediately print
|
2016-01-29 00:24:49 +01:00
|
|
|
|
|
|
|
// setup LED
|
2016-01-29 11:25:30 +01:00
|
|
|
rcc_periph_clock_enable(LED_RCC); // enable clock for LED
|
2016-01-29 00:24:49 +01:00
|
|
|
gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, LED_PIN); // set LED pin to 'output push-pull'
|
|
|
|
led_off(); // switch off LED to indicate setup started
|
|
|
|
|
2016-01-29 11:25:30 +01:00
|
|
|
// setup button
|
|
|
|
#if defined(BUTTON_RCC) && defined(BUTTON_PORT) && defined(BUTTON_PIN) && defined(BUTTON_EXTI) && defined(BUTTON_IRQ)
|
|
|
|
rcc_periph_clock_enable(BUTTON_RCC); // enable clock for button
|
|
|
|
gpio_set_mode(BUTTON_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, BUTTON_PIN); // set button pin to input
|
|
|
|
rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt
|
|
|
|
exti_select_source(BUTTON_EXTI, BUTTON_PORT); // mask external interrupt of this pin only for this port
|
|
|
|
exti_set_trigger(BUTTON_EXTI, EXTI_TRIGGER_BOTH); // trigger on both edge
|
|
|
|
exti_enable_request(BUTTON_EXTI); // enable external interrupt
|
|
|
|
nvic_enable_irq(BUTTON_IRQ); // enable interrupt
|
|
|
|
#endif
|
2016-01-17 14:54:54 +01:00
|
|
|
|
2016-03-23 07:50:53 +01:00
|
|
|
// setup WS2812b LEDs
|
2016-02-18 11:02:28 +01:00
|
|
|
ws2812b_setup(); // setup WS2812b LEDs
|
2016-02-23 20:28:55 +01:00
|
|
|
clock_hours(); // show hour markers
|
2016-02-24 10:33:21 +01:00
|
|
|
clock_clear(); // clear all LEDs
|
2016-02-23 20:28:55 +01:00
|
|
|
leds_set(); // set the colors of all LEDs
|
|
|
|
ws2812b_transmit(); // transmit set color
|
2016-02-18 11:02:28 +01:00
|
|
|
|
2016-03-23 07:50:53 +01:00
|
|
|
// setup RTC module
|
|
|
|
rtc_setup(); // setup RTC module
|
|
|
|
|
2016-02-18 11:02:28 +01:00
|
|
|
printf("welcome to the CuVoodoo LED clock\n"); // print welcome message
|
2016-01-29 00:24:49 +01:00
|
|
|
led_on(); // switch on LED to indicate setup completed
|
2016-01-18 16:23:35 +01:00
|
|
|
|
2016-03-25 13:17:48 +01:00
|
|
|
|
|
|
|
uint16_t* rtc_time = rtc_read_time(); // get current date
|
|
|
|
printf("current date: %04d-%02d-%02d %02d:%02d:%02d\n", rtc_time[6], rtc_time[5], rtc_time[4], rtc_time[2], rtc_time[1], rtc_time[0]);
|
|
|
|
uint32_t display_time = 0; // the time to display
|
|
|
|
uint32_t current_time = rtc_time[2]*ticks_hour+rtc_time[1]*ticks_minute+rtc_time[0]*ticks_second; // the current time
|
2016-02-24 10:33:21 +01:00
|
|
|
printf("setting current time\n");
|
2016-03-25 13:17:48 +01:00
|
|
|
while (display_time<current_time) {
|
|
|
|
if (display_time+ticks_hour<=current_time) { // first set hours
|
|
|
|
display_time += ticks_hour; // increment hours
|
|
|
|
} else if (display_time+ticks_minute<=current_time) { // second set minutes
|
|
|
|
display_time += ticks_minute; // increment minutes
|
|
|
|
} else if (display_time+ticks_minute<=current_time) { // third set seconds
|
|
|
|
display_time += ticks_second; // increment seconds
|
2016-02-24 10:33:21 +01:00
|
|
|
} else { // finally set time
|
2016-03-25 13:17:48 +01:00
|
|
|
display_time = current_time;
|
2016-02-24 10:33:21 +01:00
|
|
|
}
|
2016-03-25 13:17:48 +01:00
|
|
|
clock_show_time(display_time); // set time (progress)
|
2016-02-23 23:56:04 +01:00
|
|
|
leds_set(); // set the colors of all LEDs
|
|
|
|
ws2812b_transmit(); // transmit set color
|
2016-02-24 10:33:21 +01:00
|
|
|
// delay some time
|
|
|
|
for (uint32_t i=0; i<400000; i++) {
|
|
|
|
__asm__("nop");
|
|
|
|
}
|
2016-02-23 23:56:04 +01:00
|
|
|
}
|
2016-03-25 13:17:48 +01:00
|
|
|
printf("it is now %02lu:%02lu:%02lu\n", display_time/ticks_hour, (display_time%ticks_hour)/ticks_minute, (display_time%ticks_minute)/ticks_second);
|
2016-03-23 09:17:43 +01:00
|
|
|
// test RTC
|
|
|
|
printf("RTC oscillator: ");
|
|
|
|
if (rtc_oscillator_disabled()) {
|
|
|
|
printf("disbaled\n");
|
|
|
|
} else {
|
|
|
|
printf("enabled\n");
|
|
|
|
}
|
2016-03-23 09:52:53 +01:00
|
|
|
//rtc_write_time(0,52,9,4,23,3,2016);
|
|
|
|
//rtc_oscillator_enable();
|
2016-02-23 23:56:04 +01:00
|
|
|
|
2016-02-24 10:33:21 +01:00
|
|
|
printf("input commands\n");
|
2016-02-18 10:39:08 +01:00
|
|
|
bool action = false; // if an action has been performed don't go to sleep
|
|
|
|
button_flag = false; // reset button flag
|
2016-02-18 11:02:28 +01:00
|
|
|
char c; // to store received character
|
|
|
|
bool char_flag = false; // a new character has been received
|
2016-01-29 00:24:49 +01:00
|
|
|
/* toggle the LED with every transmitted character */
|
|
|
|
while (true) { // infinite loop
|
2016-01-17 15:03:10 +01:00
|
|
|
while (usart_received) { // echo every received character
|
2016-02-18 10:39:08 +01:00
|
|
|
action = true; // action has been performed
|
2016-01-29 00:24:49 +01:00
|
|
|
led_toggle(); // toggle LED
|
2016-02-18 11:02:28 +01:00
|
|
|
c = usart_getchar(); // store receive character
|
|
|
|
char_flag = true; // notify character has been received
|
2016-01-17 15:03:10 +01:00
|
|
|
}
|
2016-01-18 16:23:35 +01:00
|
|
|
while (cdcacm_received) { // echo every received character
|
2016-02-18 10:39:08 +01:00
|
|
|
action = true; // action has been performed
|
2016-01-29 00:24:49 +01:00
|
|
|
led_toggle(); // toggle LED
|
2016-02-18 11:02:28 +01:00
|
|
|
c = usart_getchar(); // store receive character
|
|
|
|
char_flag = true; // notify character has been received
|
|
|
|
}
|
|
|
|
while (char_flag) {
|
|
|
|
char_flag = false; // reset flag
|
|
|
|
action = true; // action has been performed
|
|
|
|
printf("%c",c); // echo receive character
|
2016-02-23 20:28:55 +01:00
|
|
|
|
2016-03-25 13:17:48 +01:00
|
|
|
printf("%02lu:%02lu\n", display_time/ticks_hour, (display_time%ticks_hour)/ticks_minute);
|
|
|
|
clock_show_time(display_time); // set time
|
|
|
|
display_time += ticks_minute; // increment time
|
2016-02-18 11:34:08 +01:00
|
|
|
leds_set(); // set the colors of all LEDs
|
2016-02-18 11:02:28 +01:00
|
|
|
ws2812b_transmit(); // transmit set color
|
2016-01-18 16:23:35 +01:00
|
|
|
}
|
2016-02-18 10:39:08 +01:00
|
|
|
while (button_flag) {
|
|
|
|
button_flag = false; // reset flag
|
|
|
|
action = true; // action has been performed
|
|
|
|
led_toggle(); // toggle LED
|
|
|
|
}
|
|
|
|
// go to sleep if nothing had to be done, else recheck for activity
|
2016-02-18 11:02:28 +01:00
|
|
|
if (action) {
|
2016-02-18 10:39:08 +01:00
|
|
|
action = false;
|
|
|
|
} else {
|
|
|
|
__WFI(); // go to sleep
|
|
|
|
}
|
2016-01-17 14:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-01-29 11:25:30 +01:00
|
|
|
|
|
|
|
#if defined(BUTTON_ISR) && defined(BUTTON_EXTI)
|
|
|
|
void BUTTON_ISR(void)
|
|
|
|
{
|
|
|
|
exti_reset_request(BUTTON_EXTI); // reset interrupt
|
2016-02-18 10:39:08 +01:00
|
|
|
button_flag = true; // perform button action
|
2016-01-29 11:25:30 +01:00
|
|
|
}
|
|
|
|
#endif
|