Skip to content

Instantly share code, notes, and snippets.

@46bit
Last active August 29, 2015 13:56
Show Gist options
  • Save 46bit/8890681 to your computer and use it in GitHub Desktop.
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.
// 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