'{$stamp BS2}
'version d7.3
'To do: Add RTC - may need a BS2e for this as mem at 77%
'[I/O Definitions]
LCD_RS CON 0
LCD_E CON 1
SDA CON 2 'P2 = I2C Data
SCL CON 3 'P3 = I2C Clock
ADC_CLOCK CON 5 
ADC_DATA CON 4 
ADC_ENABLE CON 6
'Switch 1 is P13
'Switch 2 is P14
'Switch 3 is P15
'[I2C devices...]
EEPROM_0_Write CON %10100000 'data storage
EEPROM_0_Read CON %10100001
EEPROM_1_Write CON %10100100 'to save BS2 EEPROM space, display messages and
'user settings are stored in this EEPROM
EEPROM_1_Read CON %10100101 
PCF8574_Write CON %01110110
'[VARIABLES]
ack VAR BIT
button_pressed VAR BIT
call_from_memory_display VAR BIT
Memory_store VAR BIT
menulevel VAR NIB
sample_rate VAR NIB 'determines the sample rate
sample_seconds VAR BYTE
sample_minutes VAR BYTE
LCDcharacter VAR BYTE 'Character to display on LCD
start VAR BYTE 'Starting character in EEPROM for LCD
finish VAR BYTE 'End character in EEPROM for LCD
display_data VAR WORD 'Data to display on LCD
memlevel VAR BYTE 'Used to determine which icon to display
i VAR BYTE 'Just a for loop variable
ButtonWorkspace VAR BYTE 'Workspace for Button command
datafromAD VAR BYTE 'Data from the ADC chip
minutes VAR BYTE
seconds VAR BYTE
Internal_Address_0 VAR WORD
Internal_Address_1 VAR BYTE
EEPROM_Internal_Address VAR BYTE
Data_to_store VAR BYTE
I2C_data VAR BYTE
'CONSTANTS
Yes CON 1
No CON 0
'[MAIN CODE BEGINS]
'Initialize BS2 ports 
DIRS=%0000000001101111
LOW LCD_RS
LOW LCD_E
HIGH ADC_ENABLE
GOSUB LCD_Init 'Set up the LCD
UPDATECGRAM: 'Upload custom Characters to LCD's CGRAM
LCDcharacter = 64 
GOSUB LCD_command
start = $BE
finish = $FD
GOSUB readI2Ceeprom_1
GOSUB DisplayStartupMessage 'Display a Message at System Power On
start = 255 'Set sample_rate from user setting in EEPROM_1
finish = start
GOSUB ReadI2CEEPROM_1
sample_rate = I2C_data 
GOTO Act_on_button_1
Main: 'Main Program Loop
BUTTON 13, 0, 255, 0, ButtonWorkspace, 1, Act_on_button_1 'Check if the buttons have been pressed
BUTTON 14, 0, 255, 0, ButtonWorkspace, 1, Act_on_button_2 
BUTTON 15, 0, 255, 0, ButtonWorkspace, 1, Act_on_button_3 
GOSUB ReadADC
GOSUB DisplayVoltage 'Display the Data from the ADC
if button_pressed = yes then Main
seconds = seconds - 1
if seconds = 0 then decrement_Minutes
GOTO Main
'[END MAIN CODE]
'[SUBROUTINES]
'************************ LCD SOUBROUTINES ********************************
LCD_Init: 
PAUSE 500 ' let the LCD settle 
LCDcharacter = 56 ' multi-line mode 
GOSUB LCD_Command 
PAUSE 5 
PULSOUT LCD_E,1
PULSOUT LCD_E,1
LCDcharacter = 6 ' inc crsr, no disp shift 
GOSUB LCD_Command 
PAUSE 5 
RETURN
newline:
'Start on next line
LCDcharacter = 192
LCD_Command: 
LOW LCD_E
LOW LCD_RS
sendtoLCD: 
GOSUB StartI2C
I2C_data = PCF8574_Write 'The address of the IC on the I2C bus
GOSUB Write_data
I2C_data = LCDcharacter
GOSUB Write_data 
GOSUB StopI2C 
PULSOUT LCD_E,1
HIGH LCD_RS 
RETURN
ClearDisplay:
LCDcharacter = 1
GOSUB LCD_Command 
LCDcharacter = 12
GOSUB LCD_Command 
RETURN
'^^^^^^^^^^^^^^^^^^^^^^^ LCD SUBROUTINES ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'*********************** I2C SUBROUTINES **********************************
'Start Procedure. Set start condition on bus: SDA Hi-Lo while SCL Hi
StartI2C:
HIGH SDA
HIGH SCL
LOW SDA
LOW SCL
RETURN
'Stop Procedure. Set stop condition on bus: SDA Lo-Hi while SCL Hi
StopI2C:
LOW SDA
HIGH SCL
HIGH SDA
RETURN
'Write Address/Data Procedure
Write_data:
shiftout SDA, SCL, msbfirst, [I2C_data] 
'Check for Receiver Acknowledge
RX_ACK:
HIGH SDA
DIRS=%0011111011111011
HIGH SCL
ack = IN2
LOW SCL
DIRS=%0011111111111111
'if ack = 1 then indicate_NO_ACK
'debug "Acknowledged", 13
'RETURN
'indicate_NO_ACK:
' debug "NO Acknowledge", 13
RETURN
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ReadI2CEEPROM_1:
for Internal_Address_1 = start to finish
GOSUB StartI2C
'READ EEPROM... 
I2C_data = EEPROM_1_Write
GOSUB Write_data
I2C_data = Internal_Address_1
GOSUB Write_data
GOSUB StartI2C
I2C_data = EEPROM_1_Read
GOSUB Write_data
shiftin SDA, SCL, msbPre, [I2C_data] 
GOSUB STOPI2C
if start = finish then skip_SendtoLCD 'might just want to read a location - eg: to get a setting
LCDCharacter = I2C_data
GOSUB SendtoLCD
skip_SendtoLCD:
NEXT
RETURN
ReadI2CEEPROM_0:
GOSUB ClearDisplay
LCDcharacter = 128
GOSUB LCD_Command
start = $A2
finish = $AF
GOSUB ReadI2CEEPROM_1
debug "Logged data", 13, "Sample", ",", "Temperature", 13
for i = 0 to 255
GOSUB StartI2C
'READ EEPROM... 
I2C_data = EEPROM_0_Write
GOSUB Write_data
I2C_data = i
GOSUB Write_data
GOSUB StartI2C
I2C_data = EEPROM_0_Read
GOSUB Write_data
shiftin SDA, SCL, msbPre, [I2C_data] 
debug dec i, ",",dec (ABS(I2C_data) * 100)/210, ".", dec (((ABS(I2C_data) * 100)/21) - (((ABS(I2C_data)*100)/210)*10)),13
GOSUB STOPI2C
NEXT
Internal_Address_0 = 0
GOSUB Menudisplay0
goto Main
WRITE_I2C_EEPROM:
GOSUB StartI2C
GOSUB Write_data
I2C_data = EEPROM_Internal_Address
GOSUB Write_data 
I2C_data = data_to_store
GOSUB Write_data 
GOSUB StopI2C
RETURN
DisplayStartupMessage: ' "Lennard Electronics "
GOSUB ClearDisplay ' "www.lennard.net.nz "
start = $0
finish = $12
GOSUB ReadI2CEEPROM_1
GOSUB newline
start = $13
finish = $24
GOSUB ReadI2CEEPROM_1
pause 5000 
RETURN
Menudisplay0: 
GOSUB ClearDisplay '"Sample Memory About"
'Display "Mem = xxx%" on line 1
if Memory_store = NO then skipmemorydisplay
LCDcharacter = 146
GOSUB LCD_Command
LCDCharacter = "M"
GOSUB SendtoLCD
skipmemorydisplay:
GOSUB newline
start = $39
finish = $4C
GOSUB ReadI2CEEPROM_1
RETURN
ReadADC:
if button_pressed = Yes then end_ReadADC
LOW ADC_ENABLE 
SHIFTIN ADC_DATA, ADC_CLOCK, MSBPRE, [datafromAD]
HIGH ADC_ENABLE 
pause 820 'This pause, along with the overheads of other statements, adds up to 1 second between samples. With RTC code, can use the RTC to get a precise reading...
end_ReadADC:
RETURN
DisplayVoltage:
if button_pressed = Yes then skip_DisplayVoltage
LCDcharacter = 128
GOSUB LCD_command
display_data = (ABS(datafromAD) * 100)/21 'Convert byte to temperature
'Display on LCD
call_from_memory_display = NO
GOSUB Display_ADC_and_Memory_Address 
LCDcharacter = "C"
GOSUB SendtoLCD
DispVoltsIcon:
skip_DisplayVoltage:
RETURN
Act_on_button_1:
button_pressed = Yes
branch Menulevel,[Menulevel0_button_1, Menulevel1_button_1, Menulevel2_button_1]
Menulevel0_button_1:
setupsampling:
GOSUB ClearDisplay 'Display reads: "Sample Rate is nnxxx"
start = $4D ' " Adjust OK "
finish = $5A
GOSUB ReadI2CEEPROM_1
GOSUB NewLine
start = $5B
finish = $6B
GOSUB ReadI2CEEPROM_1
GOSUB Display_Sample_Rate
Menulevel = 1
Goto end_Act_on_button_1
Menulevel1_button_1: 
sample_rate = sample_rate + 1 
GOSUB Display_Sample_Rate
Goto end_Act_on_button_1
Menulevel2_button_1:
Memory_store = ~ Memory_store
Menulevel = 0
button_pressed = No
GOSUB Menudisplay0
end_Act_on_button_1:
pause 300
GOTO main
Act_on_button_2:
button_pressed = YES
branch Menulevel,[setupmemorymenu]
setupmemorymenu:
Menulevel = 2
GOSUB ClearDisplay 'Display reads: "On Board Memory "
start = $6C ' "Store Download"
finish = $7A
GOSUB ReadI2CEEPROM_1
GOSUB NewLine
start = $7B
finish = $8E
GOSUB ReadI2CEEPROM_1
GOTO main
Act_on_button_3:
branch Menulevel,[displayfirmware, store_sample_rate, download_memory]
displayfirmware:
Menulevel = 1
GOSUB ClearDisplay
start = $25
finish = $32
GOSUB ReadI2CEEPROM_1
pause 4700
goto end_Act_on_button_3
store_sample_rate:
pause 300
'Store sample_rate in EEPROM_1
I2C_data = EEPROM_1_write
EEPROM_Internal_Address = 255
Data_to_store = sample_rate
GOSUB WRITE_I2C_EEPROM
goto end_Act_on_button_3
download_memory:
Menulevel = 0
button_pressed = No
goto ReadI2CEEPROM_0
end_Act_on_button_3:
Menulevel = 0
GOSUB Menudisplay0
button_pressed = No
GOTO main
Display_Sample_Rate: 
LCDcharacter = 143
GOSUB LCD_command
sample_minutes = 0
start = $B2
branch sample_rate, [sample_rate0,sample_rate1, sample_rate2, sample_rate3, sample_rate4, sample_rate5, sample_rate6, sample_rate7, sample_rate8, sample_rate9]
sample_rate0:
LCDcharacter = "1"
GOSUB SendtoLCD
finish = $B5
GOSUB ReadI2CEEPROM_1
sample_seconds = 1
GOTO end_of_Display_Sample_Rate
sample_rate1:
LCDcharacter = "5"
GOSUB SendtoLCD
finish = $B5
GOSUB ReadI2CEEPROM_1
sample_seconds = 5
GOTO end_of_Display_Sample_Rate
sample_rate2:
LCDcharacter = "1"
GOSUB SendtoLCD
LCDcharacter = "0"
GOSUB SendtoLCD
finish = $B4
GOSUB ReadI2CEEPROM_1
sample_seconds = 10
GOTO end_of_Display_Sample_Rate
sample_rate3:
LCDcharacter = "3"
GOSUB SendtoLCD
LCDcharacter = "0"
GOSUB SendtoLCD
finish = $B4
GOSUB ReadI2CEEPROM_1
sample_seconds = 30
GOTO end_of_Display_Sample_Rate
sample_rate4:
LCDcharacter = "1"
GOSUB SendtoLCD
start = $B6
finish = $B9
GOSUB ReadI2CEEPROM_1
sample_seconds = 60
GOTO end_of_Display_Sample_Rate
sample_rate5:
LCDcharacter = "5"
GOSUB SendtoLCD
start = $B6
finish = $B9
GOSUB ReadI2CEEPROM_1
sample_minutes = 4
sample_seconds = 60
GOTO end_of_Display_Sample_Rate
sample_rate6:
LCDcharacter = "1"
GOSUB SendtoLCD
LCDcharacter = "0"
GOSUB SendtoLCD
start = $B6
finish = $B8
GOSUB ReadI2CEEPROM_1
sample_minutes = 9
sample_seconds = 60
GOTO end_of_Display_Sample_Rate
sample_rate7:
LCDcharacter = "3"
GOSUB SendtoLCD
LCDcharacter = "0"
GOSUB SendtoLCD
start = $B6
finish = $B8
GOSUB ReadI2CEEPROM_1
sample_minutes = 29
sample_seconds = 60
GOTO end_of_Display_Sample_Rate
sample_rate8:
LCDcharacter = "1"
GOSUB SendtoLCD
start = $BA
finish = $BD
GOSUB ReadI2CEEPROM_1
sample_minutes = 59
sample_seconds = 60
GOTO end_of_Display_Sample_Rate
sample_rate9:
sample_rate = 0
GOTO sample_rate0
end_of_Display_Sample_Rate:
seconds = sample_seconds
minutes = sample_minutes
RETURN
decrement_Minutes:
seconds = sample_seconds
if minutes = 0 then Send_data
minutes = minutes - 1
goto Main
Send_data:
minutes = sample_minutes
if Memory_store = NO or Internal_Address_0 = 256 then skip_store_data
I2C_data = EEPROM_0_Write 'Store in EEPROM at device address 000 on I2C bus
EEPROM_Internal_Address = Internal_Address_0
Data_to_store = datafromAD
GOSUB WRITE_I2C_EEPROM
LCDcharacter = 145
GOSUB LCD_command
display_data = ABS(Internal_Address_0) 'Display current Memory address on screen
GOSUB displayMemIcon 
Internal_Address_0 = Internal_Address_0 + 1
skip_store_data:
goto Main
Display_ADC_and_Memory_Address:
'Figure out first digit
LCDcharacter = 48 + (display_data/100)
GOSUB sendtoLCD
if call_from_memory_display = Yes then displayMemIcon
return_from_displayMemIcon:
Second_digit:
'Figure out second digit
LCDcharacter = 48 + ((display_data-((display_data/100)*100))/10)
GOSUB sendtoLCD
LCDcharacter = "."
GOSUB sendtoLCD
Third_digit:
'Figure out third digit
LCDcharacter = 48 + (display_data - (10*(display_data/10)))
GOSUB sendtoLCD
RETURN
displayMemIcon:
LCDcharacter = 147
GOSUB LCD_command
pause 5
lookdown display_data, => [255,203,152,101,51, 25, 0], memlevel
branch memlevel, [mem_100, mem_80, mem_60, mem_40, mem_20, mem_10, mem_0]
mem_100:
LCDcharacter = 2
GOTO Displaylevel
mem_80:
LCDcharacter = 3
GOTO Displaylevel
mem_60:
LCDcharacter = 4
GOTO Displaylevel
mem_40:
LCDcharacter = 5
GOTO Displaylevel
mem_20:
LCDcharacter = 6
GOTO Displaylevel
mem_10:
LCDcharacter = 1
GOTO Displaylevel
mem_0:
LCDcharacter = 0
Displaylevel:
GOSUB sendtoLCD
RETURN
'[END OF SUBROUTINES]