PIC Clock Source Hi-Tech
PIC Software - clock.c for Hi-Tech
<source lang="c"> /* This version is written to use the Hi-Tech lite (free) compiler */
- include <htc.h>
- include "lcd.h"
/* Crystal oscillator, no low-voltage programming or watch dog timer */ __CONFIG(FOSC_XT & LVP_OFF & WDTE_OFF);
/* Define the hardware connections */
- define CLOCK_EN_LINE RB0 /* Enable device */
- define CLOCK_DATA_PIN 0 /* Clock Data connected to ADC pin 0 */
- define CLOCK_DATA_LED RB5 /* LED to show incomming pulses */
- define CLOCK_ERROR_LED RB4 /* LED to show error reading pulses */
const int THRESHOLD = 0x80;
enum PULSE_TYPE { PT_ERROR, /* Unidentified pulse */
PT_SHORT, /* 100ms pulse */
PT_LONG, /* 200ms pulse */
PT_FINISH, /* 300ms pulse */
PT_START, /* 500ms pulse */
PT_DOUBLE}; /* Two short pulses */
/* Global Variables */
int seconds = 0;
/* Functions */ enum PULSE_TYPE clock_get_pulse(); int clock_get_value( int no_of_pulses );
int read_adc() {
ADCON0 = 5; while (ADCON0 == 5); return ADRESH;
}
enum 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; enum PULSE_TYPE result; /* Wait for the input to go high */ while( read_adc() <= THRESHOLD ); CLOCK_DATA_LED = 1;
/* Wait for the input to go low */ while( read_adc() >= THRESHOLD ); CLOCK_DATA_LED = 0;
/* Increment the seconds and display */
lcd_command( LCD_DD_ADD_L2 + 7 );
if( ++seconds == 60 )
seconds = 0;
lcd_number( seconds );
pulse_shape = 0; factor = 1;
/* Record the shape of the pulse */
_delay( 60000 ); /* after 60ms */
for( i = 0; i < 5; i++ )
{
if( read_adc() < THRESHOLD )
{
CLOCK_DATA_LED = 0;
pulse_shape += factor;
}
else
CLOCK_DATA_LED = 1;
/* After 160, 260, 360, 460 and 560ms */
_delay( 100000 );
factor = factor << 1; }
/* Wait out some of the period, leaving 200 ms */ _delay( 240000 );
switch( pulse_shape )
{
case 1:
result = PT_SHORT;
break;
case 3:
result = PT_LONG;
break;
case 5:
result = PT_DOUBLE;
break;
case 7:
result = PT_FINISH;
break;
case 31:
CLOCK_ERROR_LED = 1;
result = PT_START;
break;
default:
CLOCK_ERROR_LED = 0;
result = PT_ERROR;
}
return result;
}
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. */
/* Errors are interpreted as zero. */
{
enum PULSE_TYPE pulse;
int p;
int value = 0;
for( p = 0; p < no_of_pulses; p++ )
{
pulse = clock_get_pulse();
switch( pulse )
{
case PT_LONG:
value *= 2;
value += 1;
break;
default:
value *= 2;
break;
}
}
if (value > 9)
{
value = 0;
}
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;
const char please_wait[15] = "Please Wait..."; const char day[25] = "SunMonTueWedThuFriSat???"; const char month[58] = "???JanFebMarAprMayJunJulAugSepOctNovDec??????????????????";
TRISB = 0b00000000; TRISC = 0b00000000;
lcd_initialise( LCD_SIZE_SMALL );
/* Enable the rugby clock */ CLOCK_EN_LINE = 0;
/* Put up the 'Please Wait...' message */
for( i = 0; i < 14; i++ )
lcd_character( please_wait[i] );
seconds = 0;
/* Wait for the current minute to finish */ while( clock_get_pulse() != PT_FINISH ); seconds = 54;
/* Wait for the start pulse from the clock */ while( clock_get_pulse() != PT_START ); lcd_command( LCD_CLEAR ); seconds = 0;
while( 1 )
{
/* 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 current minute to finish */
while( clock_get_pulse() != PT_FINISH );
/* 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>