Code for my numitron clock. Based on the STM32F042 and using a TLC5916 per numitron to drive them.
main.cpp@0:d1558f6f88bf, 2016-11-12 (annotated)
- Committer:
- riktw
- Date:
- Sat Nov 12 08:25:50 2016 +0000
- Revision:
- 0:d1558f6f88bf
- Child:
- 1:c80f72f7ee20
A program for my numitron clock;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
riktw | 0:d1558f6f88bf | 1 | #include "mbed.h" |
riktw | 0:d1558f6f88bf | 2 | #include "SWSPI.h" |
riktw | 0:d1558f6f88bf | 3 | |
riktw | 0:d1558f6f88bf | 4 | SWSPI spi( PA_2, PA_1, PA_3 ); // create the fake SPI port |
riktw | 0:d1558f6f88bf | 5 | DigitalOut OE(PA_0); // Output Enable |
riktw | 0:d1558f6f88bf | 6 | DigitalOut LE(PA_4); // The LE pin and the number of connected chips |
riktw | 0:d1558f6f88bf | 7 | BusIn buttons(PA_5, PA_6, PA_7, PB_1); // The 4 user buttons |
riktw | 0:d1558f6f88bf | 8 | // All the digits places in an array, 0-9. |
riktw | 0:d1558f6f88bf | 9 | const uint8_t numbers[10] = {0x7B, 0x60, 0x57, 0x76, 0x6C, 0x3E, 0x3F, 0x70, 0x7F, 0x7E}; |
riktw | 0:d1558f6f88bf | 10 | |
riktw | 0:d1558f6f88bf | 11 | // A flag to control the blinking dot. |
riktw | 0:d1558f6f88bf | 12 | uint8_t flipflag = 1; |
riktw | 0:d1558f6f88bf | 13 | |
riktw | 0:d1558f6f88bf | 14 | // Struct that contains all the numitron values. |
riktw | 0:d1558f6f88bf | 15 | // Even if this clock only uses 4 numitrons, the struct is already prepared for 6. |
riktw | 0:d1558f6f88bf | 16 | typedef struct |
riktw | 0:d1558f6f88bf | 17 | { |
riktw | 0:d1558f6f88bf | 18 | uint8_t second_right; |
riktw | 0:d1558f6f88bf | 19 | uint8_t second_left; |
riktw | 0:d1558f6f88bf | 20 | uint8_t minute_right; |
riktw | 0:d1558f6f88bf | 21 | uint8_t minute_left; |
riktw | 0:d1558f6f88bf | 22 | uint8_t hour_right; |
riktw | 0:d1558f6f88bf | 23 | uint8_t hour_left; |
riktw | 0:d1558f6f88bf | 24 | }clock_typ; |
riktw | 0:d1558f6f88bf | 25 | clock_typ numiclock; |
riktw | 0:d1558f6f88bf | 26 | |
riktw | 0:d1558f6f88bf | 27 | // Variables for getting time |
riktw | 0:d1558f6f88bf | 28 | struct tm t; |
riktw | 0:d1558f6f88bf | 29 | time_t rawtime; |
riktw | 0:d1558f6f88bf | 30 | |
riktw | 0:d1558f6f88bf | 31 | // Ticker to update the clock. |
riktw | 0:d1558f6f88bf | 32 | Ticker secondticker; |
riktw | 0:d1558f6f88bf | 33 | void updatetime(void); |
riktw | 0:d1558f6f88bf | 34 | |
riktw | 0:d1558f6f88bf | 35 | int main() |
riktw | 0:d1558f6f88bf | 36 | { |
riktw | 0:d1558f6f88bf | 37 | static struct tm *t3; |
riktw | 0:d1558f6f88bf | 38 | buttons.mode(PullUp); |
riktw | 0:d1558f6f88bf | 39 | |
riktw | 0:d1558f6f88bf | 40 | LE = 0; |
riktw | 0:d1558f6f88bf | 41 | OE = 1; |
riktw | 0:d1558f6f88bf | 42 | |
riktw | 0:d1558f6f88bf | 43 | // Set the time on 00:00:00 @ 1 jan 2016 |
riktw | 0:d1558f6f88bf | 44 | t.tm_sec = 0; |
riktw | 0:d1558f6f88bf | 45 | t.tm_min = 0; |
riktw | 0:d1558f6f88bf | 46 | t.tm_hour = 0; |
riktw | 0:d1558f6f88bf | 47 | t.tm_mday = 1; |
riktw | 0:d1558f6f88bf | 48 | t.tm_mon = 1-1; |
riktw | 0:d1558f6f88bf | 49 | t.tm_year = 2016-1900; |
riktw | 0:d1558f6f88bf | 50 | set_time(mktime(&t)); |
riktw | 0:d1558f6f88bf | 51 | |
riktw | 0:d1558f6f88bf | 52 | // Clear the displays |
riktw | 0:d1558f6f88bf | 53 | spi.write(0x00); |
riktw | 0:d1558f6f88bf | 54 | spi.write(0x00); |
riktw | 0:d1558f6f88bf | 55 | spi.write(0x00); |
riktw | 0:d1558f6f88bf | 56 | spi.write(0x00); |
riktw | 0:d1558f6f88bf | 57 | |
riktw | 0:d1558f6f88bf | 58 | // Toggle LE to latch in the values in the TLC5916 |
riktw | 0:d1558f6f88bf | 59 | LE = 1; |
riktw | 0:d1558f6f88bf | 60 | wait_us(10); |
riktw | 0:d1558f6f88bf | 61 | LE = 0; |
riktw | 0:d1558f6f88bf | 62 | wait_us(10); |
riktw | 0:d1558f6f88bf | 63 | |
riktw | 0:d1558f6f88bf | 64 | OE = 0; // Enable the displays |
riktw | 0:d1558f6f88bf | 65 | secondticker.attach(&updatetime, 1); |
riktw | 0:d1558f6f88bf | 66 | |
riktw | 0:d1558f6f88bf | 67 | while( 1 ) |
riktw | 0:d1558f6f88bf | 68 | { // If any button is pressed and after 50ms still is pressed, count it as a press. |
riktw | 0:d1558f6f88bf | 69 | uint8_t bpressed = buttons; |
riktw | 0:d1558f6f88bf | 70 | wait_ms(50); |
riktw | 0:d1558f6f88bf | 71 | if((bpressed == buttons) && (bpressed != 0xf)) |
riktw | 0:d1558f6f88bf | 72 | { |
riktw | 0:d1558f6f88bf | 73 | // Get the current time, see what button is pressed, update the time and use this as the new time. |
riktw | 0:d1558f6f88bf | 74 | rawtime = time(NULL); |
riktw | 0:d1558f6f88bf | 75 | t3 = localtime(&rawtime); |
riktw | 0:d1558f6f88bf | 76 | bpressed = (~bpressed)&0x0f; // The buttons are high when unpressed, invert it to make the code a bit easier. |
riktw | 0:d1558f6f88bf | 77 | switch(bpressed) |
riktw | 0:d1558f6f88bf | 78 | { |
riktw | 0:d1558f6f88bf | 79 | case 0x01: // Button most left pressed, add 10 hours to the current time |
riktw | 0:d1558f6f88bf | 80 | t3->tm_hour += 10; |
riktw | 0:d1558f6f88bf | 81 | if(t3->tm_hour >= 30) // Keep in mind that the maximum for hours is 23. |
riktw | 0:d1558f6f88bf | 82 | { |
riktw | 0:d1558f6f88bf | 83 | t3->tm_hour -= 30; |
riktw | 0:d1558f6f88bf | 84 | } |
riktw | 0:d1558f6f88bf | 85 | else if(t3->tm_hour >= 24) |
riktw | 0:d1558f6f88bf | 86 | { |
riktw | 0:d1558f6f88bf | 87 | t3->tm_hour -= 20; |
riktw | 0:d1558f6f88bf | 88 | } |
riktw | 0:d1558f6f88bf | 89 | break; |
riktw | 0:d1558f6f88bf | 90 | case 0x02: // Button second left, add 1 hour |
riktw | 0:d1558f6f88bf | 91 | t3->tm_hour += 1; |
riktw | 0:d1558f6f88bf | 92 | if((t3->tm_hour%10) == 0) |
riktw | 0:d1558f6f88bf | 93 | { |
riktw | 0:d1558f6f88bf | 94 | t3->tm_hour -= 10; |
riktw | 0:d1558f6f88bf | 95 | } |
riktw | 0:d1558f6f88bf | 96 | else if(t3->tm_hour >= 24) |
riktw | 0:d1558f6f88bf | 97 | { |
riktw | 0:d1558f6f88bf | 98 | t3->tm_hour -= 4; |
riktw | 0:d1558f6f88bf | 99 | } |
riktw | 0:d1558f6f88bf | 100 | break; |
riktw | 0:d1558f6f88bf | 101 | case 0x04: // Button second right, add 10 minutes |
riktw | 0:d1558f6f88bf | 102 | t3->tm_min += 10; |
riktw | 0:d1558f6f88bf | 103 | if(t3->tm_min >= 60) |
riktw | 0:d1558f6f88bf | 104 | { |
riktw | 0:d1558f6f88bf | 105 | t3->tm_min -= 60; |
riktw | 0:d1558f6f88bf | 106 | } |
riktw | 0:d1558f6f88bf | 107 | break; |
riktw | 0:d1558f6f88bf | 108 | case 0x08: // Button most right, add 1 minute. |
riktw | 0:d1558f6f88bf | 109 | t3->tm_min += 1; |
riktw | 0:d1558f6f88bf | 110 | if((t3->tm_min%10) == 0) |
riktw | 0:d1558f6f88bf | 111 | { |
riktw | 0:d1558f6f88bf | 112 | t3->tm_min -= 10; |
riktw | 0:d1558f6f88bf | 113 | } |
riktw | 0:d1558f6f88bf | 114 | break; |
riktw | 0:d1558f6f88bf | 115 | } |
riktw | 0:d1558f6f88bf | 116 | set_time(mktime(t3)); |
riktw | 0:d1558f6f88bf | 117 | flipflag = 0; // Update the display without the blinking dot. |
riktw | 0:d1558f6f88bf | 118 | updatetime(); |
riktw | 0:d1558f6f88bf | 119 | flipflag = 1; |
riktw | 0:d1558f6f88bf | 120 | wait_ms(150); // extra delay so a press is only seen once. |
riktw | 0:d1558f6f88bf | 121 | } |
riktw | 0:d1558f6f88bf | 122 | } |
riktw | 0:d1558f6f88bf | 123 | } |
riktw | 0:d1558f6f88bf | 124 | |
riktw | 0:d1558f6f88bf | 125 | // When called this function retrieves the current time |
riktw | 0:d1558f6f88bf | 126 | // and places this in the numiclock struct. |
riktw | 0:d1558f6f88bf | 127 | // It then sends the data to the SPI bus to display the change |
riktw | 0:d1558f6f88bf | 128 | void updatetime(void) |
riktw | 0:d1558f6f88bf | 129 | { |
riktw | 0:d1558f6f88bf | 130 | static uint8_t flipbit; |
riktw | 0:d1558f6f88bf | 131 | static struct tm *t2; |
riktw | 0:d1558f6f88bf | 132 | rawtime = time(NULL); |
riktw | 0:d1558f6f88bf | 133 | t2 = localtime(&rawtime); |
riktw | 0:d1558f6f88bf | 134 | |
riktw | 0:d1558f6f88bf | 135 | numiclock.second_right = t2->tm_sec%10; |
riktw | 0:d1558f6f88bf | 136 | numiclock.second_left = (t2->tm_sec - numiclock.second_right)/10; |
riktw | 0:d1558f6f88bf | 137 | numiclock.minute_right = t2->tm_min%10; |
riktw | 0:d1558f6f88bf | 138 | numiclock.minute_left = (t2->tm_min - numiclock.minute_right)/10; |
riktw | 0:d1558f6f88bf | 139 | numiclock.hour_right = t2->tm_hour%10; |
riktw | 0:d1558f6f88bf | 140 | numiclock.hour_left = (t2->tm_hour-numiclock.hour_right)/10; |
riktw | 0:d1558f6f88bf | 141 | |
riktw | 0:d1558f6f88bf | 142 | spi.write(numbers[numiclock.hour_left]); |
riktw | 0:d1558f6f88bf | 143 | if(flipflag) |
riktw | 0:d1558f6f88bf | 144 | { |
riktw | 0:d1558f6f88bf | 145 | if(flipbit == 1) |
riktw | 0:d1558f6f88bf | 146 | { |
riktw | 0:d1558f6f88bf | 147 | spi.write((numbers[numiclock.hour_right])+0x80); |
riktw | 0:d1558f6f88bf | 148 | flipbit = 0; |
riktw | 0:d1558f6f88bf | 149 | } |
riktw | 0:d1558f6f88bf | 150 | else |
riktw | 0:d1558f6f88bf | 151 | { |
riktw | 0:d1558f6f88bf | 152 | spi.write(numbers[numiclock.hour_right]); |
riktw | 0:d1558f6f88bf | 153 | flipbit = 1; |
riktw | 0:d1558f6f88bf | 154 | } |
riktw | 0:d1558f6f88bf | 155 | } |
riktw | 0:d1558f6f88bf | 156 | else |
riktw | 0:d1558f6f88bf | 157 | { |
riktw | 0:d1558f6f88bf | 158 | spi.write(numbers[numiclock.hour_right]); |
riktw | 0:d1558f6f88bf | 159 | } |
riktw | 0:d1558f6f88bf | 160 | spi.write(numbers[numiclock.minute_left]); |
riktw | 0:d1558f6f88bf | 161 | spi.write(numbers[numiclock.minute_right]); |
riktw | 0:d1558f6f88bf | 162 | |
riktw | 0:d1558f6f88bf | 163 | LE = 1; |
riktw | 0:d1558f6f88bf | 164 | wait_us(10); |
riktw | 0:d1558f6f88bf | 165 | LE = 0; |
riktw | 0:d1558f6f88bf | 166 | wait_us(10); |
riktw | 0:d1558f6f88bf | 167 | } |