Last active
August 29, 2015 13:56
-
-
Save 46bit/8890681 to your computer and use it in GitHub Desktop.
Show a digital clock on a 4-digit 7-segment display (http://r.46b.it/4seg.jpg), when running on an LPC1760 MBED. Use push buttons to set hour and minute. Not openly licensed, may not be mine to give away.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Serial code | |
| #include "stdhapr.h" // https://gist.github.com/46bit/8890761 | |
| #include "lpc17xx_timer.h" | |
| TIM_TIMERCFG_Type TIM_ConfigStruct; | |
| TIM_MATCHCFG_Type TIM_MatchConfigStruct; | |
| #define SEG7_0 0b11111100 | |
| #define SEG7_1 0b01100000 | |
| #define SEG7_2 0b11011010 | |
| #define SEG7_3 0b11110010 | |
| #define SEG7_4 0b01100110 | |
| #define SEG7_5 0b10110110 | |
| #define SEG7_6 0b10111110 | |
| #define SEG7_7 0b11100000 | |
| #define SEG7_8 0b11111110 | |
| #define SEG7_9 0b11110110 | |
| #define SEG7_A 0b11101110 | |
| #define SEG7_b 0b00111110 | |
| #define SEG7_C 0b10011100 | |
| #define SEG7_d 0b01111010 | |
| #define SEG7_E 0b10011110 | |
| #define SEG7_F 0b10001110 | |
| struct gpio { | |
| char segment; | |
| unsigned long mask; | |
| uint32_t port; | |
| }; | |
| const struct gpio digits[] = {{'0', 1<<2, 2}, | |
| {'1', 1<<3, 2}, | |
| {'2', 1<<4, 2}, | |
| {'3', 1<<5, 2}}; | |
| const struct gpio segments[] = {{'A', 1<<1, 2}, | |
| {'B', 1<<11, 0}, | |
| {'C', 1<<30, 1}, | |
| {'D', 1<<25, 0}, | |
| {'E', 1<<24, 0}, | |
| {'F', 1<<0, 2}, | |
| {'G', 1<<31, 1}, | |
| {'P', 1<<26, 0}}; | |
| const struct gpio buttons[] = {{' ', 1<<23, 0}, | |
| {' ', 1<<15, 0}, | |
| {' ', 1<<10, 0}}; | |
| const uint8_t symbols[] = {SEG7_0, SEG7_1, SEG7_2, SEG7_3, SEG7_4, SEG7_5, SEG7_6, | |
| SEG7_7, SEG7_8, SEG7_9, SEG7_A, SEG7_b, SEG7_C, SEG7_d, | |
| SEG7_E, SEG7_F}; | |
| uint8_t second, hour, minute, decimal = 1; | |
| void dsleep(float seconds) | |
| { | |
| volatile int j, d = (int) 10000000 * seconds; | |
| for (j = 0; j < d; j++) {} | |
| } | |
| void timer_init(int match_value) | |
| { | |
| PINSEL_CFG_Type PinCfg; | |
| PinCfg.Funcnum = 3; | |
| PinCfg.OpenDrain = 0; | |
| PinCfg.Pinmode = 0; | |
| PinCfg.Portnum = 1; | |
| PinCfg.Pinnum = 28; | |
| PINSEL_ConfigPin(&PinCfg); | |
| TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL; | |
| // Multiplies match value. 1 here produces 1uS. | |
| TIM_ConfigStruct.PrescaleValue = 1; | |
| TIM_MatchConfigStruct.MatchChannel = 0; | |
| // Enable interrupt when MR0 matches the value in TC register | |
| TIM_MatchConfigStruct.IntOnMatch = TRUE; | |
| // Enable reset on MR0: TIMER will reset if MR0 matches it | |
| TIM_MatchConfigStruct.ResetOnMatch = TRUE; | |
| // Stop on MR0 if MR0 matches it | |
| TIM_MatchConfigStruct.StopOnMatch = FALSE; | |
| // Toggle MR0.0 pin if MR0 matches it | |
| TIM_MatchConfigStruct.ExtMatchOutputType = TIM_EXTMATCH_TOGGLE; | |
| // Set Match value, 1000000 * 1uS = 1s | |
| TIM_MatchConfigStruct.MatchValue = match_value; | |
| TIM_Init(LPC_TIM0, TIM_TIMER_MODE, &TIM_ConfigStruct); | |
| TIM_ConfigMatch(LPC_TIM0, &TIM_MatchConfigStruct); | |
| // preemption = 1, sub-priority = 1 | |
| NVIC_SetPriority(TIMER0_IRQn, ((0x01<<3)|0x01)); | |
| // Enable interrupt for timer 0 | |
| NVIC_EnableIRQ(TIMER0_IRQn); | |
| } | |
| void timer_start() { | |
| TIM_Cmd(LPC_TIM0, ENABLE); | |
| } | |
| void timer_stop() { | |
| TIM_Cmd(LPC_TIM0, DISABLE); | |
| } | |
| void digit_clear() | |
| { | |
| struct gpio digit; | |
| int digit_index, digit_count = sizeof(digits) / sizeof(digits[0]); | |
| for(digit_index = 0; digit_index < digit_count; digit_index++) { | |
| digit = digits[digit_index]; | |
| GPIO_SetDir(digit.port, digit.mask, 1); | |
| GPIO_SetValue(digit.port, digit.mask); | |
| } | |
| } | |
| void digit(uint32_t index) | |
| { | |
| struct gpio digit; | |
| int digit_count = sizeof(digits) / sizeof(digits[0]); | |
| if (index < digit_count) { | |
| digit = digits[index]; | |
| GPIO_ClearValue(digit.port, digit.mask); | |
| } | |
| } | |
| void symbol_clear() | |
| { | |
| int segment_index, segment_count = sizeof(segments) / sizeof(segments[0]); | |
| for(segment_index = 0; segment_index < segment_count; segment_index++) { | |
| struct gpio segment = segments[segment_index]; | |
| GPIO_SetDir(segment.port, segment.mask, 1); | |
| GPIO_ClearValue(segment.port, segment.mask); | |
| } | |
| } | |
| void symbol(uint32_t index, uint8_t force_decimal) | |
| { | |
| uint8_t symbol = symbols[index]; | |
| int symbol_bit; | |
| for(symbol_bit = 7; symbol_bit >= 0; symbol_bit--) { | |
| if(((symbol & 1) == 1) || (symbol_bit == 7 && force_decimal)) { | |
| struct gpio segment = segments[symbol_bit]; | |
| if (symbol_bit == 7 && force_decimal) { | |
| GPIO_SetValue(segment.port, segment.mask | 1); | |
| } else { | |
| GPIO_SetValue(segment.port, segment.mask); | |
| } | |
| } | |
| symbol = symbol >> 1; | |
| } | |
| } | |
| void seg7_count(uint16_t max_n, float seconds) | |
| { | |
| // Count from 0 to 9999 | |
| uint32_t c; | |
| for(c = 0; c < 10000; c++) { | |
| uint32_t value = GPIO_ReadValue(0); | |
| uint32_t button2 = !((value & (1<<15)) >> 15); | |
| uint32_t button1 = !((value & (1<<23)) >> 23); | |
| if (button1) { | |
| c = 0; | |
| } | |
| if (button2) { | |
| c++; | |
| } | |
| uint16_t n; | |
| for(n = 0; n < max_n; n++) { | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(0); | |
| symbol(c % 10, 0); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(1); | |
| symbol((c / 10) % 10, 0); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(2); | |
| symbol((c / 100) % 10, 0); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(3); | |
| symbol((c / 1000) % 10, 0); | |
| dsleep(seconds); | |
| } | |
| } | |
| } | |
| uint8_t read_button(struct gpio button) | |
| { | |
| uint32_t portvalue = GPIO_ReadValue(button.port); | |
| uint32_t buttonvalue = (portvalue & button.mask) == 0; | |
| return buttonvalue; | |
| } | |
| void add_hour_button() | |
| { | |
| uint32_t value = read_button(buttons[0]); | |
| if (value) { | |
| second = 0; | |
| hour++; | |
| hour = hour % 24; | |
| } | |
| } | |
| void add_minute_button() | |
| { | |
| uint32_t value = read_button(buttons[1]); | |
| if (value) { | |
| second = 0; | |
| minute++; | |
| if (minute > 59) { | |
| minute = 0; | |
| hour++; | |
| hour = hour % 24; | |
| } | |
| } | |
| } | |
| void seg7_clock(uint16_t max_n, float seconds) | |
| { | |
| int m; | |
| for (m = 0; m < max_n / 2; m++) { | |
| if (m % 60 == 0) { | |
| decimal = !decimal; | |
| add_hour_button(); | |
| add_minute_button(); | |
| } | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(0); | |
| symbol(minute % 10, 0); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(1); | |
| symbol((minute / 10) % 10, 0); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(2); | |
| symbol(hour % 10, decimal); | |
| dsleep(seconds); | |
| digit_clear(); | |
| symbol_clear(); | |
| digit(3); | |
| symbol((hour / 10) % 10, 0); | |
| dsleep(seconds); | |
| } | |
| } | |
| void TIMER0_IRQHandler() | |
| { | |
| if (TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT) == SET) { | |
| second++; | |
| if (second > 59) { | |
| minute++; | |
| second = 0; | |
| if (minute > 59) { | |
| hour++; | |
| minute = 0; | |
| if (hour > 23) { | |
| hour = hour % 24; | |
| } | |
| } | |
| } | |
| } | |
| TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT); | |
| } | |
| void main(void) | |
| { | |
| led_init(); | |
| tty_init(); | |
| tty_writeln("Hello world!"); | |
| timer_init(1000000); | |
| // Button stuff. | |
| GPIO_SetDir(0, 1<<17, 1); | |
| GPIO_SetDir(0, 1<<15, 0); | |
| GPIO_ClearValue(0, 1<<17); | |
| GPIO_SetValue(0, 1<<15); | |
| GPIO_SetDir(0, 1<<16, 1); | |
| GPIO_SetDir(0, 1<<23, 0); | |
| GPIO_ClearValue(0, 1<<16); | |
| GPIO_SetValue(0, 1<<23); | |
| //while(1) seg7_count(10000, 0.000001); | |
| hour = 13; | |
| minute = 37; | |
| second = 0; | |
| timer_start(); | |
| while(1) seg7_clock(120, 0.001); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment