A silly little project in many ways, but it works and does show how tight the machine code produced by Proton is. Temperatures are displayed to the nearest 0.1 of a degree.
Thermometer.jpg
'****************************************************************
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings
Device = 12F675
Config FOSC_INTRCIO, WDTE_ON, PWRTE_ON, MCLRE_OFF, BOREN_OFF, CP_OFF, CPD_OFF
;**** End of Fuse Configurator Settings ****
'****************************************************************
Xtal = 4
'All_Digital = true ' Set all proc pins to I/O
TRISIO = 0
GPIO = 0
CMCON = 7
ANSEL = 0
Symbol SDIN = GPIO.0
Symbol SCK = GPIO.1
Symbol DQ = GPIO.2
Symbol Mode = GPIO.3
Symbol RST = GPIO.4
Symbol D_C = GPIO.5
Symbol RdOffSet = 5
Symbol X_Origin = %10000000
Symbol Y_Origin = %01000000
Symbol NormVid = %00001100
Symbol InvVid = %00001101
Dim Temperature As Word
Dim TempHigh As Temperature.HighByte
Dim TempH As Byte
Dim TempL As Byte
Dim sign As Bit
Dim MaxTemp As Word
Dim MinTemp As Word
Dim LcdReg As Byte
Dim DispLine As Byte
Dim Offset As Word
Dim Char[6] As Byte
Dim CharPtr As Byte
Dim Loop1 As Byte
Dim Loop2 As Byte
Dim LoopOut As Byte
GoTo Main
'****************************************************************
SndLcdCmd:
D_C = 0
SndLcdData:
SCK = 0
LoopOut = 0
Repeat
SDIN = LcdReg.7
LcdReg = LcdReg << 1
SCK = 1
SCK = 0
Inc LoopOut
Until LoopOut > 7
D_C = 1
Return
'****************************************************************
DisplayTemp:
Loop2 = 0
Repeat
Offset = Char[Loop2] * 20
If Offset > 159 Then Offset = Offset - 160
LcdReg = Y_Origin + 1 ' cursor Y DispLine number(0-5)
GoSub SndLcdCmd
LcdReg = 0
GoSub SndLcdData
GoSub SndLcdData
CharPtr = CharPtr + 2
GoSub PrintChar
LcdReg = X_Origin + CharPtr
GoSub SndLcdCmd
LcdReg = Y_Origin + 2 ' cursor Y DispLine number(0-5)
GoSub SndLcdCmd
GoSub PrintChar
CharPtr = CharPtr + 10
Inc Loop2
Until Loop2 > 5
Return
'****************************************************************
PrintChar:
Loop1 = 1
Repeat
If Char[Loop2] < 8 Then '***** Numbers 0- 7 inclusive ******
LcdReg = CRead font+Offset
Else
'****** Characters 8 - 13 (+,-,.,centigrade) ********
LcdReg = ERead Offset
EndIf
Inc Offset
GoSub SndLcdData
Inc Loop1
Until Loop1 > 10
Return
'****************************************************************
Temp2Dec:
sign = 0
If TempHigh.7 = 1 Then
Temperature = ~Temperature + 1
sign = 1
EndIf
TempH = Temperature >> 4
TempL = Temperature.LowByte & $0F
Temperature = TempL * 625
If TempH > 99 Then ' if the temp higher than 99'C , instead of the plus signs " 1 "
Char[0] = 1 ' hundreds
Else
Char[0] = 10 ' + plus
If sign = 1 Then Char[0] = 11
EndIf
Char[1] = Dig TempH,1 ' Tens
Char[2] = Dig TempH,0 ' Units
Char[3] = 12 ' Decimal point
Char[4] = Dig Temperature,3 ' first decimal
Char[5] = 13 ' Degrees Centigrade
Return
'****************************************************************
DisplayMaxMin:
LcdReg = Y_Origin + 5 ' cursor Y DispLine number(0-5)
GoSub SndLcdCmd
DisplayLabel:
Loop2 = 0
Repeat
Offset = Char[Loop2] * 5
Loop1 = 0
Repeat
LcdReg = CRead SmallFont+Offset
LcdReg = ~LcdReg
GoSub SndLcdData
Inc Offset
Inc Loop1
Until Loop1 > 4
LcdReg = $ff
GoSub SndLcdData
Inc Loop2
Until Loop2 > 5
Return
'****************************************************************
GetTemp:
OWrite DQ, 1, [$CC, $44] ' Start temperature conversion
Snooze 6
OWrite DQ, 1, [$CC, $BE]
ORead DQ, 0, [Temperature.LowByte, Temperature.HighByte, Skip 6]
Return
'****************************************************************
Main:
'****************** GLCD Initialisation ***********************
High RST
LcdReg = $21 '%00100001 'LCD Extended Commands.
GoSub SndLcdCmd
LcdReg = $d8'C0 '%10101001 'Set LCD Vop (Contrast).
GoSub SndLcdCmd
LcdReg = $06 '%00000110 'Set Temp coefficent.
GoSub SndLcdCmd
LcdReg = $13 '%00010011 'LCD bias mode 1:48.
GoSub SndLcdCmd
LcdReg = $20 '%00100000 'LCD Standard Commands, Horizontal addressing mode.
GoSub SndLcdCmd
LcdReg = NormVid
GoSub SndLcdCmd
'********** Draw screen frame. ***********
Loop2 = 0
Repeat
LcdReg = Y_Origin + Loop2
GoSub SndLcdCmd
LcdReg = X_Origin ' X pos left
GoSub SndLcdCmd
Loop1 = 0
Repeat
LcdReg = $00
If Loop2 = 0 Then LcdReg = $03
If Loop2 > 3 Then LcdReg = $FF
If Loop1 < 2 Then LcdReg = $FF
If Loop1 > 81 Then LcdReg = $FF
GoSub SndLcdData
Inc Loop1
Until Loop1 > 84
Inc Loop2
Until Loop2 > 5
LcdReg = Y_Origin + 4
GoSub SndLcdCmd
LcdReg = X_Origin + 4 ' X pos left
GoSub SndLcdCmd
Char[0] = 11
Char[1] = 14
Char[2] = 15
Char[3] = 16
Char[4] = 11
Char[5] = 19
GoSub DisplayLabel
LcdReg = X_Origin + 51 ' X pos left
GoSub SndLcdCmd
Char[2] = 17
Char[3] = 18
GoSub DisplayLabel
GoSub GetTemp
MaxTemp = Temperature
MinTemp = Temperature
' *********** Main program Loop1 ***********
While
LcdReg = NormVid 'LCD in normal mode.
If Mode = 0 Then LcdReg = InvVid
GoSub SndLcdCmd
If Temperature.15 = MaxTemp.15 And Temperature > MaxTemp Then MaxTemp = Temperature
If Temperature.15 = 0 And MaxTemp.15 > 0 Then MaxTemp = Temperature
If Temperature.15 = MinTemp.15 And Temperature < MinTemp Then MinTemp = Temperature
If Temperature.15 > 0 And MinTemp.15 = 0 Then MinTemp = Temperature
LcdReg = X_Origin + RdOffSet ' cursor X (0-83)
GoSub SndLcdCmd
GoSub Temp2Dec
CharPtr = RdOffSet
GoSub DisplayTemp
LcdReg = X_Origin + 1 ' cursor X (0-83)
GoSub SndLcdCmd
Temperature = MaxTemp
GoSub Temp2Dec
GoSub DisplayMaxMin
LcdReg = X_Origin + 48 ' cursor X (0-83)
GoSub SndLcdCmd
Temperature = MinTemp
GoSub Temp2Dec
GoSub DisplayMaxMin
GoSub GetTemp
Wend
'***** Numbers 0-7 inclusive ******
Font:
CData $F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8,_ ' 0
$3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,_
$00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00,_ ' 1
$00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,_
$18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8,_ ' 2
$F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,_
$06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E,_ ' 3
$60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C,_
$00,$80,$E0,$78,$1E,$06,$FE,$FE,$00,$00,_ ' 4
$0E,$0F,$0D,$0C,$0C,$0C,$FF,$FF,$0C,$0C,_
$FC,$FE,$86,$86,$86,$86,$86,$86,$86,$06,_ ' 5
$70,$F1,$C1,$C1,$C1,$C1,$C1,$C1,$7F,$3F,_
$FC,$FE,$06,$06,$06,$06,$06,$06,$06,$04,_ ' 6
$7F,$FF,$C3,$C3,$C3,$C3,$C3,$C3,$FF,$7E,_
$04,$06,$06,$06,$06,$86,$C6,$66,$3E,$1C,_ ' 7
$00,$00,$00,$FE,$FF,$01,$00,$00,$00,$00
'****** Characters 8 - 13 (8,9,+,-,.,Centigrade) ********
EData $78,$FC,$86,$86,$86,$86,$86,$86,$FC,$78,_ ' 8
$3E,$7F,$C1,$C1,$C1,$C1,$C1,$C1,$7F,$3E,_
$FC,$FE,$06,$06,$06,$06,$06,$06,$FE,$FC,_ ' 9
$41,$C3,$C3,$C3,$C3,$C3,$C3,$C3,$FF,$7F,_
$80,$80,$80,$80,$F8,$F8,$80,$80,$80,$80,_ ' +
$01,$01,$01,$01,$1F,$1F,$01,$01,$01,$01,_
$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,_ ' -
$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,_ ' .
$00,$00,$00,$60,$F0,$F0,$60,$00,$00,$00,_
$0E,$CA,$EE,$60,$60,$60,$60,$E0,$C0,$00,_ ' Degrees C
$00,$7F,$FF,$C0,$C0,$C0,$C0,$E0,$60,$00
SmallFont:
CData $3E,$51,$49,$45,$3E,_ ' 0
$00,$42,$7F,$40,$00,_ ' 1
$42,$61,$51,$49,$46,_ ' 2
$21,$41,$45,$4B,$31,_ ' 3
$18,$14,$12,$7F,$10,_ ' 4
$27,$45,$45,$45,$39,_ ' 5
$3C,$4A,$49,$49,$30,_ ' 6
$01,$71,$09,$05,$03,_ ' 7
$36,$49,$49,$49,$36,_ ' 8
$06,$49,$49,$29,$1E,_ ' 9
$08,$08,$3E,$08,$08,_ ' +
$08,$08,$08,$08,$08,_ ' -
$00,$60,$60,$00,$00,_ ' .
$03,$03,$78,$48,$48,_ ' Degrees C
$7E,$04,$08,$04,$7E,_ ' M char 14
$78,$14,$12,$14,$78,_ ' A char 15
$42,$24,$18,$24,$42,_ ' X char 16
$00,$42,$7E,$42,$00,_ ' I char 17
$7E,$04,$18,$20,$7E,_ ' N char 18
$00,$00,$00,$00,$00 ' Space - char 19
Excellent code Bob, and many thanks for the compliment.
You're in for a treat with the next compiler update, although I may have placed it in the current version 3.7.5.5. :-)
Instead of writing tables in flash memory code as:
CData $F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8,_ ' 0
$3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,_
$00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00,_ ' 1
$00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,_
$18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8,_ ' 2
$F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,_
$06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E,_ ' 3
$60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C
With the line continuation required after every line, you will be able to do:
CData {$F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8, ' 0
$3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,
$00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00, ' 1
$00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,
$18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8, ' 2
$F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,
$06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E, ' 3
$60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C}
Notice the starting and ending curly braces and the lack of any line continuation characters for the data items in the block? :-) This makes code so much easier to write and read, and I implemented it because I use it all the time with C++, so I thought it would come in handy for the users of Proton8 and Proton24.
Also, the Dim As Flash, Dim As Flash8, Dim As Flash16, Dim As Flash24, Dim As Flash32, Dim As FlashF, and Dim As FlashD directives for making flash memory tables are extremely good to write and read, and make code more efficient. The next manual update has better details of them. They are an optional name change from the Code, Code8, Code16, Code24, Code32, and CodeF directives. I originally used the name "Code" because the flash memory on PICs was always known as "Code Memory", but now it is known as "Flash Memory" in some datasheets and application notes etc... But I'm sure they will change it later to "Program Memory" like AVR devices have.
Note that the curly braces are optional, and the standard method is still, and always will be, supported.
Compliments for the masterpiece!! I never realized that a 12F675 would drive a PCD8544.
I thought I knew all the Proton commands, but another surprise: Snooze. The Proton manual filled in my ignorance once again. Handy command.
Nice program and in a 12F !!
Johan