Code for my numitron clock. Based on the STM32F042 and using a TLC5916 per numitron to drive them.

Dependencies:   SWSPI mbed-dev

main.cpp

Committer:
riktw
Date:
2016-11-12
Revision:
0:d1558f6f88bf
Child:
1:c80f72f7ee20

File content as of revision 0:d1558f6f88bf:

#include "mbed.h"
#include "SWSPI.h"

SWSPI spi( PA_2, PA_1, PA_3 );                          // create the fake SPI port
DigitalOut OE(PA_0);                                    // Output Enable
DigitalOut LE(PA_4);                                    // The LE pin and the number of connected chips
BusIn buttons(PA_5, PA_6, PA_7, PB_1);                  // The 4 user buttons
// All the digits places in an array, 0-9.
const uint8_t numbers[10] = {0x7B, 0x60, 0x57, 0x76, 0x6C, 0x3E, 0x3F, 0x70, 0x7F, 0x7E};

// A flag to control the blinking dot.
uint8_t flipflag = 1;

// Struct that contains all the numitron values. 
// Even if this clock only uses 4 numitrons, the struct is already prepared for 6.
typedef struct
    {
        uint8_t second_right;
        uint8_t second_left;
        uint8_t minute_right;
        uint8_t minute_left;
        uint8_t hour_right;
        uint8_t hour_left;
    }clock_typ; 
clock_typ numiclock;

// Variables for getting time
struct tm t;
time_t rawtime;

// Ticker to update the clock.
Ticker secondticker; 
void updatetime(void);

int main() 
{
    static struct tm *t3;
    buttons.mode(PullUp);

    LE = 0;
    OE = 1;

    // Set the time on 00:00:00 @ 1 jan 2016
    t.tm_sec = 0;
    t.tm_min = 0;
    t.tm_hour = 0;
    t.tm_mday = 1;
    t.tm_mon = 1-1;
    t.tm_year = 2016-1900;
    set_time(mktime(&t));

    // Clear the displays
    spi.write(0x00);
    spi.write(0x00);
    spi.write(0x00);
    spi.write(0x00);

    // Toggle LE to latch in the values in the TLC5916
    LE = 1;
    wait_us(10);
    LE = 0;
    wait_us(10);

    OE = 0;     // Enable the displays
    secondticker.attach(&updatetime, 1);
    
    while( 1 )
    {   // If any button is pressed and after 50ms still is pressed, count it as a press.
        uint8_t bpressed = buttons;
        wait_ms(50);
        if((bpressed == buttons) && (bpressed != 0xf))
        {
            // Get the current time, see what button is pressed, update the time and use this as the new time.
            rawtime = time(NULL);
            t3 = localtime(&rawtime);
            bpressed = (~bpressed)&0x0f;    // The buttons are high when unpressed, invert it to make the code a bit easier.
            switch(bpressed)
            {
                case 0x01:                  // Button most left pressed, add 10 hours to the current time
                    t3->tm_hour += 10;
                    if(t3->tm_hour >= 30)   // Keep in mind that the maximum for hours is 23.
                    {
                        t3->tm_hour -= 30;
                    }
                    else if(t3->tm_hour >= 24)
                    {
                        t3->tm_hour -= 20;
                    }
                break;
                case 0x02:                  // Button second left, add 1 hour
                    t3->tm_hour += 1;
                    if((t3->tm_hour%10) == 0)
                    {
                        t3->tm_hour -= 10;
                    }
                    else if(t3->tm_hour >= 24)
                    {
                        t3->tm_hour -= 4;
                    }                       
                break;
                case 0x04:                  // Button second right, add 10 minutes
                    t3->tm_min += 10;
                    if(t3->tm_min >= 60)
                    {
                        t3->tm_min -= 60;
                    }
                break;  
                case 0x08:                  // Button most right, add 1 minute.
                    t3->tm_min += 1;
                    if((t3->tm_min%10) == 0)
                    {
                        t3->tm_min -= 10;
                    }
                break;
            }
            set_time(mktime(t3));
            flipflag = 0;                   // Update the display without the blinking dot.
            updatetime();               
            flipflag = 1;
            wait_ms(150);                   // extra delay so a press is only seen once.
        }
    }
}

// When called this function retrieves the current time
// and places this in the numiclock struct.
// It then sends the data to the SPI bus to display the change
void updatetime(void)
{
    static uint8_t flipbit;
    static struct tm *t2;
    rawtime = time(NULL);
    t2 = localtime(&rawtime);

    numiclock.second_right = t2->tm_sec%10;
    numiclock.second_left = (t2->tm_sec - numiclock.second_right)/10;
    numiclock.minute_right = t2->tm_min%10;
    numiclock.minute_left = (t2->tm_min - numiclock.minute_right)/10;
    numiclock.hour_right = t2->tm_hour%10;
    numiclock.hour_left = (t2->tm_hour-numiclock.hour_right)/10;

    spi.write(numbers[numiclock.hour_left]);
    if(flipflag)
    {
        if(flipbit == 1)
        {
                spi.write((numbers[numiclock.hour_right])+0x80);
                flipbit = 0;
        }
        else
        {
                spi.write(numbers[numiclock.hour_right]);
                flipbit = 1;
        }
    }
    else
    {
        spi.write(numbers[numiclock.hour_right]);
    }
    spi.write(numbers[numiclock.minute_left]);
    spi.write(numbers[numiclock.minute_right]);
        
    LE = 1;
    wait_us(10);
    LE = 0;
    wait_us(10); 
}