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>