From Tim's website
Revision as of 22:13, 22 February 2010 by Tim (talk | contribs) (New page: == PIC Software - clock.c == <pre> →Device header and CCS compiler directives: #include <16f873.h> #device ICD=TRUE →Incase we use the ICD: #device ADC=8 ...)
PIC Software - clock.c
/* Device header and CCS compiler directives */ #include <16f873.h> #device ICD=TRUE /* Incase we use the ICD */ #device ADC=8 /* Only use the 8 MSBs */ #use delay( clock=4000000 ) /* Set for a 4MHz Clock */ /* Include the code for the LCD display */ #include "lcd.c" /* Define the hardware connections */ const int CLOCK_EN_LINE = PIN_B0; /* Enable device */ const int CLOCK_DATA_PIN = 0; /* Clock Data connected to ADC pin 0 */ const int CLOCK_DATA_LED = PIN_B5; /* LED to show incomming pulses */ const int CLOCK_EROR_LED = PIN_B4; /* LED to show error reading pulses */ const int THRESHOLD = 0x80; enum PULSE_TYPE { PT_ERROR, /* Unidentified pulse */ PT_SHORT, /* 75ms to 175ms pulse */ PT_LONG, /* 175ms to 375ms pulse */ PT_DOUBLE, /* Two short pulses */ PT_START}; /* 375ms to 600ms pulse */ /* Global Variables */ int seconds = 0; /* Functions */ PULSE_TYPE clock_get_pulse(); int clock_get_value( int no_of_pulses ); PULSE_TYPE clock_get_pulse() /* Waits for the next pulse and returns the type of pulse */ /* this can be LONG, SHORT, START, DOUBLE or ERROR as */ /* defined in the enumeration above */ { int pulse_shape; int i; int factor; set_adc_channel( CLOCK_DATA_PIN ); output_low( CLOCK_DATA_LED ); /* Wait for the input to go high */ while( TRUE ) { if( read_adc() > THRESHOLD ) break; } output_high( CLOCK_DATA_LED ); /* Wait for the input to go low */ while( TRUE ) { if( read_adc() < THRESHOLD ) break; } output_low( CLOCK_DATA_LED ); /* Increment the seconds and display */ lcd_command( LCD_DD_ADD_L2 + 7 ); if( ++seconds == 60 ) seconds = 0; lcd_number( seconds ); pulse_shape = 0; factor = 2; /* Record the shape of the pulse */ delay_ms( 70 ); /* after 70ms */ if( read_adc() < THRESHOLD ) { output_low( CLOCK_DATA_LED ); pulse_shape += 1; } else output_high( CLOCK_DATA_LED ); for( i = 0; i < 3; i++ ) { /* After 170, 270 and 370ms */ delay_ms( 100 ); if( read_adc() < THRESHOLD ) { output_low( CLOCK_DATA_LED ); pulse_shape += factor; } else output_high( CLOCK_DATA_LED ); factor *= 2; } /* Wait out the rest of the period */ if( read_adc() > THRESHOLD ) delay_ms( 600 ); switch( pulse_shape ) { case 0: case 2: case 4: case 8: output_low( CLOCK_EROR_LED ); return PT_ERROR; case 1: return PT_SHORT; case 3: case 7: return PT_LONG; case 5: return PT_DOUBLE; case 15: /* Check the low ends after 500ms */ delay_ms( 230 ); /* after 600ms */ if( read_adc() < THRESHOLD ) { output_low( CLOCK_EROR_LED ); return PT_ERROR; } else { output_high( CLOCK_DATA_LED ); output_high( CLOCK_EROR_LED ); return PT_START; } } return PT_ERROR; } int clock_get_value( int no_of_pulses ) /* Collects the given number of pulses and returns the */ /* decimal value where the first pulse is the most MSB. */ /* 255 is returned as an error. */ { PULSE_TYPE pulse; int p; int value = 0; for( p = 0; p < no_of_pulses; p++ ) { pulse = clock_get_pulse(); switch( pulse ) { case PT_SHORT: value *= 2; break; case PT_LONG: value *= 2; value += 1; break; default: return 255; } } return value; } void main() /* This loop Waits for the start pulse and then decodes */ /* the following 51 pulses to get the time and date. */ { int i; int value1; int value2; char please_wait[15] = "Please Wait..."; char day[22] = "SunMonTueWedThuFriSat"; char month[40] = " JanFebMarAprMayJunJulAugSepOctNovDec"; setup_counters( RTCC_INTERNAL, RTCC_DIV_256 ); setup_adc( ADC_CLOCK_INTERNAL ); setup_adc_ports( ALL_ANALOG ); lcd_initialise( LCD_SIZE_SMALL ); /* Enable the rugby clock */ output_low( PIN_B0 ); /* Put up the 'Please Wait...' message */ for( i = 0; i < 14; i++ ) lcd_character( please_wait[i] ); seconds = 0; /* Wait for the start pulse from the clock */ while( clock_get_pulse() != PT_START ); lcd_command( LCD_CLEAR ); seconds = 0; while( TRUE ) { /* Count the number of double pulses and display */ value1 = 0; for( i = 0; i < 8; i++ ) { if( clock_get_pulse() == PT_DOUBLE ) value1--; } for( i = 8; i < 16; i++ ) { if( clock_get_pulse() == PT_DOUBLE ) value1++; } lcd_command( LCD_DD_ADD_L2 + 11 ); lcd_character( '(' ); lcd_character( '+' ); if( value1 < 0 ) { lcd_command( LCD_SHFT_CUR_L ); lcd_character( '-' ); value1 = -value1; } lcd_character( '0' + value1 ); lcd_character( ')' ); /* Get the Year and display */ value1 = clock_get_value( 4 ); value2 = clock_get_value( 4 ); lcd_command( LCD_DD_ADD_L1 + 11 ); lcd_character( '2' ); lcd_character( '0' ); lcd_character( '0' + value1 ); lcd_character( '0' + value2 ); /* Get the Month and display */ value1 = clock_get_value( 1 ); value2 = clock_get_value( 4 ); lcd_command( LCD_DD_ADD_L1 + 7 ); value1 = 10 * value1 + value2; for( i = 0; i < 3; i++ ) lcd_character( month[ 3 * value1 + i ] ); /* Get the Date and display */ value1 = clock_get_value( 2 ); value2 = clock_get_value( 4 ); lcd_command( LCD_DD_ADD_L1 + 4 ); lcd_character( '0' + value1); lcd_character( '0' + value2); /* Get the Day and display */ value1 = clock_get_value( 3 ); lcd_command( LCD_DD_ADD_L1 + 0 ); for( i = 0; i < 3; i++ ) lcd_character( day[ 3 * value1 + i ] ); /* Get the Hour and display */ value1 = clock_get_value( 2 ); value2 = clock_get_value( 4 ); lcd_command( LCD_DD_ADD_L2 + 1 ); lcd_character( '0' + value1 ); lcd_character( '0' + value2 ); lcd_character( ':' ); /* Get the Minutes but wait for zero seconds */ value1 = clock_get_value( 3 ); value2 = clock_get_value( 4 ); /* Wait for the start pulse from the clock */ while( clock_get_pulse() != PT_START ); seconds = 0; /* Display the minutes */ lcd_command( LCD_DD_ADD_L2 + 4 ); lcd_character( '0' + value1 ); lcd_character( '0' + value2 ); } }