Version:0.9 StartHTML:0000000105 EndHTML:0000089852 StartFragment:0000001119 EndFragment:0000089836 mikroIDE
Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 12

Symbol t_right = PORTB.3
Symbol t_down = PORTB.2
Symbol t_up = PORTB.1
Symbol t_left = PORTB.0
Symbol ledcharge = PORTA.1
Symbol leddischarge = PORTA.5
Symbol charge = PORTC.2
Symbol discharge = PORTC.1
Symbol i2cclock = PORTC.3
Symbol i2cdata = PORTC.4

Define LCD_BITS = 4
Define LCD_DREG = PORTB
Define LCD_DBIT = 4
Define LCD_RSREG = PORTC
Define LCD_RSBIT = 0
Define LCD_EREG = PORTC
Define LCD_EBIT = 5

Const c_right = 1
Const c_up = 2
Const c_down = 3
Const c_left = 4

Dim vin As Word
Dim i As Byte
Dim j As Byte
Dim an0 As Word
Dim vmod As Word
Dim vfinal As Word

Dim v(13As Word
Dim vmax As Word
Dim vmaxdelay As Byte
Dim vmaxnum As Byte

Dim finish As Bit
Dim address As Word
Dim seconds As Byte
Dim minutes As Word
Dim hours As Byte

Dim voltage As Word
Dim voltage1 As Word
Dim voltage2 As Word
Dim cnt As Word
Dim sample As Word

Dim program As Byte
Dim phase As Byte
Dim key As Byte

Dim dischargelimit As Word
Dim signalfiltertype As Byte
Dim peakgap As Byte
Dim peakdetect As Byte
Dim mintime As Byte
Dim minvalue As Word
Dim maxtime As Word

PORTA = 0
PORTB = 0
PORTC = 0
TRISA.1 = 0
TRISA.5 = 0
TRISC.2 = 0
TRISC.1 = 0
AllDigital
ADCON1 = 0x0f
Hseropen 19200
Lcdinit
WaitMs 1000

Gosub loadparameters

newprogram:
Gosub welcome
Gosub selectprogram
If program = 1 Then Gosub prog_charge
If program = 2 Then Gosub prog_discharge
If program = 3 Then Goto prog_cycle
If program = 4 Then Goto prog_setup
If program = 5 Then Gosub prog_setupdefaults
If program = 6 Then Goto prog_memory
Goto newprogram
End

welcome:
Lcdcmdout LcdClear
Lcdout "OshonSoft Cycler"
Lcdcmdout LcdLine2Home
Lcdout "Initializing..."
WaitMs 3000
Return

selectprogram:
phase = 1
Lcdcmdout LcdClear
Lcdout "Select Program:"
loop1:
Lcdcmdout LcdLine2Clear
If phase = 1 Then Lcdout "1-Charge"
If phase = 2 Then Lcdout "2-Discharge"
If phase = 3 Then Lcdout "3-Cycle"
If phase = 4 Then Lcdout "4-Setup"
If phase = 5 Then Lcdout "5-Setup defaults"
If phase = 6 Then Lcdout "6-Memory"
Gosub waitkey
If key = c_down Then
        phase = phase + 1
        If phase = 7 Then phase = 1
        Goto loop1
Endif
If key = c_up Then
        phase = phase - 1
        If phase = 0 Then phase = 6
        Goto loop1
Endif
If key = c_right Then program = phase
If key = c_left Then program = 0
Return

waitkey:
key = 0
If t_right = 1 Then key = c_right
If t_up = 1 Then key = c_up
If t_down = 1 Then key = c_down
If t_left = 1 Then key = c_left
If key = 0 Then Goto waitkey
Gosub debounce
Return

getkey:
key = 0
If t_right = 1 Then key = c_right
If t_up = 1 Then key = c_up
If t_down = 1 Then key = c_down
If t_left = 1 Then key = c_left
If key > 0 Then Gosub debounce
Return

debounce:
If t_right = 1 Then i = 0
If t_up = 1 Then i = 0
If t_down = 1 Then i = 0
If t_left = 1 Then i = 0
i = i + 1
WaitMs 10
If i < 10 Then Goto debounce
Return

scankey:
If t_right = 1 Then key = c_right
If t_up = 1 Then key = c_up
If t_down = 1 Then key = c_down
If t_left = 1 Then key = c_left
Return

initroutine:
Lcdcmdout LcdClear
Lcdout "Starting..."
WaitMs 3000
Gosub getvin
For i = 1 To 12
        v(i) = vin
Next i
vmax = 0
vmaxdelay = 0
vmaxnum = 0
finish = 0
address = 0
seconds = 251
minutes = 0
hours = 0
key = 0
Lcdcmdout LcdClear
Return

prog_discharge:
discharge = 1
leddischarge = 1
Gosub initroutine
Lcdout "Discharging..."
Lcdcmdout LcdLine2Home
While finish = 0
        If signalfiltertype = 1 Then Gosub getvfinal1
        If signalfiltertype = 2 Then Gosub getvfinal2
        If signalfiltertype = 3 Then Gosub getvfinal3
        If vfinal <= dischargelimit Then finish = 1
        Gosub settime
        Gosub showvoltage
        Gosub storeeeprom
        Gosub serialroutine
        If key = c_left Then finish = 1
        key = 0
Wend
Lcdcmdout LcdLine1Clear
Lcdout "Completed!"
discharge = 0
leddischarge = 0
Gosub endroutine
WaitMs 3000
Return

prog_charge:
charge = 1
ledcharge = 1
Gosub initroutine
Lcdout "Charging..."
Lcdcmdout LcdLine2Home
While finish = 0
        If signalfiltertype = 1 Then Gosub getvfinal1
        If signalfiltertype = 2 Then Gosub getvfinal2
        If signalfiltertype = 3 Then Gosub getvfinal3
        If vfinal > vmax Then vmaxdelay = vmaxdelay + 1
        If vmaxdelay = 5 Then
                If vmaxnum < 5 Then vmaxnum = vmaxnum + 1
                vmax = vfinal
                vmaxdelay = 0
        Endif
        If peakdetect = 1 Then
                vfinal = vfinal + peakgap
                If vfinal <= vmax Then finish = 1
                vfinal = vfinal - peakgap
                If vmaxnum < 5 Then finish = 0
        Endif
        If minutes < mintime Then
                finish = 0
                vmax = vfinal
                vmaxdelay = 0
        Endif
        If vfinal < minvalue Then
                finish = 0
                vmax = vfinal
                vmaxdelay = 0
        Endif
        If minutes >= maxtime Then finish = 1
        Gosub settime
        Gosub showvoltage
        Gosub storeeeprom
        Gosub serialroutine
        If key = c_left Then finish = 1
        key = 0
Wend
Lcdcmdout LcdLine1Clear
Lcdout "Completed!"
charge = 0
ledcharge = 0
Gosub endroutine
WaitMs 3000
Return

prog_cycle:
Gosub prog_discharge
WaitMs 10000
Gosub prog_charge
Goto newprogram
Return

prog_setupdefaults:
dischargelimit = 290
signalfiltertype = 3
peakgap = 2
peakdetect = 1
mintime = 5
minvalue = 495
maxtime = 600
Gosub saveparameters
Return

prog_setup:
phase = 1
setuploop:
Lcdcmdout LcdClear
Lcdout "Setup Options:"
Lcdcmdout LcdLine2Clear
If phase = 1 Then Lcdout "1-DischargeLimit"
If phase = 2 Then Lcdout "2-FilterType"
If phase = 3 Then Lcdout "3-PeakGap"
If phase = 4 Then Lcdout "4-PeakDetect"
If phase = 5 Then Lcdout "5-MinTime"
If phase = 6 Then Lcdout "6-MinValue"
If phase = 7 Then Lcdout "7-MaxTime"
Gosub waitkey
If key = c_down Then
        phase = phase + 1
        If phase = 8 Then phase = 1
        Goto setuploop
Endif
If key = c_up Then
        phase = phase - 1
        If phase = 0 Then phase = 7
        Goto setuploop
Endif
If key = c_right Then
        If phase = 1 Then Gosub setup1
        If phase = 2 Then Gosub setup2
        If phase = 3 Then Gosub setup3
        If phase = 4 Then Gosub setup4
        If phase = 5 Then Gosub setup5
        If phase = 6 Then Gosub setup6
        If phase = 7 Then Gosub setup7
        Goto setuploop
Endif
If key = c_left Then Gosub saveparameters
Goto newprogram
Return

setup1:
Lcdcmdout LcdClear
Lcdout "DischargeLimit:"
Lcdcmdout LcdLine2Home
Lcdout #dischargelimit
Lcdout "   "
vfinal = dischargelimit
Gosub showvoltageonly
Gosub waitkey
If key = c_up Then
        If dischargelimit < 1000 Then dischargelimit = dischargelimit + 5 Else dischargelimit = 10
        Goto setup1
Endif
If key = c_down Then
        If dischargelimit > 10 Then dischargelimit = dischargelimit - 5 Else dischargelimit = 1000
        Goto setup1
Endif
Return

setup2:
Lcdcmdout LcdClear
Lcdout "FilterType:"
Lcdcmdout LcdLine2Home
Lcdout #signalfiltertype
Lcdout "   "
If signalfiltertype = 1 Then Lcdout "Raw values"
If signalfiltertype = 2 Then Lcdout "Average LO"
If signalfiltertype = 3 Then Lcdout "Average HI"
Gosub waitkey
If key = c_up Then
        If signalfiltertype < 3 Then signalfiltertype = signalfiltertype + 1
        Goto setup2
Endif
If key = c_down Then
        If signalfiltertype > 1 Then signalfiltertype = signalfiltertype - 1
        Goto setup2
Endif
Return

setup3:
Lcdcmdout LcdClear
Lcdout "PeakGap:"
Lcdcmdout LcdLine2Home
Lcdout #peakgap
Lcdout "   "
vfinal = peakgap
Gosub showvoltageonly
Gosub waitkey
If key = c_up Then
        If peakgap < 10 Then peakgap = peakgap + 1 Else peakgap = 1
        Goto setup3
Endif
If key = c_down Then
        If peakgap > 1 Then peakgap = peakgap - 1 Else peakgap = 10
        Goto setup3
Endif
Return

setup4:
Lcdcmdout LcdClear
Lcdout "PeakDetect:"
Lcdcmdout LcdLine2Home
Lcdout #peakdetect
Lcdout "   "
If peakdetect = 0 Then Lcdout "Off"
If peakdetect = 1 Then Lcdout "On "
Gosub waitkey
If key = c_up Then
        peakdetect = 1
        Goto setup4
Endif
If key = c_down Then
        peakdetect = 0
        Goto setup4
Endif
Return

setup5:
Lcdcmdout LcdClear
Lcdout "MinTime:"
Lcdcmdout LcdLine2Home
Lcdout #mintime, " min"
Gosub waitkey
If key = c_up Then
        If mintime < 60 Then mintime = mintime + 1 Else mintime = 1
        Goto setup5
Endif
If key = c_down Then
        If mintime > 1 Then mintime = mintime - 1 Else mintime = 60
        Goto setup5
Endif
Return

setup6:
Lcdcmdout LcdClear
Lcdout "MinValue:"
Lcdcmdout LcdLine2Home
Lcdout #minvalue
Lcdout "   "
vfinal = minvalue
Gosub showvoltageonly
Gosub waitkey
If key = c_up Then
        If minvalue < 1000 Then minvalue = minvalue + 5 Else minvalue = 10
        Goto setup6
Endif
If key = c_down Then
        If minvalue > 10 Then minvalue = minvalue - 5 Else minvalue = 1000
        Goto setup6
Endif
Return

setup7:
Lcdcmdout LcdClear
Lcdout "MaxTime:"
Lcdcmdout LcdLine2Home
Lcdout #maxtime, " min"
Gosub waitkey
If key = c_up Then
        If maxtime < 1000 Then maxtime = maxtime + 5 Else maxtime = 10
        Goto setup7
Endif
If key = c_down Then
        If maxtime > 10 Then maxtime = maxtime - 5 Else maxtime = 1000
        Goto setup7
Endif
Return

loadparameters:
address = 30000
I2CRead i2cdata, i2cclock, 0xa0, address, dischargelimit.LB, dischargelimit.HB
address = 30002
I2CRead i2cdata, i2cclock, 0xa0, address, signalfiltertype
address = 30003
I2CRead i2cdata, i2cclock, 0xa0, address, peakgap
address = 30004
I2CRead i2cdata, i2cclock, 0xa0, address, peakdetect
address = 30005
I2CRead i2cdata, i2cclock, 0xa0, address, mintime
address = 30006
I2CRead i2cdata, i2cclock, 0xa0, address, minvalue.LB, minvalue.HB
address = 30008
I2CRead i2cdata, i2cclock, 0xa0, address, maxtime.LB, maxtime.HB
If dischargelimit < 10 Then dischargelimit = 10
If dischargelimit > 1000 Then dischargelimit = 1000
If signalfiltertype < 1 Then signalfiltertype = 1
If signalfiltertype > 3 Then signalfiltertype = 3
If peakgap < 1 Then peakgap = 1
If peakgap > 10 Then peakgap = 10
If peakdetect > 1 Then peakdetect = 1
If mintime < 1 Then mintime = 1
If mintime > 60 Then mintime = 60
If minvalue < 10 Then minvalue = 10
If minvalue > 1000 Then minvalue = 1000
If maxtime < 10 Then maxtime = 10
If maxtime > 1000 Then maxtime = 1000
Return

saveparameters:
address = 30000
I2CWrite i2cdata, i2cclock, 0xa0, address, dischargelimit.LB, dischargelimit.HB
WaitMs 20
address = 30002
I2CWrite i2cdata, i2cclock, 0xa0, address, signalfiltertype
WaitMs 20
address = 30003
I2CWrite i2cdata, i2cclock, 0xa0, address, peakgap
WaitMs 20
address = 30004
I2CWrite i2cdata, i2cclock, 0xa0, address, peakdetect
WaitMs 20
address = 30005
I2CWrite i2cdata, i2cclock, 0xa0, address, mintime
WaitMs 20
address = 30006
I2CWrite i2cdata, i2cclock, 0xa0, address, minvalue.LB, minvalue.HB
WaitMs 20
address = 30008
I2CWrite i2cdata, i2cclock, 0xa0, address, maxtime.LB, maxtime.HB
WaitMs 20
Return

getvin:
vin = 0
For i = 1 To 60
        Adcin 0, an0
        vin = vin + an0
        Gosub scankey
        WaitMs 83
Next i
vmod = vin Mod 60
vin = vin / 60
If vmod >= 30 Then vin = vin + 1
Return

getvfinal1:
Gosub getvin
vfinal = vin
Return

getvfinal2:
For i = 1 To 5
        j = i + 1
        v(i) = v(j)
Next i
Gosub getvin
v(6) = vin
vfinal = 0
For i = 1 To 6
        vfinal = vfinal + v(i)
Next i
vmod = vfinal Mod 6
vfinal = vfinal / 6
If vmod >= 3 Then vfinal = vfinal + 1
Return

getvfinal3:
For i = 1 To 11
        j = i + 1
        v(i) = v(j)
Next i
Gosub getvin
v(12) = vin
vfinal = 0
For i = 1 To 12
        vfinal = vfinal + v(i)
Next i
vmod = vfinal Mod 12
vfinal = vfinal / 12
If vmod >= 6 Then vfinal = vfinal + 1
Return

showvoltage:
'0V=0  2.5V=1023  2500/1023=2.444
voltage = (vfinal * 2) + (vfinal * 4 / 10)
voltage = voltage + (vfinal * 4 / 100) + (vfinal * 4 / 1000)
voltage1 = voltage / 1000
voltage2 = voltage Mod 1000
Lcdcmdout LcdLine2Clear
Lcdout #voltage1, "."
If voltage2 < 100 Then Lcdout "0"
If voltage2 < 10 Then Lcdout "0"
Lcdout #voltage2, "V  "
hours = minutes / 60
If hours < 10 Then Lcdout "0"
Lcdout #hours, ":"
hours = minutes Mod 60
If hours < 10 Then Lcdout "0"
Lcdout #hours, ":"
If seconds < 10 Then Lcdout "0"
Lcdout #seconds
Return

showvoltageonly:
'0V=0  2.5V=1023  2500/1023=2.444
voltage = (vfinal * 2) + (vfinal * 4 / 10)
voltage = voltage + (vfinal * 4 / 100) + (vfinal * 4 / 1000)
voltage1 = voltage / 1000
voltage2 = voltage Mod 1000
Lcdout #voltage1, "."
If voltage2 < 100 Then Lcdout "0"
If voltage2 < 10 Then Lcdout "0"
Lcdout #voltage2, "V"
Return

serialroutine:
Hserout #vfinal, Lf
Return

endroutine:
address = address + 2
I2CWrite i2cdata, i2cclock, 0xa0, address, 255255
address = address - 2
Return

storeeeprom:
address = address + 2
I2CWrite i2cdata, i2cclock, 0xa0, address, vfinal.LB, vfinal.HB
Return

settime:
seconds = seconds + 5
If seconds >= 60 Then
        seconds = 0
        minutes = minutes + 1
Endif
Return

prog_memory:
finish = 0
While finish = 0
        Lcdcmdout LcdClear
        Lcdout "Memory Ready..."
        Gosub waitkey
        If key = c_left Then finish = 1
        If key = c_right Then
                For cnt = 2 To 20000 Step 2
                        I2CRead i2cdata, i2cclock, 0xa0, cnt, sample.LB, sample.HB
                        If sample = 65535 Then Goto exit2
                        Hserout #sample, Lf
                Next cnt
                exit2:
                address = cnt - 2
        Endif
Wend
Goto newprogram
Return