| 
 /*  * file         : dymoclock.c  * project      : Simple LED clock with thermometer  * author       : Bruno Gavand  * compiler     : mikroC V6.0.0.0  * date         : september 15, 2006  *  * description  :  *      This is a 12 hours clock with 27 LEDs display, with a 2°C resolution thermometer  *  * target device :  *      PIC16F819 with 16 Mhz crystal  *  * configuration bits :  *      HS clock  *      no watchdog  *      no power up timer  *      RA5 as MCLR pin  *      brown out detect  *      LVP disabled  *      data EE protect disabled  *      ICD disabled  *      CCP1 pin on RB2  *  * see more details and schematic on http://www.micro-examples.com/  *  */ 
/*  * display modes  */ #define MODE_HOURMN     0       // display hours:minutes #define MODE_SS         1       // display seconds #define MODE_TEMP       2       // display temperature #define MAX_MODE        3       // number off display modes 
/*  * buttons  */ #define BUTTON          ((PORTA.F1 == 0)  || (PORTA.F2 == 0))   // at least one #define BUTTON_MODE     (PORTA.F1 == 0)                         // mode / advance #define BUTTON_TOGGLE   (PORTA.F2 == 0)                         // toggle / valid #define BUTTON_SET      ((PORTA.F1 == 0) && (PORTA.F2 == 0))    // both at the same time 
#define TEMP_REF        115     // silicon junction offset : 600 mV #define MAX_TEMP        20      // number of temperature samples 
/*  * LED multiplexing tables  *  * LED index   : 1 2 3 4 5  6 7 8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  * LED number  : 1 2 3 4 9 10 5 6 11 12 25 30  7  8  5 10 35 40 45 50  2  1 15 20  3  4 55  * LED hours   : 1 2 3 4 5  6 7 8  9 10 11 12  * LED min/deg :                               5 10 15 20 25 30 35 40 45 50 55  * LED 1234    :                                                                1  2  3  4  */ 
/*  * upper row : hours from 1 to 12  */ const   unsigned char hhTable[] = { 0, 1, 2, 3, 4, 7, 8, 13, 14, 5, 6, 9, 10 } ; 
/*  * middle row : minutes/seconds/°C from 5 to 55 step 5  */ const   unsigned char mnTableH[] =         {         0, 0, 0, 0, 0,         15, 15, 15, 15, 15,         16, 16, 16, 16, 16,         23, 23, 23, 23, 23,         24, 24, 24, 24, 24,         11, 11, 11, 11, 11,         12, 12, 12, 12, 12,         17, 17, 17, 17, 17,         18, 18, 18, 18, 18,         19, 19, 19, 19, 19,         20, 20, 20, 20, 20,         27, 27, 27, 27, 27         } ; 
/*  * lower row : increment of minutes/seconds/°C from 1 to 4  */ const   unsigned char mnTableL[] =         {         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26,         0, 22, 21, 25, 26         } ; 
/*  * RAM variables  */ unsigned char   mode ;                  // display mode unsigned char   toggleMode ;            // toggle mode flag unsigned int    scaler = 0 ;            // timer overflow divider unsigned char   hh = 1 ;                // hours unsigned char   mn = 1 ;                // minutes unsigned char   ss = 0 ;                // seconds int             temp ;                  // temperature in °C unsigned char   tdeg[MAX_TEMP] ;        // array of temperatures samples unsigned char   tidx = 0 ;              // index of the temperature sample 
/*  * interrupt routine service  * called Fosc / 4 / 256 times per second  */ void    interrupt(void)         {         if(INTCON.TMR0IF)                                       // timer overflow ?                 {                 scaler++ ;                                      // increment scaler                 if(scaler == 15625)                              // one second has expired ?                         {                         scaler = 0 ;                            // reset scaler 
                        ss++ ;                                  // next second                         if(ss == 60)                            // one minute has expired ?                                 {                                 ss = 0 ;                        // reset seconds                                 mn++ ;                          // next minute                                 if(mn == 60)                    // one hour has expired ?                                         {                                         mn = 0 ;                // reset minutes                                         hh++ ;                  // next hour                                         if(hh == 13)            // 12 hours mode                                                 {                                                 hh = 1 ;        // back to first hour                                                 }                                         }                                 }                         } 
                INTCON.TMR0IF = 0 ;                             // clear interrupt flag                 }         } 
/*  * light the LED number n during d milliseconds  */ void    dymoLight(const unsigned char n, unsigned char d)         {         switch(n)                 {                 case  0 : TRISB = 0b11111111 ; PORTB = 0b00000000 ; break ;                 case  1 : TRISB = 0b11111100 ; PORTB = 0b00000001 ; break ;                 case  2 : TRISB = 0b11111100 ; PORTB = 0b00000010 ; break ;                 case  3 : TRISB = 0b11111010 ; PORTB = 0b00000001 ; break ;                 case  4 : TRISB = 0b11111010 ; PORTB = 0b00000100 ; break ;                 case  5 : TRISB = 0b11111001 ; PORTB = 0b00000010 ; break ;                 case  6 : TRISB = 0b11111001 ; PORTB = 0b00000100 ; break ;                 case  7 : TRISB = 0b11110110 ; PORTB = 0b00000001 ; break ;                 case  8 : TRISB = 0b11110110 ; PORTB = 0b00001000 ; break ;                 case  9 : TRISB = 0b11110101 ; PORTB = 0b00000010 ; break ;                 case 10 : TRISB = 0b11110101 ; PORTB = 0b00001000 ; break ;                 case 11 : TRISB = 0b11110011 ; PORTB = 0b00000100 ; break ;                 case 12 : TRISB = 0b11110011 ; PORTB = 0b00001000 ; break ;                 case 13 : TRISB = 0b11101110 ; PORTB = 0b00000001 ; break ;                 case 14 : TRISB = 0b11101110 ; PORTB = 0b00010000 ; break ;                 case 15 : TRISB = 0b11101101 ; PORTB = 0b00000010 ; break ;                 case 16 : TRISB = 0b11101101 ; PORTB = 0b00010000 ; break ;                 case 17 : TRISB = 0b11101011 ; PORTB = 0b00000100 ; break ;                 case 18 : TRISB = 0b11101011 ; PORTB = 0b00010000 ; break ;                 case 19 : TRISB = 0b11100111 ; PORTB = 0b00001000 ; break ;                 case 20 : TRISB = 0b11100111 ; PORTB = 0b00010000 ; break ;                 case 21 : TRISB = 0b11011110 ; PORTB = 0b00000001 ; break ;                 case 22 : TRISB = 0b11011110 ; PORTB = 0b00100000 ; break ;                 case 23 : TRISB = 0b11011101 ; PORTB = 0b00000010 ; break ;                 case 24 : TRISB = 0b11011101 ; PORTB = 0b00100000 ; break ;                 case 25 : TRISB = 0b11011011 ; PORTB = 0b00000100 ; break ;                 case 26 : TRISB = 0b11011011 ; PORTB = 0b00100000 ; break ;                 case 27 : TRISB = 0b11010111 ; PORTB = 0b00001000 ; break ;                 case 28 : TRISB = 0b11010111 ; PORTB = 0b00100000 ; break ;                 case 29 : TRISB = 0b11001111 ; PORTB = 0b00010000 ; break ;                 case 30 : TRISB = 0b11001111 ; PORTB = 0b00100000 ; break ;                 }         VDelay_ms(d) ;         } 
/*  * set clock time  */ void    setTime()         {         INTCON.GIE = 0 ;                        // stop time counting                  hh = 1 ;                                // set hours         for(;;)                 {                 dymoLight(hhTable[hh], 20) ;    // light hour 
                if(BUTTON_MODE)                 // advance hour ?                         {                         VDelay_ms(15) ;          // debounce button                         while(BUTTON_MODE) ;                         VDelay_ms(15) ; 
                        hh++ ;                  // next hour                         if(hh > 12)             // overflow ?                                 {                                 hh = 1 ;        // back to first hour                                 }                         } 
                if(BUTTON_TOGGLE)               // valid ?                         {                         VDelay_ms(15) ;                         while(BUTTON_TOGGLE) ;  // debounce button                         VDelay_ms(15) ;                         break ;                 // exit loop                         }                 } 
        mn = 1 ;                                // set minutes         for(;;)                 {                 dymoLight(mnTableH[mn], 10) ;   // light minutes, upper row                 dymoLight(mnTableL[mn], 10) ;   // light minutes, lower row 
                if(BUTTON_MODE)                 // advance minute ?                         {                         VDelay_ms(15) ;          // debounce button                         while(BUTTON_MODE) ;                         VDelay_ms(15) ; 
                        mn++ ;                  // next minute                         if(mn > 59)             // overflow ?                                 {                                 mn = 0 ;        // back to first minute                                 }                         } 
                if(BUTTON_TOGGLE)               // valid ?                         {                         VDelay_ms(15) ;          // debounce button                         while(BUTTON_TOGGLE) ;                         VDelay_ms(15) ;                         break ;                 // exit loop                         }                 } 
        ss = 0 ;                                // reset seconds                  INTCON.GIE = 1 ;                        // start clock                  toggleMode = 0 ;                        // no toggle         mode = MODE_HOURMN ;                    // display hours:minutes         } 
/*  * main entry  */ void    main()         {         unsigned int    loopCtr = 0 ;           // counter for temperature sampling delay         unsigned int    toggleCtr = 0 ;         // counter for toggle delay          //        OSCCON |= 0b01110000 ;                // untag if you use internal RC clock, 8Mhz 
        ADCON1 = 0b00001110 ;                   // RA0 as analog input, other input as digital I/O         TRISA = 0b11111111 ;                    // all PORTA as inputs         PORTA = 0 ;                             // clear PORTA 
        TRISB = 0xff ;                          // switch off display 
        INTCON.TMR0IF = 0 ;                     // clear timer 0 overflow interrupt flag         INTCON.TMR0IE = 1 ;                     // allow timer 0 overflow interrupt                  OPTION_REG.T0CS = 0 ;                   // timer 0 clock source is internal instruction cycle clock 
        OPTION_REG.PS2 = 0 ;                    // no prescaler         OPTION_REG.PS1 = 0 ;         OPTION_REG.PS0 = 0 ;         OPTION_REG.PSA = 1 ;                  setTime() ;                             // set time 
        for(;;)                 {                 loopCtr++ ;                                     // increment loop counters                 toggleCtr++ ; 
                if(BUTTON)                                      // if at least one button is pressed                         {                         unsigned char   b = 0 ;                                                  VDelay_ms(15) ;                          // debounce                         while(BUTTON)                           // while one button is pressed                                 {                                 if(BUTTON_SET)                  // are they both pressed ?                                         {                                         dymoLight(hhTable[0], 1) ;      // clear display                                         dymoLight(mnTableH[0], 1) ;                                         dymoLight(mnTableL[0], 1) ; 
                                        VDelay_ms(1000) ;                // 1 second delay 
                                        setTime() ;                     // enter time setting                                                                                  break ;                                         }                                 else if(BUTTON_MODE)            // change mode ?                                         {                                         b = 1 ;                                         }                                 else if(BUTTON_TOGGLE)          // toggle the toggle mode ?                                         {                                         b = 2 ;                                         } 
                                VDelay_ms(15) ;                                 }                                                  if(b == 1)                      // change mode                                 {                                 VDelay_ms(15) ;          // debounce button                                 while(BUTTON_MODE) ;                                 VDelay_ms(15) ; 
                                mode++ ;                // next mode                                 toggleMode = 0 ;        // clear toggle mode                                 if(mode == MAX_MODE)    // last mode ?                                         {                                         mode = 0 ;      // back to first one                                         }                                 }                         else if(b == 2)                 // toggle mode                                 {                                 VDelay_ms(15) ;          // debounce button                                 while(BUTTON_TOGGLE) ;                                 VDelay_ms(15) ; 
                                toggleMode = !toggleMode ;      // toggle display mode                                 }                         }                                          if(mode == MODE_HOURMN)                         // display mode is hours:minutes                         {                         dymoLight(hhTable[hh], 5) ;             // light hours 
                        dymoLight(mnTableH[mn], 5) ;            // light minutes, upper row                         dymoLight(mnTableL[mn], 5) ;            // light minutes, lower row                                                  if(toggleMode && (toggleCtr > 400))     // if toggle mode and delay expired                                 {                                 toggleCtr = 0 ;                 // reset counter                                 mode = MODE_TEMP ;              // switch to temperature                                 }                         }                 else if(mode == MODE_SS)                        // display mode is seconds                         {                         dymoLight(mnTableH[ss], 5) ;            // light seconds, upper row                         dymoLight(mnTableL[ss], 5) ;            // light seconds, lower row                         }                 else if(mode == MODE_TEMP)                      // display mode is temperature                         {                         unsigned char   i ; 
                        if(loopCtr > 20)                        // if delay expired                                 {                                 loopCtr = 0 ;                   // reset counter                                 temp = TEMP_REF - Adc_Read(0) ;         // get sample 
                                temp *= 221 ;           // temperature coefficient of the silicon junction                                 temp /= 102 ;                                 temp = 25 + temp ;      // get the result in celcius 
                                tdeg[tidx] = temp ;     // store temperature sample into array                                 tidx++ ;                // advance index                                 if(tidx == MAX_TEMP)    // index overflow ?                                         {                                         tidx = 0 ;      // back to first slot                                         } 
                                temp = 0 ;              // compute average temperature                                 for(i = 0 ; i < MAX_TEMP ; i++) // for all samples                                         {                                         temp += tdeg[i] ;       // add them                                         }                                 temp /= MAX_TEMP ;              // divide by sample number                                 } 
                        if((temp > 0) && (temp < 60))           // if temperature wihtin 0...59                                 {                                 dymoLight(mnTableL[temp], 5) ;  // display temperature, upper row                                 dymoLight(mnTableH[temp], 5) ;  // display temperature, lower row                                 } 
                        if(toggleMode && (toggleCtr > 200))     // if toggle mode and delay expired                                 {                                 toggleCtr = 0 ;                 // reset counter                                 mode = MODE_HOURMN ;            // switch to hours:minutes                                 }                         }                 }         }
   |