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>