app: crow count app implemented and working

This commit is contained in:
King Kévin 2022-10-28 12:54:36 +02:00
parent 5ac10a1733
commit 6d73e728c6
1 changed files with 134 additions and 1 deletions

View File

@ -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
}