app: crow count app implemented and working
This commit is contained in:
parent
5ac10a1733
commit
6d73e728c6
135
application.c
135
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue