From 6b80135f67b31e737403f6dadc6ace712138a426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Tue, 2 May 2017 17:20:00 +0200 Subject: [PATCH] control 7 TM1637 displays using multiplexer --- main.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/main.c b/main.c index 85babe6..5f7a1ff 100644 --- a/main.c +++ b/main.c @@ -65,6 +65,15 @@ volatile uint16_t standby_timer = 0; /**< number of seconds since last wake-up/a #define FRAME_RATE 25 /**< frame rate */ volatile uint8_t frame_count = 0; /**< number of frames passed */ +#define MUX_EN_PORT B +#define MUX_EN_PIN 9 +#define MUX_S0_PORT B +#define MUX_S0_PIN 3 +#define MUX_S1_PORT B +#define MUX_S1_PIN 4 +#define MUX_S2_PORT B +#define MUX_S2_PIN 5 + /** user input command */ static char command[32] = {0}; /** user input command index */ @@ -174,6 +183,58 @@ error: return; } +static void mux_select(uint8_t output) +{ + if (output>7) { // multiplexer is only controlling 8 outputs + return; + } + gpio_clear(GPIO(MUX_EN_PORT), GPIO(MUX_EN_PIN)); // enable multiplexer + switch (output) { + case 0: // output on channel C0 + gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 1: // output on channel C1 + gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 2: // output on channel C2 + gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 3: // output on channel C3 + gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 4: // output on channel C4 + gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 5: // output on channel C5 + gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 6: // output on channel C6 + gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + case 7: // output on channel C7 + gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN)); + gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN)); + gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN)); + break; + default: + break; + } +} + /** program entry point * this is the firmware function started by the micro-controller */ @@ -198,6 +259,7 @@ void main(void) board_setup(); // setup board usart_setup(); // setup USART for user communication cdcacm_setup(); // setup USB ACM (serial) for user communication + gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,0); // disable JTAG (but leave SWD on) since we need most of the GPIOs printf("welcome to the STM32F1 CuVoodoo clapperboard\n"); // print welcome message #if !(DEBUG) @@ -256,26 +318,45 @@ void main(void) rtc_ds1307_oscillator_enable(); // enable oscillator again } + // setup analog multiplexer for TM1637 clock + printf("setup multiplexer: "); + rcc_periph_clock_enable(RCC_GPIO(MUX_EN_PORT)); + gpio_set_mode(GPIO(MUX_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_EN_PIN)); + gpio_set(GPIO(MUX_EN_PORT), GPIO(MUX_EN_PIN)); // disable multiplexer + rcc_periph_clock_enable(RCC_GPIO(MUX_S0_PORT)); + gpio_set_mode(GPIO(MUX_S0_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S0_PIN)); + rcc_periph_clock_enable(RCC_GPIO(MUX_S1_PORT)); + gpio_set_mode(GPIO(MUX_S1_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S1_PIN)); + rcc_periph_clock_enable(RCC_GPIO(MUX_S2_PORT)); + gpio_set_mode(GPIO(MUX_S2_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S2_PIN)); + printf("OK\n"); + // setup TM1637 and MAX7219 7-segments displays printf("setup 7-segment displays: "); led_tm1637_setup(); // setup TM1637 + for (uint8_t tm1637=0; tm1637<7; tm1637++) { + mux_select(tm1637); + if (!led_tm1637_time(88,88)) { // test TM1637 display + printf("could not send time to TM1637 %u\n", tm1637); + } + if (!led_tm1637_on()) { // switch on TM1637 display + printf("could not switch on TM1637 %u\n", tm1637); + } + } 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,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"); } - if (!led_tm1637_text(" ")) { // clear display - printf("could not clear\n"); - } - if (!led_tm1637_off()) { // switch off display - printf("could not switch off TM1637\n"); + for (uint8_t tm1637=0; tm1637<7; tm1637++) { + mux_select(tm1637); + if (!led_tm1637_text(" ")) { // clear display + printf("could not clear on TM1637 %u\n", tm1637); + } + if (!led_tm1637_off()) { // switch off display + printf("could not switch off TM1637 %u\n", tm1637); + } } led_max7219_test(false,0xff); // go back in normal operation led_max7219_off(0xff); // switch displays off @@ -367,7 +448,7 @@ void main(void) rtc_tick_flag = false; // reset flag action = true; // action has been performed led_toggle(); // toggle LED (good to indicate if main function is stuck) - frame_count = 0; // resync frame counter to second +/* if (standby_timer>=STANDBY_TIMEOUT) { // standby timeout complete // go into standby mode printf("standing by\n"); @@ -376,6 +457,7 @@ void main(void) SCB_SCR |= SCB_SCR_SLEEPDEEP; // enable deep sleep pwr_set_standby_mode(); // go to deep sleep } +*/ 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) { @@ -388,6 +470,15 @@ void main(void) } } } + for (uint8_t tm1637=0; tm1637<7; tm1637++) { + mux_select(tm1637); + if (!led_tm1637_time(rtc_ds1307_time[1],rtc_seconds+tm1637)) { // test TM1637 display + printf("could not send time to TM1637 %u\n", tm1637); + } + if (!led_tm1637_on()) { // switch on TM1637 display + printf("could not switch on TM1637 %u\n", tm1637); + } + } } while (pwr_get_wakeup_flag()) { // someone is moving the clapperboard pwr_clear_wakeup_flag(); // clear flag @@ -405,6 +496,7 @@ void main(void) void EXTI_ISR(SQUARE_WAVE_PIN)(void) { exti_reset_request(EXTI(SQUARE_WAVE_PIN)); // reset interrupt + frame_count = 0; // re-sync frame counter to second rtc_seconds++; // increment number of seconds passed if (standby_timer