diff --git a/main.c b/main.c index feb050a..1de147e 100644 --- a/main.c +++ b/main.c @@ -34,6 +34,7 @@ #include // independent watchdog utilities #include // debug utilities #include // flash utilities +#include // timer utilities /* own libraries */ #include "global.h" // board definitions @@ -50,10 +51,16 @@ * @{ */ volatile bool rtc_tick_flag = false; /**< flag set when RTC ticked */ +volatile bool frame_flag = false; /**< flag set when a frame has passed */ /** @} */ #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 */ +volatile uint8_t rtc_seconds = 0; /** number of seconds passed incremented by the square wave */ + +#define FRAME_TIMER 1 /**< timer to count frame time */ +#define FRAME_RATE 25 /**< frame rate */ +volatile uint8_t frame_count = 0; /**< number of frames passed */ /** user input command */ static char command[32] = {0}; @@ -188,7 +195,7 @@ void main(void) board_setup(); // setup board usart_setup(); // setup USART for user communication cdcacm_setup(); // setup USB ACM (serial) for user communication - printf("welcome to the STM32F1 CuVoodoo example code\n"); // print welcome message + printf("welcome to the STM32F1 CuVoodoo clapperboard\n"); // print welcome message #if !(DEBUG) // show watchdog information @@ -226,7 +233,6 @@ void main(void) // 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 { @@ -242,17 +248,15 @@ void main(void) // setup TM1637 and MAX7219 7-segments displays printf("setup 7-segment displays: "); led_tm1637_setup(); // setup TM1637 - led_max7219_setup(); // setup MAX7219 + led_max7219_setup(2); // setup MAX7219 if (!led_tm1637_time(88,88)) { // test TM1637 display printf("could not send time to TM1637\n"); } if (!led_tm1637_on()) { // switch on TM1637 display printf("could not switch on TM1637\n"); } - led_max7219_intensity(15,8,0); // set brightness max and enable all digits on 1st display - led_max7219_intensity(15,8,1); // set brightness max and enable all digits on 1st display - led_max7219_test(true,0); // test 1st MAX7219 display - led_max7219_test(true,1); // test 2nd MAX7219 display + led_max7219_intensity(15,8,0xff); // set brightness max and enable all digits + led_max7219_test(true,0xff); // test all MAX7219 displays for (uint32_t i=0; i<5000000; i++) { // wait a bit to have the user check the display __asm__("nop"); } @@ -262,17 +266,34 @@ void main(void) if (!led_tm1637_off()) { // switch off display printf("could not switch off TM1637\n"); } - led_max7219_test(false,0); // go back in normal operation - led_max7219_test(false,1); // go back in normal operation - led_max7219_off(0); // switch 1st display off - led_max7219_off(1); // switch 2nd display off + led_max7219_test(false,0xff); // go back in normal operation + led_max7219_off(0xff); // switch displays off printf("OK\n"); - - led_max7219_number(rtc_ds1307_time[2]*1000000+rtc_ds1307_time[1]*10000+rtc_ds1307_time[0]*100, 0x54, 0); // display time on 1nd display + + // display date and time on 7-segments 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 - led_max7219_on(0); // switch 1st display on - led_max7219_on(1); // switch 2nd display on - + led_max7219_number(rtc_ds1307_time[2]*1000000+rtc_ds1307_time[1]*10000+rtc_ds1307_time[0]*100, 0x54, 0); // display time on 1nd display + led_max7219_on(0xff); // switch displays on + + // setup frame timer + printf("setup frame timer: "); + rcc_periph_clock_enable(RCC_TIM(FRAME_TIMER)); // enable clock for timer block + timer_reset(TIM(FRAME_TIMER)); // reset timer state + timer_set_mode(TIM(FRAME_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(TIM(FRAME_TIMER), (rcc_ahb_frequency/0xffff+1)-1); // set the prescaler to so count up to one second + timer_set_period(TIM(FRAME_TIMER), 0xffff/FRAME_RATE); // overflow at the end of every rate + timer_update_on_overflow(TIM(FRAME_TIMER)); // only use counter overflow as UEV source (use overflow as timeout) + timer_clear_flag(TIM(FRAME_TIMER), TIM_SR_UIF); // clear flag + timer_enable_irq(TIM(FRAME_TIMER), TIM_DIER_UIE); // enable update interrupt for timer +#if FRAME_TIMER==1 + nvic_enable_irq(NVIC_TIM1_UP_IRQ); // catch interrupt in service routine +#else + nvic_enable_irq(NVIC_TIM_IRQ(FRAME_TIMER)); // catch interrupt in service routine +#endif + timer_set_counter(TIM(FRAME_TIMER),0); // restart timer + timer_enable_counter(TIM(FRAME_TIMER)); // enable timer to start counting frames + printf("OK\n"); + // main loop printf("command input: ready\n"); bool action = false; // if an action has been performed don't go to sleep @@ -319,11 +340,23 @@ void main(void) } button_flag = false; // reset flag } + while (frame_flag) { // a frame has passed + frame_flag = false; // reset flag + action = true; // action has been performed + uint8_t dots = 0x40; // dot for minutes on display + if (0==(rtc_seconds%2)) { // even seconds + dots |= 0x10; // add dot for seconds + } + if (0==(frame_count%2)) { // even frames + dots |= 0x04; // add dot for frame + } + led_max7219_number(rtc_ds1307_time[2]*1000000+rtc_ds1307_time[1]*10000+rtc_seconds*100+(frame_count%100), dots, 0); // display frame time on 1nd display + } while (rtc_tick_flag) { // the external RTC ticked rtc_tick_flag = false; // reset flag action = true; // action has been performed led_toggle(); // toggle LED (good to indicate if main function is stuck) - rtc_seconds++; // increment number of seconds passed + frame_count = 0; // resync frame counter to second 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) { @@ -348,6 +381,22 @@ void main(void) void EXTI_ISR(SQUARE_WAVE_PIN)(void) { exti_reset_request(EXTI(SQUARE_WAVE_PIN)); // reset interrupt - rtc_tick_flag = true; // perform button action + rtc_seconds++; // increment number of seconds passed + rtc_tick_flag = true; // let main know a second passed +} + +#if FRAME_TIMER==1 +void tim1_up_isr(void) +#else +void TIM_ISR(FRAME_TIMER)(void) +#endif +{ + if (timer_get_flag(TIM(FRAME_TIMER), TIM_SR_UIF)) { // overflow update event happened + timer_clear_flag(TIM(FRAME_TIMER), TIM_SR_UIF); // clear flag + frame_count++; // increment frame counter since frame finished + frame_flag = true; // let main know the counter changed + } else { // no other interrupt should occur + while (true); // unhandled exception: wait for the watchdog to bite + } }