This is a simple little routine to demonstrate the use of GUI gauges for the hands of the clock.
I tried to implement some other GUI functions but unfortunately, because the gauge does an 'undraw' when it updates, to get the clock hands to sit on top of each other, it is necessary to do a double refesh which causes flicker on the other controls.
There are ten example clock faces. Some use jpg files (hopefully attached below, which need to be loaded into the root folder) and the others are drawn old-school.
I've included an annoying routine to cycle through each example every 15 seconds. Just knock out the TIMER1 line to stop it.
It is primarily aimed as being a demo of setting gauge angles (annex uses radians, not degrees) but, some fairly sweet clock faces as well.
They were created in the open source graphics package GIMP. Not for the faint hearted but a very powerful graphics package. Check it out.
Edit: Minor bug now fixed.
Code: [Local Link Removed for Guests]
'****************************************************************************
'* *
'* Analogue Clock by BeanieBots July 2022 *
'* *
'* Optimised for TFT screens with a resolution of 240x320 *
'* Tested on ESP32 with Annex32 WiFi BLE CAN 1.44.2 firmware *
'* TO DO - Add compensation for different text fonts (only 4 supported) *
'* V1.0.0 15/07/2022 Added user defineable examples *
'* V1.0.1 16/07/2022 Covnerted main text from tft.print to tft.draw *
'* V1.0.2 16/07/2022 A little tidy up before posting *
'* *
'* Please try out all the examples & some yourself. *
'* *
'****************************************************************************
Example = 1 'There are 10 example setups
Example_old = Example
Gosub Declarations 'Configure the text values for days & months
Gosub DefaultValues 'Ensure ALL variables are set
Gosub UserPrefs 'Override defaults as required
Gosub Initialise 'Set everything up ready to go.
Gosub DrawFace 'Draw the clock face.
Timer0 1000, Update_Clock 'Print & draw current values every second
Timer1 15000, ChangeExample'Delete this line to stop cycling the examples
wait
'###########################################################################
ChangeExample: 'Delete this entire section ^
Example = Example + 1 'once you have observed all |
If Example > 10 then 'the different examples |
Example = 1 ' |
EndIf ' |
Return ' v
'###########################################################################
Update_Clock:
'--------------------------------------------------------------------
If Example_Old <> Example then '
Gosub DefaultValues '
Gosub UserPrefs '
Gosub Initialise '
Gosub Drawface '
Example_Old = Example '
EndIF '
'--------------------------------------------------------------------
tft.text.col Col_Text,Col_Back
DoW = (dateunix(Date$)) mod 7
TFT.TEXT.ALIGN 1 'ALIGN_TOP_MID
TFT.TEXT.PADDING 150
tft.text.draw Day$(Dow),120,0,4
secs = val(mid$(time$,7,2))+30 mod 59
mins = val(mid$(time$,4,2))+30 mod 59
Hrs = (val(mid$(time$,1,2)))*5+28 +(mins/14) mod 59
Month = Val(mid$(date$,4,2))
Day = Val(mid$(date$,1,2))
TFT.TEXT.ALIGN 8 'ALIGN_BOT_RIGHT
TFT.TEXT.PADDING 80
TFT.TEXT.DRAW Month$(Month)+" "+str$(Day),90,57,4
Select Case Day 'Calculate the Ordinal Suffix
Case 1: OS$ = "st"
Case 2: OS$ = "nd"
Case 3: OS$ = "rd"
Case 4 to 20: OS$ = "th"
Case 21: OS$ = "st"
Case 22: OS$ = "nd"
Case 23: OS$ = "rd"
Case 24 to 30: OS$ = "th"
Case 31: OS$ = "st"
Case Else: OS$ = " "
End Select
tft.text.font 2
tft.text.pos 93,28
tft.print OS$;" "
tft.text.align 7 'ALIGN_BOT_MID
tft.text.padding 70
tft.text.draw "20"+right$(date$,2),175,57,4
tft.text.align 7 'ALIGN_BOT_MID
tft.text.padding 115
tft.text.draw time$,120,320,4
secs = val(mid$(time$,7,2))+30 mod 59
mins= val(mid$(time$,4,2))+30 mod 59
Hrs = (val(mid$(time$,1,2)))*5+28 +(mins/14) mod 59'[min/19.2]
Gui.SetValue Hand_H, hrs
Gui.SetValue Hand_M, mins
Gui.SetValue Hand_S, secs
gui.redraw
gui.redraw '2nd redraw required to tidy up hands below second hand.
tft.circle x,y,7,tft.rgb(0,0,0),1
tft.circle x,y,3,tft.rgb(255,255,255),0
Return
'###############################################################################
DrawFace:
If Filename$ <> "" then
TFT.JPG FileName$, x-120,y-120,0
Else 'It needs to be drawn the old fashioned way!
tft.text.font FaceFont
S_Arc = FaceSize * 0.89-TickLength-(Padsize/2.1)
tft.circle x, y , FaceSize,Col_ring,1
tft.circle x, y , (FaceSize-TickLength-2),Col_Face,1
For N = 0 to 59 step 5
A=2*Pi*N/60
X1=cos(A) * S_Arc+x
Y1=sin(A) * S_Arc+y
tft.circle x1, y1 , PadSize, Col_Face_Back, 1
H$=str$(int((n/5)+2) MOD 12 + 1)
tft.text.pos X1+TextCompX-(len(H$)*TextCompS),Y1-TextCompY
tft.text.col Col_Digit,Col_Face_Back
tft.print H$
Next N
S_Arc = FaceSize * 0.99
TS=0.005 'Small tick angle
For Z = -TS to TS step 0.001
For N = 0 to 59 step 1
A=2*Pi*N/60
X1=cos(A+Z) * (S_Arc)+x
Y1=sin(A+Z) * (S_Arc)+y
X2=cos(A+Z) * (S_Arc-TickLength)+x
Y2=sin(A+Z) * (S_Arc-TickLength)+y
TFT.Line X1, Y1, X2, Y2, Col_Tick_Small
Next N
Next Z
TS=0.02 'Large tick angle
For Z = -TS to TS step 0.001
For N = 0 to 59 step 5
A=2*Pi*N/60
X1=cos(A+Z) * (S_Arc)+x
Y1=sin(A+Z) * (S_Arc)+y
X2=cos(A+Z) * (S_Arc-TickLength)+x
Y2=sin(A+Z) * (S_Arc-TickLength)+y
TFT.Line X1, Y1, X2, Y2, Col_Tick_Large
Next N
Next Z
EndIF
Return
'###############################################################################
Declarations:
Dim Day$(6)
Day$(0)="Thursday"
Day$(1)="Wednesday"
Day$(2)="Tuesday"
Day$(3)="Monday"
Day$(4)="Sunday"
Day$(5)="Saturday"
Day$(6)="Friday"
Dim Month$(12)
Month$(0) = "Err"
Month$(1) = "Jan"
Month$(2) = "Feb"
Month$(3) = "Mar"
Month$(4) = "Apr"
Month$(5) = "May"
Month$(6) = "Jun"
Month$(7) = "Jul"
Month$(8) = "Aug"
Month$(9) = "Sep"
Month$(10)= "Oct"
Month$(11)= "Nov"
Month$(12)= "Dec"
Return
'###############################################################################
Initialise:
Length_S = FaceSize - 30 - TickLength - FaceFont*3.9 + HandLengthAdjust
Length_M = Length_S * 0.93 'compensation for each clock hand length
Length_H = Length_M * 0.85 '
tft.init 0 'Force screen orientation
gui.init 3, Col_Face '(back colour does not appear to work so set in gui.gauge)
X=120 'Location for clock face center
Y=175
tft.brightness 240
tft.fill Col_Back
tft.text.font FaceFont
tft.text.pos 0,10
tft.text.col Col_Text,Col_Back
Select Case FaceFont
Case 1
TextCompS = 4 'X Scale
TextCompX = 3 'X Offset
TextCompY = 4 'Y Offset
PadSize = 10
Case 2
TextCompS = 5 'X Scale
TextCompX = 3 'X Offset
TextCompY = 8 'Y Offset
PadSize = 12
Case 3
TextCompS = 7.5 'X Scale
TextCompX = 4 'X Offset
TextCompY = 8 'Y Offset
PadSize = 16
Case 4
TextCompS = 8.5 'X Scale
TextCompX = 3 'X Offset
TextCompY = 11 'Y Offset
PadSize = 19
Case 5
TextCompS = 9.5 'X Scale
TextCompX = 3 'X Offset
TextCompY = 11 'Y Offset
PadSize = 20
Case else
FaceFont = 1
TextCompS = 4 'X Scale
TextCompX = 3 'X Offset
TextCompY = 4 'Y Offset
PadSize = 10
End Select
Hand_H = GUI.Gauge(x, y, 0, 0, 0 ,Col_Hand_H ,Col_Face)
Hand_M = GUI.Gauge(x, y, 0, 0, 0 ,Col_Hand_M ,Col_Face)
Hand_S = GUI.Gauge(x, y, 0, 0, 0 ,Col_Hand_S ,Col_Face)
gui.setrange Hand_H, 0, 60
gui.setrange Hand_M, 0, 60
gui.setrange Hand_S, 0, 60
gui.setstyle Hand_H, Length_H,Width_H
gui.setstyle Hand_M, Length_M,Width_M
gui.setstyle Hand_S, Length_S,Width_S
Return
'###############################################################################
DefaultValues:
Filename$ = ""
FaceSize = 118
TickLength = 9
FaceFont = 2 '1,2,3 & 4 Only sizes valid
TextFont = 4
Width_S = 3
Width_M = 4
Width_H = 6
Col_Face = tft.rgb(64,196,64)
Col_Digit = tft.rgb(255,255,255)
Col_Back = tft.rgb(0,0,255)
Col_Text = tft.rgb(255,255,0)
Col_Face_Back = tft.rgb(0,0,0)
Col_Ring = tft.rgb(255,0,255)
Col_Hand_H = tft.rgb(32,255,32)
Col_Hand_M = tft.rgb(255,240,32)
Col_Hand_S = tft.rgb(255,64,0)
Col_Tick_Large = tft.rgb(255,255,255)
Col_Tick_Small = tft.rgb(128,128,128)
HandLengthAdjust = 0
Return
'###############################################################################
UserPrefs:
'You can fiddle here with values that are set as default above
'Please note, the hand lengths are a function of FaceSize
'If a filename is set, no face will be drawn, just the hands.
Select Case Example
Case 1 'Very basic. Simplest is often best.
Filename$ = "/Classic.jpg"
FaceSize = 114
Col_Back = tft.rgb(0,0,0)
Col_Face = tft.rgb(0,0,0)
Col_Text = tft.rgb(255,255,255)
Case 2 'Thin font roman numerals
Filename$ = "/Roman_I.jpg"
FaceSize = 120
Col_Back = tft.rgb(0,0,0)
Col_Face = tft.rgb(0,0,0)
Col_Text = tft.rgb(255,255,255)
Case 3 'Larger roman numerals
Filename$ = "/Roman_II.jpg"
FaceSize = 112
Col_Back = tft.rgb(0,0,0)
Col_Face = tft.rgb(0,0,0)
Col_Text = tft.rgb(96,128,255)
Case 4 'A slightly fancier face.
Filename$ = "/Fancy.jpg"
FaceSize = 110
Col_Back = tft.rgb(255,255,0)
Col_Face = tft.rgb(255,255,0)
Col_Text = tft.rgb(0,0,255)
Col_Hand_H = tft.rgb(32,32,255)
Col_Hand_M = tft.rgb(32,240,32)
Col_Hand_S = tft.rgb(240,16,16)
Case 5 'Classic Old school (My personal favourite)
Filename$ = ""
FaceSize = 118
FaceFont = 4
Col_Face = tft.rgb(0,0,0)
Col_Digit = tft.rgb(255,255,255)
Col_Back = tft.rgb(0,0,0)
Col_Text = tft.rgb(255,255,0)
Col_Face_Back = tft.rgb(0,0,0)
Col_Ring = tft.rgb(64,64,196)
Col_Hand_H = tft.rgb(32,255,32)
Col_Hand_M = tft.rgb(255,240,32)
Col_Hand_S = tft.rgb(255,64,0)
Col_Tick_Large = tft.rgb(255,255,255)
Col_Tick_Small = tft.rgb(0,0,0)
HandLengthAdjust = 10
Case 6 'A bigger brighter face
Filename$ = ""
FaceSize = 118
FaceFont = 2
Col_Face = tft.rgb(240,240,255)
Col_Digit = tft.rgb(0,0,255)
Col_Back = tft.rgb(255,255,128)
Col_Text = tft.rgb(0,0,240)
Col_Face_Back = tft.rgb(240,240,255)
Col_Ring = tft.rgb(240,240,240)
Col_Hand_H = tft.rgb(32,255,32)
Col_Hand_M = tft.rgb(255,240,32)
Col_Hand_S = tft.rgb(255,64,0)
Col_Tick_Large = tft.rgb(0,0,0)
Col_Tick_Small = tft.rgb(0,0,0)
Col_Hand_M = tft.rgb(255,196,0)
HandLengthAdjust = 10
Case 7 'Hacker. Classic green screen.
Filename$ = ""
FaceSize = 85
FaceFont = 3
Col_Face = tft.rgb(0,0,0)
Col_Digit = tft.rgb(0,255,0)
Col_Back = tft.rgb(0,0,0)
Col_Text = tft.rgb(0,255,0)
Col_Face_Back = tft.rgb(0,0,0)
Col_Ring = tft.rgb(0,128,0)
Col_Hand_H = tft.rgb(32,196,32)
Col_Hand_M = tft.rgb(64,196,64)
Col_Hand_S = tft.rgb(128,240,64)
Col_Tick_Large = tft.rgb(96,255,96)
Col_Tick_Small = tft.rgb(0,255,0)
TickLength = 4
Width_S = 2
Width_M = 3
Width_H = 4
HandLengthAdjust = 10
Case 8 'Black on white. Small clock digits
Filename$ = ""
FaceSize = 100
FaceFont = 1
Col_Face = tft.rgb(255,255,255)
Col_Digit = tft.rgb(0,0,0)
Col_Back = tft.rgb(255,255,255)
Col_Text = tft.rgb(0,64,0)
Col_Face_Back = tft.rgb(255,255,255)
Col_Ring = tft.rgb(196,196,196)
Col_Hand_H = tft.rgb(64,64,64)
Col_Hand_M = tft.rgb(96,96,96)
Col_Hand_S = tft.rgb(240,128,128)
Col_Tick_Large = tft.rgb(0,0,0)
Col_Tick_Small = tft.rgb(255,255,255)
TickLength = 3
Width_S = 2
Width_M = 3
Width_H = 4
HandLengthAdjust = 10
Case 9 'As Small as realisticly possible
Filename$ = ""
FaceSize = 45
FaceFont = 1
Col_Face = tft.rgb(0,0,0)
Col_Digit = tft.rgb(0,255,255)
Col_Back = tft.rgb(0,0,0)
Col_Text = tft.rgb(0,255,255)
Col_Face_Back = tft.rgb(0,0,0)
Col_Ring = tft.rgb(0,128,128)
Col_Hand_H = tft.rgb(32,255,192)
Col_Hand_M = tft.rgb(240,240,64)
Col_Hand_S = tft.rgb(255,64,64)
Col_Tick_Large = tft.rgb(255,255,255)
Col_Tick_Small = tft.rgb(64,240,240)
TickLength = 2
Width_S = 2
Width_M = 3
Width_H = 4
HandLengthAdjust = 18
Case 10 'Clock face numbers drawn on pads
Filename$ = ""
FaceSize = 110
TickLength = 11
Col_Face = tft.rgb(96,96,192)
Col_Digit = tft.rgb(0,0,0)
Col_Back = tft.rgb(0,128,0)
Col_Text = tft.rgb(255,255,0)
Col_Face_Back = tft.rgb(255,255,64)
Col_Ring = tft.rgb(255,96,255)
Col_Hand_H = tft.rgb(32,255,32)
Col_Hand_M = tft.rgb(255,240,32)
Col_Hand_S = tft.rgb(255,64,0)
Col_Tick_Large = tft.rgb(255,255,255)
Col_Tick_Small = tft.rgb(128,128,96)
HandLengthAdjust = 6
Case Else
'use purely default values
End Select
Example_Old = Example
Return
'###############################################################################