Created
May 9, 2024 13:38
-
-
Save pwillard/b782d871ced136b2d34bba424f73edf5 to your computer and use it in GitHub Desktop.
TM1637 TIME using TIMEAPI and MMBASIC on a PICOW
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'============================================================================== | |
' TTTTT M M 1 666 3333 77777 BBBB AAA SSSS | |
' T MM MM 11 6 3 7 B B A A S | |
' T M M M 1 6666 333 7 BBBB AAAAA SSS | |
' T M M M 1 6 6 3 7 .. B B A A S | |
' T M M 111 666 3333 7 .. BBBB A A SSSS | |
'============================================================================== | |
' WIFI EDITION | |
'============================================================================== | |
' Program: Tm1637.Bas | |
' Author: Pete Willard | |
' Version: 1.1 | |
' Target: Picomite Web - relies on the WIFI Capable version of the PICO | |
' Date: 2023/02/07 | |
' Notes: Much Help From Pete Maher for TM1637 code. | |
' Stop Using WEB NTP as it is unreliable | |
' Making calls to a TIME API as a client instead | |
' | |
' Reference: Tm1637 Datasheet In Wonderful Chinglish. | |
' It Kind Of Wants To Be True Spi And Then It Doesn't Feel Like It So Much. | |
' It's Really Just Simpler "Shift Register" Stuff. The Tm1637 Treats These | |
' As Open Collector, Two Pullups Resistors Are Used To Pull The Pins To Vcc. | |
' The Board Has The Following Pins: | |
' Clk, Dio, Gnd And 5v | |
' Pull Dio Low Before Clk Transition To Create A Start Condition | |
' Pull Clk High Before Dio After And 8 Bit Data Transfer To Signal | |
' End Condition | |
' There Are 3 Basic Command Modes: | |
' Display On/Off &H8f/&H80 | |
' Data Write &H40/&H44 | |
' Write To Register &Hc0/&Hc1... | |
' | |
'============================================================================== | |
' MMbasic Clock OPTIONS | |
'-------------- | |
'OPTION SYSTEM SPI GP18,GP19,GP16 | |
'OPTION WIFI SSID, PASSWORD | |
'OPTION SDCARD GP22 | |
' Not really using the sd card yet. | |
'----------------------------- | |
'=====[ Configuration ]======================================================== | |
Option Explicit | |
Option Default None | |
'=====[ Variables ]============================================================ | |
Dim Digittosegment%(15)=(&H3f,&H06,&H5b,&H4f,&H66,&H6d,&H7d,&H07,&H7f,&H6f,&H77,&H7c,&H39,&H47,&H79,&H71) | |
Dim Integer M_Brightness ' 0-15 | |
Dim Integer Displaydata(3)=(0,0,0,0) ' Holds Segment Data For Digits | |
Const False=0 | |
Const True=1 | |
Const Colon=1 | |
Const Nocolon=0 | |
Const Noleadingzeros=1 | |
Const Leadingzeros=0 | |
Const Tm1637_I2c_Comm1 = &H40 | |
Const Tm1637_I2c_Comm2 = &Hc0 | |
Const Tm1637_I2c_Comm3 = &H80 | |
' | |
Dim Mytime$ Length 8 | |
' TIME API Related Variables | |
Dim Integer tmin | |
Dim buff%(512) ' WEB Response Buffer | |
Dim CRLF$ = Chr$(10)+Chr$(13) ' Carriage Return and Linefeed chars | |
Dim TimeZone$ = "America/New_York" 'From KNOWN Timezone List | |
Dim GetRequest$ = "GET /api/timezone/"+TimeZone$+" HTTP/1.1"+CRLF$+CRLF$ | |
Dim ADDRESS$ = "worldtimeapi.org" | |
Dim Integer apiupdate = 0 | |
'=====[ Pins ]================================================================= | |
Dim Integer Dio = 17 ' Gpio 12 | |
Dim Integer Clk = 16 ' Gpio 13 | |
'=====[ Subroutines ]========================================================== | |
Sub Tm1637init(Pinclk As Integer, Pindio As Integer) | |
Dim Integer M_Pinclk,M_Pindio | |
' Copy The Pin Numbers | |
M_Pinclk = Pinclk | |
M_Pindio = Pindio | |
' Set The Pin Direction And Default Value. | |
' Both Pins Are Set As Inputs, Allowing The Pull-Up Resistors To Pull Them Up | |
Pin(M_Pindio)=0 | |
Pin(M_Pinclk)=0 | |
SetPin M_Pindio,Din | |
SetPin M_Pinclk,Din | |
End Sub | |
'============================================= | |
Sub Setbrightness(Brightness As Integer) | |
M_Brightness = Brightness | |
End Sub | |
'============================================= | |
Sub Setsegments(Segments() As Integer) | |
Local Integer K | |
' Write Comm1 | |
Sendstart | |
Writebyte(Tm1637_I2c_Comm1) | |
Sendstop | |
' Write Comm2 + First Digit Address | |
Sendstart | |
Writebyte(Tm1637_I2c_Comm2) | |
' Write The Data Bytes | |
For K=0 To 3 | |
Writebyte(Segments(K)) | |
Next K | |
Sendstop | |
' Write Comm3 + Brightness | |
Sendstart | |
Writebyte(Tm1637_I2c_Comm3 + (M_Brightness And &H0f)) | |
Sendstop | |
End Sub | |
'============================================= | |
Sub Sendstart | |
SetPin M_Pindio, Dout | |
' Bitdelay | |
Pause 0.01 | |
End Sub | |
'============================================= | |
Sub Sendstop | |
SetPin M_Pindio, Dout | |
SetPin M_Pinclk, Din | |
SetPin M_Pindio, Din | |
' Bitdelay | |
Pause 0.01 | |
End Sub | |
'============================================= | |
Sub Writebyte(B As Integer) As Integer | |
Local Integer I,Ack,Odata = B | |
' 8 Data Bits | |
For I=0 To 7 | |
' Clk Low | |
SetPin M_Pinclk,Dout | |
' Set Data Bit | |
If (Odata And 1) Then | |
SetPin M_Pindio,Din | |
Else | |
SetPin M_Pindio,Dout | |
EndIf | |
'Pause 0.01 | |
' Clk High | |
SetPin M_Pinclk, Din | |
Odata = Odata >> 1 | |
Next I | |
'Pause 0.01 | |
' Wait For Acknowledge | |
' Clk To Zero | |
SetPin M_Pinclk, Dout | |
SetPin M_Pindio, Din | |
' Clk To High | |
SetPin M_Pinclk, Din | |
Ack = Pin(M_Pindio) | |
If (Ack = 0) Then | |
SetPin M_Pindio, Dout | |
EndIf | |
SetPin M_Pinclk, Dout | |
Pause 0.01 | |
End Sub | |
'============================================= | |
Function Encodedigit(Digit As Integer) As Integer | |
Encodedigit=Digittosegment%(Digit And &H0f) | |
End Function | |
'============================================= | |
Sub Convertnumber(Dd() As Integer,N As Integer, Nolead As Integer) | |
Local Integer D(2),M | |
M=Abs(N Mod 10000) | |
If N<0 Then M=Abs(N Mod 1000) | |
D(0)=(M - (M Mod 1000)) | |
D(1)=(M - D(0) - (M Mod 100)) | |
D(2)=(M - D(0) - D(1) - (M Mod 10)) | |
Dd(3)=Encodedigit(M - D(0) -D(1)- D(2)) | |
Dd(0)=Encodedigit(D(0)\1000) | |
Dd(1)=Encodedigit(D(1)\100) | |
Dd(2)=Encodedigit(D(2)\10) | |
If Nolead Then | |
If D(0)=0 Then | |
Dd(0)=0 | |
If D(1)=0 Then | |
Dd(1)=0 | |
If D(2)=0 Then | |
Dd(2)=0 | |
EndIf | |
EndIf | |
EndIf | |
If N<0 Then | |
If Dd(2)=0 Then | |
Dd(2)=64 | |
Else | |
If (Dd(1)=0) Then | |
Dd(1)=64 | |
Else | |
Dd(0)=64 | |
EndIf | |
EndIf | |
EndIf | |
Else | |
If N<0 Then Dd(0)= 64 | |
EndIf | |
End Sub | |
'============================================= | |
Sub Converttime(Dd() As Integer,Displaycolon As Integer,Nolead As Integer) As Integer | |
Local Integer I=Val(Left$(Time$,2)) | |
Local Integer M=Val(Mid$(Time$,4,2)) | |
If I > 12 Then | |
I = I -12 | |
EndIf | |
I = (I * 100) + M | |
Convertnumber(Dd(),I,Nolead) | |
If Displaycolon Then Dd(1)=Dd(1) Or &H80 | |
End Sub | |
'============================================ | |
Sub Initialize() | |
'============================================ | |
' do this first... | |
' local N as integer | |
Print "DHCP Address: "; | |
Print MM.Info(ip address) | |
' Stop using WEB NTP until maybe someday it starts behaving the way I expect | |
' it to. | |
call_time_api() | |
End Sub | |
'============================================ | |
Sub call_time_api() | |
'============================================ | |
Local integer dst_offset, raw_offset, utctime, localtime | |
Local string now$ | |
' Use the WIFI connection to get time using WEB CLIENT and a call to | |
' the "worldtimeapi" at https://worldtimeapi.org/ | |
' for a list of TIMEZONES use: | |
' "curl https://worldtimeapi.org/api/timeszone.txt" | |
On error skip 10 | |
WEB OPEN TCP CLIENT Address$,80 | |
WEB TCP CLIENT REQUEST GetRequest$, buff%(),10000 | |
WEB CLOSE TCP CLIENT | |
' Trim header from request result | |
LongString trim buff%(),LInStr(buff%(),"{")-1 | |
' Get JSON Values related UTC UNIXTIME and Local OFFSETS | |
dst_offset = Val(Json$(buff%(),"dst_offset")) ' 1 hour shift or not | |
raw_offset = Val(Json$(buff%(),"raw_offset")) ' seconds adj from UTC | |
utctime = Val(Json$(buff%(),"unixtime")) ' UTC time in unix format | |
localtime = utctime + raw_offset + dst_offset ' Unix Local Time | |
NOW$ = DateTime$(localtime) ' Function to convert UNIX time to date string | |
Time$ = Right$(now$,8) ' extract time | |
Date$ = Left$(now$,10) ' extract date, though we are not using it yet | |
Print "Current Time and Date from API" | |
Print Time$ | |
Print Date$ | |
apiupdate = 1 | |
End Sub | |
'============================================ | |
Sub MYCLOCKSET | |
'============================================ | |
'WEB NTP -4 ' No longer used, too unreliable at the moment | |
End Sub | |
'=====[ Main Code ]============================================================ | |
INITIALIZE() ' Setup - Show IP address and make initial API call for time. | |
Tm1637init(Clk,Dio)' Initialize The Display | |
Setbrightness(15)' Load The Brightness Into The Global Variable | |
Setsegments(Displaydata()) 'Displaydata Is Set To Zeroes So Clear The Display | |
Mytime$=Time$ | |
apiupdate = 0 | |
Pause 500 | |
Do | |
Tmin = Val(Mid$(mytime$, 4, 2)) | |
' Call the API once per hour on the hour (When hour = 0) | |
' Then supress further API calls until it is no longer on the hour | |
' and prepare for future API calls. | |
If tmin = 0 And apiupdate = 0 Then call_time_api() ' sets apiupdate to 1 | |
If tmin <> 0 Then apiupdate = 0 | |
If Mytime$<>Time$ Then 'The Clock Seconds Have Changed | |
If Val(Right$(Time$,1)) Mod 2 Then 'Flash The Colon Each Second | |
'Set The Time Into The Display Array Including The Colon | |
'But No Leading Zeroes | |
Converttime(Displaydata(),Colon,Noleadingzeros) | |
Else | |
Converttime(Displaydata(),Nocolon,Noleadingzeros) | |
'Set The Time Into The Display Array Without The Colon | |
' Or Leading Zeroes | |
EndIf | |
Setsegments(Displaydata()) 'Update The Display | |
Mytime$=Time$ | |
EndIf | |
Pause 500 | |
Loop | |
'============================================================================== | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment