PK ‘îI I PIC\controller.mcp[HEADER]
magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13}
file_version=1.0
device=PIC16F1827
[PATH_INFO]
BuildDirPolicy=BuildDirIsProjectDir
dir_src=
dir_bin=
dir_tmp=
dir_sin=
dir_inc=
dir_lib=
dir_lkr=
[CAT_FILTERS]
filter_src=*.asm
filter_inc=*.h;*.inc
filter_obj=*.o
filter_lib=*.lib
filter_lkr=*.lkr
[CAT_SUBFOLDERS]
subfolder_src=
subfolder_inc=
subfolder_obj=
subfolder_lib=
subfolder_lkr=
[FILE_SUBFOLDERS]
file_000=.
file_001=.
file_002=.
file_003=.
file_004=.
file_005=.
file_006=.
[GENERATED_FILES]
file_000=no
file_001=no
file_002=no
file_003=no
file_004=no
file_005=no
file_006=no
[OTHER_FILES]
file_000=no
file_001=no
file_002=no
file_003=no
file_004=no
file_005=no
file_006=no
[FILE_INFO]
file_000=main.asm
file_001=timer.asm
file_002=display.asm
file_003=motor.asm
file_004=temp.asm
file_005=eeprom.asm
file_006=jobeaux.inc
[SUITE_INFO]
suite_guid={6B3DAA78-59C1-46DD-B6AA-DBDAE4E06484}
suite_state=generate-relocatable-code
[TOOL_SETTINGS]
TS{DD2213A8-6310-47B1-8376-9430CDFC013F}=
TS{BFD27FBA-4A02-4C0E-A5E5-B812F3E7707C}=/o"$(BINDIR_)$(TARGETBASE).cof" /M"$(BINDIR_)$(TARGETBASE).map" /W
TS{ADE93A55-C7C7-4D4D-A4BA-59305F7D0391}=
[INSTRUMENTED_TRACE]
enable=0
transport=0
format=0
[CUSTOM_BUILD]
Pre-Build=
Pre-BuildEnabled=1
Post-Build=
Post-BuildEnabled=1
PK 4Hš š PIC\main.asm LIST p=16f1827
;==========================================================================
; Jobeaux Processor Main Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "Main Module"
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF
__config _CONFIG2, _WRT_OFF & _PLLEN_OFF & _LVP_OFF
EXTERN InitMotor, InitHeater, InitTimer, InitDisplay
EXTERN InitTempDisplay, ConfigureUnits
EXTERN ReadSpeed, ReadTemp, ReadReset
EXTERN TendMotor, TendHeater, TendDisplay
EXTERN DisplaySplash, StartMotor
EXTERN TimerIntHandler, RotIntHandler
EXTERN msDelay
;==========================================================================
; RESET VECTOR
; Program execution starts at location 0 on reset
;==========================================================================
BOOT CODE 0x0000
pagesel Start
goto Start
;==========================================================================
; INTERRUPT VECTOR
; Interrupt vector is at location 4
;==========================================================================
INTR CODE 0x0004
pagesel IntHandler
goto IntHandler
;==========================================================================
; MAIN code body.
; This can be anywhere - linker decides.
;==========================================================================
MAIN CODE
;==========================================================================
; Interrupt handler
; Hand off to timer and direction sensor interrupt handlers.
; It is the responsibility of each individual inteerupt routine to
; determine if its interrupt was actually requested.
;==========================================================================
IntHandler:
pagesel TimerIntHandler
call TimerIntHandler
pagesel RotIntHandler
call RotIntHandler
retfie
;==========================================================================
; Main Program Code
; Initialize all devices then enter main polling loop
;==========================================================================
Start:
pagesel InitWorld
call InitWorld
call CheckSetup ; Holding SW3 at power on allows setting F/C
call DisplaySplash
; Reinitialize the timer so it starts at 00:00:00 after splash screen
pagesel InitTimer
call InitTimer
call StartMotor
; This is where all the work gets done.
Loop:
pagesel ReadSpeed
call ReadSpeed
pagesel ReadTemp
call ReadTemp
pagesel ReadReset
call ReadReset
pagesel TendMotor
call TendMotor
pagesel TendHeater
call TendHeater
pagesel TendDisplay
call TendDisplay
goto Loop
;==========================================================================
; Initialize the world on power up
;==========================================================================
InitWorld:
call InitCPU
pagesel InitDisplay
call InitDisplay
pagesel InitTempDisplay
call InitTempDisplay
pagesel InitTimer
call InitTimer
pagesel InitHeater
call InitHeater
pagesel InitMotor
call InitMotor
return
;==========================================================================
; Initialize the CPU I/O ports and other settings
;
; Digital Inputs: RA6, RB0
; Digital Outputs: RA2, RA4, RB5
; Analog Inputs: AN0, AN11
; PWM Outputs: P1A
; ADC Voltage ref Input: VREF+
; SPI Interface (all outputs): RA1, RA7, SCK1, SDO1
; 32,768 KHz Timer1 clock: T1OSI, T1OSO
; Internal Processor clock speed: 4MHz
; Timer1 generates interrupt @ 1 second intervals
; Modifies: bank
;==========================================================================
InitCPU:
; Set up I/O pins
; Inputs/Outputs:
banksel TRISA ; Bank 1
movlw B'00111001' ; TRISA0 | TRISA3 | TRISA4 | TRISA5 inputs
movwf TRISA
movlw B'11000011' ; TRISB0 | TRISB1 | TRISB6 | TRISB7 inputs
movwf TRISB
; Internal pullup on RA5 (Still Bank 1)
bcf OPTION_REG, NOT_WPUEN
; Configure ADC (also on Bank 1)
movlw B'10010010' ; Right Justify, Fosc/8, Vref=VREF+/Vss
movwf ADCON1
; Finish internal pullup configuration
banksel WPUA ; Bank 4
bsf WPUA, WPUA5 ; RA5 ON
movlw B'00000000' ; RB* OFF
movwf WPUB
; Analog inputs:
banksel ANSELA ; Bank 3
movlw B'00000001' ; ANSA0
movwf ANSELA
movlw B'00000010' ; ANSB1
movwf ANSELB
; Enable 32KHz crystal
banksel T1CON ; Bank 0
movlw B'00001100' ; Enable LP oscillator, don't sync
movwf T1CON
; Initialize outputs (also Bank 0)
movlw B'10000100' ; /CSB=1, RS=0, Direction=1, Brake=0
movwf PORTA
movlw B'00010010' ; Motor Ctl=0, Heater Ctl=1, SDO1=0, SCK1=1
movwf PORTB
; Configure SPI
banksel SSP1CON1 ; Bank 4
movlw B'00110000' ; Enable, Idle hi, 1MHz clock
movwf SSP1CON1
; Configure rotation sensor interrupt detector
banksel IOCBP ; Bank 7
movlw B'00000001' ; Int on rising edge of RB0
movwf IOCBP
movwf IOCBN ; Also int on falling edge of RB0
; Select CPU clock speed by setting IRCF<3:0> bits of OSCCON
banksel OSCCON ; Bank 1
movlw B'01101010' ; 4MHz, int osc
movwf OSCCON
; Wait for HF osc to be ready
btfss OSCSTAT, HFIOFR
goto $-1
; Give the LP oscillator 40 msec to start
movlw 40
pagesel msDelay
call msDelay
; Set up Timer2 for PWM operation
banksel T2CON ; Bank 0
movlw B'00000001' ; Prescaler is 4
movwf T2CON
movlw PWM_PERIOD
movwf PR2 ; Set PWM period
; Set CCP1 configuration for PWM operation
banksel CCP1CON ; Bank 5
movlw B'00001100' ; Single output, PWM Mode, active hi
movwf CCP1CON
movlw B'00000001' ; Output goes to P1A
movwf PSTR1CON
; Set up Timer1
; Make sure there's no current int request -
; Clear TMR1IF in PIR1 register
banksel PIR1 ; Bank 0
bcf PIR1, TMR1IF
; Is LP oscillator ready?
btfss OSCSTAT, T1OSCR
goto useIntClock ; No. Use internal clock for timer
movlw B'10001100' ; Source is oscillator, 1:1
movwf T1CON
; Initialize Timer1 for 32.768 KHz clock
; Same bank as PIR1
movlw T1_LP_START_HI
movwf TMR1H
movlw T1_LP_START_LO
movwf TMR1L
goto enableT1
useIntClock:
; Oscillator not working for some reason. Use instruction clock
; as Timer1 clock. This will be less accurate than the crystal...
movlw B'00110000' ; Source is instr clock, 1:8, LP osc off
movwf T1CON
; Initialize timer for 125KHz clock
movlw T1_IC_START_HI
movwf TMR1H
movlw T1_IC_START_LO
movwf TMR1L
enableT1:
; Now enable Timer1 interrupt by
; setting TMR1IE in PIE1 register
banksel PIE1 ; Bank 1
bsf PIE1, TMR1IE
; Enable interrupts
movlw B'11001000' ; IOCIE, PEIE, GIE
movwf INTCON
; Turn Timer1 & Timer2 on
banksel T1CON ; Bank 0
bsf T1CON, TMR1ON
clrf T1GCON
bsf T2CON, TMR2ON
return
;==========================================================================
; Check if SW3 is pressed.
; This funtion is called just before the splash screen is displayed, so
; if SW3 is held at power on, we will see it here.
; Modifies: bank, page
;==========================================================================
CheckSetup:
banksel TIMER_RESET_PORT ; Bank 0
btfsc TIMER_RESET_PORT, TIMER_RESET_IN
return ; Not pressed
; Button is pressed!
pagesel ConfigureUnits
call ConfigureUnits
return
end
PK }+Õ6 6
PIC\timer.asm;==========================================================================
; Jobeaux Processor Timer Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "Timer Module"
GLOBAL InitTimer, ReadReset, TimerIntHandler
GLOBAL DisplayTimer, OKUpdate
EXTERN StopTicks
MAX_SEC EQU 0x60
MAX_MIN EQU 0x60
MAX_HRS EQU 0xA0
BCD_BUMP EQU 7
;==========================================================================
; The clock is stored as a BCD value in 3 bytes (HH:MM:SS)
; This makes generating the display a little easier
; (no divide by 10), but makes incrementing the value in the ISR
; a little more involved.
; These values are stored in shared RAM (Common RAM), and that helps
; reduce the overhead in the interrupt handler a little
; (saves a banksel)
;==========================================================================
UDATA_SHR
Hours RES 1
Minutes RES 1
Seconds RES 1
Maxed RES 1
Ticker RES 1 ; Fractional second counter
OKUpdate RES 1
TIMER CODE
;==========================================================================
; Initialize the timer to 00:00:00
; Modifies: bank
;==========================================================================
InitTimer:
bcf INTCON, GIE ; Disable Interrupts
clrf Hours
clrf Minutes
clrf Seconds
clrf Maxed
movlw TICKS_PER_SEC
movwf Ticker
; Reset the counter
banksel T1CON ; Bank 0
bcf T1CON, TMR1ON ; Stop Timer1
btfss T1CON, TMR1CS1 ; Which clock is running?
goto instClockInit ; Internal
; Running on LP clock.
movlw T1_LP_START_HI ; Set to initial value
movwf TMR1H
movlw T1_LP_START_LO
movwf TMR1L
goto restartTimer
instClockInit:
; Instruction clock/8
movlw T1_IC_START_HI
movwf TMR1H
movlw T1_IC_START_LO
movwf TMR1L
restartTimer:
bsf T1CON, TMR1ON ; Restart Timer1
bsf INTCON, GIE ; Enable Interrupts
return
;==========================================================================
; Read the setting of the timer reset switch.
; Timer reset switch is on RA4
; If it is pressed, reset the timer value to 00:00:00
; Modifies: bank, page
;==========================================================================
ReadReset:
banksel TIMER_RESET_PORT ; Bank 0
btfsc TIMER_RESET_PORT, TIMER_RESET_IN
return
pagesel InitTimer ; Button is pressed!
call InitTimer
movlw 1
movwf OKUpdate ; Update the display next opportunity
return
;==========================================================================
; Process a Timer1 interrupt
; These occur once a second.
; The timer value is incremented and the interrupt is cleared.
; Modifies: bank
;==========================================================================
TimerIntHandler:
; Verify Timer1 requesting interrupt
banksel PIR1 ; Bank 0
btfss PIR1, TMR1IF
return ; Not set - must be someone else
movlw 1
movwf OKUpdate ; Update the display next opportunity
; Clear the interrupt request (TMR1IF in PIR1 register)
bcf PIR1, TMR1IF
btfss T1CON, TMR1CS1 ; Which clock is running?
goto instClockHandler ; Internal
; LP Clock -
; Reset Timer1 to initial value
; Same bank as PIR1
movlw T1_LP_START_HI
movwf TMR1H
movlw T1_LP_START_LO
addwf TMR1L, F
goto checkClock
instClockHandler:
; Running on internal clock.
; Reset the counter
movlw T1_IC_START_HI
movwf TMR1H
; Due to interrupt overhead and fast clock, low byte may have
; incremented already, throwing the timing off. This gets us
; closer...
movlw T1_IC_START_LO
addwf TMR1L, F
checkClock:
movf StopTicks, F
btfss STATUS, Z ; If the motor is waiting
decf StopTicks, F ; tell it the clock ticked
decfsz Ticker, F ; Count the ticks til we get to 1 sec
return
movlw TICKS_PER_SEC ; A second has elapsed! Reset counter
movwf Ticker
; Is the clock maxed out?
btfsc Maxed, 1
return ; Yes - Just leave it there
; Increment the clock (BCD values)
movfw Seconds
andlw 0x0F
sublw 0x09 ; Low nibble @ 9?
btfsc STATUS, Z
goto secwrap
incf Seconds, F ; No, just increment
return
secwrap:
movfw Seconds
addlw BCD_BUMP ; (9+7) = 16: low nibble = 0, hi += 1
movwf Seconds
sublw MAX_SEC ; Have we hit the next minute?
btfss STATUS, Z
return ; No. Done.
clrf Seconds ; Yes. Clear seconds & inc minutes
movfw Minutes
andlw 0x0F
sublw 0x09 ; Low nibble @ 9?
btfsc STATUS, Z
goto minwrap
incf Minutes, F ; No, just increment
return
minwrap:
movfw Minutes
addlw BCD_BUMP ; (9+7) = 16: low nibble = 0, hi += 1
movwf Minutes
sublw MAX_MIN ; Have we hit the next hour?
btfss STATUS, Z
return ; No. Done.
clrf Minutes ; Yes. Clear minutes & inc hours
movfw Hours
andlw 0x0F
sublw 0x09 ; Low nibble @ 9?
btfsc STATUS, Z
goto hrwrap
incf Hours, F ; No, just increment
return
hrwrap:
movfw Hours
addlw BCD_BUMP ; (9+7) = 16: low nibble = 0, hi += 1
movwf Hours
sublw MAX_HRS ; Have we maxed out?
btfsc STATUS, Z
bsf Maxed, 1 ; Yes. Set flag
return ; Done.
;==========================================================================
; Display the current timer value
; Actually just returns the character for the current column (in W)
; and the calling routine does the output
;==========================================================================
DisplayTimer:
brw
retlw ' ' ; Column 0
retlw ' ' ; Column 1
retlw ' ' ; Column 2
retlw ' ' ; Column 3
goto htens ; Column 4: Hours tens digit
goto hones ; Column 5: Hours ones digit
retlw ':' ; Column 6: Separator
goto mtens ; Column 7: Minutes tens digit
goto mones ; Column 8: Minutes ones digit
retlw ':' ; Column 9: Separator
goto stens ; Column 10: Seconds tens digit
goto sones ; Column 11: Seconds ones digit
retlw ' ' ; Column 12
goto timerIndicator ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
htens:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Hours ; Get current hours value
tensdigit:
swapf WREG, W ; Put the tens digit in the low nibble
onesdigit:
andlw 0x0F ; Mask it
addlw '0' ; and make it ASCII
return
hones:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Hours
goto onesdigit
mtens:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Minutes
goto tensdigit
mones:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Minutes
goto onesdigit
stens:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Seconds
goto tensdigit
sones:
; Is the clock maxed out?
btfsc Maxed, 1
retlw '*' ; Yes - Display *
movfw Seconds
goto onesdigit
timerIndicator:
; Indicate if we're running on the internal timer so the user knows
; it may not be as accurate as he wants
banksel T1CON
btfss T1CON, TMR1CS1 ; Which clock is running?
retlw INTERNAL_CLOCK_IND ; Internal
retlw ' ' ; LP crystal oscillator
end
PK V:«Om4 m4 PIC\display.asm;==========================================================================
; Jobeaux Processor Display Driver Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "Display Driver Module"
GLOBAL InitDisplay, TendDisplay, DisplaySplash
GLOBAL msDelay
GLOBAL DisplaySetupScreen
EXTERN CheckWaterLevel
EXTERN DisplayTimer, DisplaySetTemp, DisplayCurTemp, DisplayLowTemp
EXTERN CountToTemp
EXTERN SetupScr1, SetupScr2, SetupScr3
EXTERN OKUpdate
;==========================================================================
; Shared variables for cursor position
;==========================================================================
UDATA_SHR
Column RES 1
DelayCounter RES 1
UDATA
LoopCounter RES 1
DISPLAY CODE
;==========================================================================
; Update the display
; Modifies: bank, page
;==========================================================================
TendDisplay:
; Set Data Mode
banksel LCD_MODE_PORT ; Bank 0
bsf LCD_MODE_PORT, LCD_MODE_OUT
; If water level is too low, display warning message
pagesel CheckWaterLevel
call CheckWaterLevel
btfss WREG, 0
goto DisplayWarning
movf OKUpdate, F ; Only update if the timer has ticked
btfsc STATUS, Z
return
clrf OKUpdate
; Line 1 = Desired Temp
movlw 0 ; 0 = Convert Desired temp
pagesel CountToTemp
call CountToTemp
clrf Column
setloop:
movfw Column
incf Column, F
pagesel DisplaySetTemp
call DisplaySetTemp ; Get next char for line 1
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto setloop
; Line 2 = Current Temp
clrf Column
movlw 1 ; 1 = Convert Current temp
pagesel CountToTemp
call CountToTemp
andlw 0xFF
btfss STATUS, Z
goto curloop ; Valid conversion
; Current temperature is below display range
lowTemp:
movfw Column
incf Column, F
pagesel DisplayLowTemp
call DisplayLowTemp ; Get next char for line 2
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto lowTemp
goto dispTimer
curloop:
movfw Column
incf Column, F
pagesel DisplayCurTemp
call DisplayCurTemp ; Get next char for line 2
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto curloop
dispTimer:
; Line 3 = Timer
clrf Column
timerloop:
movfw Column
incf Column, F
pagesel DisplayTimer
call DisplayTimer ; Get next char for line 3
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto timerloop
return
;==========================================================================
; Display a warning message that the water level is too low
; Modifies: bank, page
;==========================================================================
DisplayWarning:
clrf Column
warn1:
movfw Column
incf Column, F
pagesel Warning1
call Warning1 ; Get next char for line 1
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto warn1
clrf Column
warn2:
movfw Column
incf Column, F
pagesel Warning2
call Warning2 ; Get next char for line 2
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto warn2
clrf Column
warn3:
movfw Column
incf Column, F
pagesel Warning3
call Warning3 ; Get next char for line 3
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto warn3
return
;==========================================================================
; Warning1: Line 1 of low water level warning
;==========================================================================
Warning1:
brw
retlw '*' ; Column 0
retlw '*' ; Column 1
retlw '*' ; Column 2
retlw ' ' ; Column 3
retlw ' ' ; Column 4
retlw 'C' ; Column 5
retlw 'h' ; Column 6
retlw 'e' ; Column 7
retlw 'c' ; Column 8
retlw 'k' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw '*' ; Column 13
retlw '*' ; Column 14
retlw '*' ; Column 15
;==========================================================================
; Warning2: Line 2 of low water level warning
;==========================================================================
Warning2:
brw
retlw '*' ; Column 0
retlw '*' ; Column 1
retlw '*' ; Column 2
retlw ' ' ; Column 3
retlw ' ' ; Column 4
retlw 'W' ; Column 5
retlw 'a' ; Column 6
retlw 't' ; Column 7
retlw 'e' ; Column 8
retlw 'r' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw '*' ; Column 13
retlw '*' ; Column 14
retlw '*' ; Column 15
;==========================================================================
; Warning3: Line 3 of low water level warning
;==========================================================================
Warning3:
brw
retlw '*' ; Column 0
retlw '*' ; Column 1
retlw '*' ; Column 2
retlw ' ' ; Column 3
retlw ' ' ; Column 4
retlw 'L' ; Column 5
retlw 'e' ; Column 6
retlw 'v' ; Column 7
retlw 'e' ; Column 8
retlw 'l' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw '*' ; Column 13
retlw '*' ; Column 14
retlw '*' ; Column 15
;==========================================================================
; Display a splash screen on the LCD for 5 seconds
; Modifies: bank, page
;==========================================================================
DisplaySplash:
clrf Column
spl1:
movfw Column
incf Column, F
pagesel Splash1
call Splash1 ; Get next char for line 1
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto spl1
clrf Column
spl2:
movfw Column
incf Column, F
pagesel Splash2
call Splash2 ; Get next char for line 2
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto spl2
clrf Column
spl3:
movfw Column
incf Column, F
pagesel Splash3
call Splash3 ; Get next char for line 3
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto spl3
; Wait 5 seconds (50 * 100 msec)
movlw 50
banksel LoopCounter
movwf LoopCounter
splashDelay:
movlw 100
pagesel msDelay
call msDelay
decfsz LoopCounter, F
goto splashDelay
return
;==========================================================================
; Splash1: Line 1 of splash screen
;==========================================================================
Splash1:
brw
retlw 'J' ; Column 0
retlw 'o' ; Column 1
retlw 'b' ; Column 2
retlw 'e' ; Column 3
retlw 'a' ; Column 4
retlw 'u' ; Column 5
retlw 'x' ; Column 6
retlw ' ' ; Column 7
retlw ' ' ; Column 8
retlw ' ' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; Splash2: Line 2 of splash screen
;==========================================================================
Splash2:
brw
retlw 'P' ; Column 0
retlw 'r' ; Column 1
retlw 'o' ; Column 2
retlw 'c' ; Column 3
retlw 'e' ; Column 4
retlw 's' ; Column 5
retlw 's' ; Column 6
retlw 'o' ; Column 7
retlw 'r' ; Column 8
retlw ' ' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; Splash3: Line 3 of splash screen
;==========================================================================
Splash3:
brw
retlw 'R' ; Column 0
retlw 'e' ; Column 1
retlw 'v' ; Column 2
retlw ' ' ; Column 3
retlw '0' ; Column 4
retlw '.' ; Column 5
retlw '0' ; Column 6
retlw ' ' ; Column 7
retlw ' ' ; Column 8
retlw ' ' ; Column 9
retlw ' ' ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; Display the setup screen to allow user to configure temp units
; Modifies: bank, page
;==========================================================================
DisplaySetupScreen:
clrf Column
setup1:
movfw Column
incf Column, F
pagesel SetupScr1
call SetupScr1 ; Get next char for line 1
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto setup1
clrf Column
setup2:
movfw Column
incf Column, F
pagesel SetupScr2
call SetupScr2 ; Get next char for line 2
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto setup2
clrf Column
setup3:
movfw Column
incf Column, F
pagesel SetupScr3
call SetupScr3 ; Get next char for line 3
pagesel LCDOut
call LCDOut
movfw Column
andlw 0x0F
btfss STATUS, Z
goto setup3
return
;==========================================================================
; Output a byte (command or data) to the display
; Caller must set RA1 output to indicate cmd/data
; Byte to be sent is in W
; Returns with W unchanged, Bank 0 selected
;==========================================================================
LCDOut:
; Set Chip Select
banksel LCD_ENABLE_PORT ; Bank 0
bcf LCD_ENABLE_PORT, LCD_ENABLE_OUT
; Send the char
banksel SSP1BUF ; Bank 4
movwf SSP1BUF
; Wait for completion
btfss SSP1STAT, BF
goto $-1
; Deassert Chip Select
banksel LCD_ENABLE_PORT ; Bank 0
bsf LCD_ENABLE_PORT, LCD_ENABLE_OUT
; Most commands take about 20 usec to complete
; There's 10 usec overhead in the call and return
; so let's waste the other 10 here just to be safe
; For those that take longer (Clear Display, Home),
; the caller must add appropriate delay
goto $+1 ; 2 usec
goto $+1 ; 2 usec
goto $+1 ; 2 usec
goto $+1 ; 2 usec
goto $+1 ; 2 usec
return
;==========================================================================
; Initialize the DOGM163 display
; Modifies: bank, page
;==========================================================================
InitDisplay:
; Wait 40msec before attempting to talk to LCD
movlw 40
call msDelay
; Set Command Mode
banksel LCD_MODE_PORT ; Bank 0
bcf LCD_MODE_PORT, LCD_MODE_OUT
pagesel LCDOut
movlw B'00111001' ; Function Set
call LCDOut
movlw B'00011101' ; Bias Set
call LCDOut
movlw B'01010000' ; Power Control
call LCDOut
movlw B'01101100' ; Follower Control
call LCDOut
movlw B'01111100' ; Contrast Set
call LCDOut
movlw B'00111000' ; Function Set
call LCDOut
movlw B'00001100' ; Display ON, no cursor
call LCDOut
movlw B'00000001' ; Clear Display
call LCDOut
movlw 1
pagesel msDelay
call msDelay
pagesel LCDOut
movlw B'00000110' ; Entry Mode Set
call LCDOut
; Set Data Mode
bsf LCD_MODE_PORT, LCD_MODE_OUT
return
;==========================================================================
; Delay the number of milliseconds in W
; (Actual: W*1000 + 4 usec)
; Assumes 4 MHz system clock
; W range 1-255
; Does not change selected register bank or memory page
;==========================================================================
msDelay:
movwf DelayCounter ; 1 usec
delayLoop:
; Each time through this inner loop is 500 usec
; (166 * 3 + 2)
movlw 166 ; 1 usec
decfsz WREG, W ; 1 usec (2 on skip)
goto $-1 ; 2 usec
; Do it again for 497 usec
; (165 * 3 + 2)
movlw 165 ; 1 usec
decfsz WREG, W ; 1 usec (2 on skip)
goto $-1 ; 2 usec
decfsz DelayCounter, F ; 1 usec (2 on skip)
goto delayLoop ; 2 usec
return ; 2 usec
end
PK l^Y# #
PIC\motor.asm;==========================================================================
; Jobeaux Processor Motor Control Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "Motor Control Module"
GLOBAL InitMotor, ReadSpeed, StartMotor, TendMotor
GLOBAL RotIntHandler
GLOBAL StopTicks
GLOBAL Rotate, MotorState, Phase ; DEBUG
UDATA_SHR
Rotate RES 1 ; Rotation counter
Phase RES 1 ; Tracks rising/falling edges
StopTicks RES 1 ; Tick counter for stopping motor
UDATA
Speed RES 1 ; Motor speed. 1 = high, 0 = low
MotorState RES 1 ; Current motor state
Direction RES 1 ; Current motor direction (0/1)
MOTOR CODE
;==========================================================================
; Initialize the motor controller
; Modifies: bank
;==========================================================================
InitMotor:
movlw REVERSE_COUNT
movwf Rotate ; Init rotation counter
clrf StopTicks
clrf Phase
banksel Direction
clrf Direction ; ...and motor direction
banksel MotorState
movlw MSTATE_STOPPED ; ...and set state to stopped
movwf MotorState
call ReadSpeed ; Get initial speed setting
; Set initial state for DRV8801:
; Enable=0, Phase=0, {Mode1=1, Mode2=0} (=> Brake=1)
clrw
banksel CCPR1L ; Bank 5
movwf CCPR1L
banksel MOTOR_DIR_PORT ; Bank 0
bcf MOTOR_DIR_PORT, MOTOR_DIR_OUT
bsf MOTOR_BRAKE_PORT, MOTOR_BRAKE_OUT
return
;==========================================================================
; Read the setting of the motor speed switch (on RA6) & save value for
; later reference.
; Modifies: bank
;==========================================================================
ReadSpeed:
clrw
banksel MOTOR_SPEED_PORT ; Bank 0
btfsc MOTOR_SPEED_PORT, MOTOR_SPEED_IN
incf WREG, W
banksel Speed
movwf Speed
return
;==========================================================================
; Tend the motor based on current MotorState
; Modifies: bank
;==========================================================================
TendMotor:
banksel MotorState
movfw MotorState
brw
goto MotorStopped ; MSTATE_STOPPED (0)
goto MotorStarting ; MSTATE_STARTING (1)
goto MotorRunning ; MSTATE_TURNING (2)
goto MotorStopping ; MSTATE_STOPPING (3)
;==========================================================================
; MSTATE_STOPPED handler
; The motor is stopped (brake applied). We wait for some amount of time
; (STOP_TIME timer ticks) and then start it running again.
; Modifies: bank
;==========================================================================
MotorStopped:
movf StopTicks, F
btfss STATUS, Z ; Has the delay time elapsed?
return ; No - try again later
; We have waited for the prescribed time. We can start the motor
; again after reversing the direction value.
clrw ; Assume we want to set Direction to 0
banksel Direction
movf Direction, F
btfsc STATUS, Z
incf WREG, W ; Was zero - now make it 1
movwf Direction ; Save updated value
call StartMotor
return
;==========================================================================
; MSTATE_STARTING handler
; The motor is starting (brake applied). We wait until we see a falling
; edge from the rotation sensor and then turn off the brake and consider
; it running.
; Modifies: bank
;==========================================================================
MotorStarting:
; FixFixFix - If we don't start in a reasonable time, shut down
; motor and indicate fault?
btfss Phase, PHASE_FALLING ; Have we seen a falling edge?
return ; No. Keep waiting.
; Falling edge detected - the motor is in fact running.
; Initialize rotation counter
movlw REVERSE_COUNT
movwf Rotate
; And set to TURNING state
banksel MotorState
movlw MSTATE_TURNING
movwf MotorState
return
;==========================================================================
; MSTATE_TURNING handler
; The motor is running. We let it run for some number of full revolutions
; (specified by REVERSE_COUNT in jobeaux.inc) and then go to the STOPPING
; state.
; This code assumes a single rotation sensor pulse per revolution.
; Modifies: bank
;==========================================================================
MotorRunning:
movf Rotate, F
btfss STATUS, Z ; Have we reached the stop point?
return ; Nope.
; We've done two rotations - move to STOPPING state
; Stop PWM1
clrw
banksel CCPR1L ; Bank 5
movwf CCPR1L
movlw COAST_TIME
movwf StopTicks
; Turn off the brake - let it coast initially
banksel MOTOR_BRAKE_PORT
bcf MOTOR_BRAKE_PORT, MOTOR_BRAKE_OUT
banksel MotorState
movlw MSTATE_STOPPING
movwf MotorState
return
;==========================================================================
; MSTATE_STOPPING handler
; The motor is coasting (brake not applied). We let it coast for some
; amount of time (COAST_TIME timer ticks) and then hit the brakes.
; Modifies: bank
;==========================================================================
MotorStopping:
movf StopTicks, F
btfss STATUS, Z ; Has the delay time elapsed?
return ; No - try again later
; We have waited for the prescribed time. We can now hit the brakes.
banksel MOTOR_BRAKE_PORT
bsf MOTOR_BRAKE_PORT, MOTOR_BRAKE_OUT
; Update StopTicks for STOPPED state delay
movlw STOP_TIME
movwf StopTicks
; And set new state
banksel MotorState
movlw MSTATE_STOPPED
movwf MotorState
return
;==========================================================================
; Start the motor running.
; Brake should be set (MotorState = STOPPED) when calling this routine -
; Despite what the data sheet might indicate, the DRV8801 doesn't like to
; start the motor if brake not set. This extends to the case where we're
; sending a PWM signal to the Enable input. Therefore, brake is ON
; whenever we're starting or running.
; Modifies: bank
;==========================================================================
StartMotor:
clrf Phase
; Update the motor state
banksel MotorState
movlw MSTATE_STARTING
movwf MotorState
; Set the direction
banksel Direction
movf Direction, F
banksel MOTOR_DIR_PORT
btfsc STATUS, Z
goto dir0
bsf MOTOR_DIR_PORT, MOTOR_DIR_OUT
goto enableMotor
dir0: bcf MOTOR_DIR_PORT, MOTOR_DIR_OUT
enableMotor:
; Set PWM1 to run motor at selected speed
; Set duty cycle based on switch setting
movlw PWM_DUTY_SLOW ; Assume low speed
banksel Speed
movf Speed, F
btfss STATUS, Z
movlw PWM_DUTY_FAST ; Nope, it's high speed
banksel CCPR1L ; Bank 5
movwf CCPR1L
return
;==========================================================================
; Rotation sensor interrupt handler
; Just counts the number of motor rotations - it's up to the TendMotor
; function to figure out when to reverse rotation and reset the counter...
; Phase is used to debounce the input signal.
; Modifies: bank
;==========================================================================
RotIntHandler:
banksel IOCBF ; Bank 7
btfss IOCBF, IOCBF0 ; See if we actually got an interrupt
return ; No - just ignore
; Yes - we saw a rotation event
bcf IOCBF, IOCBF0 ; Clear the int request
banksel MOTOR_ROT_PORT ; Determine if rising or falling
btfss MOTOR_ROT_PORT, MOTOR_ROT_IN
goto fell
; Detected rising edge
btfsc Phase, PHASE_RISING ; Did we already see a rising edge?
return ; Yes - can't have another until we
; first see a falling edge
movf Rotate, F
btfss STATUS, Z ; If not already at zero,
decf Rotate ; bump the counter
bsf Phase, PHASE_RISING ; and update Phase
bcf Phase, PHASE_FALLING
return
fell:
; Detected falling edge
btfsc Phase, PHASE_FALLING
return
bcf Phase, PHASE_RISING ; Update Phase
bsf Phase, PHASE_FALLING
return
end
PK …ç| ç| PIC\temp.asm;==========================================================================
; Jobeaux Processor Temperature Control Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "Temp Control Module"
EXTERN msDelay, DisplaySetupScreen ; In display.asm
EXTERN OKUpdate ; In timer.asm
EXTERN UpdateEEPROM ; In eeprom.asm
EXTERN Rotate, MotorState, Phase ; DEBUG
GLOBAL InitHeater, InitTempDisplay, ConfigureUnits
GLOBAL ReadTemp, TendHeater, CheckWaterLevel
GLOBAL DisplaySetTemp, DisplayCurTemp, DisplayLowTemp
GLOBAL CountToTemp
GLOBAL SetupScr1, SetupScr2, SetupScr3
GLOBAL DisplayF
UDATA_SHR
DisplayF RES 1 ; 1: display degrees F, 0: display C
DesiredHi RES 1 ; Desired temp from R6
DesiredLo RES 1
CurrentHi RES 1 ; Currently read temp from thermistor
CurrentLo RES 1
UDATA
; Working registers for temp conversion
TempHi RES 1 ; The temp we're looking for
TempLo RES 1
EntryHi RES 1 ; Current table entry value
EntryLo RES 1
PrevHi RES 1 ; Previous table entry value
PrevLo RES 1
OffCountHi RES 1 ; When to turn off heater
OffCountLo RES 1
RecentPeakHi RES 1 ; Recent peak temp when stabilizing
RecentPeakLo RES 1
SmoothedHi RES 1 ; Smoothed current temp
SmoothedLo RES 1
TempHTBCD RES 1 ; Temp Hundreds/Tens digit (BCD)
TempOFBCD RES 1 ; Temp Ones/Tenths digit (BCD)
HeaterState RES 1 ; Current heater state
PauseCount RES 1
tmp RES 1 ; Temporary working register
equal RES 1
innerCount RES 1 ; Display Configuration inner loop counter
outerCount RES 1 ; Display Configuration outer loop counter
TEMP CODE
;==========================================================================
; ADC values for temperatures from 50-110 degrees F
; This saves the wimpy PIC from having to do a lot of math.
; These are based on the Steinhart-Hart Equation for
; "Material Z" (a=1.12924E-3, b=2.34108E-4, c=0.87755E-7)
; Computed at 1/2 degree intervals, interpolate to get finer
; intervals.
;==========================================================================
FTemps:
MinSel: ; Minimum valid desired temp
dw 12, 26, 39, 53, 66, 79, 93, 106 ; 50.0 - 53.5
dw 119, 132, 144, 157, 170, 182, 195, 207 ; 54.0 - 57.5
dw 219, 231, 243, 255, 267, 278, 290, 301 ; 58.0 - 61.5
dw 313, 324, 335, 346, 357, 368, 379, 389 ; 62.0 - 65.5
dw 400, 410, 421, 431, 441, 451, 461, 471 ; 66.0 - 69.5
dw 481, 491, 500, 510, 519, 529, 538, 547 ; 70.0 - 73.5
dw 556, 565, 574, 583, 592, 601, 609, 618 ; 74.0 - 77.5
dw 626, 634, 643, 651, 659, 667, 675, 683 ; 78.0 - 81.5
dw 690, 698, 706, 713, 721, 728, 735, 743 ; 82.0 - 85.5
dw 750, 757, 764, 771, 778, 785, 791, 798 ; 86.0 - 89.5
dw 805, 811, 818, 824, 830, 837, 843, 849 ; 90.0 - 93.5
dw 855, 861, 867, 873, 879, 884, 890, 896 ; 94.0 - 97.5
dw 901, 907, 912, 918, 923, 928, 934, 939 ; 98.0 - 101.5
dw 944, 949, 954, 959, 964, 969, 974, 978 ; 102.0 - 105.5
dw 983, 988, 992, 997,1001,1006,1010,1015 ; 106.0 - 109.5
dw 1019,1023 ; 110.0 - 110.5
;==========================================================================
; ADC values for temperatures from 10-44 degrees C
; We can't actually get a reading of 44.0, as the ADC is only 10 bits.
; Highest setting is actually 43.6
; Essentially same range as above table, but for Celsius readout
;==========================================================================
CTemps:
dw 12, 37, 61, 85, 108, 132, 155, 177 ; 10.0 - 13.5
dw 199, 221, 243, 264, 285, 306, 326, 346 ; 14.0 - 17.5
dw 366, 385, 404, 423, 441, 459, 477, 495 ; 18.0 - 21.5
dw 512, 529, 545, 562, 578, 594, 609, 624 ; 22.0 - 25.5
dw 639, 654, 668, 683, 697, 710, 724, 737 ; 26.0 - 29.5
dw 750, 763, 775, 787, 799, 811, 823, 834 ; 30.0 - 33.5
dw 845, 856, 867, 877, 888, 898, 908, 918 ; 34.0 - 37.5
dw 927, 937, 946, 955, 964, 973, 981, 990 ; 38.0 - 41.5
dw 998,1006,1014,1022,1029 ; 42.0 - 44.0
;==========================================================================
; Initialize the heater
; Nothing much to do. Only control is Heater Ctl. It's an inverted
; signal, so set to 1 to turn the heater off for now.
; Also initializes the Heater state to IDLE
; Modifies: bank
;==========================================================================
InitHeater:
banksel HeaterState
movlw HSTATE_IDLE
movwf HeaterState
banksel HEATER_CTL_PORT ; Bank 0
bsf HEATER_CTL_PORT, HEATER_CTL_OUT
return
;==========================================================================
; Initialize the temperature display
; Read the configuration byte in EEPROM to determine if we are displaying
; in Fahrenheit or Celsius
; Modifies: bank
;==========================================================================
InitTempDisplay:
clrf DisplayF ; Assume Celsius
; Read the Display configuration from EEPROM
banksel EEADRL ; Bank 3
movlw EE_FC_CONFIG
movwf EEADRL
bcf EECON1, CFGS
bcf EECON1, EEPGD
bsf EECON1, RD
movfw EEDATL
btfss STATUS, Z ; zero = C, non-zero = F
incf DisplayF, F ; Change to Fahrenheit
return
;==========================================================================
; Read the desired and current water temp values & saves them
; Modifies: bank
;==========================================================================
ReadTemp:
banksel ADCON0 ; Bank 1
movlw B'00101101' ; Select AN11 (Desired Temp)
movwf ADCON0 ; Turn ADC on
call sampleTime ; Acquisition delay
bsf ADCON0, ADGO ; Start Conversion
btfsc ADCON0, ADGO ; Wait for completion
goto $-1
movfw ADRESH ; Get the high 2 bits
movwf DesiredHi
movfw ADRESL ; And the lower 8 bits
movwf DesiredLo
movlw B'00000001' ; Select AN0 (Current Temp)
movwf ADCON0 ; Turn ADC on
call sampleTime ; Acquisition delay
bsf ADCON0, ADGO ; Start Conversion
btfsc ADCON0, ADGO ; Wait for completion
goto $-1
movfw ADRESH ; Get the high 2 bits
movwf CurrentHi
movfw ADRESL ; And the lower 8 bits
movwf CurrentLo
return
;==========================================================================
; Acquisition delay function.
; Wastes a few microseconds
;==========================================================================
sampleTime:
goto $+1
goto $+1
goto $+1
return
;==========================================================================
; Verify that the water level is not too low.
; Returns value in W
; 0 = Too Low
; 1 = OK
; Modifies: bank
;==========================================================================
CheckWaterLevel:
; Compare temp select value vs MinSel value
; If below MinSel we assume float switch is turned on
banksel EEADRL ; Bank 3
movlw LOW MinSel ; Set MinSel addr
movwf EEADRL
movlw HIGH MinSel
movwf EEADRH
bcf EECON1, CFGS
bsf EECON1, EEPGD
bcf INTCON, GIE ; Disable interrupts
bsf EECON1, RD ; Initiate read of MinSel to EEDAT regs
nop
nop
bsf INTCON, GIE ; Reenable interrupts
movfw EEDATL ; MinSel in W
subwf DesiredLo, W ; Desired in f
movfw EEDATH
subwfb DesiredHi, W
btfss STATUS, C ; Carry set if W <= f
retlw 0 ; Desired < MinSel
retlw 1 ; Desired >= MinSel
;==========================================================================
; Turn the heater on if the current temp is below the requested temp.
; May have to get clever about when to turn it off, as the heater element
; will have some retained heat at turn off. Will have to experiment to
; see how much this affects the temperature.
; Modifies: bank, page
;==========================================================================
TendHeater:
; If water level is too low, turn off heater & bail
pagesel CheckWaterLevel
call CheckWaterLevel
andlw 0xFF
btfsc STATUS, Z
goto waterFault
banksel HeaterState
movfw HeaterState ; Dispatch to appropriate state handler
brw
goto IdleState ; HSTATE_IDLE
goto HeatingState ; HSTATE_HEATING
goto PauseState ; HSTATE_PAUSE
goto StabilizeState ; HSTATE_STABILIZE
IdleState:
; If too cold, turn the heater ON
; Too cold if (Current + TOO_COLD_COUNT) < Desired
; Use PrevLo/PrevHi to hold intermediate result
banksel PrevLo
movfw CurrentLo
addlw TOO_COLD_COUNT_LO
movwf PrevLo
movfw CurrentHi
movwf PrevHi
movlw TOO_COLD_COUNT_HI
addwfc PrevHi, F
; Now compare Desired with Prev
movfw DesiredLo ; Desired in W
subwf PrevLo, W ; Prev in f
movfw DesiredHi
subwfb PrevHi, W
btfsc STATUS, C ; Carry set if W <= f
return ; Desired <= (Current + TOO_COLD_COUNT)
; Desired > (Current + TOO_COLD_COUNT): Compute off value
; Off count = Desired + (Current - Desired)/4 + OFF_COUNT_OFFSET
; Since Desired > Current, the second term is <= 0
banksel OffCountLo
movfw DesiredLo ; OffCount = Current - Desired
subwf CurrentLo, W
movwf OffCountLo
movfw DesiredHi
subwfb CurrentHi, W
movwf OffCountHi
asrf OffCountHi, F ; Divide by 2
rrf OffCountLo, F
asrf OffCountHi, F ; And again to get 4
rrf OffCountLo, F
movfw DesiredLo ; Now add Desired to the result
addwf OffCountLo, F
movfw DesiredHi
addwfc OffCountHi, F
movlw OFF_COUNT_OFFSET_LO
addwf OffCountLo, F
movlw OFF_COUNT_OFFSET_HI
addwfc OffCountHi, F
; Now set new state & turn the heater on
banksel HeaterState
movlw HSTATE_HEATING
movwf HeaterState ; Set new state
banksel HEATER_CTL_PORT ; Bank 0
bcf HEATER_CTL_PORT, HEATER_CTL_OUT
return
HeatingState:
; User can adjust desired temp during heating phase.
; If a temp lower than the current temp is selected, we need
; to turn off the heater and bail (go back to IDLE state)
; right now.
movfw DesiredLo ; Desired in W
subwf CurrentLo, W ; Current in f
movfw DesiredHi
subwfb CurrentHi, W
btfsc STATUS, C ; Carry set if W <= f
goto InitHeater ; It is - back to idle state
; If desired < off count, also bail. User has adjusted desired
; temp down, but still above curent temp.
; (Does this make the above test redundant?)
movfw OffCountLo ; OffCount in W
subwf DesiredLo, W ; Desired in f
movfw OffCountHi
subwfb DesiredHi, W
btfss STATUS, C ; Carry set if W <= f
goto InitHeater ; It isn't - back to idle state
; If Current >= previously computed off count, turn off heater
; Off Count should always be <= Desired - if they're equal, we
; will have bailed out above. Otherwise we go into PAUSE
; state when we reach the count.
banksel OffCountLo
movfw OffCountLo ; Computed off count in W
subwf CurrentLo, W ; Current in f
movfw OffCountHi
subwfb CurrentHi, W
btfss STATUS, C ; Carry set if W <= f
return ; Current < off count - keep heating
; Current >= Desired: Set new state
banksel HeaterState
movlw HSTATE_PAUSE
movwf HeaterState
movlw PAUSE_TIME
movwf PauseCount
; Initialize Recent Peak value
banksel RecentPeakLo
movfw CurrentLo
movwf RecentPeakLo
movwf SmoothedLo
movfw CurrentHi
movwf RecentPeakHi
movwf SmoothedHi
; And fall through to heater off code
waterFault:
; Turn off heater & go back to IDLE state.
; We'll start over from scratch when the fault is cleared.
goto InitHeater
PauseState:
; Wait for PAUSE_COUNT clock ticks
call Smooth
movf OKUpdate, F
btfsc STATUS, Z
return
banksel PauseCount
decfsz PauseCount, F
return
banksel HeaterState
movlw HSTATE_STABILIZE
movwf HeaterState
return
StabilizeState:
; User can adjust desired temp during heating phase.
; If a temp lower than the current temp is selected, we need
; to turn off the heater and bail (go back to IDLE state)
; right now. Also causes exit of STABILIZE state on overshoot
; of desired temp.
movfw DesiredLo ; Desired in W
subwf CurrentLo, W ; Current in f
movfw DesiredHi
subwfb CurrentHi, W
btfsc STATUS, C ; Carry set if W <= f
goto InitHeater ; It is - back to idle state
call Smooth
; We need to (try to) remain in the STABILIZE state as long as
; the temperature keeps increasing.
banksel RecentPeakLo
movfw RecentPeakLo ; Recent peak count in W
subwf SmoothedLo, W ; Current in f
movfw RecentPeakHi
subwfb SmoothedHi, W
btfss STATUS, C ; Carry set if W <= f
goto checkStable ; Current < Recent Peak
; Current >= Recent Peak: update peak value
movfw SmoothedLo
movwf RecentPeakLo
movfw SmoothedHi
movwf RecentPeakHi
return
checkStable:
; Only check once a second (twice a second if using internal clock)
; FixFixFix - This is now 1/4 second
movf OKUpdate, F
btfsc STATUS, Z
return
; See if we've dropped enough to consider the temperature
; stabilized. Using PrevLo/Hi as temp again
banksel PrevLo
movlw STABLE_COUNT_LO
addwf SmoothedLo, W
movwf PrevLo
movlw STABLE_COUNT_HI
addwfc SmoothedHi, W
movwf PrevHi
movfw RecentPeakLo ; Recent peak count in W
subwf PrevLo, W ; (Current + STABLE_COUNT) in f
movfw RecentPeakHi
subwfb PrevHi, W
btfsc STATUS, C ; Carry set if W <= f
return ; No state change
banksel HeaterState
movlw HSTATE_IDLE ; (Current + STABLE_COUNT) < Recent Peak
movwf HeaterState ; Save new state
return
;==========================================================================
; Smooth the temp readings a bit
;==========================================================================
Smooth:
banksel SmoothedLo
movfw SmoothedLo
addwf SmoothedLo, W ; old * 2
btfsc STATUS, C
incfsz SmoothedHi, F
nop
addwf SmoothedLo, F ; *3
btfsc STATUS, C
incfsz SmoothedHi, F
nop
movfw SmoothedHi
addwf SmoothedHi, W
addwf SmoothedHi, F
movfw CurrentLo
addwf SmoothedLo, F
movfw CurrentHi ; + Current
addwfc SmoothedHi, F
asrf SmoothedHi, F ; / 4
rrf SmoothedLo, F
asrf SmoothedHi, F
rrf SmoothedLo, F
return
;==========================================================================
; Convert the ADC value to temperature for display
; On entry, W specifies which temp to convert:
; 0 = Desired
; 1 = Current
;
; On return, W indicates success/failure
; 0 = Temp < 50 degrees
; 1 = Success
; Modifies: bank
;==========================================================================
CountToTemp:
banksel TempHi
; Copy selected temp to working regs
andlw 0xFF
btfsc STATUS, Z
goto copySel
; Current temp selected - copy it
movfw CurrentHi
movwf TempHi
movfw CurrentLo
movwf TempLo
goto convert
copySel:
; Desired temp selected - copy it
movfw DesiredHi
movwf TempHi
movfw DesiredLo
movwf TempLo
convert:
; Initialize temp digits to 50.0 if F, 10.0 if C
movlw 0x01 ; Assume C
btfsc DisplayF, 0 ; Is it?
movlw 0x05 ; No, it's F
movwf TempHTBCD
movlw 0x00
movwf TempOFBCD
; Is the temp less than the lowest value we know how to convert?
banksel EEADRL ; Bank 3
movlw LOW CTemps ; Set Temps[0] addr - C or F
btfsc DisplayF, 0
movlw LOW FTemps
movwf EEADRL
movlw HIGH CTemps
btfsc DisplayF, 0
movlw HIGH FTemps
movwf EEADRH
bcf EECON1, CFGS
bsf EECON1, EEPGD
bcf INTCON, GIE ; Disable interrupts
bsf EECON1, RD ; Initiate read of Temps[0] to EEDAT regs
nop
nop
bsf INTCON, GIE ; Reenable interrupts
movfw EEDATL ; Temps[0] in W
banksel EntryLo
movwf EntryLo
subwf TempLo, W ; Temp in f
banksel EEDATH ; Bank 3
movfw EEDATH
banksel EntryHi
movwf EntryHi
subwfb TempHi, W
btfss STATUS, C ; Carry set if W <= f
retlw 0 ; f < W: Can't convert
; Scan Temps table to find bounding .5 degree entries
scan:
banksel EntryLo
movfw EntryLo ; Save previous values in case
movwf PrevLo ; we need to interpolate
movfw EntryHi
movwf PrevHi
banksel EEADRL ; Bank 3
incfsz EEADRL, F ; Move to next table entry
goto readit
incfsz EEADRH, F ; page wrap
nop
readit:
bcf EECON1, CFGS
bsf EECON1, EEPGD
bcf INTCON, GIE ; Disable interrupts
bsf EECON1, RD ; Initiate read of Temps[0] to EEDAT regs
nop
nop
bsf INTCON, GIE ; Reenable interrupts
; Compare table entry to temp we're converting
; If temp is >= table entry, we've found the right entry
movfw EEDATL
banksel EntryLo
movwf EntryLo
movlw 1
movwf equal ; Assume equal
movfw TempLo ; Temp in W
subwf EntryLo, W ; Temps[n] in f
btfss STATUS, Z
clrf equal ; Low bytes not equal
banksel EEDATH ; Bank 3
movfw EEDATH
banksel EntryHi
movwf EntryHi
movfw TempHi
subwfb EntryHi, W
btfsc STATUS, C ; Carry set if W <= f
goto found
; Haven't found it yet - update BCD by .5 & try again
movlw 5
call UpdateBCD
goto scan
found:
banksel equal
btfss STATUS, Z
clrf equal ; High bytes not equal
movf equal, F
btfsc STATUS, Z ; Is it right on?
goto interpolate ; Nope
movlw 5 ; Yes - just update BCD by .5 & we're done
call UpdateBCD
retlw 1
; Interpolate to nearest .1 degree
interpolate:
; Compute diff between entry & previous
; Value of result will be between 4 and 14
banksel PrevLo
movfw PrevLo
subwf EntryLo, F ; Leave result in EntryLo
; Compute diff between temp & prev
subwf TempLo, F ; Leave result in TempLo
; Times 5 - biggest diff between entries is 14
; so guaranteed to fit in a byte
movfw TempLo
lslf WREG, W ; * 2
lslf WREG, W ; * 4
addwf TempLo, F ; * 5 result in TempLo
; Subtract half of EntryLo - this provides proper rounding
movfw EntryLo
asrf WREG, W
subwf TempLo, F
btfss STATUS, C ; Are we done?
retlw 1 ; Yes - close enough already
; Divide by successive subtraction
clrf tmp
movfw EntryLo
subdiv:
subwf TempLo, F ; Carry is 0 if TempLo was < EntryLo
incf tmp, F
btfss STATUS, C
goto divdone ; Which means we're done...
goto subdiv ; and loop
divdone:
; Final result should be in range 1-5
movfw tmp
call UpdateBCD
retlw 1
;==========================================================================
; Update the BCD temperature value
; Number of tenths to add is in W (1-5)
; Modifies: bank
;==========================================================================
UpdateBCD:
banksel TempOFBCD
addwf TempOFBCD, F ; Add the specified number of tenths
movfw TempOFBCD ; Now need to see if we went over
andlw 0x0F
sublw 9 ; Sets carry if W <= 9
btfsc STATUS, C
return ; Good to go.
movlw 0x06 ; Get tenths back in range & inc ones
addwf TempOFBCD, F
swapf TempOFBCD, W ; Now see if that wrapped
andlw 0x0F
sublw 9 ; Can't go past 9
btfsc STATUS, C
return ; Didn't
movlw 0x60
addwf TempOFBCD, F ; Force upper nibble (ones) to zero
incfsz TempHTBCD, F ; Bump tens (can't skip)
movfw TempHTBCD ; Now see if it's wrapped
andlw 0x0F
sublw 9
btfsc STATUS, C
return ; No - we're good
movlw 0x06 ; Sure did - bump it to 0 and inc hundreds
addwf TempHTBCD, F ; Don't worry about hundreds wrapping
return
;==========================================================================
; Display the requested temperature
; Column is in W on entry
;==========================================================================
DisplaySetTemp:
brw
retlw 'S' ; Column 0
retlw 'e' ; Column 1
retlw 't' ; Column 2
retlw ':' ; Column 3
retlw ' ' ; Column 4
retlw ' ' ; Column 5
goto tempH ; Column 6: Hundreds digit
goto tempT ; Column 7: Tens digit
goto tempO ; Column 8: Ones digit
retlw '.' ; Column 9
goto tempF ; Column 10: Tenths digit
retlw DEGREES ; Column 11
goto CorF ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
; DEBUG
goto hi7
goto hi6
goto hi5
goto hi4
goto hi3
goto hi2
goto hi1
goto hi0
goto lo7
goto lo6
goto lo5
goto lo4
goto lo3
goto lo2
goto lo1
goto lo0
hi7:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x80
btfss STATUS, Z
retlw '1'
retlw '0'
hi6:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x40
btfss STATUS, Z
retlw '1'
retlw '0'
hi5:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x20
btfss STATUS, Z
retlw '1'
retlw '0'
hi4:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x10
btfss STATUS, Z
retlw '1'
retlw '0'
hi3:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x08
btfss STATUS, Z
retlw '1'
retlw '0'
hi2:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x04
btfss STATUS, Z
retlw '1'
retlw '0'
hi1:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x02
btfss STATUS, Z
retlw '1'
retlw '0'
hi0:
; banksel OffCountHi
; movfw OffCountHi
movfw DesiredHi
andlw 0x01
btfss STATUS, Z
retlw '1'
retlw '0'
lo7:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x80
btfss STATUS, Z
retlw '1'
retlw '0'
lo6:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x40
btfss STATUS, Z
retlw '1'
retlw '0'
lo5:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x20
btfss STATUS, Z
retlw '1'
retlw '0'
lo4:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x10
btfss STATUS, Z
retlw '1'
retlw '0'
lo3:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x08
btfss STATUS, Z
retlw '1'
retlw '0'
lo2:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x04
btfss STATUS, Z
retlw '1'
retlw '0'
lo1:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x02
btfss STATUS, Z
retlw '1'
retlw '0'
lo0:
; banksel OffCountLo
; movfw OffCountLo
movfw DesiredLo
andlw 0x01
btfss STATUS, Z
retlw '1'
retlw '0'
;==========================================================================
; Display the current temperature
; Column is in W on entry
;==========================================================================
DisplayCurTemp:
brw
retlw 'T' ; Column 0
retlw 'e' ; Column 1
retlw 'm' ; Column 2
retlw 'p' ; Column 3
retlw ':' ; Column 4
retlw ' ' ; Column 5
goto tempH ; Column 6: Hundreds digit
goto tempT ; Column 7: Tens digit
goto tempO ; Column 8: Ones digit
retlw '.' ; Column 9
goto tempF ; Column 10: Tenths digit
retlw DEGREES ; Column 11
goto CorF ; Column 12
; retlw ' ' ; Column 13
goto DisplayPhase ; DEBUG
; retlw ' ' ; Column 14
goto DisplayHState ; DEBUG
; retlw ' ' ; Column 15
goto DisplayMState ; DEBUG
DisplayPhase: ; DEBUG
movfw Phase ; DEBUG
addlw '0' ; DEBUG
return ; DEBUG
DisplayHState: ; DEBUG
; banksel HeaterState ; DEBUG
; movfw HeaterState ; DEBUG
movfw Rotate ; DEBUG
addlw '0' ; DEBUG
return ; DEBUG
DisplayMState: ; DEBUG
banksel MotorState ; DEBUG
movfw MotorState ; DEBUG
addlw '0' ; DEBUG
return ; DEBUG
;==========================================================================
; Return the hundreds digit of the converted temp as ASCII
; Leading zero is suppressed
; Modifies: bank
;==========================================================================
tempH:
banksel TempHTBCD
movfw TempHTBCD
swapf WREG, W
andlw 0x0F
btfsc STATUS, Z
retlw ' ' ; It's zero - return a space
convertToASC:
addlw '0' ; Convert to ASCII digit
return
;==========================================================================
; Return the tens digit of the converted temp as ASCII
; Modifies: bank
;==========================================================================
tempT:
banksel TempHTBCD
movfw TempHTBCD
andlw 0x0F ; Low nibble
goto convertToASC
;==========================================================================
; Return the ones digit of the converted temp as ASCII
; Modifies: bank
;==========================================================================
tempO:
banksel TempOFBCD
movfw TempOFBCD
swapf WREG, W ; High nibble
andlw 0x0F
goto convertToASC
;==========================================================================
; Return the tenths digit of the converted temp as ASCII
; Modifies: bank
;==========================================================================
tempF:
banksel TempOFBCD
movfw TempOFBCD
andlw 0x0F ; Low nibble
goto convertToASC
;==========================================================================
; Return the temperature units (C or F) based on configuration
;==========================================================================
CorF:
btfsc DisplayF, 0
retlw 'F'
retlw 'C'
;==========================================================================
; Return the tens digit of the minimum temperature for C or F
; based on configuration
;==========================================================================
CFMin:
btfsc DisplayF, 0
retlw '5' ; F: min is 50 degrees
retlw '1' ; C: min is 10 degrees
;==========================================================================
; Display a message showing the temperature is too low
; Column is in W on entry
;==========================================================================
DisplayLowTemp:
brw
retlw 'T' ; Column 0
retlw 'e' ; Column 1
retlw 'm' ; Column 2
retlw 'p' ; Column 3
retlw ':' ; Column 4
retlw ' ' ; Column 5
retlw '<' ; Column 6
goto CFMin ; Column 7: Tens digit
retlw '0' ; Column 8: Ones digit
retlw '.' ; Column 9
retlw '0' ; Column 10: Tenths digit
retlw DEGREES ; Column 11
goto CorF ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; Configure whether temperature display is in F or C
; Modifies: bank, page
;==========================================================================
ConfigureUnits:
; Set outer loop count
banksel outerCount
movlw 9 ; Give user 9 seconds
movwf outerCount ; to make changes
cuOuterLoop: ; Repeats at 1 sec intervals
; Set inner loop count
banksel innerCount
movlw 100
movwf innerCount
cuInnerLoop: ; Repeats at 10 msec intervals
pagesel DisplaySetupScreen
call DisplaySetupScreen
; Wait for button unpressed
banksel TIMER_RESET_PORT ; Bank 0
btfss TIMER_RESET_PORT, TIMER_RESET_IN
goto $-1 ; Still pressed
; delay 10 msec
movlw 10
pagesel msDelay
call msDelay
; Check if button pressed
movlw 1 ; Prepare for toggle
banksel TIMER_RESET_PORT ; Bank 0
btfss TIMER_RESET_PORT, TIMER_RESET_IN
xorwf DisplayF, F ; Yes => toggle DisplayF
; Decrement inner loop counter
banksel innerCount
decfsz innerCount, F
goto cuInnerLoop ; Non-zero: repeat inner loop
; zero: decrement outer loop counter
decfsz outerCount, F
goto cuOuterLoop
; outer loop counter zero: save to EEPROM and return
; To minimize code, we always write the value back to EEPROM
; even if it hasn't changed. Should not be a problem since
; this setup mode is rarely invoked.
pagesel UpdateEEPROM
call UpdateEEPROM
return
;==========================================================================
; SetupScr1: Line 1 of setup screen
; Column is in W on entry
;==========================================================================
SetupScr1:
brw
retlw 'C' ; Column 0
retlw 'o' ; Column 1
retlw 'n' ; Column 2
retlw 'f' ; Column 3
retlw 'i' ; Column 4
retlw 'g' ; Column 5
retlw 'u' ; Column 6
retlw 'r' ; Column 7
retlw 'e' ; Column 8
retlw ' ' ; Column 9
retlw 'U' ; Column 10
retlw 'n' ; Column 11
retlw 'i' ; Column 12
retlw 't' ; Column 13
retlw 's' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; SetupScr2: Line 2 of setup screen
; Column is in W on entry
; Modifies: bank
;==========================================================================
SetupScr2:
btfss DisplayF, 0
goto scr2Celsius
brw
retlw 'F' ; Column 0
retlw 'a' ; Column 1
retlw 'h' ; Column 2
retlw 'r' ; Column 3
retlw 'e' ; Column 4
retlw 'n' ; Column 5
retlw 'h' ; Column 6
retlw 'e' ; Column 7
retlw 'i' ; Column 8
retlw 't' ; Column 9
retlw ' ' ; Column 10
retlw '(' ; Column 11
retlw DEGREES ; Column 12
retlw 'F' ; Column 13
retlw ')' ; Column 14
retlw ' ' ; Column 15
scr2Celsius:
brw
retlw 'C' ; Column 0
retlw 'e' ; Column 1
retlw 'l' ; Column 2
retlw 's' ; Column 3
retlw 'i' ; Column 4
retlw 'u' ; Column 5
retlw 's' ; Column 6
retlw ' ' ; Column 7
retlw '(' ; Column 8
retlw DEGREES ; Column 9
retlw 'C' ; Column 10
retlw ')' ; Column 11
retlw ' ' ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
;==========================================================================
; SetupScr3: Line 3 of setup screen
; Column is in W on entry
;==========================================================================
SetupScr3:
brw
retlw 'R' ; Column 0
retlw 'e' ; Column 1
retlw 's' ; Column 2
retlw 'e' ; Column 3
retlw 't' ; Column 4
retlw ' ' ; Column 5
retlw 'i' ; Column 6
retlw 'n' ; Column 7
retlw ':' ; Column 8
retlw ' ' ; Column 9
goto displayOLC ; Column 10
retlw ' ' ; Column 11
retlw ' ' ; Column 12
retlw ' ' ; Column 13
retlw ' ' ; Column 14
retlw ' ' ; Column 15
displayOLC:
banksel outerCount
movfw outerCount
addlw '0' ; Now you know why it starts at 9
return
end
PK ܾêg g PIC\eeprom.asm;==========================================================================
; Jobeaux Processor EEPROM Module
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "jobeaux.inc"
SUBTITLE "EEPROM Module"
GLOBAL UpdateEEPROM
EXTERN DisplayF
EEPROM CODE
;==========================================================================
; Update the EEPROM data.
; Modifies: bank
;==========================================================================
UpdateEEPROM:
; Offset 0: Version
banksel EEADRL ; Bank 3
movlw EE_VERSION
movwf EEADRL ; Set EEPROM address
movlw EE_CURRENT_VERSION
movwf EEDATL ; And the data
call eewrite
; Offset 1: Fahrenheit/Celsius display
banksel EEADRL ; Bank 3
movlw EE_FC_CONFIG
movwf EEADRL ; Set EEPROM address
movfw DisplayF
movwf EEDATL ; And the data
call eewrite
return
;==========================================================================
; Write the current data in EEDATL to the address in EEADRL.
; Modifies: bank
;==========================================================================
eewrite:
banksel EECON1 ; Bank 3
bcf EECON1, CFGS
bcf EECON1, EEPGD
bsf EECON1, WREN ; Enable writes
bcf INTCON, GIE ; Disable interrupts
movlw 0x55 ; output special sequence to show
movwf EECON2 ; we really do want to write it
movlw 0xAA
movwf EECON2
bsf EECON1, WR ; Go for it!
bsf INTCON, GIE ; Enable interrupts
bcf EECON1, WREN ; Disable writes
; Wait for completion
wwait: btfsc EECON1, WR
goto wwait
return
end
PK çÄÊÆ Æ PIC\jobeaux.inc;==========================================================================
; Jobeaux Processor Global definitions
;
; Copyright (C) 2011
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; Revision History:
; Who Date Description
; sgt TBD Initial Release
;==========================================================================
#include "p16f1827.inc"
TITLE "Jobeaux Processor, rev 0.0"
RADIX DEC
;==========================================================================
; Define I/O ports
;==========================================================================
TIMER_RESET_IN EQU RA5 ; Reset switch
TIMER_RESET_PORT EQU PORTA
LCD_ENABLE_OUT EQU RA7 ; LCD Display /CSB
LCD_ENABLE_PORT EQU PORTA
LCD_MODE_OUT EQU RA1 ; LCD Display RS
LCD_MODE_PORT EQU PORTA
MOTOR_ROT_IN EQU RB0 ; Motor rotation sensor (interrupt line)
MOTOR_ROT_PORT EQU PORTB
MOTOR_SPEED_IN EQU RA4 ; Hi/Lo speed switch
MOTOR_SPEED_PORT EQU PORTA
MOTOR_DIR_OUT EQU RA2 ; Motor direction (Phase)
MOTOR_DIR_PORT EQU PORTA
MOTOR_BRAKE_OUT EQU RA6 ; Brake (Mode) control
MOTOR_BRAKE_PORT EQU PORTA
MOTOR_CTL_OUT EQU RB3 ; DRV8801 Enable (PWM)
MOTOR_CTL_PORT EQU PORTB
MOTOR_CTL_TRIS EQU TRISB
PWM_DUTY_SLOW EQU 4 ; CCPR1L value for half-speed
PWM_DUTY_FAST EQU 8 ; full speed
PWM_PERIOD EQU 7
HEATER_CTL_OUT EQU RB5 ; Heater on/off
HEATER_CTL_PORT EQU PORTB
;==========================================================================
; Starting value for Timer1.
; This causes the timer to overflow (and interrupt) at a rate of
; TICKS_PER_SEC
;==========================================================================
;T1_LP_START_HI EQU 0xC0 ; Using LP clock (32.768 KHz)
;T1_LP_START_LO EQU 0x00 ; Values for 2 ticks/sec
T1_LP_START_HI EQU 0xE0 ; Using LP clock (32.768 KHz)
T1_LP_START_LO EQU 0x00 ; Values for 4 ticks/sec
;T1_IC_START_HI EQU 0x0B ; Using instruction clock/8 (125KHz)
;T1_IC_START_LO EQU 0xDC ; Values for 2 ticks/sec
T1_IC_START_HI EQU 0x85 ; Using instruction clock/8 (125KHz)
T1_IC_START_LO EQU 0xEE ; Values for 4 ticks/sec
TICKS_PER_SEC EQU 4
;==========================================================================
; TOO_COLD_COUNT is the value that tells us whether to turn the heater on
; or not. If the current temperature is more than TOO_COLD_COUNT ticks
; below the desired temperature, we turn on.
;==========================================================================
TOO_COLD_COUNT_LO EQU 3
TOO_COLD_COUNT_HI EQU 0
STABLE_COUNT_LO EQU 3 ; Should be <= TOO_COLD_COUNT
STABLE_COUNT_HI EQU 0
OFF_COUNT_OFFSET_LO EQU 1
OFF_COUNT_OFFSET_HI EQU 0
;==========================================================================
; Motor states
;==========================================================================
MSTATE_STOPPED EQU 0 ; Motor is stopped
MSTATE_STARTING EQU 1 ; Motor is starting
MSTATE_TURNING EQU 2 ; Motor is running
MSTATE_STOPPING EQU 3 ; Motor is coasting to a stop
; Phase bits (these are bit numbers)
PHASE_RISING EQU 0
PHASE_FALLING EQU 1
; How many motor revolutions before we reverse direction
REVERSE_COUNT EQU 2
; How long (ticks) to stay in the STOPPING & STOPPED states
COAST_TIME EQU 3
STOP_TIME EQU 3
;==========================================================================
; Heater states
;==========================================================================
HSTATE_IDLE EQU 0 ; Heater OFF; turn on if temp drops
; TOO_COLD ticks below desired temp
HSTATE_HEATING EQU 1 ; Heater ON; turn off when temp reaches
; computed value below desired temp
HSTATE_PAUSE EQU 2 ; Heater OFF; just pausing for a second
; or so before going to STABILIZE state
HSTATE_STABILIZE EQU 3 ; Heater OFF; cannot go back on until
; peak drops by STABLE_COUNT. Water is
; still heating due to retained heat in
; heater element
; How long (ticks) to stay in the PAUSE state
PAUSE_TIME EQU 40
;==========================================================================
; EEPROM configuration bytes
; Only one byte is currently defined.
; If you define any more, you may have to modify the code in
; ConfigureUnits (temp.asm) to wait for write completion
;==========================================================================
; OFFSETS
EE_VERSION EQU 0 ; Version number
EE_FC_CONFIG EQU 1 ; Fahrenheit/Celsius display
; Define current version number. This value gets stored at offset
; EE_VERSION in the EEPROM
EE_CURRENT_VERSION EQU 0
;==========================================================================
; Non-ASCII display characters
;==========================================================================
DEGREES EQU 0xF2 ; Degree symbol for display
INTERNAL_CLOCK_IND EQU 0xFD ; Not-equal sign
PK ‘îI I PIC\controller.mcpPK 4Hš š y PIC\main.asmPK }+Õ6 6
=&