PIC Clock Source
PIC Software - clock.c for CCS
<source lang="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 ); }
} </source>