diff --git a/main.c b/main.c index 3e71856..feb050a 100644 --- a/main.c +++ b/main.c @@ -49,9 +49,12 @@ /** @defgroup main_flags flag set in interrupts to be processed in main task * @{ */ -volatile bool rtc_internal_tick_flag = false; /**< flag set when internal RTC ticked */ +volatile bool rtc_tick_flag = false; /**< flag set when RTC ticked */ /** @} */ +#define SQUARE_WAVE_PORT B /**< port connected to RTC DS1307 square wave output */ +#define SQUARE_WAVE_PIN 0 /**< pin connected to RTC DS1307 square wave output */ + /** user input command */ static char command[32] = {0}; /** user input command index */ @@ -199,32 +202,42 @@ void main(void) } #endif - // setup internal RTC - printf("setup internal RTC: "); - rtc_auto_awake(RCC_LSE, 32768-1); // ensure internal RTC is on, uses the 32.678 kHz LSE, and the prescale is set to our tick speed, else update backup registers accordingly (power off the micro-controller for the change to take effect) - rtc_interrupt_enable(RTC_SEC); // enable RTC interrupt on "seconds" - nvic_enable_irq(NVIC_RTC_IRQ); // allow the RTC to interrupt + // disable internal RTC + printf("disable internal RTC: "); + rcc_periph_clock_enable(RCC_PWR); // enable power domain clock + rcc_periph_clock_enable(RCC_BKP); // enable backup domain clock + pwr_disable_backup_domain_write_protect(); // enable write on backup domain (including RTC) + RCC_BDCR &= ~RCC_BDCR_RTCEN; // disable RTC printf("OK\n"); - // display uptime - uint32_t ticks_time = rtc_get_counter_val(); // get time from internal RTC (since first start/power up) - printf("uptime: %u.%02u:%02u:%02u\n", ticks_time/(60*60*24), (ticks_time/(60*60))%24, (ticks_time%(60*60))/60, (ticks_time%60)); // display uptime // setup external RTC printf("setup external RTC: "); rtc_ds1307_setup(); // setup external RTC module + // enable square wave output and configure input interrupt + rtc_ds1307_write_square_wave(1); // enable 1 Hz square wave output to sync on seconds + rcc_periph_clock_enable(RCC_GPIO(SQUARE_WAVE_PORT)); // enable clock for GPIO + gpio_set_mode(GPIO(SQUARE_WAVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(SQUARE_WAVE_PIN)); // set button pin to input + rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt + exti_select_source(EXTI(SQUARE_WAVE_PIN), GPIO(SQUARE_WAVE_PORT)); // mask external interrupt of this pin only for this port + exti_set_trigger(EXTI(SQUARE_WAVE_PIN), EXTI_TRIGGER_FALLING); // trigger on falling edge of square wave (this is also when the RTC register are updated) + exti_enable_request(EXTI(SQUARE_WAVE_PIN)); // enable external interrupt + nvic_enable_irq(NVIC_EXTI_IRQ(SQUARE_WAVE_PIN)); // enable interrupt printf("OK\n"); + + // display date + uint8_t* rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC + uint8_t rtc_seconds = 0; // count the number of seconds passed and sync time on minute + if (rtc_ds1307_time==NULL) { + printf("could not get time from DS1307\n"); + } else { + rtc_seconds = rtc_ds1307_time[0]; // remember seconds of minute + printf("current date: 20%02u-%02u-%02u %02u:%02u:%02u\n", rtc_ds1307_time[6], rtc_ds1307_time[5], rtc_ds1307_time[4], rtc_ds1307_time[2], rtc_ds1307_time[1], rtc_ds1307_time[0]); + } // verify is external RTC is running if (rtc_ds1307_oscillator_disabled()) { printf("/!\\ RTC oscillator is disabled: the battery may be empty\n"); rtc_ds1307_oscillator_enable(); // enable oscillator again } - // display date - uint8_t* rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC - if (rtc_ds1307_time==NULL) { - printf("could not get time from DS1307\n"); - } else { - printf("current date: 20%02u-%02u-%02u %02u:%02u:%02u\n", rtc_ds1307_time[6], rtc_ds1307_time[5], rtc_ds1307_time[4], rtc_ds1307_time[2], rtc_ds1307_time[1], rtc_ds1307_time[0]); - } // setup TM1637 and MAX7219 7-segments displays printf("setup 7-segment displays: "); @@ -306,26 +319,23 @@ void main(void) } button_flag = false; // reset flag } - while (rtc_internal_tick_flag) { // the internal RTC ticked - rtc_internal_tick_flag = false; // reset flag - led_toggle(); // toggle LED (good to indicate if main function is stuck) - ticks_time = rtc_get_counter_val(); // copy time from internal RTC for processing + while (rtc_tick_flag) { // the external RTC ticked + rtc_tick_flag = false; // reset flag action = true; // action has been performed - if ((ticks_time%(60))==0) { // one minute passed - printf("uptime: %u.%02u:%02u:%02u\n", ticks_time/(60*60*24), (ticks_time/(60*60))%24, (ticks_time%(60*60))/60, (ticks_time%60)); // display uptime - } - rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC - if (rtc_ds1307_time==NULL) { - printf("could not get time from DS1307: resetting\n"); - rtc_ds1307_setup(); // resetting periph - } else { - if (!led_tm1637_time(rtc_ds1307_time[1], rtc_ds1307_time[0])) { - printf("could not set time on TM1637\n"); + led_toggle(); // toggle LED (good to indicate if main function is stuck) + rtc_seconds++; // increment number of seconds passed + if (rtc_seconds>=60) { // one minute passed + rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC + if (rtc_ds1307_time==NULL) { + printf("could not get time from DS1307: resetting\n"); + rtc_ds1307_setup(); // resetting periph + } else { + rtc_seconds = rtc_ds1307_time[0]; // get actual number of seconds + if (0==rtc_ds1307_time[1] && 0==rtc_ds1307_time[2]) { // new day arrived + led_max7219_number(20000000+rtc_ds1307_time[6]*10000+rtc_ds1307_time[5]*100+rtc_ds1307_time[4], 0x14, 1); // display date on 2nd display + } } } - if (!led_tm1637_on()) { // switch on display - printf("could not switch on TM1637\n"); - } } if (action) { // go to sleep if nothing had to be done, else recheck for activity action = false; @@ -335,9 +345,9 @@ void main(void) } // main loop } -/** @brief interrupt service routine called when tick passed on RTC */ -void rtc_isr(void) +void EXTI_ISR(SQUARE_WAVE_PIN)(void) { - rtc_clear_flag(RTC_SEC); // clear flag - rtc_internal_tick_flag = true; // notify to show new time + exti_reset_request(EXTI(SQUARE_WAVE_PIN)); // reset interrupt + rtc_tick_flag = true; // perform button action } +