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.

Accepted Answer
Paul Staron
poster
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 

  }

}

posted by Wim Huiskamp 23 Dec 2012

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 Paul Staron 07 Jan 2013