Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:340305453f64, committed 2022-01-07
- Comitter:
- dswood
- Date:
- Fri Jan 07 12:12:25 2022 +0000
- Commit message:
- A simple library to decode MSF time signal. Probably useful for DSF
Changed in this revision
| MSF_Time.cpp | Show annotated file Show diff for this revision Revisions of this file |
| MSF_Time.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MSF_Time.cpp Fri Jan 07 12:12:25 2022 +0000
@@ -0,0 +1,746 @@
+/*This library will decode an MSF signal on a digital input pin and turn it
+into a timestamp.
+Copyright (C) 2017 Duncan Wood
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+
+
+
+#ifndef MSF_Time_h
+#define MSF_Time_h
+
+#include "mbed.h"
+#include "MSF_Time.h"
+
+MSF_Time::MSF_Time(PinName InputPin, int polarity, int OffsetTuning)
+ : Time_Data(InputPin), Polarity(polarity), OffsetTuning(OffsetTuning),
+ MyInput(InputPin)
+{
+ DataValid=false;
+ Time_Data_Count=0;
+ Time_Data_Duration=0x0000;
+ Time_Data.fall(this, &MSF_Time::Falling);
+ Time_Data.rise(this, &MSF_Time::Rising);
+ Received_timestamp=0; //set time to zero until we can set it properly
+ MyData.BCDMonth=0;
+ MyData.BCDTime=0;
+ MyData.BCDYear=0;
+ MyData.SyncByte=0;
+ MyData.DayOfWeek=0;
+ MyData.BST=0;
+ MyData.DUT=0;
+
+}
+
+void MSF_Time::Rising()
+{
+ if (Polarity==0) {
+ LogicOne();
+ } else {
+ LogicZero();
+ }
+
+
+}
+void MSF_Time::LogicOne() //When there is no carrier (pulse every second)
+{
+ Time_Data_timer.reset();
+ Time_Data_timer.start();
+}
+void MSF_Time::LogicZero() // When carrier is present (most of the time)
+{
+ Time_Data_timer.stop();
+ Time_Data_Duration=Time_Data_timer.read_us();
+ // Test for the 500ms minute sync pulse
+ if (Time_Data_Duration > 450000 && Time_Data_Duration < 550000 ) { // +/-50ms for now
+ Received_Time.tm_sec=0; //set time to zero until we can set it properly
+ Time_Data_Count=0;
+ MyData.BCDMonth=0;
+ MyData.BCDTime=0;
+ MyData.BCDYear=0;
+ MyData.SyncByte=0;
+ MyData.DayOfWeek=0;
+ Time_Data_Sync=true;
+ Time_Data_Ticker.attach(this, &MSF_Time::Time_Data_Strobe,0.05); // start a timer to read data
+ }
+}
+void MSF_Time::Falling()
+{
+ if (Polarity==0) {
+ LogicZero();
+ } else {
+ LogicOne();
+ }
+
+}
+
+void MSF_Time::IncrementSeconds()
+{
+ // called 50ms ish before the second. Add delay of 50ms ish.
+ offset.attach_us(this, &MSF_Time::IncrementSecondsNow,OffsetTuning);
+}
+void MSF_Time::IncrementSecondsNow()
+{
+ Received_timestamp++;
+ if (DV) { //this is the signal to set time now at 00 seconds
+ DV=false;
+ Received_Time.tm_sec=0;
+ Received_timestamp=mktime(&Received_Time);
+ if (Received_timestamp != -1 ) {//0x80000001
+ DataValid=true;
+ }
+ }
+}
+
+
+void MSF_Time::Time_Data_Strobe()
+{
+ Time_Data_Count++;
+ switch(Time_Data_Count) {
+ case 1:
+ break;
+ case 9: //zero seconds
+ IncrementSeconds();
+ break;
+ //case 13://01A
+ //case 15://01B DUT1+
+ //break;
+ case 29:// Incerment seconds
+ IncrementSeconds();
+ break;
+ //case 33://02A
+ //case 35://02B DUT1+
+ //break;
+ case 49:
+ IncrementSeconds();
+ break;
+ //case 53://03A
+ //case 55://03B DUT1+
+ //break;
+ case 69:
+ IncrementSeconds();
+ break;
+ //case 73://04A
+ //case 75://04B DUT1+
+ case 89:
+ IncrementSeconds();
+ break;
+ //case 93://05A
+ //case 95://05B DUT1+
+ case 109:
+ IncrementSeconds();
+ break;
+ //case 113://06A
+ //case 115://06B DUT1+
+ case 129:
+ IncrementSeconds();
+ break;
+ //case 133://07A
+ //case 135://07B DUT1+
+ case 149:
+ IncrementSeconds();
+ break;
+ //case 153://08A
+ //case 155://08B DUT1+
+ case 169:
+ IncrementSeconds();
+ break;
+ //case 173://09A
+ //case 175://09B DUT1-
+ case 189:
+ IncrementSeconds();
+ break;
+ //case 193://10A
+ //case 195://10B DUT1-
+ case 209:
+ IncrementSeconds();
+ break;
+ //case 213://11A
+ //case 215://11B DUT1-
+ case 229:
+ IncrementSeconds();
+ break;
+ //case 233://12A
+ //case 235://12B DUT1-
+ case 249:
+ IncrementSeconds();
+ break;
+ //case 253://13A
+ //case 255://13B DUT1-
+ case 269:
+ IncrementSeconds();
+ break;
+ //case 273://14A
+ //case 275://14B DUT1-
+ case 289:
+ IncrementSeconds();
+ break;
+ //case 293://15A
+ //case 295://15B DUT1-
+ case 309:
+ IncrementSeconds();
+ break;
+ case 313://16A
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ //leap second
+ break;
+ //case 315://16B DUT1-
+ case 329:
+ IncrementSeconds();
+ break;
+ case 333://17A Year 80
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+
+ break;
+ //case 335://17B
+ case 349:
+ IncrementSeconds();
+ break;
+ case 353://18A Year 40
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 355://18B
+ case 369:
+ IncrementSeconds();
+ break;
+ case 373://19A Year 20
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 375://19B
+ case 389:
+ IncrementSeconds();
+ break;
+ case 393://20A Year 10
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 395://20B
+ case 409:
+ IncrementSeconds();
+ break;
+ case 413://21A Year 8
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 415://21B
+ case 429:
+ IncrementSeconds();
+ break;
+ case 433://22A Year 4
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 435://22B
+ case 449:
+ IncrementSeconds();
+ break;
+ case 453://23A Year 2
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ //case 455://23B
+ case 469:
+ IncrementSeconds();
+ break;
+ case 473://24A Year 1
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ MyData.BCDMonth+= MyInput.read()^Polarity;; //leap second minus
+
+ break;
+ //case 475://24B
+
+ case 489:
+ IncrementSeconds();
+ break;
+ case 493://25A Month 10
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity; //leap second
+ break;
+
+ //case 495://25B
+
+ case 509:
+ IncrementSeconds();
+ break;
+ case 513://26A Month 8
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 515://26B
+ case 529:
+ IncrementSeconds();
+ break;
+ case 533://27A Month 4
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 535://27B
+ case 549:
+ IncrementSeconds();
+ break;
+ case 553://28A Month 2
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 555://28B
+ case 569:
+ IncrementSeconds();
+ break;
+ case 573://29A Month 1
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 575://29B
+ case 589:
+ IncrementSeconds();
+ break;
+ case 593://30A Day of Month 20
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 595://30B
+ case 609:
+ IncrementSeconds();
+ break;
+ case 613://31A Day of Month 10
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 615://31B
+ case 629:
+ IncrementSeconds();
+ break;
+ case 633://32A Day of Month 8
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 635://32B
+ case 649:
+ IncrementSeconds();
+ break;
+ case 653://33A Day of Month 4
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 655://33B
+ case 669:
+ IncrementSeconds();
+ break;
+ case 673://34A Day of Month 2
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ //case 675://34B
+ case 689:
+ IncrementSeconds();
+ break;
+ case 693://35A Day of Month 1
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+
+ break;
+ //case 695://35B
+
+ case 709:
+ IncrementSeconds();
+ break;
+ case 713://36A Day of Week 4
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ // case 715://36B
+
+ case 729:
+ IncrementSeconds();
+ break;
+ case 733://37A Day of Week 2
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+ break;
+ //case 735://37B
+ case 749:
+ IncrementSeconds();
+ break;
+ case 753://38A Day of Week 1
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+ MyData.BCDTime+= MyInput.read()^Polarity; //leap second
+
+ break;
+ //case 755://38B
+
+ case 769:
+ IncrementSeconds();
+ break;
+ case 773://39A Hour 20
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity; //leap second
+ break;
+
+ //case 775://39B
+
+ case 789:
+ IncrementSeconds();
+ break;
+ case 793://40A Hour 10
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 795://40B
+ case 809:
+ IncrementSeconds();
+ break;
+ case 813://41A Hour 8
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 815://41B
+ case 829:
+ IncrementSeconds();
+ break;
+ case 833://42A Hour 4
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 835://42B
+ case 849:
+ IncrementSeconds();
+ break;
+ case 853://43A Hour 2
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 855://43B
+ case 869:
+ IncrementSeconds();
+ break;
+ case 873://44A Hour 1
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 875://44B
+ case 889:
+ IncrementSeconds();
+ break;
+ case 893://45A Minute 40
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 895://45B
+ case 909:
+ IncrementSeconds();
+ break;
+ case 913://46A Minute 20
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 915://46B
+ case 929:
+ IncrementSeconds();
+ break;
+ case 933://47A Minute 10
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 935://47B
+ case 949:
+ IncrementSeconds();
+ break;
+ case 953://48A Minute 8
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 955://48B
+ case 969:
+ IncrementSeconds();
+ break;
+ case 973://49A Minute 4
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 975://49B
+ case 989:
+ IncrementSeconds();
+ break;
+ case 993://50A Minute 2
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ //case 995://50B
+
+ case 1009:
+ IncrementSeconds();
+ break;
+ case 1013://51A Minute 1
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ MyData.SyncByte+= MyInput.read()^Polarity; // Or is it a leap second
+
+ break;
+ //case 1015://51B
+
+ case 1029:
+ IncrementSeconds();
+ break;
+ case 1033://52A set to 0
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity; //leap second
+ break;
+ //case 1035://52B
+ case 1049:
+ IncrementSeconds();
+ break;
+ case 1053://53A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ break;
+ case 1055://53B Change of summertime soon
+ // Fortunately leap seconds are never added in spring or autumn
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ break;
+ case 1069:
+ IncrementSeconds();
+ break;
+
+
+ case 1073://54A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ break;
+ case 1075://54B Year Parity
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ break;
+ case 1089:
+ IncrementSeconds();
+ break;
+
+ case 1093://55A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ break;
+ case 1095://55B Month Parity
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ MyData.BCDYear=MyData.BCDYear << 1;
+ MyData.BCDYear+= MyInput.read()^Polarity;
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+ break;
+ case 1109:
+ IncrementSeconds();
+ break;
+ case 1113://56A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ break;
+ case 1115://56B day of Week Parity
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+ MyData.BCDMonth=MyData.BCDMonth << 1;
+ MyData.BCDMonth+= MyInput.read()^Polarity;
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ break;
+ case 1129:
+ IncrementSeconds();
+ break;
+ case 1133://57A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+ break;
+ case 1135://57B Time - hour minute parity
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ MyData.DayOfWeek=MyData.DayOfWeek <<1;
+ MyData.DayOfWeek+= MyInput.read()^Polarity;
+ break;
+ case 1149:
+ IncrementSeconds();
+ break;
+ case 1153://58A set to 1
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+
+
+ break;
+ case 1155://58B British Summertime
+ MyData.BCDTime=MyData.BCDTime << 1;
+ MyData.BCDTime+= MyInput.read()^Polarity;
+ MyData.BST=MyInput.read()^Polarity;
+
+ break;
+ case 1169:
+ IncrementSeconds();
+ ProcessData();// if success count will be stopped but increment will still happen
+ break;
+ case 1173://59A set to 0
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity;
+ break;
+ // case 1175://59B
+ case 1189:
+ IncrementSeconds();
+ ProcessData();
+ break;
+ case 1193://60A
+ MyData.SyncByte=MyData.SyncByte <<1;
+ MyData.SyncByte+= MyInput.read()^Polarity; //
+ break;
+ // case 1195://60B
+ case 1209:
+ IncrementSeconds();
+ ProcessData();
+ // End stop
+ // On a leap second we should count extra but not dealing with it
+ // so for one minute time will be out by a second.
+ Time_Data_Ticker.detach();
+ Time_Data_Count=0; // Should stop this being called more than once
+ DataValid=false; //no data received
+
+ }
+}
+
+int MSF_Time::ParityCheck(unsigned int CheckMe) //0=even 1= odd naturally
+{
+// My parity is going to check 16 bit feel free to add more
+// Stolen shamelessly from internet
+//x ^= x >> 16;
+//x ^= x >> 8;
+//x ^= x >> 4;
+//x ^= x >> 2;
+//x ^= x >> 1;
+//return (~x) & 1;
+ CheckMe^=CheckMe>>8;
+ CheckMe^=CheckMe>>4;
+ CheckMe^=CheckMe>>2;
+ CheckMe^=CheckMe>>1;
+ CheckMe&=1;// 1=odd 0=even
+
+ return CheckMe;
+}
+
+void MSF_Time::ProcessData()
+{
+ DV=false;
+ int shift=0; // by how much to shift just to leave data
+
+
+ // Find sync
+ // sync data is 01111110
+ if ((MyData.SyncByte&0x0FF) == 0x07E) { // sync byte
+
+ /* There are 3 processdata calls. The ticker will be either
+ 1155 or 1173 or 1193. If it is on time or late, extra data will
+ have been collected. We shall get rid.*/
+ } else {
+ if (Time_Data_Count==1193) {
+ //pc.printf("last chance of sync failed - data not valid");
+ DataValid=false;
+ }
+ return;
+ }
+
+ if (Time_Data_Count==1169) { //leap second early
+ shift=2;
+
+ }
+ if (Time_Data_Count==1189) {
+ shift=1;
+
+ }
+ if (Time_Data_Count==1209) {
+ shift=0;
+ }
+ Time_Data_Ticker.detach();
+ Time_Data_Count=0; // Should stop this being called more than once
+ MyData.BCDYear>>=shift;
+ MyData.BCDMonth>>=shift;
+ MyData.DayOfWeek>>=shift;
+ MyData.BCDTime>>=shift;
+ MyData.BCDYear&=0x7F9 ; //8 bits +2 rubbish + parity
+ MyData.BCDMonth&=0x3FF9; // 11 bits +2 rubbish + parity
+ MyData.DayOfWeek&=0x039 ; //3 bits +2 rubbish + parity
+ MyData.BCDTime&=0xFFF9; // 13bits +2 rubbish + parity
+
+ if (ParityCheck(MyData.BCDYear) &&
+ ParityCheck(MyData.BCDMonth) &&
+ ParityCheck(MyData.DayOfWeek) &&
+ ParityCheck(MyData.BCDTime) ) {
+ // Parity ok - remove parity bits
+ MyData.BCDYear>>=3;
+ MyData.BCDMonth>>=3;
+ MyData.DayOfWeek>>=3;
+ MyData.BCDTime>>=3;
+ DV=true;
+ } else {
+ DataValid=false; //sync but parity fail
+ return;
+ }
+
+ //Convert BCD to binary
+ // pc.printf("Year Month DOW Time\n\r");
+//pc.printf("%x %x %x %x\n\r",MyData.BCDYear,MyData.BCDMonth,MyData.DayOfWeek,MyData.BCDTime);
+ if (DV) {
+ Received_Time.tm_year=100+(MyData.BCDYear & 0x0F)+(10*((MyData.BCDYear>>4) & 0x01)) ; //years _since_ 1900
+ Received_Time.tm_mon=((MyData.BCDMonth>>6) & 0x0F)+(10*((MyData.BCDMonth>>10) & 0x01))-1;
+ Received_Time.tm_mday=(MyData.BCDMonth & 0x0F)+(10*((MyData.BCDMonth>>4) & 0x03)) ;
+ Received_Time.tm_hour=((MyData.BCDTime>>7)& 0x0F)+(10*((MyData.BCDTime>>11) & 0x03));
+ Received_Time.tm_min=(MyData.BCDTime&0x0F)+(10*((MyData.BCDTime>>4) & 0x07));
+ Received_Time.tm_wday = (MyData.DayOfWeek&0x07);
+ Received_Time.tm_sec=0;
+ }
+}
+bool MSF_Time::Valid()
+{
+ //if (DataValid) pc.printf("Data Valid\n\r");
+
+ return DataValid;
+}
+time_t MSF_Time::Read()
+{
+ // pc.printf("Received ts %s\n\r",ctime(&Received_timestamp));
+ return Received_timestamp;
+}
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MSF_Time.h Fri Jan 07 12:12:25 2022 +0000
@@ -0,0 +1,75 @@
+/*This library will decode an MSF signal on a digital input pin and turn it
+into a timestamp.
+Copyright (C) 2017 Duncan Wood
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+
+#include "mbed.h"
+class MSF_Time
+{
+public:
+/* Start MSF_Time with this function
+InputPin is the data coming from your reciever
+ Polarity is 0 if your receiver output is high for no carrier
+ polarity is 1 to invert this logic. */
+
+
+MSF_Time(PinName InputPin, int polarity,int OffsetTuning =48000);
+
+bool Valid(); // Is the time valid
+time_t Read();
+
+protected:
+struct MSF_Data {
+ int BCDYear;
+ int BCDMonth;
+ int DayOfWeek;
+ int BCDTime;
+ int SyncByte; //This is sent and allows you to detect leap seconds
+ int DUT;
+ int BST;
+};
+
+struct MSF_Data MyData;
+struct tm Received_Time; // Normal data coming in
+time_t Received_timestamp; //Data converted to timestamp
+unsigned int Time_Data_Duration; //Pulse length - The minute marker is 500ms
+bool Time_Data_Sync; // True when a 500ms pulse is detected denoting the start of a minute
+Ticker Time_Data_Ticker; // A 50ms clock used to clock in data
+unsigned int Time_Data_Count;// counts the 50ms for clocking in the data
+void Time_Data_Strobe(); // When the ticker ticks do this
+void Falling();
+void Rising();
+bool DataValid;
+Timeout offset; // used to fine tune the seconds 50ms equals zero offset
+InterruptIn Time_Data;
+DigitalIn MyInput;
+int Polarity;
+int OffsetTuning;
+Timer Time_Data_timer;
+void LogicOne();
+void LogicZero();
+int ParityCheck(unsigned int CheckMe);
+void ProcessData();
+void IncrementSeconds();
+void IncrementSecondsNow();
+//int const OffsetTuning=48000; //in microseconds
+bool debug; //turn on off debugging noise
+bool DV;
+
+};
\ No newline at end of file