'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' GPS CLOCK ' Geoff Graham, March 2014 ' ' Demonstration of the Micromite ' This program will get the time from an EM-408 GPS module, add the timezone ' and daylight saving then display on a two line LCD. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Configuration constants TimeZone = 8.0 ' hours from GMT (+ or -) UseDST = 0 ' set to 1 to enable daylight saving for AWST ' global arrays Dim md(12), arg$(20) Data 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 For i = 1 To 12: Read md(i): Next i LCD Init 23, 24, 25, 26, 17, 18 ' setup the LCD for display Open "COM1:4800" As #1 ' open the GPS serial interface ' this is the main program loop, it never exits Do KeepSearching: Do GetGPSRecord ' get a GPS record Loop Until arg$(0) = "GPRMC" ' we only want the RMC record If arg$(2) <> "A" Then ' "A" means valid record LCD 1, C16, "Searching" LCD 2, C16, "For Satellites" GoTo KeepSearching ' go back and keep looking EndIf ' the GPS has the valid time ' first extract the elements of the date/time from the GPS record year = Val(Right$(arg$(9), 2)) ' extract the date month = Val(Mid$(arg$(9), 3, 2)) day = Val(Left$(arg$(9), 2)) hour = Val(Left$(arg$(1), 2)) ' extract the time min = Val(Mid$(arg$(1), 3, 2)) sec = Val(Mid$(arg$(1), 5, 2)) ' convert the time to minutes since midnight 1st Jan 2014 ' then add/subtract the timezone and if required add daylight saving ' this calculation takes just 15mS at 40MHz mins = GetMins(year, month, day, hour, min) mins = mins + TimeZone * 60 ' adjust for the timezone If UseDST Then ' if we observe daylight saving If mins < GetDST(year, 4, 2) Or mins > GetDST(year, 10, 2) Then mins = mins + 60 ' adjust for AWST DST EndIf EndIf ' because we will display the time at the start of the next second ' we have to add 1 second to the current time sec = sec + 1 If sec >= 60 Then sec = 0 : mins = mins + 1 ' finally convert the minutes back into the current date/time Line1$ = GetDate$(mins) Line2$ = GetTime$(mins) ' we now have the date/time for the next second ready for display ' we have to wait for the end of the data stream from the GPS ' then we wait for the start of the next second and only then update the LCD Do : Loop While Timer < 950 ' wait for the data to finish Do : Loop While Input$(200, #1) <> "" ' clear the input buffer Do While Input$(1, #1) <> "$" : Loop ' wait for a new second to start Timer = 0 ' display the date and time for this second LCD 1, C16, Line1$ LCD 2, C16, Line2$ Loop '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' subroutine to get a GPS record into the array arg$() Sub GetGPSRecord Do Do While Input$(1, #1) <> "$" : Loop ' wait for the start For i = 0 To 20 arg$(i) = "" ' clear ready for data Do ' loops until a specific exit x$ = Input$(1, #1) ' get the character If x$ = "," Then Exit Do ' new data item, new field If x$ = "*" Then Exit Sub ' end of record, so return with it arg$(i) = arg$(i) + x$ ' add to the data Loop ' keep going Next i ' increment the field Loop End Sub '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' calculate the minutes since midnight 1st Jan 2014 Function GetMins(yr, mth, day, hr, min) GetMins = (yr - 14) * (365 * 24 * 60) + ((yr - 13) \ 4) * (24 * 60) GetMins = GetMins + (md(mth) * (24 * 60)) GetMins = GetMins + ((day - 1) * (24 * 60)) GetMins = GetMins + (hr * 60) GetMins = GetMins + min If (yr - 16) Mod 4 = 0 And mth > 2 Then GetMins = GetMins + (24 * 60) End Function ' convert minutes back into the time (as a string) Function GetTime$(minutes) Local hr, min, am$ am$ = "AM" hr = (minutes \ 60) Mod 24 If hr > 12 Then am$ = "PM" : hr = hr - 12 If hr = 0 Then hr = 12 min = minutes Mod 60 GetTime$ = Str$(hr) + ":" GetTime$ = GetTime$ + Right$("0" + Str$(min), 2) + ":" GetTime$ = GetTime$ + Right$("0" + Str$(sec), 2) + " " + am$ End Function ' convert minutes back into the date (as a string) Function GetDate$(minutes) Local yr, mth, day, mths$, days$ mths$ = " JanFebMarAprMayJunJulAugSepOctNovDec" days$ = "SunMonTueWedThuFriSat" For yr = 14 To 99 If minutes < GetMins(yr + 1, 1, 1, 0, 0) Then Exit For Next yr For mth = 1 To 12 If minutes < GetMins(yr, mth, 1, 0, 0) Then Exit For Next mth mth = mth - 1 day = ((minutes - GetMins(yr, mth, 1, 0, 0)) \ (24 * 60)) + 1 GetDate$ = Mid$(days$, ((((minutes \ (24 * 60)) + 3) Mod 7) * 3) + 1,3)+" " GetDate$ = GetDate$ + Right$(" " + Str$(day), 2) GetDate$ = GetDate$ + "-" + Mid$(mths$,mth*3,3) + "-" + Str$(yr + 2000) End Function ' get the minutes that DST will start or end in a month Function GetDST(yr, mth, hr) Local d, m m = GetMins(yr, mth, 1, hr, 0) d = ((m \ (24 * 60)) + 3) Mod 7 GetDST = m + (((7 - d) Mod 7) * 24 * 60) End Function