/ RFout1MHzV1_0 / RFout1MHzV1_0.ino
RFout1MHzV1_0.ino
  1  /*Software for Zachtek "GPS Referenced RF generator 1MHz Out V1R2" 
  2  This only programs teh Neo-6 at every start up to output a signal of the desired frequency
  3  It can be set to diffrent freqency and duty cycles for not fixed and fixed.
  4  The standard setting would be no output if no fix (duty cycle =0% is used to turn off the output)
  5  and 1MHz 50% when a fix has been acuired.
  6  
  7  The Version of this software is stored in the constant "softwareversion" and is displayed on the Serialport att startup
  8  Arduino pin A3 is output - Voltage Regulator Enable
  9          pin 2 and 3 is Sofware serial port to GPS module
 10          pin 4 is output  - High when a fix have been acuired. Goes to the IDC connector
 11          pin 5 is output  - Yellow LED indicator, blinking when waiting for fix. 
 12           
 13  For Arduino Pro Mini 8MHz
 14  */
 15  
 16  #include <SoftwareSerial.h>
 17  #include <MicroNMEA.h>
 18  #define LEDIndicator1 5  //LED to indicator for GPS Lock on pin A3
 19  #define FIXOut 4         //Output high at fix
 20  #define LDO_Enable A3    //GPS Voltage regulator Enable on pin A0
 21  SoftwareSerial GPSSerial(2, 3); // RX, TX
 22  const char softwareversion[] = "1.0" ; //Version of this program, sent to serialport at startup
 23  
 24  char NMEAbuffer[500];
 25  int  bufferIndex = 0; 
 26  unsigned long LastCheck, LastConfig;
 27  MicroNMEA nmea(NMEAbuffer, sizeof(NMEAbuffer));
 28  Stream& console = Serial;
 29  boolean GPSOK;
 30  
 31   
 32  void setup() {
 33    GPSSerial.begin(9600);
 34    Serial.begin (57600);
 35    delay(500);//Wait for Serialport to be initialized properly
 36    Serial.print(F("Zachtek GPS referenced RF, Software version: "));
 37    Serial.println(softwareversion);
 38     
 39     Serial.println(F("Initializing.."));
 40     pinMode(LDO_Enable, OUTPUT); // Set Voltage Regulator Enable pin as output.
 41     Serial.println (F("Turning on Voltage Regulator for GPS module"));
 42     digitalWrite(LDO_Enable, HIGH); //Turn on 3.1V Power supply for the Ublox GPS module
 43  
 44     pinMode(LEDIndicator1, OUTPUT); // Set GPS Lock LED pin as output.
 45     pinMode(FIXOut, OUTPUT);        // Set GPS Lock line as output.
 46     digitalWrite(LEDIndicator1, LOW); //Turn off Lock LED 
 47     digitalWrite(FIXOut, LOW);        //Go low on Lock line 
 48     delay(250);//Wait for GPSmodule to complete it's initialization.
 49  
 50   //Send command to GPS that its RF output will be 2MHz at GPS unlock and GPS referenced 2MHz at GPS Lock
 51   if (setGPS_OutputFreq1MHz()) {
 52    GPSOK=true;
 53      Serial.println ("GPS module detected OK"); 
 54      Serial.println ("RF Output programed for 1MHz (Output will be off until the GPS have accuired the correct position)");
 55      Serial.println ("Initialization is complete.");
 56      Serial.println ("");
 57     
 58    }
 59    else
 60    {
 61      Serial.println ("Error! Could not connect to GPS!"); 
 62    GPSOK=false;  
 63    }
 64   LastConfig=millis();
 65  }
 66  
 67  void loop() {
 68   if(GPSSerial.available())
 69   {
 70     char ch = GPSSerial.read();
 71     nmea.process(ch);//send to NMEA parsing routine
 72     if( bufferIndex>499) //
 73     {
 74       NMEAbuffer[ bufferIndex ] = 0; // terminate the string with a 0     
 75       bufferIndex = 0;  // reset the index ready for another string
 76     }
 77     else
 78       NMEAbuffer[ bufferIndex++ ] = ch; // add the character into the buffer
 79   }
 80  
 81  
 82  
 83  //Read the GPS Serial port every second and parse the data to be able detect any loss of signal
 84   if ((millis()-LastCheck) >1000) { 
 85    LastCheck=millis();
 86      if (nmea.isValid()) {
 87        digitalWrite(LEDIndicator1, HIGH);   // turn the LED on 
 88        digitalWrite(FIXOut, HIGH);          // Set Lock Line high  
 89      }
 90      else
 91       {
 92        if (GPSOK) { //If the GPS is connected but not locked then short blink
 93          digitalWrite(LEDIndicator1, HIGH);   // turn the LED on 
 94          digitalWrite(FIXOut, LOW);          // Set Lock Line low  
 95          delay(100); 
 96          digitalWrite(LEDIndicator1, LOW);    // turn the LED off  
 97       }
 98      }
 99    
100    if (GPSOK) {
101      console.print("Valid fix: ");
102      console.println(nmea.isValid() ? "yes" : "no");
103      if (nmea.isValid())
104       {
105        console.print("Nav. system: ");
106        if (nmea.getNavSystem())
107          console.println(nmea.getNavSystem());
108        else
109          console.println("none");
110  
111        console.print("Num. satellites: ");
112        console.println(nmea.getNumSatellites());
113     
114        console.print("UTC: ");
115        console.print(int(nmea.getHour()));
116        console.print(':');
117        console.print(int(nmea.getMinute()));
118        console.print(':');
119        console.println(int(nmea.getSecond()));
120  
121        long latitude_mdeg = nmea.getLatitude();
122        long longitude_mdeg = nmea.getLongitude();
123        console.print("Latitude (deg): ");
124        console.println(latitude_mdeg / 1000000., 6);
125  
126        console.print("Longitude (deg): ");
127        console.println(longitude_mdeg / 1000000., 6);
128  
129        long alt;
130        console.print("Altitude (m): ");
131        if (nmea.getAltitude(alt))
132          console.println(alt / 1000., 3);
133        else
134          console.println("not available");
135        nmea.clear();
136      }
137    }
138   } 
139  }
140  
141  
142  
143  
144  bool setGPS_OutputFreq100kHz()
145  {
146   int gps_set_sucess=0;
147   uint8_t setOutputFreq[] = {
148   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
149   0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
150   0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x20, 0x1B };
151  
152   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
153   gps_set_sucess=getUBX_ACK(setOutputFreq);
154   //Serial.println("Set output Freq Done");
155   return gps_set_sucess;
156  }
157  
158  bool setGPS_OutputFreq1MHz()
159  {
160   int gps_set_sucess=0;
161   uint8_t setOutputFreq[] = {
162   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
163   0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
164   0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x8A, 0x8B };
165  
166   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
167   gps_set_sucess=getUBX_ACK(setOutputFreq);
168   //Serial.println("Set output Freq Done");
169   return gps_set_sucess;
170  }
171  
172  bool setGPS_OutputFreq2MHz()
173  {
174   int gps_set_sucess=0;
175   uint8_t setOutputFreq[] = {
176   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
177   0x00, 0x00, 0x80, 0x84, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
178   0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x1B, 0x7F };
179  
180   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
181   gps_set_sucess=getUBX_ACK(setOutputFreq);
182   //Serial.println("Set output Freq Done");
183   return gps_set_sucess;
184  }
185  
186  
187  bool setGPS_OutputFreq4MHz()
188  {
189   int gps_set_sucess=0;
190   uint8_t setOutputFreq[] = {
191   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
192   0x00, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
193   0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x3F, 0x8C };
194  
195   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
196   gps_set_sucess=getUBX_ACK(setOutputFreq);
197   //Serial.println("Set output Freq Done");
198   return gps_set_sucess;
199  }
200  
201  //8MHz is the highest low-jitter frequency possible
202  bool setGPS_OutputFreq8MHz()
203  {
204   int gps_set_sucess=0;
205   uint8_t setOutputFreq[] = {
206   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
207   0x00, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
208   0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xD4, 0x28 };
209  
210   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
211   gps_set_sucess=getUBX_ACK(setOutputFreq);
212   //Serial.println("Set output Freq Done");
213   return gps_set_sucess;
214  }
215  
216  //10 MHz is very jittery. Frequencies that are an integer division of 48MHz will produce the lowest jitter.
217  //If 10MHz low jitter is needed an option is to output 2MHz and filter out the 5th overtone from it arriving at 10MHz
218  bool setGPS_OutputFreq10MHz()
219  {
220   int gps_set_sucess=0;
221   uint8_t setOutputFreq[] = {
222   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
223   0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
224   0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xF6, 0x10 };
225  
226   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
227   gps_set_sucess=getUBX_ACK(setOutputFreq);
228   //Serial.println("Set output Freq Done");
229   return gps_set_sucess;
230  }
231  
232  //Ublox Neo-6 is not accurate or stable above 10MHz so only use this in experiments. 
233  //This will not produce as clean Square wave.
234  bool setGPS_OutputFreq16MHz()
235  {
236   int gps_set_sucess=0;
237   uint8_t setOutputFreq[] = {
238   0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
239   0x00, 0x00, 0x00, 0x24, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
240   0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x60, 0x12 };
241  
242   sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t));
243   gps_set_sucess=getUBX_ACK(setOutputFreq);
244   //Serial.println("Set output Freq Done");
245   return gps_set_sucess;
246  }
247  
248  void sendUBX(uint8_t *MSG, uint8_t len) {
249   GPSSerial.flush();
250   GPSSerial.write(0xFF);
251   _delay_ms(500);
252   for(int i=0; i<len; i++) {
253   GPSSerial.write(MSG[i]);
254   }
255  }
256  
257  boolean getUBX_ACK(uint8_t *MSG) {
258   uint8_t b;
259   uint8_t ackByteID = 0;
260   uint8_t ackPacket[10];
261   unsigned long startTime = millis();
262   
263  // Construct the expected ACK packet
264   ackPacket[0] = 0xB5; // header
265   ackPacket[1] = 0x62; // header
266   ackPacket[2] = 0x05; // class
267   ackPacket[3] = 0x01; // id
268   ackPacket[4] = 0x02; // length
269   ackPacket[5] = 0x00;
270   ackPacket[6] = MSG[2]; // ACK class
271   ackPacket[7] = MSG[3]; // ACK id
272   ackPacket[8] = 0; // CK_A
273   ackPacket[9] = 0; // CK_B
274   
275  // Calculate the checksums
276   for (uint8_t ubxi=2; ubxi<8; ubxi++) {
277   ackPacket[8] = ackPacket[8] + ackPacket[ubxi];
278   ackPacket[9] = ackPacket[9] + ackPacket[8];
279   }
280   
281    while (1) {  // Test for success
282      if (ackByteID > 9) {
283        // All packets in order!
284        return true;
285      }
286   
287    // Timeout if no valid response in 3 seconds
288    if (millis() - startTime > 3000) {
289      return false;
290    }
291   
292    // Make sure data is available to read
293    if (GPSSerial.available()) {
294      b = GPSSerial.read();
295      // Check that bytes arrive in sequence as per expected ACK packet
296      if (b == ackPacket[ackByteID]) {
297        ackByteID++;
298      }
299      else {
300        ackByteID = 0; // Reset and look again, invalid order
301      }//else
302    }//If
303   }//While
304  }//getUBX_ACK
305  
306  
307