From 111c0a545515ee8acebfc48c0fce6ba8104ab252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Sun, 27 Mar 2016 23:35:39 +0200 Subject: [PATCH] use timer to count ticks based on square wave output --- lib/rtc_ds1307.h | 6 ++-- main.c | 71 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/lib/rtc_ds1307.h b/lib/rtc_ds1307.h index 1bca56d..773fc64 100644 --- a/lib/rtc_ds1307.h +++ b/lib/rtc_ds1307.h @@ -28,9 +28,9 @@ #define SQUARE_WAVE_PORT GPIOB /**< GPIO port (port B) */ #define SQUARE_WAVE_PIN GPIO10 /**< GPIO pin (pin PA10) */ #define SQUARE_WAVE_EXTI EXTI10 /**< GPIO external interrupt (exti 10 for pin 12) */ -#define SQUARE_WAVE_IRQ NVIC_EXTI15_10_IRQ /**< GPIO line interrupt (interrupt for line 15 to 10 for pin 10) */ -#define SQUARE_WAVE_ISR exti15_10_isr /**< GPIO line interrupt service routine (isr for line 15 to 10 for pin 10) */ -#define SQUARE_WAVE_HANDLING false /**< to to have the library handle the square wave interrupt (setting square_wave_flag) */ +//#define SQUARE_WAVE_IRQ NVIC_EXTI15_10_IRQ /**< GPIO line interrupt (interrupt for line 15 to 10 for pin 10) */ +//#define SQUARE_WAVE_ISR exti15_10_isr /**< GPIO line interrupt service routine (isr for line 15 to 10 for pin 10) */ +//#define SQUARE_WAVE_HANDLING true /**< to to have the library handle the square wave interrupt (setting square_wave_flag) */ /** @} */ #if defined(SQUARE_WAVE_EXTI) && defined(SQUARE_WAVE_IRQ) && defined(SQUARE_WAVE_ISR) && defined(SQUARE_WAVE_HANDLING) && SQUARE_WAVE_HANDLING diff --git a/main.c b/main.c index 8d66f50..9398c91 100644 --- a/main.c +++ b/main.c @@ -13,12 +13,12 @@ * */ /** @file main.c -@author King Kévin -@date 2016 -@brief show the time on a LED strip - -The LED strip consists of 60 WS2812b LEDs. -The time is read from a DS1307 RTC module. + * @author King Kévin + * @date 2016 + * @brief show the time on a LED strip + * + * The LED strip consists of 60 WS2812b LEDs. + * The time is read from a DS1307 RTC module. */ /* standard libraries */ @@ -36,6 +36,7 @@ The time is read from a DS1307 RTC module. #include // Cortex M3 utilities #include // interrupt utilities #include // external interrupt utilities +#include // timer utilities /* own libraries */ #include "global.h" // board definitions @@ -52,7 +53,6 @@ volatile bool time_flag = false; /**< flag set when time changed */ /** @} */ #define TICKS_PER_SECOND 256 /**< the number of ticks in one second */ -#define SQUARE_WAVE_FREQUENCY 4096 /**< square wave output frequency from the RTC IC */ /** @defgroup main_ticks ticks per time units * @note these are derived from TICKS_PER_SECOND * @note I have to use type variables because defines would be stored in signed integers, leading to an overflow it later calculations @@ -68,6 +68,22 @@ const uint32_t ticks_hour = 60*60*TICKS_PER_SECOND; const uint32_t ticks_midday = 12*60*60*TICKS_PER_SECOND; /** @} */ +/** @defgroup square_wave_timer timer peripheral used to count timer based on RTC IC square wave output + * @{ + */ +#define SQUARE_WAVE_FREQUENCY 4096 /**< square wave output frequency from the RTC IC */ +#define SQUARE_WAVE_TIMER TIM2 /**< timer peripheral */ +#define SQUARE_WAVE_TIMER_RCC RCC_TIM2 /**< timer peripheral clock */ +#define SQUARE_WAVE_TIMER_IC TIM_IC1 /**< input capture channel (for TIM2_CH1) */ +#define SQUARE_WAVE_TIMER_IN TIM_IC_IN_TI1 /**< input capture input source (TIM2_CH1 becomes TI1, then TI1F, then TI1FP1) */ +#define SQUARE_WAVE_TIMER_TS TIM_SMCR_TS_IT1FP1 /**< input capture trigger (actually TI1FP1) */ +#define SQUARE_WAVE_TIMER_IRQ NVIC_TIM2_IRQ /**< timer interrupt */ +#define SQUARE_WAVE_TIMER_ISR tim2_isr /**< timer interrupt service routine */ +#define SQUARE_WAVE_GPIO_RCC RCC_GPIOA /**< timer port peripheral clock (TIM2_CH1 on PA0)*/ +#define SQUARE_WAVE_GPIO_PORT GPIOA /**< timer port (TIM2_CH1 on PA0) */ +#define SQUARE_WAVE_GPIO_PIN GPIO_TIM2_CH1_ETR /**< timer pin input, connect to RTC IC square wave output (TIM2_CH1 on PA0) */ +/** @} */ + /** RGB values for the WS2812b clock LEDs */ uint8_t clock_leds[WS2812B_LEDS*3] = {0}; /** current time in tick */ @@ -209,12 +225,12 @@ static void clock_show_time(uint32_t time) } uint16_t led_second = (WS2812B_LEDS*(time%ticks_minute))/ticks_minute; // get LED for seconds uint8_t brightness_second = (255*(time%ticks_second))/ticks_second; // get brightness for seconds - // set second LED + // set seconds LED clock_leds[led_second*3+0] = brightness_second; //clock_leds[led_second*3+1] = 0; // clear other colors (minutes/hours indication) //clock_leds[led_second*3+2] = 0; // clear other colors (minutes/hours indication) - // set previous LED - led_second = (led_second==0) ? WS2812B_LEDS-1 : led_second-1; // previous LED + // set previous seconds LED + led_second = ((led_second==0) ? WS2812B_LEDS-1 : led_second-1); // previous LED clock_leds[led_second*3+0] = 0xff-brightness_second; //clock_leds[led_second*3+1] = 0; // clear other colors (minutes/hours indication) //clock_leds[led_second*3+2] = 0; // clear other colors (minutes/hours indication) @@ -373,6 +389,25 @@ int main(void) rtc_setup(); // setup RTC module rtc_write_square_wave(SQUARE_WAVE_FREQUENCY); // set square wave output frequency + // setup timer to generate tick from square wave output */ + rcc_periph_clock_enable(SQUARE_WAVE_GPIO_RCC); // enable clock for GPIO peripheral + gpio_set_mode(SQUARE_WAVE_GPIO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SQUARE_WAVE_GPIO_PIN); // set pin as input + gpio_set(SQUARE_WAVE_GPIO_PORT, SQUARE_WAVE_GPIO_PIN); // enable pull-up + rcc_periph_clock_enable(SQUARE_WAVE_TIMER_RCC); // enable clock for timer peripheral + timer_reset(SQUARE_WAVE_TIMER); // reset timer state + timer_ic_set_input(SQUARE_WAVE_TIMER, SQUARE_WAVE_TIMER_IC, SQUARE_WAVE_TIMER_IN); // configure channel as input capture + timer_ic_set_filter(SQUARE_WAVE_TIMER, SQUARE_WAVE_TIMER_IC, TIM_IC_OFF); // use no input capture filter + timer_ic_set_polarity(SQUARE_WAVE_TIMER, SQUARE_WAVE_TIMER_IC, TIM_IC_FALLING); //capture on falling edge + timer_slave_set_trigger(SQUARE_WAVE_TIMER, SQUARE_WAVE_TIMER_TS); // select trigger + timer_slave_set_mode(SQUARE_WAVE_TIMER, TIM_SMCR_SMS_ECM1); // select external clock more 1 as input + timer_ic_enable(SQUARE_WAVE_TIMER, SQUARE_WAVE_TIMER_IC); // enable input capture + timer_set_mode(SQUARE_WAVE_TIMER, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up + timer_set_prescaler(SQUARE_WAVE_TIMER, 0); // no need to prescale + timer_set_period(SQUARE_WAVE_TIMER, SQUARE_WAVE_FREQUENCY/TICKS_PER_SECOND-1); // set the tick period + timer_enable_irq(SQUARE_WAVE_TIMER, TIM_DIER_UIE); // enable interrupt for timer + nvic_enable_irq(SQUARE_WAVE_TIMER_IRQ); // allow interrupt for timer + timer_enable_counter(SQUARE_WAVE_TIMER); // enable timer to count ticks + printf("welcome to the CuVoodoo LED clock\n"); // print welcome message led_on(); // switch on LED to indicate setup completed @@ -383,8 +418,8 @@ int main(void) // get date and time uint16_t* rtc_time = rtc_read_time(); // get RTC time/date - printf("current date: %04d-%02d-%02d %02d:%02d:%02d\n", rtc_time[6], rtc_time[5], rtc_time[4], rtc_time[2], rtc_time[1], rtc_time[0]); current_time = rtc_time[2]*ticks_hour+rtc_time[1]*ticks_minute+rtc_time[0]*ticks_second; // the current time + printf("current date: %04d-%02d-%02d %02d:%02d:%02d\n", rtc_time[6], rtc_time[5], rtc_time[4], rtc_time[2], rtc_time[1], rtc_time[0]); clock_animate_time(current_time); // set time with animation printf("input commands\n"); @@ -430,7 +465,6 @@ int main(void) while (time_flag) { // time passed time_flag = false; // reset flag action = true; // action has been performed - led_toggle(); if ((current_time%ticks_minute)==0) { // sync each minute rtc_time = rtc_read_time(); // get RTC time/date current_time = rtc_time[2]*ticks_hour+rtc_time[1]*ticks_minute+rtc_time[0]*ticks_second; // calculate current time @@ -459,18 +493,13 @@ void BUTTON_ISR(void) } #endif -#if defined(SQUARE_WAVE_EXTI) && defined(SQUARE_WAVE_IRQ) && defined(SQUARE_WAVE_ISR) && defined(SQUARE_WAVE_HANDLING) && !SQUARE_WAVE_HANDLING -/** @brief square wave input interrupt */ -void SQUARE_WAVE_ISR(void) +#if defined(SQUARE_WAVE_TIMER_IRQ) && defined(SQUARE_WAVE_TIMER_ISR) +void SQUARE_WAVE_TIMER_ISR(void) { - static uint16_t square_wave_prescale = 0; /**< prescale the square wave output to generate a tick */ - -exti_reset_request(SQUARE_WAVE_EXTI); // reset interrupt - square_wave_prescale = (square_wave_prescale+1)%(SQUARE_WAVE_FREQUENCY/TICKS_PER_SECOND); // increment pre-scale counter - if (square_wave_prescale==0) { // pre-scale completed + if (timer_get_flag(SQUARE_WAVE_TIMER, TIM_SR_UIF)) { // overflow even happened + timer_clear_flag(SQUARE_WAVE_TIMER, TIM_SR_UIF); // clear flag current_time++; // increment time time_flag = true; // update flag } } #endif -