///////////////////////////////////////////////////////////////////////// //// GPS Disciplined OscillatorRef10Mhz.C //// //// V2p //// //// PLL lock detection based on EFC //// ///////////////////////////////////////////////////////////////////////// #include <16F88.h> #device adc=16 #FUSES NOWDT //No Watch Dog Timer #FUSES HS //Crystal osc >= 4mhz #FUSES NOPUT //No Power Up Timer #FUSES NOMCLR //Master Clear pin used for I/O #FUSES NOBROWNOUT //No brownout reset #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NOCPD //No EE protection #FUSES NOWRT //Program memory not write protected #FUSES NODEBUG //No Debug mode for ICD #FUSES NOPROTECT //Code not protected from reading #FUSES NOFCMEN //Fail-safe clock monitor disabled #FUSES NOIESO //Internal External Switch Over mode disabled #use delay(clock=10000000) #define PIN_AUX4 PIN_A0 // AUX I/O no.4 #define PIN_AUX3 PIN_A1 // AUX I/O no.3 #define PIN_AUX1 PIN_A2 // AUX I/O no.1 #define PIN_LOCK_LED PIN_A4 // (LED5) PLL LOCK status LED #define PIN_SATS_LED PIN_A3 // (LED4) SATS IN USE status LED #define PIN_AUX2 PIN_A5 // AUX I/O no.2 ** input only ** #define PIN_ACQ_LED PIN_B0 // (LED3) GPS AQUIRING LED #define PIN_OVEN_LED PIN_B1 // (LED2) OCXO OVEN status LED #define PIN_RX PIN_B2 // SERIAL data in #define PIN_POWER_LED PIN_B3 // (LED1) POWER ON status LED #define PIN_OVEN PIN_B4 // OVEN TEMP STATUS from OCXO #define PIN_TX PIN_B5 // SERIAL data out #define PIN_OCV PIN_B6 // Declared here but "sAN5" used in code //#define PIN_B7 PIN_B7 // UNUSED #use rs232(baud=4800,parity=N,xmit=PIN_TX,rcv=PIN_RX,bits=8) // Constants #define EFC_thr 16 // EFC stability counter thresold (max 254) // Variables int i; // General purpose int OVEN_old=0; // Oven status register int OVEN_new=0; // New oven status int SATS_old=0; // Number of satellites in use register int SATS_new=0; // New numer of satellites in use int REF_lock_old=0; // Reference lock status register int REF_lock_new=0; // New reference lock status int EFC_osc=0; // EFC value oscillation counter int EFC_rep=0; // EFC value repeated counter int16 EFC_1=0; // EFC value 1 register int16 EFC_2=0; // EFC value 2 register int16 EFC_new=0; // New OCV value // Functions void NewLine(){ printf("\r\n"); } void CheckSATS() { char CH=0x00; // NMEA data char // We look for $GPGGA (simplified to xxxxG). If fifth character is not "G", // we discard this sentence and study the next one. // ( At 4800bps, NMEA shows a bit time of 208.33uS ) while (CH!='G') { // Wait for current NMEA sentence to finish setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); set_rtcc(0); while (get_rtcc()<90) // 0,4uS*128 / Count if (!input(PIN_RX)) set_rtcc(0); // Prepare UART to start receiving the next NMEA sentence setup_uart(false); // Turn UART off and on to discard overrun errors setup_uart(true); if (kbhit()) // Empty the two-char buffer CH=getc(); if (kbhit()) // Get the 5th char CH=getc(); // get 1st character, which is "$" CH=getc(); // get 2nd & discard 1st CH=getc(); // get 3rd & discard 2nd CH=getc(); // get 4th & discard 3rd CH=getc(); // get 5th & discard 4th }; // Skip 6 commas and stay in the 6th one i=0; while (i<6) { CH=getc(); if (CH==',') i++; }; // Parse number of sats in use CH=getc(); if (CH=='1') { // Check for 2D or 3D fix CH=getc(); // Skip the comma CH=getc(); // Get the tens in number of sats if (CH=='0'){ CH=getc(); // 9 or less sats in use, get the number SATS_new=CH-'0'; // Convert the char to number } else { CH=getc(); // More than 9 sats in use, get the number SATS_new=CH-'0'; // Conver the char to number SATS_new=SATS_new+10;// Add 10 to the units } } else SATS_new=0; // No fix, zero sats in use // Update SATS and send the new number via RS232 if changed if (SATS_new!=SATS_old) if (SATS_new==0){ printf("$GPS,nofix"); NewLine(); } else if (SATS_old==0){ printf("$GPS,fix"); NewLine(); }; SATS_old=SATS_new; // Blink the satellites LED if (SATS_new==0){ // No sats, long blink output_high(PIN_ACQ_LED); delay_ms(250); output_low(PIN_ACQ_LED); } else for (i=0;i=EFC_thr) REF_lock_new=1; else REF_lock_new=0; if (REF_lock_new!=REF_lock_old) if (REF_lock_new){ output_high(PIN_LOCK_LED); printf("$REF,lock"); NewLine(); } else{ output_low(PIN_LOCK_LED); printf("$REF,unlock"); NewLine(); }; REF_lock_old=REF_lock_new; } void StrobeLeds(){ output_high(PIN_B3); delay_ms(50); // LED1 output_high(PIN_B1); delay_ms(50); // LED2 output_high(PIN_B0); delay_ms(50); // LED3 output_high(PIN_A3); delay_ms(50); // LED4 output_high(PIN_A4); delay_ms(50); // LED5 output_low(PIN_B3); delay_ms(50); // LED1 output_low(PIN_B1); delay_ms(50); // LED2 output_low(PIN_B0); delay_ms(50); // LED3 output_low(PIN_A3); delay_ms(50); // LED4 output_low(PIN_A4); delay_ms(50); // LED5 delay_ms(500); } void main() { // Wizard Generated Code setup_adc_ports(sAN5|VSS_VDD); setup_adc(ADC_CLOCK_DIV_32); set_adc_channel(5); setup_spi(SPI_SS_DISABLED); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); //User Code printf("EB4EQA GPSDO v2.0"); NewLine(); StrobeLeds(); output_high(PIN_POWER_LED); while (TRUE) { CheckOVEN(); CheckSATS(); CheckEFC(); CheckLOCK(); }; }