please dont rip this site

Scenix Buttons_vp.src

; ******************************************************************************
;       Push Buttons & Path Switcher (with abbreviated real time clock)
;
;
;       Length: >=74 bytes (depends upon number of buttons & clock type)
;       Author: Craig Webb
;       Written: 98/8/17
;
;	This program implements a software time clock virtual peripheral
;	that keeps a 16 bit count of elapsed time in milliseconds.
;	The option is available to include seconds, minutes, hours and even
;	days to this clock if desired.
;	The code takes advantage of the SX's internal RTCC-driven interrupt
;	to operate in the background while the main program loop is executing.
;
;******************************************************************************
;
;****** Assembler directives
;
; uses: SX28AC, 2 pages of program memory, 8 banks of RAM, high speed osc.
;       operating in turbo mode, with 8-level stack & extended option reg.
;                
		DEVICE  pins28,pages2,banks8,oschs
		DEVICE  turbo,stackx,optionx
		ID      'Buttons'			;program ID label
		RESET   reset_entry			;set reset/boot address
;
;******************************* Program Variables ***************************
;
;****** Program Parameters
;
clock_type	=	0			;16 bit msec count only
;clock_type	=	1			;include sec, min, hours
;clock_type	=	2			;include day counter
;
num_buttons	=	2			;number of buttons (1-4)
;
;******	Program Constants
;
int_period	=	163			;period between interrupts
;
hold_bit	=	4-(num_buttons/2)	;debounce period = 2^hold_bit msec
;
tick_lo		=	80			;50000 = msec instruction count
tick_hi		=	195			; for 50MHz, turbo, prescaler=1
;
mspersec_hi	=	1000/256		;msec per second hi count
mspersec_lo	=	1000-(mspersec_hi*256)	;msec per second lo count
;
;******	Port definitions
;
button0		EQU	RB.0			;Push button 0
button1		EQU	RB.1			;Push button 1
button2		EQU	RB.2			;Push button 2
button3		EQU	RB.3			;Push button 3
;
;****** Register definitions
;
		ORG	8			;start of program registers
main            =	$			;main bank
;
temp            DS	1			;temporary storage
temp2		DS	1
;
		ORG	010H			;bank0 variables
clock		EQU	$			;clock bank
buttons		EQU     $                       ;push button bank
;
time_base_lo	DS	1			;time base delay (low byte)
time_base_hi	DS	1			;time base delay (high byte)
msec_lo		DS	1			;millisecond count (low)
msec_hi		DS	1			;millisecond count (high)

		IF	clock_type>0		;do we want sec, min, hours?
seconds		DS	1			;seconds count
minutes		DS	1			;minutes count
hours		DS	1			;hours count
		ENDIF				

		IF	clock_type>1		;do we want day count?
days		DS	1			;days count
		ENDIF				
;
;
debounce0	DS	1			;push button 0 debounce count
debounce1	DS	1			;push button 1 debounce count
debounce2	DS	1			;push button 2 debounce count
debounce3	DS	1			;push button 3 debounce count
pbflags		DS	1			;push button status flags
pb0_pressed	EQU	pbflags.0		;push button 0 action status
pb1_pressed	EQU	pbflags.1		;push button 1 action status
pb2_pressed	EQU	pbflags.2		;push button 2 action status
pb3_pressed	EQU	pbflags.3		;push button 3 action status
pb0_down	EQU	pbflags.4		;push button 0 down status
pb1_down	EQU	pbflags.5		;push button 1 down status
pb2_down	EQU	pbflags.6		;push button 2 down status
pb3_down	EQU	pbflags.7		;push button 3 down status
;
;*************************** INTERRUPT VECTOR ******************************
;
; Note: The interrupt code must always originate at 0h.
;	A jump vector is not needed if there is no program data that needs
;	to be accessed by the IREAD instruction, or if it can all fit into
;	the lower half of page 0 with the interrupt routine.
;
		ORG     0				;interrupt always at 0h
;		JMP	interrupt			;interrupt vector
;
;**************************** INTERRUPT CODE *******************************
;
; Note: Care should be taken to see that any very timing sensitive routines
;       (such as adcs, etc.) are placed before other peripherals or code
;       which may have varying execution rates (like the software clock, for
;	   example).
;
interrupt						;beginning of interrupt code
;
;****** Virtual Peripheral: Time Clock
;
; This routine maintains a real-time clock count (in msec) and allows processing
; of routines which only need to be run once every millisecond.
;
;	Input variable(s) : time_base_lo,time_base_hi,msec_lo,msec_hi
;				seconds, minutes, hours, days
;	Output variable(s) : msec_lo,msec_hi
;				seconds, minutes, hours, days
;	Variable(s) affected : time_base_lo,time_base_hi,msec_lo,msec_hi
;				seconds, minutes, hours, days
;	Flag(s) affected : 
;	Size : 17/39/45 bytes (depending upon clock type)
;		+ 1 if bank select needed
;	Timing (turbo) : [99.9% of time] 14 cycles
;			 [0.1% of time] 17/39/45 cycles (or less)
;			+ 1 if bank select needed
;
;		BANK	clock			;select clock register bank
		MOV	W,#int_period		;load period between interrupts
		ADD	time_base_lo,W		;add it to time base
		SNC				;skip ahead if no underflow
		INC	time_base_hi		;yes overflow, adjust high byte
		MOV	W,#tick_hi		;check for 1 msec click
		MOV	W,time_base_hi-W	;Is high byte above or equal?
		MOV	W,#tick_lo		;load instr. count low byte
		SNZ				;If hi byte equal, skip ahead
		MOV	W,time_base_lo-W	;check low byte vs. time base
		SC				;skip ahead if low

;commented out because of path_switcher/pushbutton routines which use msec count
;		JMP	:done_clock		;If not, end clock routine
		JMP	done_pbs		;If not, end clock routine

:got_tick	CLR	time_base_hi		;Yes, adjust time_base reg.'s
		SUB	time_base_lo,#tick_lo	; leaving time remainder
		INCSZ	msec_lo			;And adjust msec count
		DEC	msec_hi			; making sure to adjust high
		INC	msec_hi			; byte as necessary

		IF	clock_type>0		;do we want sec, min, hours?
		MOV	W,#mspersec_hi		;check for 1000 msec (1 sec tick)
		MOV	W,msec_hi-W		;Is high byte above or equal?
		MOV	W,#mspersec_lo		;load #1000 low byte
		SNZ				;If hi byte equal, skip ahead
		MOV	W,msec_lo-W		;check low byte vs. msec count
		SC				;skip ahead if low
		JMP	:done_clock		;If not, end clock routine
		INC	seconds			;increment seconds count
		CLR	msec_lo			;clear msec counters
		CLR	msec_hi			;
		MOV	W,#60			;60 seconds per minute
		MOV	W,seconds-W		;are we at minute tick yet
		JNZ	:done_clock		;if not, jump
		INC	minutes			;increment minutes count
		CLR	seconds			;clear seconds count
		MOV	W,#60			;60 minutes/hour
		MOV	W,minutes-W		;are we at hour tick yet?
		JNZ	:done_clock		;if not, jump
		INC	hours			;increment hours count
		CLR	minutes			;clear minutes count
		ENDIF				;<if> we wanted sec, min, hours

		IF	clock_type>1		;do we want to count days?
		MOV	W,#24			;24 hours per day
		MOV	W,hours-W		;are we at midnight?
		JNZ	:done_clock		;if not, jump
		INC	days			;increment days count
		CLR	hours			;clear hours count
		ENDIF				;<if> we wanted day count
:done_clock
;
;****** Virtual Peripheral: Path Switch
;
; This routine allows alternating execution of multiple modules which don't
; need to be run during every interrupt pass in order to reduce the overall
; execution time of the interrupt on any given pass (i.e. it helps the code
; run faster).
; This version runs with the software clock virtual peripheral msec_lo variable
; allowing altenation between the switch positions once each millisecond.
;
;       Input variable(s) : msec_lo
;       Output variable(s) : 
;       Variable(s) affected : 
;       Flag(s) affected : 
;	Size : 3 bytes + 1 bytes per jump location
;       Timing (turbo) : 8 cycles
;
:path_switch	MOV	W,msec_lo		;load switch selector byte
		AND	W,#00000011b		;keep low 2 bits - 4 position
		JMP	PC+W			;jump to switch position pointer
:pos0		JMP	pb0			;pushbutton 0 checking routine
:pos1		JMP	pb1			;pushbutton 1 checking routine
:pos2		JMP	pb2			;pushbutton 2 checking routine
:pos3		JMP	pb3			;pushbutton 3 checking routine
;
;
;****** Virtual Peripheral: Push Buttons*
;
; This routine monitors any number of pushbuttons, debounces them properly
; as needed, and flags the main program code as valid presses are received.
; *Note: this routine requires the Time Clock virtual peripheral or similar
;	 pre-processing timer routine.
;
;       Input variable(s) : pb0_down,pb1_down,debounce0,debounce1
;       		    pb2_down,pb3_down,debounce2,debounce3
;       Output variable(s) : pb0_pressed, pb1_pressed, pb2_pressed, pb3_pressed
;       Variable(s) affected : debounce0, debounce1, debounce2, debounce3
;       Flag(s) affected : pb0_down,pb1_down,pb0_pressed,pb1_pressed
;       		   pb2_down,pb3_down,pb2_pressed,pb3_pressed
;	Size : 12 bytes per pushbutton + actions (see below**)
;		+ 1 byte if path switch not used
;       Timing (turbo) : 7,10, or 12 cycles/pushbutton (unless path switch used)
;			 + actions (see below**)
;
pb0
;		BANK	buttons			;select bank (if not done elsewhere)
		JB	button0,:pb0_up		;button0 pressed?
		JB	pb0_down,:done_pb0	;yes, but is it new press?
		INC	debounce0		; and adjust debounce count
		JNB	debounce0.hold_bit,:done_pb0	;wait till long enough
		SETB	pb0_down		;yes, flag that button is down

;**If the button activity is short (a few bytes), it can fit here, though be
; careful that longest possible interrupt doesn't exceed int_period # of cycles.
;
; <short code segment can go here>
;
;**Otherwise, use this flag to process button press in main code (and don't
; forget to reset the flag once the button activity is complete).
		SETB	pb0_pressed		; and set pb0 action flag

		SKIP				;skip next instruction
:pb0_up		CLRB	pb0_down		;button up, clear flag
		CLR	debounce0		; and clear debounce count
:done_pb0
;
		JMP	done_pbs		;this needed only if path switch used


pb1		
		IF	num_buttons>1		;more than 1 push button?
;		BANK	buttons			;do bank select (if not done elsewhere)
		JB	button1,:pb1_up		;button1 pressed?
		JB	pb1_down,:done_pb1	;yes, but is it new press?
		INC	debounce1		; and adjust debounce count
		JNB	debounce1.hold_bit,:done_pb1	;wait till long enough
		SETB	pb1_down		;yes, flag that button is down

;**If the button activity is short (a few bytes), it can fit here, though be
; careful that longest possible interrupt doesn't exceed int_period # of cycles.
;
; <short code segment can go here>
;
;**Otherwise, use this flag to process button press in main code (and don't
; forget to reset the flag once the button activity is complete).
		SETB	pb1_pressed		; and set pb1 action flag

		SKIP				;skip next instruction
:pb1_up		CLRB	pb1_down		;button up, clear flag
		CLR	debounce1		; and clear debounce count
:done_pb1
;
		JMP	done_pbs		;this needed only if path switch used
		ENDIF				;more than 1 push button

pb2
		IF	num_buttons>2		;more than 2 push buttons?
;		BANK	buttons			;do bank select (if not done elsewhere)
		JB	button2,:pb2_up		;button2 pressed?
		JB	pb2_down,:done_pb2	;yes, but is it new press?
		INC	debounce2		; and adjust debounce count
		JNB	debounce2.hold_bit,:done_pb2	;wait till long enough
		SETB	pb2_down		;yes, flag that button is down

;**If the button activity is short (a few bytes), it can fit here, though be
; careful that longest possible interrupt doesn't exceed int_period # of cycles.
;
;**Otherwise, use this flag to process button press in main code (and don't
;  orget to reset the flag once the button activity is complete).
		SETB	pb2_pressed		; and set pb2 action flag

		SKIP				;skip next instruction
:pb2_up		CLRB	pb2_down		;button up, clear flag
		CLR	debounce2		; and clear debounce count
:done_pb2
;

		JMP	done_pbs		;this needed only if path switch used
		ENDIF				;more than 2 push buttons

pb3		
		IF	num_buttons>2		;more than 3 push buttons?
;		BANK	buttons			;do bank select (if not done elsewhere)
		JB	button3,:pb3_up		;button3 pressed?
		JB	pb3_down,:done_pb3	;yes, but is it new press?
		INC	debounce3		; and adjust debounce count
		JNB	debounce3.hold_bit,:done_pb3	;wait till long enough
		SETB	pb3_down		;yes, flag that button is down

;**If the button activity is short (a few bytes), it can fit here, though be
;  careful that longest possible interrupt doesn't exceed int_period # of cycles.
;
;**Otherwise, use this flag to process button press in main code (and don't
;  forget to reset the flag once the button activity is complete).
		SETB	pb3_pressed		; and set pb3 action flag

		SKIP				;skip next instruction
:pb3_up		CLRB	pb3_down		;button up, clear flag
		CLR	debounce3		; and clear debounce count
:done_pb3
		ENDIF				;more than 3 push buttons
;
done_pbs
;

done_int	mov     w,#-int_period     	;interrupt every 'int_period' clocks
		retiw                      	;exit interrupt
;
;******	End of interrupt sequence
;
;************************** RESET ENTRY POINT *****************************
;
reset_entry
;		PAGE	start			;Set page bits and then
;		JMP	start			; jump to start of code
;
;*********************
;* Main Program Code *
;*********************
;
start		mov     !rb,#%00001111          ;Set RB in/out directions
		CLR     FSR                     ;reset all ram starting at 08h
:zero_ram	SB      FSR.4	                ;are we on low half of bank?
		SETB    FSR.3                   ;If so, don't touch regs 0-7
		CLR     IND                     ;clear using indirect addressing
		IJNZ    FSR,:zero_ram           ;repeat until done

		MOV     !OPTION,#%10011111      ;enable rtcc interrupt
;
Main:loop
;
;the following code watches pb0-pb3 for presses and acts on them
button_check
;		BANK	buttons			;select pb bank
		MOV	W,pbflags		;load pushbutton flags
		AND	W,#00001111b		;keep only 'pressed' flags
		JZ	:no_press		;jump ahead if not pressed
		MOV	temp,W			;store flags temporarily
		CLR	temp2			;clear 2nd temp storage reg.
:which_pb	INC	temp2			;increment 2nd temp value
		RR	temp			;check which button
		SC				;skip ahead if not this one
		JMP	:which_pb		;keep looping
		MOV	W,--temp2		;get 2nd temp value (less 1)
		MOV	temp,W			;save it in temp
		MOV	W,#11110000b		;get clear mask for pbflags
		AND	pbflags,W		;clear all "pressed" flags
		MOV	W,temp			;get which button pressed
		JMP	PC+W			;Go do PB routines
:pb0		JMP	pb0_action		;do pb0 action	
:pb1		JMP	pb1_action		;do pb1 action	
:pb2		JMP	pb2_action		;do pb2 action	
:pb3		JMP	pb3_action		;do pb3 action	

:no_press
;
;	<main program code goes here>
;
		JMP     Main:loop			;back to main loop
;
pb0_action
;
;	<pb0 action here>
;
		JMP	Main:loop
;
pb1_action
;
;	<pb1 action here>
;
		JMP	Main:loop
;
pb2_action
;
;	<pb2 action here>
;
		JMP	Main:loop
;
pb3_action
;
;	<pb3 action here>
;
		JMP	Main:loop
;
;***************
		END                             ;End of program code

file: /Techref/scenix/buttons_vp.src, 14KB, , updated: 1999/2/20 12:23, local time: 2024/11/14 08:25,
TOP NEW HELP FIND: 
18.220.35.83:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/Techref/scenix/buttons_vp.src"> scenix buttons_vp</A>

Did you find what you needed?