Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save pwillard/b782d871ced136b2d34bba424f73edf5 to your computer and use it in GitHub Desktop.
Save pwillard/b782d871ced136b2d34bba424f73edf5 to your computer and use it in GitHub Desktop.
TM1637 TIME using TIMEAPI and MMBASIC on a PICOW
'==============================================================================
' 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