;******************************************************************
; *
; Filename: 12F1822_Test.asm *
; Author: Mike McLaren, K8LH *
; Date: 13-Aug-2017 *
; *
; 12F1822 experiment *
; *
; *
; MPLab: 8.92 (tabs=8) *
; MPAsm: 5.51 *
; *
;******************************************************************
include "P12F1822.INC"
errorlevel -302
list st=off
radix dec
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _BORV_19 & _LVP_OFF & _PLLEN_OFF
;
; _MCLRE_ON default
; _PWRTE_OFF default
; _CP_OFF default
; _CPD_OFF default
; _BOREN_ON default
; _CLKOUTEN_OFF default
;
; _WRT_OFF default
; _STVREN_ON default
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; variables ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cblock 0x20 ; 0x20..0x6F, bank 0
swold ;
swnew ;
flags ;
delayhi ; DelayCy() function variable
endc
cblock 0x70 ; 0x70..0x7F common all banks
endc
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; constants ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; K8LH DelayCy() subsystem macro generates four instructions ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
radix dec
clock equ 16 ; 4, 8, 12, 16, 20 (MHz), etc.
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
dloop equ 5 ; loop size, 5 to 8 cycles
;
; -- 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)
call uLoop-((cycles-11)%dloop)
endif
endm
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; reset vector ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
org 0x0000
v_reset
goto setup ;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; interrupt vector ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
org 0x004
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; main setup ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setup
banksel ANSELA ; bank 3 |03
clrf ANSELA ; set digital I/O |03
banksel TRISA ; bank 01 |01
movlw b'00000111' ; |01
movwf TRISA ; |01
;
; setup INTOSC
;
banksel OSCCON ; bank 1 |01
movlw b'01111010' ; |01
movwf OSCCON ; setup 16-MHz INTOSC |01
waitfs btfss OSCSTAT,HFIOFS ; stable? yes, skip, else |01
bra waitfs ; branch and wait |01
banksel PORTA ; bank 0 |00
clrf swold ; |00
clrf flags ; |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; main loop ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; /*
; * Lighted Push Button Switches (emulated toggle switches)
; *
; * swnew ____---____-----___ sample active lo switches
; * swold _____---____-----__ switch state latch
; * swnew ____-__-___-____-__ changes, press or release
; * swnew ____-______-_______ filter out 'release' bits
; * flags _____-------_______ toggle flag bits for main
; * trisa -----_______------- toggle tris bits for LEDs
; */
;
; while(1)
; { delay_ms(25); // sample at 25-ms intervals
; trisa |= 0b00000111; // set RA2-RA0 pins to input
; swnew = ~porta; // sample active lo switches
; swnew &= 0b00000111; // only RA2-RA0 switch pins
; swnew ^= swold; // changes, press or release
; swold ^= swnew; // update switch state latch
; swnew &= swold; // filter out 'release' bits
; flags ^= swnew; // toggle flag bits for main
; porta &= 0b11111000; // set output latches to '0'
; trisa ^= flags; // light only active sw LEDs
;
; if(swnew) // on any "new press"
; beep(); // task a "new press" beep
;
; if(swnew.0) // if sw RA0 'new press'
; { //
; } //
; if(swnew.1) // if sw RA1 'new press'
; { //
; } //
; if(swnew.2) // if sw RA2 'new press'
; { //
; } //
; }
;
loop
DelayCy(25*msecs) ; sample at 25 msec intervals |00
;
; K8LH parallel switch state logic and "new press" filter
;
; wreg ____---____-----_____ inverted active lo sample
; swold _____---____-----____ switch state latch
; wreg ____-__-___-____-____ changes, press or release
; wreg ____-______-_________ filter out 'release' bits
; flags _____-------_________ toggle flag bits for main
;
banksel TRISA ; bank 1 |01
movlw b'00000111' ; |01
iorwf TRISA,F ; set RA2..RA0 pins to inputs |01
banksel PORTA ; bank 0 |00
comf PORTA,W ; sample active lo switches |00
xorwf swold,W ; changes, press or release |00
xorwf swold,F ; update switch state latch |00
andwf swold,W ; filter out 'release' bits |00
movwf swnew ; save 'new press' bits |00
skpz ; new switch? no, skip, else |00
movwf flags ; update 'on' flags (1 of n) |00
; xorwf flags,F ; toggle 'on' flags (n of n) |00
;
; light LEDs for switches with an 'on' flag
;
movlw b'11111000' ; mask off RA2-RA0 bits |00
andwf PORTA,F ; set output latches to '0' |00
movf flags,W ; pickup sw2..sw0 states |00
banksel TRISA ; bank 1 |01
xorwf TRISA,F ; trisa ^= flags (light LEDs) |01
banksel PORTA ; bank 0 |00
;
; check for "new" switch position change
;
btfsc swnew,0 ; RA0 on? no, skip, else |00
call off_mode ; |00
btfsc swnew,1 ; RA1 on? no, skip, else |00
call man_mode ; |00
btfsc swnew,2 ; RA2 on? no, skip, else |00
call auto_mode ; |00
goto loop ; |00
off_mode
man_mode
auto_mode
return ; |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; K8LH DelayCy() subsystem 16-bit uDelay subroutine ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a = dloop-1
while a > 0
nop ; (cycles-11)%dloop entry points |00
a -= 1
endw
uLoop addlw -1 ; subtract 'dloop' loop time |00
skpc ; borrow? no, skip, else |00
decfsz delayhi,F ; done? yes, skip, else |00
goto uLoop-dloop+5 ; do another loop |00
return ; |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end