Code:
@ errorlevel -205
'****************************************************************
' Config settings
'****************************************************************
asm
; 18F2550/4550, 20mhz crystal
__CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
DEFINE OSC 48
CLEAR
'****************************************************************
ADCON0 = 0 'Set ADCON0
ADCON1 = %00001111 'Set D i/o
CMCON = 7 'Disable Comparators
CCP1CON = %00001100 'set pwm white - pin12
CCP2CON = %00001100 'set pwm blue - pin12
TRISA = %00000000 'set PORTA as all output
TRISB = %00000011 'set PORTB as all output
TRISC = %01011000 'set PORTC as all output apart from port 6 used for backlight button
PR2 = 249
'T2CON = %00000100 ' Start Timer2, Prescaller 1:1
'****************************************************************
DEFINE LCD_DREG PORTB ' Setup the ports for the LCD (as not set to the default layout as set in PBP)
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 4 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 5 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Set command delay time in us
DEFINE LCD_DATAUS 50 ' Set data delay time in us
'****************************************************************
LCD_BACKLIGHT var PORTB.7 'Set port b .7 for LCD backlight (High = on)
PBUTTON var PORTC.6 'set PORTC.6 for the button for the lcd
SDA_Pin var PORTB.0 'RTC SDA Data pin
SCL_Pin var PORTB.1 'RTC SCL clock pin
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
option var byte
H_butt VAR PORTE.2
M_butt VAR PORTE.0
S_butt VAR PORTE.1
'****************************************************************
i var word 'Misc counter
iv var word
LCD_Mode var word 'LCD light mode
LCD_Timer var word 'Timer for how long the LCD is on for.
LCD_Time var word 'Counter for the timer
LCD_Tmr var word
'****************************************************************
' Temp probes
Temperature var word[4]
Temperature1 var temperature[0]
Temperature2 var Temperature[1]
Temperature3 var Temperature[2]
Temperature4 var Temperature[3]
'****************************************************************
' RTC Variables
'RTC_Msecs var byte
RTC_Secs var byte
RTC_Mins var byte
RTC_Hours var byte
RTC_Day var byte
RTC_WDay var byte
RTC_Month var byte
RTC_Year var byte
RTC_Ctrl var byte
dummy var byte
RTclock var byte[8]
Tick_Tmr var byte
SetupPreset:
RTC_Secs=$00 ' Seconds preset to 00
RTC_Mins=$59 ' Minutes preset
RTC_Hours=$09 ' Hours preset
RTC_WDay=$01 ' Weekday preset to 01
RTC_Day=$12 ' Day preset 12
RTC_Month=$06 ' Months preset to June
RTC_Year=$02 ' Year preset to 2002
RTC_Ctrl=$10
'****************************************************************
' LED variables
' Whites:
W_Min var word 'Min Light value
W_Max var word 'Max Light value
W_Fade_In var word 'Fade in duration
W_Fade_Out var word 'Fade out duration
W_On_Time_H var word 'What time to turn the lights on
W_On_Time_M var word 'What time to turn the lights on
W_Off_Time_H var word 'Time to turn lights off
W_Off_Time_M var word 'Time to turn lights off
' Blues:
B_Min var word 'Min Light value
B_Max var word 'Max Light value
B_Fade_In var word 'Fade in duration
B_Fade_Out var word 'Fade out duration
B_On_Time_H var word 'What time to turn the lights on
B_On_Time_M var word 'What time to turn the lights on
B_Off_Time_H var word 'Time to turn lights off
B_Off_Time_M var word 'Time to turn lights off
'Running fade variables
B_FadeIn_Time var word 'LIVE fade delay time seconds
B_FadeOut_Time var word
W_FadeIn_Time var word
W_FadeOut_Time var word
B_Cnt var word 'Seconds counter for the timing of adjusting the PWM
W_Cnt var word
B_Tick var word
W_Tick var word
'PWM Variables where the current output values are stored
W_PWM var word 'Whites
B_PWM var word 'Royal Blues
'****************************************************************
Blue_Day_Cycle var word 'Store for which part of the day cycle we are in
White_Day_Cycle var word
' Constants for the current running mode cycle for the lights
DAWN con 0
DAY con 1
DUSK con 2
NIGHT con 3
'****************************************************************
'Expendable variables used for misc calculations etc
Vb_1 var word
Vb_2 Var word
Vb_3 var word
Vb_4 var word
'****************************************************************
USBBufferCount Var Byte
Firstsend var byte ' When first connected the pc auto sends data, but we want to READ first otherwise
' the eeprom gets overwritten with zeros as the pc sends a packet we DONT want.
'****************************************************************
' Set default data in internal EEPROM
data @0
data 10 'Whites ON Time HOURS
data 00 'Whites ON Time MINS
data 10 'Whites OFF Time HOURS
data 10 'Whites OFF Time MINS
data 0 'Whites Fade IN duration HOURS
data 5 'Whites Fade IN duration MINS
data 0 'Whites Fade OUT duration HOURS
data 3 'Whites Fade OUT duration MINS
data 0 'Whites MIN Intensity %
data 100 'Whites MAX Intensity %
data 10 'Blues ON Time HOURS
data 0 'Blues ON Time MINS
data 10 'Blues OFF Time HOURS
data 10 'Blues OFF Time MINS
data 0 'Blues Fade IN duration HOURS
data 5 'Blues Fade IN duration MINS
data 0 'Blues Fade OUT duration HOURS
data 5 'Blues Fade OUT duration MINS
data 0 'Blues MIN Intensity %
data 100 'Blues MAX Intensity %
Data @150,74,97,110,70,101,98,77,97,114,65,112,114
' Jan Feb Mar Apr
Data 77,97,121,74,117,110,74,117,108,65,117,103
' May Jun Jul Aug
Data 83,101,112,79,99,116,78,111,118,68,101,99
' Sep Oct Nov Dec
Data 84,117,101,87,101,100,84,104,117,70,114,105
' Tue Wed Thu Fri
Data 83,97,116,83,117,110,77,111,110
' Sat Sun Mon
'****************************************************************
'Setup Interrupts
'****************************************************************
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler USB_Handler
INT_Handler TMR1_INT, _MyTimer, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm
T1CON = %10000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
'****************************************************************
'Setup USB
'****************************************************************
INCLUDE "DT_HID260.pbp"
DEFINE USB_VENDORID 6017
DEFINE USB_PRODUCTID 1969
DEFINE USB_VERSION 1
DEFINE USB_VENDORNAME "CSL Designs"
DEFINE USB_PRODUCTNAME "Aqua-LED"
DEFINE USB_SERIAL "001"
DEFINE USB_INSIZE 64 ; IN report is PIC to PC (8,16,32,64)
DEFINE USB_OUTSIZE 64 ; OUT report is PC to PIC
DEFINE USB_POLLIN 10 ; Polling times in mS, MIN=1 MAX=10
DEFINE USB_POLLOUT 10
'****************************************************************
' Start the program
'****************************************************************
code_start:
' i2cwrite SDA_Pin,scl_pin,$D0,$00,[$00,$00,$00,$59,$19,$24,$08,$00]
I2Cwrite SDA_pin,SCL_pin,$D0,$00,[RTC_Secs,RTC_Mins,RTC_Hours,RTC_WDay,RTC_Day,RTC_Month,RTC_Year,RTC_Ctrl]
Blue_Day_Cycle = DAWN
White_Day_Cycle = DAWN
b_cnt = 0
w_cnt = 0
gosub read_eeprom 'Read in the data needed for the lighting periods
Firstsend = 1
USBBufferCount = 64 'Size of the USB buffer we use
LCD_Mode = 3 'LCD Backlight always ON
LCD_Time = 0 'Both these are used for the duration the backlight
LCD_Tmr = 0 'is on when not in mode 3.
gosub Calc_Fade
high LCD_BACKLIGHT
LCDOUT $FE,1
' Display splash screen
lcdout $FE,$C0," AquaLED V1.0 "
lcdout $FE,$94," (C)2010 M.Jervis "
pause 1000 'wait a seconds so they can see it
lcdout $FE,1 'Clear the screen
'****************************************************************
'Main program loop
'****************************************************************
main:
'Main body of program where we determine which time of day we are in
'*** Do BLUE daily cycle
select case Blue_Day_Cycle
case DAWN
lcdout $FE,$94,"BL: DAWN "
if b_cnt = B_Fadein_time and B_PWM < B_Max then
B_PWM = B_PWM + 1
b_cnt = 0
endif
if B_PWM = b_max then
Blue_Day_Cycle = DAY
endif
case DAY
lcdout $FE,$94,"BL: DAY "
if RTC_Hours = B_Off_Time_H and RTC_Mins = B_Off_Time_M then
Blue_Day_Cycle = DUSK
b_cnt = 0
endif
CASE DUSK
lcdout $FE,$94,"BL: DUSK "
if b_cnt >= B_Fadeout_time and B_PWM > B_Min then
B_PWM = B_PWM - 1
b_cnt = 0
endif
if B_PWM = b_min then
Blue_Day_Cycle = NIGHT
endif
case NIGHT
lcdout $FE,$94,"BL: NIGHT"
if RTC_Hours = B_On_Time_H and RTC_Mins = B_On_Time_M then
Blue_Day_Cycle = DAWN
b_cnt = 0
endif
end select
'*** Do WHITE daily cycle
select case White_Day_Cycle
case DAWN
lcdout $FE,$94+11,"WT: DAWN "
if w_cnt = w_Fadein_time and W_PWM < w_max then
W_PWM = W_PWM + 1
w_cnt = 0
endif
if W_PWM = W_max then White_Day_Cycle = DAY
case DAY
lcdout $FE,$94+11,"WT: DAY "
if RTC_Hours = W_Off_Time_H and RTC_Mins = W_Off_Time_M then
White_Day_Cycle = DUSK
w_cnt = 0
endif
CASE DUSK
lcdout $FE,$94+11,"WT: DUSK "
if w_cnt >= w_Fadeout_time and W_PWM > w_min then
W_PWM = W_PWM - 1
w_cnt = 0
endif
if W_PWM = W_min then White_Day_Cycle = NIGHT
case NIGHT
lcdout $FE,$94+11,"WT: NIGHT"
if RTC_Hours = W_On_Time_H and RTC_Mins = W_On_Time_M then
White_Day_Cycle = DAWN
w_cnt = 0
endif
end select
hpwm 1,W_PWM,1500
hpwm 2,B_PWM,1500
gosub Read_Clock
i = (((RTC_Secs>>4)&$0F)*10)+(RTC_Secs&$0F)
lcdout $FE,$80,"BLUES ",dec3 (B_PWM *100)/255,"%"
lcdout $FE,$C0,"WHITES ",dec3 (W_PWM *100)/255,"%"
gosub USB_Plugged
if TX_READY = 1 and plugged = 1 then gosub SendUSB
if RX_READY = 1 and plugged = 1 then gosub GetUSB
if plugged = 0 then FirstSend = 1 'If we unplug then reset the first read packet as dont want it!
lcdout $FE,$D4+6," ",dec RX_READY
'**** FINSISH BUTTON CODE ****
if PBUTTON = 1 then
LCDOUT $FE,1
goto mainmenu
endif
goto main
'****************************************************************
' LCD Backlight time
' Keeps the LCD backlight on until time is met unless its set to
' always on.
'****************************************************************
LCD_Blight:
if LCD_Mode = 0 then '10 seconds
LCD_Timer = 10
elseif LCD_Mode = 1 then '30 seconds
LCD_Timer = 30
else
LCD_Timer = 60 '1 minute
endif
LCD_Time = LCD_Time + 1
if LCD_Time = 100 then
LCD_Tmr = LCD_Tmr + 1
LCD_Time = 0
endif
if LCD_Tmr >= LCD_Timer then
low LCD_BACKLIGHT
LCD_Tmr = 0
LCD_Time = 0
endif
return
'****************************************************************
' USB Services.
' Send and recieve data packets
'
' Packet sizes are 64 bytes which should cover the amount of
' data we need for now.
'****************************************************************
SendUSB:
for i = 0 to USBBufferCount - 1
read i,USBTXBuffer[i] 'Read the eeprom data and store in the outward bound buffer
next i
SendData:
USBOut 1, USBTXBuffer, USBBufferCount , SendDATA ' if bus available, transmit data
return
GetUSB:
USBin 1, USBRXBuffer, USBBufferCount, Timeout ' if bus available, receive data
if Firstsend = 0 then
for i = 0 to USBBufferCount - 1
write i,USBRXBuffer[i] 'Write the eeprom data received from the PC
next i
gosub Read_eeprom 'Read eeprom data into the variables
else
Firstsend = 0
endif
Timeout:
return
' If USB plugged display USB on the display
USB_Plugged:
if plugged = 0 then
lcdout $FE,$91," "
else
lcdout $FE,$91,"USB"
endif
return
'******************************************************************
' LED Fade calculations
' This routine takes the fade in/out durations and also the min/max
' LED power values and calculates what the duration is between
' changing the PWM value to give us a smooth fade from min to max
Calc_Fade:
vb_1 = ((b_fade_in.highbyte * 60) + b_fade_in.lowbyte) *60 'Get total duration time in seconds
vb_2 = b_max - b_min 'Work out the 'distance' the lights go from min to max
b_fadein_time = vb_1 / vb_2 'Get number of seconds between each PWM change
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then b_fadein_time = b_fadein_time + 1 'If its over half a second then round up
vb_1 = ((b_fade_out.highbyte * 60) + b_fade_out.lowbyte) *60
b_fadeout_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then b_fadeout_time = b_fadeout_time + 1 'If its over half a second then round up
vb_1 = ((w_fade_in.highbyte * 60) + w_fade_in.lowbyte) *60
vb_2 = w_max - w_min
w_fadein_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then w_fadein_time = w_fadein_time + 1 'If its over half a second then round up
vb_1 = ((w_fade_out.highbyte * 60) + w_fade_out.lowbyte) *60
w_fadeout_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then w_fadeout_time = w_fadeout_time + 1 'If its over half a second then round up
return
'Lets say 2 hours (120 mins) & 191 for the fade amount (ie 0 to 255 or 0% to 100% intensity)
'So we need to do:
' convert hours into minutes, then add minutes and then multiply by 60 to convert to seconds
' so: 2 hours = 120 mins + 0 mins * 60 to get 7200 seconds
' The distance is now based on the converted % into the PWM range of 0-255
' calculate the 'distance' the light goes from min to max (0 to 255 in this eg: 75% = 191 so: 191- 0 = 191)
' now divide total seconds by 'distance' ie: 7200 / 191 = 37.69 seconds between each PWM change
' Now we test the milliseconds and if above .5 we round up to the next second
'******************************************************************
' Check current time and adjust the position in the cycle to
' make sure that its where it should be in case of a power failure
' or if the settings are changed via the PC
Check_Lighting:
if rtc_hours < b_on_time_h then 'Are we earlier than the fade in time?
blue_day_cycle = NIGHT 'Yes so set the current mode to night
white_day_cycle = NIGHT
elseif rtc_hours > b_off_time_h then 'Are we later than time off?
vb_1 = b_off_time_h + b_fade_out.highbyte 'need to find out if were actually past the end of the fade out time
vb_2 = b_off_time_m + b_fade_out.lowbyte
if vb_2 > 59 then 'if the minutes are more than 59
vb_1 = vb_1 + 1 'then add 1 to the hour
vb_2 = vb_2 - 60 'Adjust the minutes back to between 0-59
endif
if rtc_hours > vb_1 and rtc_mins > vb_2 then
blue_day_cycle = NIGHT 'Yes so set the current mode to NIGHT
white_day_cycle = NIGHT
else
blue_day_cycle = DUSK 'No, were inbetween so set to DUSK
white_day_cycle = DUSK
vb_1 = rtc_hours - b_off_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - b_off_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
B_PWM = B_max - (vb_3 / b_fadeout_time) 'Divide by the seconds count between each PWM to get how far we are in
vb_1 = rtc_hours - w_off_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - w_off_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
W_PWM = w_max - (vb_3 / w_fadeout_time) 'Divide by the seconds count between each PWM to get how far we are in
endif
else
vb_1 = w_on_time_h + w_fade_in.highbyte 'need to find out if were actually past the end of the fade out time
vb_2 = w_on_time_m + w_fade_in.lowbyte
if vb_2 > 59 then 'if the minutes are more than 59
vb_1 = vb_1 + 1 'then add 1 to the hour
vb_2 = vb_2 - 60 'Adjust the minutes back to between 0-59
endif
if rtc_hours > vb_1 and rtc_mins > vb_2 then
blue_day_cycle = DAY 'Yes so set the current mode to DAY
white_day_cycle = DAY
B_PWM = B_MAX
W_PWM = w_max
else
blue_day_cycle = DAWN 'No, were inbetween so set to DAWN
white_day_cycle = DAWN
vb_1 = rtc_hours - b_on_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - b_on_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
B_PWM = b_min + (vb_3 / b_fadein_time) 'Divide by the seconds count between each PWM to get how far we are in
vb_1 = rtc_hours - w_on_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - w_on_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
W_PWM = w_min + (vb_3 / w_fadein_time) 'Divide by the seconds count between each PWM to get how far we are in
endif
endif
return
'******************************************************************
' Read Eeprom data into variables
Read_eeprom:
read 0,w_on_time_h 'Whites ON time hours
read 1,w_on_time_m 'Whites ON time minutes
read 2,w_off_time_h 'Whites OFF time hours
read 3,w_off_time_m 'Whites OFF time minutes
read 4,w_fade_in.highbyte 'Whites fade IN duration hours
read 5,w_fade_in.lowbyte 'Whites fade IN duration minutes
read 6,w_fade_out.highbyte 'Whites fade IN duration hours
read 7,w_fade_out.lowbyte 'Whites fade IN duration minutes
read 8,w_min 'Whites MIN intensity
read 9,w_max 'Whites MAX intensity
read 10,b_on_time_h 'Whites ON time hours
read 11,b_on_time_m 'Whites ON time minutes
read 12,b_off_time_h 'Whites OFF time hours
read 13,b_off_time_m 'Whites OFF time minutes
read 14,b_fade_in.highbyte 'Whites fade IN duration hours
read 15,b_fade_in.lowbyte 'Whites fade IN duration minutes
read 16,b_fade_out.highbyte 'Whites fade IN duration hours
read 17,b_fade_out.lowbyte 'Whites fade IN duration minutes
read 18,b_min 'Whites MIN intensity
read 19,b_max 'Whites MAX intensity
W_Min = (W_Min *255)/100 'Convert intensity % to real PWM value (from 0-100% to 0-255)
W_Max = (W_Max *255)/100
B_Min = (B_Min *255)/100
B_Max = (B_Max *255)/100
gosub Read_Clock
gosub Check_Lighting
return
'******************************************************************
Read_Clock:
I2CRead SDA_pin,SCL_pin,$D0,$00,[RTC_Secs,RTC_Mins,RTC_Hours,RTC_WDay,RTC_Day,RTC_Month,RTC_Year,RTC_Ctrl]
If RTC_Hours.6=1 then
CounterA=(RTC_Hours>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTC_Hours>>4)&$03
endif
CounterA=CounterA*10+(RTC_Hours&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTC_Hours.6=1 then
LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTC_Mins>>4)&$0F,#RTC_Mins&$0F
i = (((RTC_Hours>>4)&$0F)*10)+(RTC_Hours&$0F)
rtc_hours = i
i = (((RTC_Mins>>4)&$0F)*10)+(RTC_Mins&$0F)
rtc_mins = i
Return
'************************************
MyTimer:
Tick_Tmr = Tick_Tmr + 1
if Tick_Tmr >107 then
Tick_Tmr = 0
b_cnt = b_cnt + 1
W_cnt = W_cnt + 1
endif
@ INT_RETURN
mainmenu:
LCDOUT $FE,$80,"Setup Menu"
lcdout $FE, $C0, "Select Option"
IF Option = 1 THEN lcdout $FE, $D4, "Set Time and Date "
if option = 2 then lcdout $FE, $D4, "op2 "
if option = 3 then lcdout $FE, $D4, "op3 "
if option = 4 then lcdout $FE, $D4, "opt4"
if option = 5 then lcdout $FE, $D4, "Run "
IF PBUTTON THEN Option = option + 1
if option >5 then option = 1
Pause 250
If option = 1 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto setup
endif
endif
If option = 2 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt2
endif
endif
If option = 3 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt3
endif
endif
If option = 4 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt4
endif
endif
If option = 5 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
goto main
endif
endif
Goto mainmenu
Bookmarks