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 "usb_cdcacm.h" // USB CDC ACM utilities
|
||||||
#include "terminal.h" // handle the terminal interface
|
#include "terminal.h" // handle the terminal interface
|
||||||
#include "menu.h" // menu utilities
|
#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 */
|
/** watchdog period in ms */
|
||||||
#define WATCHDOG_PERIOD 10000
|
#define WATCHDOG_PERIOD 10000
|
||||||
|
|
||||||
/** wakeup frequency (i.e. least number of times per second to perform the main loop) */
|
/** 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
|
/** @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
|
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 */
|
/** list of all supported commands */
|
||||||
static const struct menu_command_t menu_commands[] = {
|
static const struct menu_command_t menu_commands[] = {
|
||||||
{
|
{
|
||||||
|
@ -323,6 +353,14 @@ static const struct menu_command_t menu_commands[] = {
|
||||||
.argument_description = NULL,
|
.argument_description = NULL,
|
||||||
.command_handler = &command_bootloader,
|
.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)
|
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)
|
// 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("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
|
// setup terminal
|
||||||
terminal_prefix = ""; // set default prefix
|
terminal_prefix = ""; // set default prefix
|
||||||
terminal_process = &process_command; // set central function to process commands
|
terminal_process = &process_command; // set central function to process commands
|
||||||
|
@ -468,15 +545,64 @@ void main(void)
|
||||||
action = true; // action has been performed
|
action = true; // action has been performed
|
||||||
puts("button pressed\n");
|
puts("button pressed\n");
|
||||||
led_toggle(); // toggle LED
|
led_toggle(); // toggle LED
|
||||||
|
command_clear(NULL);
|
||||||
sleep_ms(100); // wait a bit to remove noise and double trigger
|
sleep_ms(100); // wait a bit to remove noise and double trigger
|
||||||
button_flag = false; // reset flag
|
button_flag = false; // reset flag
|
||||||
}
|
}
|
||||||
if (wakeup_flag) { // time to do periodic checks
|
if (wakeup_flag) { // time to do periodic checks
|
||||||
wakeup_flag = false; // clear flag
|
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
|
if (second_flag) { // one second passed
|
||||||
second_flag = false; // clear flag
|
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
|
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
|
if (action) { // go to sleep if nothing had to be done, else recheck for activity
|
||||||
action = false;
|
action = false;
|
||||||
|
@ -499,3 +625,10 @@ void rtc_wkup_isr(void)
|
||||||
tick = WAKEUP_FREQ; // restart count down
|
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