/* for Arduino Mega (has 4 serial ports) using Arduino 1.0 environment read Serial-1 input from picPET (see http://www.leapsecond.com/pic/picpet.htm ) send parsed data out main Serial port CPU: Atmel ATmega1280: http://www.atmel.com/dyn/resources/prod_documents/doc2549.pdf J.Beale Dec.18 2011 */ #define BUFSIZE 400 // how many past readings to store (ATmega1280 has 8k SRAM memory) #define DTOFFSET 128 // enabling signed integers in type BYTE long tck,tckold,dtck; // receive time using ATMega clock time in milliseconds char buf[16]; // can read 15 chars into this buffer (+ null termination) byte inbytes; // how many characters were actually read byte lastsec; // previous integer second value read long lasttime; // previous fractional second read (units of 0.1 microseconds) long startfrac; // very first time stamp we read (units of 0.1 microseconds) long glitch; // how many glitches we've seen long count; // how many timestamps we've seen float dtimeAvg; char abuf[BUFSIZE]; // store this many past readings (-128 ... 127) int abufPtr; // pointer into abuf[] boolean bfill; int boff1, boff2; void setup() { // initialize both serial ports: Serial.begin(19200); Serial1.begin(19200); // 2nd serial port at this rate Serial1.setTimeout(1000); // how long to wait for input, units of milliseconds inbytes = Serial1.readBytesUntil(0x0a,buf,15); // end char,char buffer,max byte count) lastsec = Serial1.parseInt(); // read the integer portion of the seconds startfrac = Serial1.parseInt(); // skip the '.' and read the 0.1 microseconds inbytes = Serial1.readBytesUntil(0x0a,buf,15); // read until end: char,char buffer,max bytes) tckold = millis(); glitch = 0; // we start out glitch free, ok? count = 0; lasttime = startfrac; dtimeAvg = 0; abufPtr = 0; bfill = 0; boff2 = 0; Serial.println("sec,diff,dtimeAvg,dtime,df,glitch"); } void loop() { // read from port 1, send to port 0: int boff; long sec = Serial1.parseInt(); // read the integer portion of the seconds long secfrac = Serial1.parseInt(); // skip the '.' and read the 0.1 microseconds inbytes = Serial1.readBytesUntil(0x0a,buf,15); // end char,char buffer,max byte count) tck = millis(); // milliseconds from ATmega internal clock count++; // total number of lines read dtck = (tck - tckold); tckold = tck; if ((dtck <= 995) || (dtck >= 1005)) // fails the sniff test using crude internal time? {glitch++;} else { if (!((sec==0) && (lastsec==99))) { if (sec != lastsec+1) glitch++; } } lastsec = sec; long dtime = (secfrac - lasttime); // delta between this and last, in 0.1 microseconds) long diff = (secfrac - startfrac); // dtimeAvg = 0.98*dtimeAvg + 0.02*diff; lasttime = secfrac; abuf[abufPtr] = ( (diff) - boff2); abufPtr++; if (abufPtr >= BUFSIZE) { abufPtr = 0; // wraps around bfill = 1; // we've filled the buffer (again) boff1 = boff2; // boff2 is 'current' working offset boff2 = diff; // new offset is current value of diff } sec = sec * 10000000; // now in units of 0.1 microseconds sec = sec + secfrac; float df = 1000.0 * diff / count; // delta-f in units of 1E-10 // if (count%10 == 0) { // print every 10th line if (bfill) { dtimeAvg = 0; for (int j=0;j