;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include <P16F628A.inc>
errorlevel -302 ; suppress bank warnings
list st=off ; suppress symbol table
radix dec ; default radix = decimal
__CONFIG _LVP_OFF & _WDT_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_OFF
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cblock 0x70 ; common RAM
delayhi ; DelayCy() subsystem variable
endc
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; K8LH DelayCy() subsystem macro generates four instructions ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
radix dec
clock equ 20 ; 4, 8, 12, 16, 20 (MHz), etc.
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
dloop equ 80 ; loop size (minimum 5)
;
; -- loop -- -- delay range -- -- memory overhead ----------
; 5-cyc loop, 11..327690 cycles, 9 words (+4 each macro call)
; 6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
; 7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
; 8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;
DelayCy macro cycles ; range, see above
if (cycles<11)|(cycles>(dloop*65536+10))
error " DelayCy range error "
else
movlw high((cycles-11)/dloop)+1
movwf delayhi
movlw low ((cycles-11)/dloop)
; rcall uLoop-(((cycles-11)%dloop)*2) ; (18F version)
call uLoop-((cycles-11)%dloop) ; (16F version)
endif
endm
;******************************************************************
; reset vector *
;******************************************************************
org 0x000
;
swold equ 0x20
count equ 0x21
duration equ 0x22
movlw 7 ; |B0
movwf CMCON ; camparator module off |B0
bsf STATUS,RP0 ; bank 01 |B1
movlw b'00111110' ; make RA0 and output |B1
movwf TRISA ; " |B1
bcf STATUS,RP0 ; bank 00 |B0
movlw 20 ; value for 100-msecs |B0
movwf duration ; " |B0
movwf count ; " |B0
bsf PORTA,RA0 ; |B0 <-- set PC here and
; zero stopwatch
; wreg ____---____-----_____ inverted active lo sample
; swold _____---____-----____ switch state latch
; wreg ____-__-___-____-____ changes, press or release
; wreg ____-______-_________ filter out 'release' bits
;
durtmr
comf PORTA,W ; sample active lo switches |B0
andlw 1<<RA3 ; on RA3 pin only |B0
xorwf swold,W ; changes, press or release |B0
xorwf swold,F ; update switch state latch |B0
andwf swold,W ; filter out 'release' bits |B0
skpz ; new press? no, skip, else |B0
goto nextfx ; branch (exit timer loop) |B0
d1 DelayCy(50*msecs-11) ; 50-ms minus 11 cycle loop time |B0
movlw 1<<RA0 ; RA0 output 'toggle' mask |B0
decfsz count,F ; done? yes, skip, else |B0
goto durtmr ; loop (another 50 msecs) |B0
toggle
xorwf PORTA,F ; toggle RA0 output |B0 <-- breakpoint
movlw 20^180 ; toggle 1-sec & 9-sec timing |B0
xorwf duration,W ; " |B0
movwf duration ; " |B0
movwf count ; setup new timer loop count |B0
nop ; |B0
goto d1 ; |B0
nextfx
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; K8LH DelayCy() subsystem 16-bit uLoop subroutine ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a = dloop-1
while a > 0
nop ; (cycles-11)%dloop entry points |
a -= 1
endw
uLoop addlw -1 ; subtract 'dloop' loop time |
skpc ; borrow? no, skip, else |
decfsz delayhi,F ; done? yes, skip, else |
; bra uLoop-dloop*2+10 ; do another loop (18F version) |
goto uLoop-dloop+5 ; do another loop (16F version) |
return ; |
end