#rem OLED Portable Display.bas
This is a hand-held OLED display receiving data from the
Mobile Logger, the Solar Transmitter.and the Alpha LED Clock
John Saunders
10/11/2018, 1/14/2018 changed line 305 because of negative altitude
#endrem
#picaxe 14M2
rem Connections
symbol DispRst = B.1
symbol ButtonLeft = pinB.2
symbol ButtonRight = pinB.5
symbol Rcvr_In = C.0
symbol VoltPort = C.4
symbol TP = C.1
symbol Int_Port = pinC.2
rem Dedicated I2C pins: SCL = b.3, SDA = B.4
rem Interrupt only variables
symbol Msg_Start = b1
symbol Plen = b2
symbol Key_Code = b3
symbol ChckHex = b4
symbol ChckSum = b5
symbol Msg_End = b6
symbol I_tmp = b7
symbol MsgLoc = b8
#rem Global variables
Pages:0=Battery Volts,1=Alitude&Logger Volts,2=Logger temperature&humidity
3=Outside Solar Current and battery volts,4= outside temperature&humidity
5=Time&Date
#endrem
symbol Page = b10
rem flags
symbol Pressed = bit0
symbol NewData = bit1
symbol ButtonEvent = bit2
symbol Row = bit3 '0 = top, 1 = bottom
rem Pointer Vatiables
symbol DataAddr = b14
symbol ConfigAddr = b15
symbol MemAddr = b16
symbol TableAddr = b17
rem Local Variables
symbol Loop_Count = b19
symbol Scratch = b20
symbol DecData = b21
symbol Indx = b22 'Used for iteration in top-level subroutines
symbol Iter = b23 'Used for iteration in subroutines called from loops
symbol Limit = b24
symbol Column = b25
symbol BattVolt = w13
rem constants
symbol MsgBase = 210
rem Fixed strings which will be partly overwritten by values
TABLE 0,("Batt V Gate Door") 'Row 0, Page 0
TABLE 16,("0.00 V ") 'Row 1, Page 0
TABLE 32,("Alt&Logger Volts") 'Row 0, Page 1
TABLE 48,("00000 00.00V ") 'Row 1, Page 1
TABLE 64,("Logger Temp&Hum ") 'Row 0, Page 2
TABLE 80,("000.0",$80,"F 000% ") 'Row 1, Page 2
TABLE 96,("Solar Curr&Bat V") 'Row 0, Page 3
TABLE 112,("000 MA 000 V ") ;Row 1, Page 3
TABLE 128,("Outside Temp&Hum") 'Row 0, Page 4
TABLE 144,("000",$80,"F 000% ") 'Row 1, Page 4
TABLE 160,("Master Time&Date") 'Row 0, Page 5
TABLE 176,("HH:MM MO/DD ") 'Row 1, Page 5
#rem Memory Map (28 - 255 total) MSB first, all in ASCII
: 28,
30= Battery Volts ("0.00")
34= Altitude ("00000", 2nd may be "-"),49 Logger supply volts ("00.00")
39= Logger Temperature ("000.0"), 44= Logger Humidity ("000")
60= Solar Current ("000"),63=Solar Battery Voltage ("0.00")
54= Outside temperature("000"),57=Outside Humidity ("000")
67= Date("00/00"), 72=Time("00:00")
80= Gate(" " or "OPEN" or "SHUT") Used on Row 1 of Page 0
84= Garage Door (" " or "DOWN" or "UP ") Used on Row 1 of Page 0
these 2 also in positions 14 & 15 of pages 1-5 as " ","O","S", "D", "U"
Received messages: 210 - 238 (ASCII, no decimal points (MS first),
rem Variable coonfiguration tables. Indexed by Page (Page 0 is separate)
rem Each entry has three numbers for each of 2 variables.
The first is the memory address ddress, the second the number of characters, the third is the column of the MSB
#endrem
DATA 0,(30,4,0,80,9,7) 'Page 0 lower variables
DATA 6,(34,5,0,48,5,7) 'Page 1 lower variables
DATA 12,(39,5,0,44,3,9) 'Page 2 lower variables
DATA 18,(60,3,0,63,4,7) 'Page 3 lower variables
DATA 24,(54,3,0,57,3,6) 'Page 4 lower variables
DATA 30,(72,5,0,67,5,6) 'Page 5 lower variables
rem ------------------------------------ Execution Code --------------------------------------
Init:
SETFREQ m8
HI2CSETUP I2CMASTER,$78,i2cfast,i2cbyte 'The OLED Display
GOSUB InitDisp
FOR Scratch = 28 TO 76
POKE Scratch, "0"
NEXT
FOR Scratch = 80 TO 88
POKE Scratch, " "
NEXT
LOW TP
LET Page = 1 'Altitude 11/6/2018
LET Loop_Count = 0
GOSUB Refresh
Main:
IF ButtonLeft = 0 THEN
IF Page > 0 THEN
DEC Page
ELSE
LET Page = 5
ENDIF
LET ButtonEvent = 1
ENDIF
IF ButtonRight = 0 THEN
IF Page < 5 THEN
INC Page
ELSE
LET Page = 0
ENDIF
LET ButtonEvent = 1
ENDIF
IF ButtonEvent = 1 THEN
SETINT OFF
GOSUB Refresh 'The background
GOSUB Update 'The variable content
DO WHILE ButtonLeft = 0 OR ButtonRight = 0
PAUSE 10
LOOP
LET ButtonEvent = 0
SETINT %00000100,%00000100 'Interrupt when Int_Port high.
ELSEIF Page = 0 THEN
GOSUB GetVolts
ELSE
PAUSE 10
ENDIF
GOTO Main
rem ------------------------------------ Top level subroutines --------------------------------------
InitDisp: 'From the display datasheet
PAUSE 100
HI2COUT (0,0x2A); //function set (extended command set)
HI2COUT (0,0x71); //function selection A
HI2COUT ($40,0x5C); // data(0x5C) = enable regulator (5V I/O)
HI2COUT (0,0x28); //function set (fundamental command set)
HI2COUT (0,0x08); //display off, cursor off, blink off
HI2COUT (0,0x2A); //function set (extended command set)
HI2COUT (0,0x79); //OLED command set enabled
HI2COUT (0,0xD5); //set display clock divide ratio/oscillator frequency
HI2COUT (0,0x70); //set display clock divide ratio/oscillator frequency
HI2COUT (0,0x78); //OLED command set disabled
HI2COUT (0,0x08); //extended function set (2-lines)
HI2COUT (0,0x06); //COM SEG direction
HI2COUT (0,0x72); //function selection B
HI2COUT ($40,0x00); //ROM CGRAM selection A
HI2COUT (0,0x2A); //function set (extended command set)
HI2COUT (0,0x79); //OLED command set enabled
HI2COUT (0,0xDA); //set SEG pins hardware configuration
HI2COUT (0,0x00); //set SEG pins hardware configuration
HI2COUT (0,0xDC); //function selection C
HI2COUT (0,0x00); //function selection C
HI2COUT (0,0x81); //set contrast control
HI2COUT (0,0x7F); //set contrast control
HI2COUT (0,0xD9); //set phase length
HI2COUT (0,0xF1); //set phase length
HI2COUT (0,0xDB); //set VCOMH deselect level
HI2COUT (0,0x40); //set VCOMH deselect level
HI2COUT (0,0x78); //OLED command set disabled
HI2COUT (0,0x28); //function set (fundamental command set)
HI2COUT (0,0x01); //clear display
HI2COUT (0,0x80); //set DDRAM address to 0x00
HI2COUT (0,0x0C); //display ON
RETURN
GetVolts:
rem Measure and store Battery voltage
FVRSETUP FVR4096
ADCCONFIG %011
READADC10 VoltPort,BattVolt
LET BattVolt = 4 * BattVolt + 5 / 10
LET BattVolt = BattVolt // 1000
LET Scratch = BattVolt/100 + "0"
POKE 30,Scratch
POKE 31,"."
LET BattVolt = BattVolt // 100
LET Scratch = BattVolt / 10 + "0"
POKE 32,Scratch
LET Scratch = BattVolt // 10 + "0"
POKE 33,Scratch
RETURN
Refresh: 'Writes the fixed strings to the buffers when the Page changes
FOR Row = 0 TO 1
LET DecData = Row * $40 + $80
HI2COUT 0,(DecData)
LET Scratch = 2 * Page + Row
LET DecData = 16 * Scratch
FOR Indx = 0 TO 15
LET TableAddr = DecData + Indx
READTABLE TableAddr,Scratch
Hi2COUT $40,(Scratch)
NEXT
NEXT
RETURN
Update: 'Writes the numerical information to the display
FOR Indx = 0 TO 1 'Two vatiables per page lower row '
LET Scratch = 6*Page 'The configuration table entry for the page variables
LET ConfigAddr = 3 * Indx + Scratch
READ ConfigAddr,DecData,Limit, Column
LET Scratch = $C0 + Column
HI2COUT 0,(Scratch) 'Set cursor to MSD columb
FOR Iter = 1 TO Limit
LET MemAddr = DecData + Iter - 1
PEEK MemAddr, Scratch
Hi2COUT $40,(Scratch)
NEXT
NEXT
rem Put event markers at the end 2 columns of the lower line except for Page 0
IF Page <> 0 THEN
HI2COUT 0,($CE)
PEEK 80,Scratch
Hi2COUT $40,(Scratch)
PEEK 84,Scratch
Hi2COUT $40,(Scratch)
ENDIF
RETURN
Interrupt:
LET bptr=MsgBase
LET Key_Code = "Z"
rem First gate is to reject short bursts
LET Plen =0
DO WHILE Int_Port = 1 'Noise interrupts are nearly always shorter
INC Plen
LOOP
IF Plen < 10 OR Plen > 20 THEN End_Interrupt 'Minimises the time to recover from a noise interrupt
FOR I_tmp = 0 TO 5
IF Int_Port = 1 THEN
SERTXD ("Positive pulse=",#plen,",Low = ",#I_tmp,13,10)
GOTO End_Interrupt
ENDIF
NEXT
rem Second gate is to use a 7-character SERIN unlock code, min timeout is 60 ms
HIGH TP
rem Input commands and message with length character, checksum and up t0 21 data characters, including included, but not enclosed,commas
SERIN [40,timeout],Rcvr_In,N2400_8,("14L1776"),Key_Code,I_tmp,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr
LOW TP
rem No timeout: Must be a Message
PEEK MsgBase, I_tmp 'The length code, 60 + number of data bytes between commas, including commas between fields
LET Msg_End = MsgBase - 59 + I_Tmp 'Address of last data character
LET Msg_Start = MsgBase + 2
rem Calculate the checksum of the received message
LET Chcksum = 0
FOR MsgLoc = Msg_Start TO Msg_End 'Sum of message bytes not including bracketing commas
PEEK MsgLoc,ChckHex
LET ChckSum = ChckSum + ChckHex
NEXT
rem Compare the calculated with the 2 received checksum characters, one at a time
LET ChckHex = ChckSum / 16 'Convert calculated checksum to first hax character
IF ChckHex < 10 THEN
LET ChckHex = ChckHex + "0"
ELSE
LET ChckHex = ChckHex + "7"
ENDIF
LET bptr = Msg_End + 2 'Address of first checksun byte, which are in hex
LET I_tmp = @bptrinc 'first Checksum character
IF ChckHex <> I_tmp THEN End_Interrupt
LET ChckHex = ChckSum & $F 'Convert calculated checksum to secong hax character
IF ChckHex < 10 THEN
LET ChckHex = Chckhex + "0"
ELSE
LET ChckHex = ChckHex + "7"
ENDIF
LET I_tmp = @bptr 'second Checksum character
IF ChckHex <> I_tmp THEN End_Interrupt
rem Store the desired data values
timeout:
LET NewData = 1
SELECT Key_Code
CASE= "w" 'Put the Mobile Logger data into memory at 34, no commas
LET bptr = 34
FOR MsgLoc = Msg_Start TO Msg_End
PEEK MsgLoc,I_Tmp
IF I_Tmp <> "," THEN '12/14/2018 allow space and minus
LET @bptrinc = I_Tmp
IF bptr = 42 OR bptr = 50 THEN
LET @bptrinc = "."
ENDIF
ENDIF
NEXT
CASE "s" 'Put the Solar Trnsmitter data into memory at 54
LET bptr = 54
FOR MsgLoc = Msg_Start TO Msg_End
PEEK MsgLoc,I_Tmp
IF I_Tmp >= "0" AND I_Tmp <= "9" THEN
LET @bptrinc = I_Tmp
IF bptr = 64 THEN
LET @bptrinc = "."
ENDIF
ENDIF
NEXT
CASE "t" 'Put the time and date into memory at 67
LET bptr = 67
FOR MsgLoc = Msg_Start TO Msg_End
PEEK MsgLoc,I_Tmp
IF I_Tmp >= "0" AND I_Tmp <= "9" THEN
LET @bptrinc = I_Tmp
IF bptr = 69 THEN
LET @bptrinc = "/"
ENDIF
IF bptr = 74 THEN
LET @bptrinc = ":"
ENDIF
ENDIF
NEXT
CASE "u" 'The garage fan control reports the position of the door
LET MsgLoc = MsgBase + 14
PEEK MsgLoc,I_tmp
POKE 85,I_tmp
IF I_tmp = "D" THEN
POKE 86,"O","W","N"
ELSE
POKE 86,"P"," "," "
ENDIF
CASE "Q" 'Gate open
POKE 80,"O","P","E","N"
CASE "B"
POKE 80,"S","H","U","T"
ELSE
LET NewData = 0
ENDSELECT
LET Msg_End = MsgBase + 25
SERTXD (Key_Code,",")
FOR MsgLoc = Msg_Start TO Msg_End
PEEK MsgLoc,I_tmp
IF I_tmp < " " THEN EXIT
SERTXD (I_tmp)
NEXT
SERTXD (13,10)
IF NewData = 1 THEN
GOSUB Update
ENDIF
End_Interrupt:
LOW TP
LET bptr = MSGBase
FOR I_tmp = 0 TO 28
LET @bptrinc = ":"
NEXT
SETINT %00000100,%00000100 'Interrupt when Integrator high
RETURN