From 6d73e728c6c144a46493dc8089292053afc465cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Fri, 28 Oct 2022 12:54:36 +0200 Subject: [PATCH] app: crow count app implemented and working --- application.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/application.c b/application.c index 16eb5ea..6c71337 100644 --- a/application.c +++ b/application.c @@ -32,12 +32,23 @@ #include "usb_cdcacm.h" // USB CDC ACM utilities #include "terminal.h" // handle the terminal interface #include "menu.h" // menu utilities +#include "led_tm1637.h" // first 7-segment display +#include "led_tm1638.h" // second 7-segment display /** watchdog period in ms */ #define WATCHDOG_PERIOD 10000 /** wakeup frequency (i.e. least number of times per second to perform the main loop) */ -#define WAKEUP_FREQ 16 +#define WAKEUP_FREQ 8 + +/** pin to IR-barrier, pulled low on trigger */ +#define BARRIER_PIN PB5 +/** number of times the barrier has been crossed (e.g. by a cap) */ +volatile uint16_t barrier_count = 0; +/** number of crossing for a cap to be valid */ +#define BARRIER_VALID 1U +/** delay between cap (in ms) */ +#define BARRIER_DELAY 500 /** @defgroup main_flags flag set in interrupts to be processed in main task * @{ @@ -265,6 +276,25 @@ static void command_bootloader(void* argument) dfu_bootloader(); // start DFU bootloader } +/** clear counter + * @param[in] argument no argument required + */ +static void command_clear(void* argument) +{ + (void)argument; // we won't use the argument + RTC_BKPXR(0) = 0; + RTC_BKPXR(1) = 0; + RTC_BKPXR(2) = 0; + RTC_BKPXR(3) = 0; + RTC_BKPXR(4) = 0; + RTC_BKPXR(5) = 0; + RTC_BKPXR(6) = 0; + RTC_BKPXR(7) = 0; + RTC_BKPXR(8) = 0; + RTC_BKPXR(9) = 0; + scb_reset_system(); // reset device +} + /** list of all supported commands */ static const struct menu_command_t menu_commands[] = { { @@ -323,6 +353,14 @@ static const struct menu_command_t menu_commands[] = { .argument_description = NULL, .command_handler = &command_bootloader, }, + { + .shortcut = 'c', + .name = "clear", + .command_description = "clear counter", + .argument = MENU_ARGUMENT_NONE, + .argument_description = NULL, + .command_handler = &command_clear, + }, }; static void command_help(void* argument) @@ -447,6 +485,45 @@ void main(void) // important: do not re-enable backup_domain_write_protect, since this will prevent clearing flags (but RTC registers do not need to be unlocked) puts_debug("OK\n"); + puts_debug("setup TM1637 7-segment displays: "); + led_tm1637_setup(false); + led_tm1637_on(); + led_tm1637_number(8888, false); + led_tm1638_setup(false); + led_tm1638_on(); + led_tm1638_number(8888, false); + puts_debug("OK\n"); + + puts_debug("setup IR barrier: "); + rcc_periph_clock_enable(RCC_SYSCFG); // for exti port mapping + rcc_periph_clock_enable(GPIO_RCC(BARRIER_PIN)); // enable clock for port + exti_select_source(GPIO_EXTI(BARRIER_PIN), GPIO_PORT(BARRIER_PIN)); // mask external interrupt of this pin only for this port + gpio_mode_setup(GPIO_PORT(BARRIER_PIN), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(BARRIER_PIN)); // set GPIO to input and pull up + exti_set_trigger(GPIO_EXTI(BARRIER_PIN), EXTI_TRIGGER_FALLING); // trigger when button is pressed + exti_reset_request(GPIO_EXTI(BARRIER_PIN)); // reset interrupt + exti_enable_request(GPIO_EXTI(BARRIER_PIN)); // enable external interrupt + nvic_enable_irq(GPIO_NVIC_EXTI_IRQ(BARRIER_PIN)); // enable interrupt + sleep_ms(100); // wait for IR barrier to stabilize + barrier_count = 0; // reset count + puts_debug("OK\n"); + + // read cap counter + uint8_t counter_first_year = RTC_BKPXR(0); + uint8_t counter_first_month = RTC_BKPXR(1); + uint8_t counter_first_day = RTC_BKPXR(2); + uint16_t counter_total = (RTC_BKPXR(3) << 8) + RTC_BKPXR(4); + uint16_t counter_daily = (RTC_BKPXR(5) << 8) + RTC_BKPXR(6); + uint8_t counter_last_year = RTC_BKPXR(7); + uint8_t counter_last_month = RTC_BKPXR(8); + uint8_t counter_last_day = RTC_BKPXR(9); + printf("first cap: %04u-%02u-%02u\n", 2000 + counter_first_year, counter_first_month, counter_first_day); + printf("total caps: %u\n", counter_total); + printf("daily caps: %u\n", counter_daily); + // display first date + led_tm1637_number(2000 + counter_first_year, false); + led_tm1638_time(counter_first_month ,counter_first_day); + sleep_ms(1000); + // setup terminal terminal_prefix = ""; // set default prefix terminal_process = &process_command; // set central function to process commands @@ -468,15 +545,64 @@ void main(void) action = true; // action has been performed puts("button pressed\n"); led_toggle(); // toggle LED + command_clear(NULL); sleep_ms(100); // wait a bit to remove noise and double trigger button_flag = false; // reset flag } if (wakeup_flag) { // time to do periodic checks wakeup_flag = false; // clear flag + if (barrier_count) { + printf("cross: %u\n", barrier_count); + if (barrier_count >= BARRIER_VALID) { + printf("cap detected\n"); + if (0 == counter_first_year) { // no first cap yet + counter_first_year = ((RTC_DR >> RTC_DR_YT_SHIFT) & RTC_DR_YT_MASK) * 10 + ((RTC_DR >> RTC_DR_YU_SHIFT) & RTC_DR_YU_MASK); // get year + counter_first_month = ((RTC_DR >> RTC_DR_MT_SHIFT) & RTC_DR_MT_MASK) * 10 + ((RTC_DR >> RTC_DR_MU_SHIFT) & RTC_DR_MU_MASK); // get month + counter_first_day = ((RTC_DR >> RTC_DR_DT_SHIFT) & RTC_DR_DT_MASK) * 10 + ((RTC_DR >> RTC_DR_DU_SHIFT) & RTC_DR_DU_MASK); // get day + // save values + RTC_BKPXR(0) = counter_first_year; + RTC_BKPXR(1) = counter_first_month; + RTC_BKPXR(2) = counter_first_day; + } + counter_total++; + counter_daily++; + led_tm1637_number(counter_total, false); // display total cap counter + led_tm1638_number(counter_daily, false); // display daily cap counter + RTC_BKPXR(3) = counter_total >> 8; + RTC_BKPXR(4) = counter_total; + RTC_BKPXR(5) = counter_daily >> 8; + RTC_BKPXR(6) = counter_daily; + counter_last_year = ((RTC_DR >> RTC_DR_YT_SHIFT) & RTC_DR_YT_MASK) * 10 + ((RTC_DR >> RTC_DR_YU_SHIFT) & RTC_DR_YU_MASK); // get year + counter_last_month = ((RTC_DR >> RTC_DR_MT_SHIFT) & RTC_DR_MT_MASK) * 10 + ((RTC_DR >> RTC_DR_MU_SHIFT) & RTC_DR_MU_MASK); // get month + counter_last_day = ((RTC_DR >> RTC_DR_DT_SHIFT) & RTC_DR_DT_MASK) * 10 + ((RTC_DR >> RTC_DR_DU_SHIFT) & RTC_DR_DU_MASK); // get day + // save values + RTC_BKPXR(7) = counter_last_year; + RTC_BKPXR(8) = counter_last_month; + RTC_BKPXR(9) = counter_last_day; + sleep_ms(BARRIER_DELAY); // wait for cap to fall through + second_flag = true; // update display + } + barrier_count = 0; // reset count + } } if (second_flag) { // one second passed second_flag = false; // clear flag + led_tm1637_number(counter_total, false); // display total cap counter + led_tm1638_number(counter_daily, false); // display daily cap counter led_toggle(); // toggle LED to indicate if main function is stuck + const uint8_t hour = ((RTC_TR >> RTC_TR_HT_SHIFT) & RTC_TR_HT_MASK) * 10 + ((RTC_TR >> RTC_TR_HU_SHIFT) & RTC_TR_HU_MASK); // get hours + const uint8_t minute = ((RTC_TR >> RTC_TR_MNT_SHIFT) & RTC_TR_MNT_MASK) * 10 + ((RTC_TR >> RTC_TR_MNU_SHIFT) & RTC_TR_MNU_MASK); // get minutes + // reset daily counter + const uint8_t year = ((RTC_DR >> RTC_DR_YT_SHIFT) & RTC_DR_YT_MASK) * 10 + ((RTC_DR >> RTC_DR_YU_SHIFT) & RTC_DR_YU_MASK); // get year + const uint8_t month = ((RTC_DR >> RTC_DR_MT_SHIFT) & RTC_DR_MT_MASK) * 10 + ((RTC_DR >> RTC_DR_MU_SHIFT) & RTC_DR_MU_MASK); // get month + const uint8_t day = ((RTC_DR >> RTC_DR_DT_SHIFT) & RTC_DR_DT_MASK) * 10 + ((RTC_DR >> RTC_DR_DU_SHIFT) & RTC_DR_DU_MASK); // get day + if (year != counter_last_year || month != counter_last_month || day != counter_last_day) { + if (hour > 8 && minute > 8) { + counter_daily = 0; + RTC_BKPXR(5) = counter_daily >> 8; + RTC_BKPXR(6) = counter_daily; + } + } } if (action) { // go to sleep if nothing had to be done, else recheck for activity action = false; @@ -499,3 +625,10 @@ void rtc_wkup_isr(void) tick = WAKEUP_FREQ; // restart count down } } + +/** interrupt service routine called when barrier is crossed */ +void GPIO_EXTI_ISR(BARRIER_PIN)(void) +{ + exti_reset_request(GPIO_EXTI(BARRIER_PIN)); // reset interrupt + barrier_count++; // remember barrier is crossed +}