Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
11 years, 4 months ago.
Arduino MSF Atomic Clock code conversion to Mbed
Hello
Can anyone help please?
I'm trying to convert a program that was writen by Lynton Towler for the Arduino.
It works particularly well and would like to use something similar with the Mbed.
I get as far as " byte maxDay(byte year, byte month) { " then hit errors.
Also I do not have a " int main() " at the start of the main code, not sure if its needed in this example.
I believe 'byte' on Arduino is similar to 'int' on Mbed.
Any help will be appreciated.
Thank you
Paul
#include "mbed.h" // #include "OLED32028P1T.h" // modified Mbed OLED160G1 library from Steven Blair, can substitue this with the OLED160 display //#include <LiquidCrystal.h> for Arduino now using OLED32028P1T.h //#include <avr/io.h> for Arduino, not sure if mbed version neded //#include <avr/interrupt.h> for Arduino, not sure if mbed version neded //#include <stdio.h> for Arduino, not sure if mbed version neded // OLED32028P1T oled(p28,p27,p26);// Oled Display tx, rx, rs DigitalIn dcf_in(p21);//conection of output NON inverting dcf module #define msfSignalIn 10 #define signalLED 13 #define BIN2BCD(b) (((b)%10) | (((b)/10)<<4)) /* Binary 2 BCD conversion */ #define BCD2BIN(b) (((b)&0xf) + ((b)>>4)*10) /* BCD 2 Binary conversion */ #define ZERO 1e-10 #define isBetween(A, B, C) (((A-B) > -ZERO) && ((A-C) < ZERO)) struct status { bool last_min_OK; // Last minute received OK counts parity test results bool par_year; // Year parity checks out OK flag bool par_day_month; // Day of Month parity checks out OK flag bool par_dayofweek; // Day of Week parity checks out OK flag bool par_hour_min; // Hour & Min parity checks out OK flag bool sec_started; // Second started flag int second; // MSF second (NOT actually transmitted but calculated) bool is_leap; // Leap year flag (NOT actually transmitted but calculated) bool sample70; // MSF sample at 70mS into the start of the second bool sample170; // MSF sample at 170mS into the start of the second bool sample270; // MSF sample at 270mS into the start of the second bool sample370; // MSF sample at 370mS into the start of the second bool sample650; // MSF sample at 650mS into the start of the second unsigned char frame; // Received MSF framing code 01111110 } msf_status; struct msf { char dut1; // DUT1 (0.1 - 0.8) char dut2; // DUT2 (-0.1 - -0.8) char year; // Year (00 - 99) char month; // Month (01 - 12) char dayofmonth; // Day of month (01 - 31) char dayofweek; // Day of week (Sunday=0 Saturday=6) char hour; // Hour (00 - 23) char minute; // Minute (00 - 59) bool dst_warning; // Daylight Savings Time warning bool dst; // Daylight Savings Time bool parity_year; // Year parity (17 - 24A, odd parity) bool parity_day_month; // Day parity (25 - 35A, odd parity) bool parity_hour_min; // Time parity (39 - 51A, odd parity) bool parity_dayofweek; // Day of week parity (36 - 38A, odd parity) } msf_time; // Global variables int in_sec_counter = 0; int interrupt_counter = 0; int hour = 12; int minute = 0; int second = 0; int dayofweek = 6; int dayofmonth = 1; int month = 1; int year = 0; // Various text strings used in display char weekDayName[7][4] = {"Sun","Mon","Tue","Wed","Thu", "Fri","Sat"}; char monthName[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char lastMinOKSymbol[2][2] = {" ", "*"}; char dstSymbol[2][4] = {" ", "DST"}; char dstWarnSymbol[2][2] = {" ", "+"}; char leapSymbol[2][2] = {" ", "L"}; // Max days in a month for a non-leap year char MAX_DAY[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Return the maximum day in month for a given month & year // *************** error's start here *********** byte maxDay(byte year, byte month) { byte lastday, leap; leap = year%4 == 0 && year%100 !=0 || year%400 == 0; lastday = MAX_DAY[month - 1]; /* condition-test ? first-expression : second-expression * If condition-test is non-zero the first-expression is evaluated, * otherwise the second-expression is evaluated. */ msf_status.is_leap = leap > 0 ? 1 : 0; if ((leap > 0) && (month == 2)) lastday++; return lastday; } int dayOfWeek(int y, int m, int d) { // 0 = Sunday static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; } byte parityCheck(byte n, byte y, byte parity) { unsigned int b; // b accumulates the total bits set in n unsigned int c; // c accumulates the total bits set in y for (b = 0; n; b++) n &= n - 1; // clear the least significant bit set for (c = 0; y; c++) y &= y - 1; // clear the least significant bit set return (b+c+parity & 1); } ISR (TIMER1_COMPA_vect) { OCR1A += 625; // Add 625 (0x271) to comparator for 10mS interrupts interrupt_counter++; digitalWrite(signalLED, digitalRead(msfSignalIn)); if (interrupt_counter == 100) { // 100 = 1000mS = 1 Second interrupt_counter = 0; second++; } if (second >= 60) { ++minute; second -=60; msf_status.last_min_OK = 0; } if (minute >= 60) { ++hour; minute-=60; } if (hour >= 24) { hour -=24; ++dayofweek; ++dayofmonth; } if (dayofweek > 6) dayofweek = 0; if (dayofmonth > maxDay(year, month)) { dayofmonth = 1; month++; } if (month > 12) { month = 1; year++; } if (year > 99) year = 1; if (msf_status.sec_started == 1) { in_sec_counter++; // Increments every 10mS after the start of the second switch (in_sec_counter) { case 7: // 70mS after start of second msf_status.sample70 = digitalRead(msfSignalIn); break; case 17: // 170mS after start of second (1st Level MSF Data) msf_status.sample170 = !digitalRead(msfSignalIn); break; case 27: // 270mS after start of second (2nd Level MSF Data) msf_status.sample270 = !digitalRead(msfSignalIn); break; case 37: // 370mS after start of second msf_status.sample370 = digitalRead(msfSignalIn); break; case 65: // 650mS after start of second msf_status.sample650 = digitalRead(msfSignalIn); if (digitalRead(msfSignalIn)) { if (msf_status.frame == 0x7E) { // Framing code 01111110 msf_status.par_year = parityCheck(msf_time.year, 0, msf_time.parity_year); msf_status.par_day_month = parityCheck(msf_time.dayofmonth, msf_time.month, msf_time.parity_day_month); msf_status.par_dayofweek = parityCheck(msf_time.dayofweek, 0, msf_time.parity_dayofweek); msf_status.par_hour_min = parityCheck(msf_time.hour, msf_time.minute, msf_time.parity_hour_min); // This is just horrible but is needed at least temporarily to check // the validity of the received MSF data. I hope to make it much nicer. int maxday = maxDay(BCD2BIN(msf_time.year), BCD2BIN(msf_time.month)); if ((BCD2BIN(msf_time.minute) < 60) && (BCD2BIN(msf_time.hour) < 24) && (BCD2BIN(msf_time.dayofweek) < 7) && (BCD2BIN(msf_time.dayofmonth) <= maxday) && // Was < maxday (BCD2BIN(msf_time.month) <= 12) && // Was < 12 (BCD2BIN(msf_time.year) < 199) && (msf_status.par_year) && (msf_status.par_day_month) && (msf_status.par_dayofweek) && (msf_status.par_hour_min) && (msf_time.dayofweek == dayOfWeek(2000+BCD2BIN(msf_time.year), BCD2BIN(msf_time.month), BCD2BIN(msf_time.dayofmonth)))) { msf_status.last_min_OK = 1; year = BCD2BIN(msf_time.year); month = BCD2BIN(msf_time.month); dayofmonth = BCD2BIN(msf_time.dayofmonth); dayofweek = BCD2BIN(msf_time.dayofweek); hour = BCD2BIN(msf_time.hour); minute = BCD2BIN(msf_time.minute); second = 0; // Moved to stop seconds resetting on correct framing code (Now needs good parity as well) } msf_status.frame = 0; msf_time.year = msf_time.month = msf_time.dayofmonth = 0; msf_time.dayofweek = msf_time.hour = msf_time.minute = 0; msf_time.dut1 = msf_time.dut2 = 0; msf_status.second = 0; //second = 0; No need for seconds to reset only when framing code is received interrupt_counter = 60; // Make seconds align with MSF } // End if msf_status.frame msf_status.frame = msf_status.frame << 1 | msf_status.sample170; if (isBetween(msf_status.second, 17, 24)) { msf_time.year = msf_time.year << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 25, 29)) { msf_time.month = msf_time.month << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 30, 35)) { msf_time.dayofmonth = msf_time.dayofmonth << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 36, 38)) { msf_time.dayofweek = msf_time.dayofweek << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 39, 44)) { msf_time.hour = msf_time.hour << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 45, 51)) { msf_time.minute = msf_time.minute << 1 | msf_status.sample170; } switch (msf_status.second) { case 53: msf_time.dst_warning = msf_status.sample270; break; case 54: msf_time.parity_year = msf_status.sample270; break; case 55: msf_time.parity_day_month = msf_status.sample270; break; case 56: msf_time.parity_dayofweek = msf_status.sample270; break; case 57: msf_time.parity_hour_min = msf_status.sample270; break; case 58: msf_time.dst = msf_status.sample270; break; } // End (msf_status.second) switch } // End if (msfSignal) msf_status.sec_started = 0; break; // End 650mS after start of second default: break; } // End (in_sec_counter) switch } else { // MSF second not started in_sec_counter = 0; if (!digitalRead(msfSignalIn)) { msf_status.sec_started = 1; msf_status.second++; } // End if !msfSignalIn } // End if (msf_status.sec_started) } // End of ISR } void showClock() { char timeBuff[21]; char dateBuff[21]; /* **************Mbed oled print functions to be written later ************ sprintf(timeBuff, "%02d:%02d:%02d%s %s %s", hour, minute, second, dstWarnSymbol[msf_time.dst_warning], leapSymbol[msf_status.is_leap], dstSymbol[msf_time.dst]); sprintf(dateBuff, "%s %02d/%02d/20%02d %s", weekDayName[dayofweek], dayofmonth, month, year, lastMinOKSymbol[msf_status.last_min_OK]); sprintf(dateBuff, "%s %02d %s '%02d %s", weekDayName[dayofweek], dayofmonth, monthName[month-1], year, lastMinOKSymbol[msf_status.last_min_OK]); lcd.setCursor(0, 0); // top left lcd.print(timeBuff); lcd.setCursor(0, 1); // bottom left lcd.print(dateBuff); */ } void setupTimer10ms() { TIMSK1 = B00000010; // Timer/counter Interrupt Mask Register intrpt on match A TCCR1A = 0; // normal operation no external pins connected TCCR1B = B00000100; // divide by 256 With 16MHz clock gives timer input rate of 62500Hz TCCR1C = 0; OCR1A =0xFFF0; OCR1A=625; TCNT1=0; } void setup() { pinMode(msfSignalIn, INPUT); // MSF signal input pinMode(signalLED, OUTPUT); // MSF signal digitalWrite(msfSignalIn, HIGH); // Turn on pullup resistors setupTimer10ms(); //lcd.begin(16, 2); Mbed Oled to be written later //lcd.clear(); Mbed Oled to be written later } void loop() { showClock(); delay(50); }
2 Answers
11 years, 4 months ago.
You can do a quick fix for the unknown type byte by adding your own typedef somewhere before its first use:
typedef unsigned char byte;
You will also need to add a DigitalIn pin for 'msfSignalIn' and a DigitalOut pin for 'signalLED'
and fix all 'digitalRead(msfSignalIn)' calls and 'signalLED' outputs
and replace 'void setupTimer10ms()' by an mbed ticker that calls 'ISR(TIMER1_COMPA_vect)'
and you probably need to fix more...
and yes, you will need a main()
Note that mbed has a realtime clock onboard that could do most of this timekeeping. There are also libs to deal with DCF timesignal decoding.
11 years, 4 months ago.
Thank's Wim, I have made a few changes that allows the code to compile just to one error.
"expected a declaration" at line 292.
I can't see where, however I think the Ticker code part is wrong, as I have not used this function before I'm not realy sure how to implement this.
I have "REM'd" out some other code I'm not sure of and may not be needed, I can deal with that later.
From what I understand the code must be able to check the MSF signal without interupt and all other functions (updateing display) has be durring other "free" time.
Note sure where to put the "int main()" and if some of the code should be "void"'d out and called when needed.
Again speed is quite important so as not to loose sync with the time signal.
Is "ISR" needed in this program? (again not sure what this function is doing and is there another way using Ticker to deal with this part?)
Again any help will be welcome, I do apologise, my capabilities only extened to manipulating and changing code written by others however I do learn a lot by doing this.
Many thanks
paul
//MSF (uk) Atomic Clock #include "mbed.h" // #include "OLED32028P1T.h" // modified OLED160G1 library from Steven Blair, can substitue this for the OLED160 display // OLED32028P1T oled(p28,p27,p26);// Oled Display tx, rx, rs DigitalIn msfSignalIn(p21);//conection of output NON inverting MSF module DigitalOut signalLED(LED1); Ticker Timer10ms(); #define msfSignalIn 10 #define signalLED 13 #define BIN2BCD(b) (((b)%10) | (((b)/10)<<4)) /* Binary 2 BCD conversion */ #define BCD2BIN(b) (((b)&0xf) + ((b)>>4)*10) /* BCD 2 Binary conversion */ #define ZERO 1e-10 #define isBetween(A, B, C) (((A-B) > -ZERO) && ((A-C) < ZERO)) struct status { bool last_min_OK; // Last minute received OK counts parity test results bool par_year; // Year parity checks out OK flag bool par_day_month; // Day of Month parity checks out OK flag bool par_dayofweek; // Day of Week parity checks out OK flag bool par_hour_min; // Hour & Min parity checks out OK flag bool sec_started; // Second started flag int second; // MSF second (NOT actually transmitted but calculated) bool is_leap; // Leap year flag (NOT actually transmitted but calculated) bool sample70; // MSF sample at 70mS into the start of the second bool sample170; // MSF sample at 170mS into the start of the second bool sample270; // MSF sample at 270mS into the start of the second bool sample370; // MSF sample at 370mS into the start of the second bool sample650; // MSF sample at 650mS into the start of the second unsigned char frame; // Received MSF framing code 01111110 } msf_status; struct msf { char dut1; // DUT1 (0.1 - 0.8) char dut2; // DUT2 (-0.1 - -0.8) char year; // Year (00 - 99) char month; // Month (01 - 12) char dayofmonth; // Day of month (01 - 31) char dayofweek; // Day of week (Sunday=0 Saturday=6) char hour; // Hour (00 - 23) char minute; // Minute (00 - 59) bool dst_warning; // Daylight Savings Time warning bool dst; // Daylight Savings Time bool parity_year; // Year parity (17 - 24A, odd parity) bool parity_day_month; // Day parity (25 - 35A, odd parity) bool parity_hour_min; // Time parity (39 - 51A, odd parity) bool parity_dayofweek; // Day of week parity (36 - 38A, odd parity) } msf_time; // Global variables int in_sec_counter = 0; int interrupt_counter = 0; int hour = 12; int minute = 0; int second = 0; int dayofweek = 6; int dayofmonth = 1; int month = 1; int year = 0; typedef unsigned char byte; // Various text strings used in display char weekDayName[7][4] = {"Sun","Mon","Tue","Wed","Thu", "Fri","Sat"}; char monthName[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char lastMinOKSymbol[2][2] = {" ", "*"}; char dstSymbol[2][4] = {" ", "DST"}; char dstWarnSymbol[2][2] = {" ", "+"}; char leapSymbol[2][2] = {" ", "L"}; // Max days in a month for a non-leap year char MAX_DAY[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Return the maximum day in month for a given month & year byte maxDay(byte year, byte month) { byte lastday, leap; leap = year%4 == 0 && year%100 !=0 || year%400 == 0; lastday = MAX_DAY[month - 1]; /* condition-test ? first-expression : second-expression * If condition-test is non-zero the first-expression is evaluated, * otherwise the second-expression is evaluated. */ msf_status.is_leap = leap > 0 ? 1 : 0; if ((leap > 0) && (month == 2)) lastday++; return lastday; } int dayOfWeek(int y, int m, int d) // 0 = Sunday { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; } byte parityCheck(byte n, byte y, byte parity) { unsigned int b; // b accumulates the total bits set in n unsigned int c; // c accumulates the total bits set in y for (b = 0; n; b++) n &= n - 1; // clear the least significant bit set for (c = 0; y; c++) y &= y - 1; // clear the least significant bit set return (b+c+parity & 1); } int main() { // ISR (TIMER1_COMPA_vect) Timer10ms(); // OCR1A += 625; // Add 625 (0x271) to comparator for 10mS interrupts interrupt_counter++; //digitalWrite(signalLED, digitalRead(msfSignalIn)); if (interrupt_counter == 100) { // 100 = 1000mS = 1 Second interrupt_counter = 0; second++; } if (second >= 60) { ++minute; second -=60; msf_status.last_min_OK = 0; } if (minute >= 60) { ++hour; minute-=60; } if (hour >= 24) { hour -=24; ++dayofweek; ++dayofmonth; } if (dayofweek > 6) dayofweek = 0; if (dayofmonth > maxDay(year, month)) { dayofmonth = 1; month++; } if (month > 12) { month = 1; year++; } if (year > 99) year = 1; if (msf_status.sec_started == 1) { in_sec_counter++; // Increments every 10mS after the start of the second switch (in_sec_counter) { case 7: // 70mS after start of second //msf_status.sample70 = digitalRead(msfSignalIn); msf_status.sample70 = (msfSignalIn); break; case 17: // 170mS after start of second (1st Level MSF Data) //msf_status.sample170 = !digitalRead(msfSignalIn); msf_status.sample170 = msfSignalIn; break; case 27: // 270mS after start of second (2nd Level MSF Data) //msf_status.sample270 = !digitalRead(msfSignalIn); msf_status.sample270 = msfSignalIn; break; case 37: // 370mS after start of second //msf_status.sample370 = digitalRead(msfSignalIn); msf_status.sample370 = msfSignalIn; break; case 65: // 650mS after start of second //msf_status.sample650 = digitalRead(msfSignalIn); msf_status.sample650 = msfSignalIn; //if (digitalRead(msfSignalIn)) { if (msfSignalIn) { if (msf_status.frame == 0x7E) { // Framing code 01111110 msf_status.par_year = parityCheck(msf_time.year, 0, msf_time.parity_year); msf_status.par_day_month = parityCheck(msf_time.dayofmonth, msf_time.month, msf_time.parity_day_month); msf_status.par_dayofweek = parityCheck(msf_time.dayofweek, 0, msf_time.parity_dayofweek); msf_status.par_hour_min = parityCheck(msf_time.hour, msf_time.minute, msf_time.parity_hour_min); // This is just horrible but is needed at least temporarily to check // the validity of the received MSF data. I hope to make it much nicer. int maxday = maxDay(BCD2BIN(msf_time.year), BCD2BIN(msf_time.month)); if ((BCD2BIN(msf_time.minute) < 60) && (BCD2BIN(msf_time.hour) < 24) && (BCD2BIN(msf_time.dayofweek) < 7) && (BCD2BIN(msf_time.dayofmonth) <= maxday) && // Was < maxday (BCD2BIN(msf_time.month) <= 12) && // Was < 12 (BCD2BIN(msf_time.year) < 199) && (msf_status.par_year) && (msf_status.par_day_month) && (msf_status.par_dayofweek) && (msf_status.par_hour_min) && (msf_time.dayofweek == dayOfWeek(2000+BCD2BIN(msf_time.year), BCD2BIN(msf_time.month), BCD2BIN(msf_time.dayofmonth)))) { msf_status.last_min_OK = 1; year = BCD2BIN(msf_time.year); month = BCD2BIN(msf_time.month); dayofmonth = BCD2BIN(msf_time.dayofmonth); dayofweek = BCD2BIN(msf_time.dayofweek); hour = BCD2BIN(msf_time.hour); minute = BCD2BIN(msf_time.minute); second = 0; // Moved to stop seconds resetting on correct framing code (Now needs good parity as well) } msf_status.frame = 0; msf_time.year = msf_time.month = msf_time.dayofmonth = 0; msf_time.dayofweek = msf_time.hour = msf_time.minute = 0; msf_time.dut1 = msf_time.dut2 = 0; msf_status.second = 0; //second = 0; No need for seconds to reset only when framing code is received interrupt_counter = 60; // Make seconds align with MSF } // End if msf_status.frame msf_status.frame = msf_status.frame << 1 | msf_status.sample170; if (isBetween(msf_status.second, 17, 24)) { msf_time.year = msf_time.year << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 25, 29)) { msf_time.month = msf_time.month << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 30, 35)) { msf_time.dayofmonth = msf_time.dayofmonth << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 36, 38)) { msf_time.dayofweek = msf_time.dayofweek << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 39, 44)) { msf_time.hour = msf_time.hour << 1 | msf_status.sample170; } else if (isBetween(msf_status.second, 45, 51)) { msf_time.minute = msf_time.minute << 1 | msf_status.sample170; } switch (msf_status.second) { case 53: msf_time.dst_warning = msf_status.sample270; break; case 54: msf_time.parity_year = msf_status.sample270; break; case 55: msf_time.parity_day_month = msf_status.sample270; break; case 56: msf_time.parity_dayofweek = msf_status.sample270; break; case 57: msf_time.parity_hour_min = msf_status.sample270; break; case 58: msf_time.dst = msf_status.sample270; break; } // End (msf_status.second) switch } // End if (msfSignal) msf_status.sec_started = 0; break; // End 650mS after start of second default: break; } // End (in_sec_counter) switch } else { // MSF second not started in_sec_counter = 0; //if (!digitalRead(msfSignalIn)) { if (msfSignalIn) { msf_status.sec_started = 1; msf_status.second++; } // End if !msfSignalIn } // End if (msf_status.sec_started) } // End of ISR } { // ***************Declaration error here************** void showClock() { char timeBuff[21]; char dateBuff[21]; } // **************Mbed oled print functions to be written later ************ /* oled.printf(timeBuff, "%02d:%02d:%02d%s %s %s", hour, minute, second, dstWarnSymbol[msf_time.dst_warning], leapSymbol[msf_status.is_leap], dstSymbol[msf_time.dst]); sprintf(dateBuff, "%s %02d/%02d/20%02d %s", weekDayName[dayofweek], dayofmonth, month, year, lastMinOKSymbol[msf_status.last_min_OK]); sprintf(dateBuff, "%s %02d %s '%02d %s", weekDayName[dayofweek], dayofmonth, monthName[month-1], year, lastMinOKSymbol[msf_status.last_min_OK]); lcd.setCursor(0, 0); // top left lcd.print(timeBuff); lcd.setCursor(0, 1); // bottom left lcd.print(dateBuff); */ void Timer10ms() { Timer10ms.attach_ms(&Timer10ms, 10); //TIMSK1 = B00000010; // Timer/counter Interrupt Mask Register intrpt on match A //TCCR1A = 0; // normal operation no external pins connected //TCCR1B = B00000100; // divide by 256 With 16MHz clock gives timer input rate of 62500Hz //TCCR1C = 0; //OCR1A =0xFFF0; //OCR1A=625; //TCNT1=0; } void setup() { pinMode(msfSignalIn, INPUT); // MSF signal input pinMode(signalLED, OUTPUT); // MSF signal //digitalWrite(msfSignalIn, HIGH); // Turn on pullup resistors setupTimer10ms(); //lcd.begin(16, 2); Mbed Oled to be written later //lcd.clear();Mbed Oled to be written later } void loop() { showClock(); delay(50); }
I fixed some problems in code below. See comments
//MSF (uk) Atomic Clock #include "mbed.h" // #include "OLED32028P1T.h" // modified OLED160G1 library from Steven Blair, can substitue this for the OLED160 display // OLED32028P1T oled(p28,p27,p26);// Oled Display tx, rx, rs DigitalIn msfSignalIn(p21);//conection of output NON inverting MSF module DigitalOut signalLED(LED1); //declare Ticker as variable Ticker Ticker10ms; //Add serialport Serial pc (USBTX,USBRX); //replaced by mbed pins //#define msfSignalIn 10 //#define signalLED 13 snip //This is the interrupt service routine (ISR) that must be called every 10ms ///int main() void myISR() { // ISR (TIMER1_COMPA_vect) // Timer10ms(); // OCR1A += 625; // Add 625 (0x271) to comparator for 10mS interrupts interrupt_counter++; //digitalWrite(signalLED, digitalRead(msfSignalIn)); // Show msfSignal state on LED signalLED = msfSignalIn; //after 100 calls at 10ms we have 1 second if (interrupt_counter == 100) { // 100 = 1000mS = 1 Second interrupt_counter = 0; second++; } snip //if (!digitalRead(msfSignalIn)) { // if (msfSignalIn) { // Should be inverted if (!msfSignalIn) { msf_status.sec_started = 1; msf_status.second++; } // End if !msfSignalIn } // End if (msf_status.sec_started) } // End of ISR } //This is a dangling bracket //{ // ***************Declaration error here************** void showClock() { char timeBuff[21]; char dateBuff[21]; pc.printf("Time is ...\r\n"); } //Ticker setup should be done as part on main //void Timer10ms() //{ // Timer10ms.attach_ms(&Timer10ms, 10); // //TIMSK1 = B00000010; // Timer/counter Interrupt Mask Register intrpt on match A //TCCR1A = 0; // normal operation no external pins connected //TCCR1B = B00000100; // divide by 256 With 16MHz clock gives timer input rate of 62500Hz //TCCR1C = 0; //OCR1A =0xFFF0; //OCR1A=625; //TCNT1=0; //} //Not needed anymore void setup() { pinMode(msfSignalIn, INPUT); // MSF signal input pinMode(signalLED, OUTPUT); // MSF signal //digitalWrite(msfSignalIn, HIGH); // Turn on pullup resistors setupTimer10ms(); //lcd.begin(16, 2); Mbed Oled to be written later //lcd.clear();Mbed Oled to be written later } void loop() { showClock(); delay(50); } int main() { msfSignalIn.mode(PullUp); // Turn on pullup resistors Ticker10ms.attach_ms(&myISR, 10); //Setup Ticker to call myISR every 10 ms pc.printf("Ready\r\n"); // This endless while will be interrupted by the Ticker every 10ms while (true) { loop(); // Display time } }
Hi Wim. Well done! I have made the changes as you indicated, fixed some of the inverted msfSignalIn (some need to be inverted, some not) and added the Oled display drive code. Works perfectly, exactly as the origonal Arduino version. The clock runs steady with or without the MSF signal and locks the time when a good time frame is received. Many thanks for your help, I will tidy it up and publish it soon.
Kind regards Paul
posted by 07 Jan 2013