    #include <pic.h>
     
    // filament clock
    // (c) Mike Harrison 2015
    // www.electricstuff.co.uk
    // Target PIC16F1824
     
    #pragma config FOSC=INTOSC,MCLRE=ON,WDTE=ON,PWRTE=ON,BOREN=ON,CLKOUTEN=OFF
    #pragma config LVP=OFF,BORV=HI,WRT=OFF
     
    #define oe LATA2 // tpic595 latch output enable. Could use PWM for global dimming, or multi-cycle pulses for per-segment dimming
    #define lat LATB1 // tpic595 latch
     
    // set switches
    #define minsw RA0
    #define hrsw RA1
     
    // segment bits within shift registers
    #define sa 4
    #define sb 8
    #define sc 16
    #define sd 32
    #define se 64
    #define sf 2
    #define sg 128
    #define sx 1 // 10Hrs, colon
     
    // seven-segment lookup
     
    const char sevenseg[10]={
    sa | sb | sc | sd | se | sf,
    sb | sc,
    sa | sb | sd | se | sg,
    sa | sb | sc | sd | sg,
    sb | sc | sf | sg,
    sa | sc | sd | sf | sg,
    sa | sc | sd | se | sf | sg,
    sa | sb | sc ,
    sa | sb | sc | sd | se | sf | sg,
    sa | sb | sc | sd | sf | sg
    };
     
     
    unsigned char hsecs,mins,hours,colon; // NB hsecs counts half-seconds
     
    void spibyte(char c)
    { // send byte to SPI port
    SSP1IF=0;
    SSP1BUF=c;
    while(~SSP1IF);
    }
     
    void main(void)
    {
     
        OSCCON=0b01110000; // 8MHz
        LATA=0;
        TRISA=0b00110011;
        WPUA =0b00000011; // pullups for switches
        ANSELA=0;
     
        LATB=0;
        TRISB=0b00000000;
        WPUB =0b00000000;
        ANSELB=0;
        OPTION_REG=0b00000000;
        APFCON0=0; APFCON1=0;
        // SPI setup
        SSP1STAT=0b01000000; // CKE high
        SSP1CON1=0b00100000; // master mode, clk=fosc/4
        SSP1CON2=SSP1CON3=0;
     
        T1CON=0b10001001; // timer1 on, T1 oscillator
     
    oe=0; // output enable
     
    hours=0; // "power out" indication, prevent counting
    mins=0;
    hsecs=0;
    TMR1IF=1; // force initial update - 32K osc can take a few secs to start
     
    do {
     
    asm("clrwdt");
     
    if (hours==0) if((minsw==0) || (hrsw==0)) hours=1; // start running after powerdown
     
    if(TMR1IF) { // 2Hz tick
    TMR1IF=0;
    TMR1H|=0xC0; // preload Tmr1 for 2Hz=16384 counts
     
    colon=hsecs&1;
     
    if(minsw==0) if(++mins==60) mins=0;
    if(hrsw==0) if(++hours==13) hours=1;
     
    if(hours) // not startup
    if(++hsecs==120) {
    hsecs=0;
    if(++mins==60) {
    mins=0;
    if(++hours==13) {
    hours=1;
    }
        }
    }
     
    lat=0;
    spibyte(sevenseg[hours%10] | (hours>9?sx:0));
    spibyte(sevenseg[mins/10] | (colon?sx:0));
    spibyte(sevenseg[mins%10]);
    lat=1;
     
     
    }
     
     
    } while(1);
       
        }