//Code to make my funky, wire coat hanger clock //The code is taken from the 3LED_clock project //Edited 2 April 2005 //Came back 11 Feb 2006 //Corrected time 14 Mar 2006 #include <16F877.h> #fuses XT,NOWDT,NOPROTECT,PUT #include #use delay(clock=2000000) #define TENHOUR PIN_C3 #define HOUR1 PIN_A5 #define HOUR2 PIN_E0 #define HOUR3 PIN_A3 #define HOUR4 PIN_A2 #define HOUR5 PIN_A1 #define HOUR6 PIN_E2 #define HOUR7 PIN_E1 #define COLON PIN_C1 #define TEN1 PIN_B7 #define TEN2 PIN_B6 #define TEN3 PIN_B0 #define TEN4 PIN_B1 #define TEN5 PIN_B2 #define TEN6 PIN_B4 #define TEN7 PIN_B5 #define MIN1 PIN_D7 #define MIN2 PIN_D6 #define MIN3 PIN_C5 #define MIN4 PIN_C6 #define MIN5 PIN_C7 #define MIN6 PIN_D4 #define MIN7 PIN_D5 #define SETHOUR PIN_D1 #define SETTEN PIN_D3 #define SETMIN PIN_D2 // Each digit is drawn with this set of named segments: // // 111111 // 6 2 // 6 2 // 777777 // 5 3 // 5 3 // 444444 static int8 hours = 12; //times are reprented this way: 11:37 static int8 tens = 0; //hours = 11, tens = 3, minutes = 7 static int8 minutes = 0; #INT_TIMER0 time_keeper() { //this is called every 16.384ms: 2.000MHz, 4 cycles, 256 overflow, 32 pre-scaler // need to count 3662 per minute // setting it to 3662 made the clock get 1+sec ahead per hour, so changed to 3663 static int16 count=0; static int16 correction=0; static int8 flash=0; count++; if (count%61 == 0) //flash the colon between the numbers on and off each second { if (flash==0) { output_high(COLON); flash=1; } else { output_low(COLON); flash=0; } } if (count>=3663) //a minute has gone by { count = 0; minutes++; if(minutes > 9) //going from :19 to :20 { minutes = 0; tens++; if(tens > 5) //going from 3:59 to 4:00 { tens = 0; hours++; if(hours > 12) hours = 1; } } } //Now to correct for the clock running 0.0194% too fast (gained 2 min 13 sec in 7days, 10.5 hours) correction++; if (correction==5157) //Inverse of 0.000194 { count--; correction=0; } } void show_hour(int8 n) { //drawing the figure of the number segment by segment //first, does this hour start with the tens digit? 10,11 or 12 if (n==10) { output_high(TENHOUR); n=0; } else if (n==11) { output_high(TENHOUR); n=1; } else if (n==12) { output_high(TENHOUR); n=2; } else output_low(TENHOUR); if (n==1 || n==4) output_low(HOUR1); else output_high(HOUR1); if (n==5 || n==6) output_low(HOUR2); else output_high(HOUR2); if (n==2) output_low(HOUR3); else output_high(HOUR3); if (n==1 || n==4 || n==7) output_low(HOUR4); else output_high(HOUR4); if (n==1 || n==3 || n==4 || n==5 || n==7 || n==9) output_low(HOUR5); else output_high(HOUR5); if (n==1 || n==2 || n==3 || n==7) output_low(HOUR6); else output_high(HOUR6); if (n==1 || n==7 || n==0) output_low(HOUR7); else output_high(HOUR7); } void show_ten(int8 n) { //drawing the figure of the number segment by segment if (n==1 || n==4) output_low(TEN1); else output_high(TEN1); if (n==5 || n==6) output_low(TEN2); else output_high(TEN2); if (n==2) output_low(TEN3); else output_high(TEN3); if (n==1 || n==4 || n==7) output_low(TEN4); else output_high(TEN4); if (n==1 || n==3 || n==4 || n==5 || n==7 || n==9) output_low(TEN5); else output_high(TEN5); if (n==1 || n==2 || n==3 || n==7) output_low(TEN6); else output_high(TEN6); if (n==1 || n==7 || n==0) output_low(TEN7); else output_high(TEN7); } void show_minute(int8 n) { //drawing the figure of the number segment by segment if (n==1 || n==4) output_low(MIN1); else output_high(MIN1); if (n==5 || n==6) output_low(MIN2); else output_high(MIN2); if (n==2) output_low(MIN3); else output_high(MIN3); if (n==1 || n==4 || n==7) output_low(MIN4); else output_high(MIN4); if (n==1 || n==3 || n==4 || n==5 || n==7 || n==9) output_low(MIN5); else output_high(MIN5); if (n==1 || n==2 || n==3 || n==7) output_low(MIN6); else output_high(MIN6); if (n==1 || n==7 || n==0) output_low(MIN7); else output_high(MIN7); } void alert_low_batt() { //Need to inform user that bettery is low. //Spell out "Lo" on middle digits delay_ms(900); output_low(TENHOUR); output_low(HOUR1); output_low(HOUR2); output_low(HOUR3); output_high(HOUR4); output_high(HOUR5); output_high(HOUR6); output_low(HOUR7); output_low(TEN1); output_low(TEN2); output_high(TEN3); output_high(TEN4); output_high(TEN5); output_low(TEN6); output_high(TEN7); output_low(MIN1); output_low(MIN2); output_low(MIN3); output_low(MIN4); output_low(MIN5); output_low(MIN6); output_low(MIN7); delay_ms(1000); } main() { //long voltage; //long v1, v2, v3; //setup ports set_tris_a(0B00000001); //A0 input (ADC), all others output set_tris_b(0x00); //all pins output set_tris_c(0x00); set_tris_d(0b00001110); //pins D1, D2 & D3 input (clock set) set_tris_e(0x00); //set ADC to read battery level setup_adc(ADC_CLOCK_DIV_32); setup_adc_ports(RA0_ANALOG); set_adc_channel(0); //start timer interrupt enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); setup_timer_0(RTCC_DIV_32|RTCC_INTERNAL); set_timer0(0); while(true) { show_hour(hours); show_ten(tens); show_minute(minutes); delay_ms(100); //check if user is setting time. I decided not to do this in an interrupt because of layout. if (input(SETHOUR)==0) { hours++; if (hours>12) hours=1; show_hour(hours); delay_ms(400); //make sure user can let go of pin in time } else if (input(SETTEN)==0) { tens++; if (tens>5) tens=0; show_ten(tens); delay_ms(400); //make sure user can let go of pin in time } else if (input(SETMIN)==0) { minutes++; if (minutes>9) minutes=0; show_minute(minutes); delay_ms(400); //make sure user can let go of pin in time } //check battery level if (read_adc()<153) //battery power sampled halfway thru resistor bridge { //Battery at 6V shows at 3V, compared to 5V ref, 153 on ADC out of 255 range alert_low_batt(); } /* while (true) //Just in an effort to find what my ADC output range was, { //I ended up making my own voltmeter! That was easy! //Range is 0 - 255 voltage = read_adc(); v1 = voltage % 10; //ones digit voltage = voltage - v1; voltage = voltage/10; v2 = voltage % 10; //tens digit voltage = voltage - v2; voltage = voltage/10; v3 = voltage; //hundreds digit show_hour(v3); show_ten(v2); show_minute(v1); delay_ms(1000); } */ } }