Actions

Reading Rotary Encoders

From Just in Time

Revision as of 23:26, 5 September 2006 by 84.27.206.102 (talk)

The following SX28 assembly contains two virtual pheripherals:

  • Reading a rotary encoder
  • driving 4 7-segment led displays

The main program just loops and does nothing. The first vp communicates directly with the second. This code is an adapted version (made into a vp) of sources found on sxlist.

;=======================================================================

;TITLE:         4x7segments.src
;
;PURPOSE:       Read pulses from a rotary encoder, adapt a counter
;			and output to 4 7-segment led displays
;
;AUTHOR:        Danny Havenith
;
;REVISIONS:
;  <mm/dd/yy> - <details of revision>
;               <more details of same revision>
;
;CONNECTIONS:
;	ra.0 and ra.1: encoder inputs
;	rc: led segment outputs
;	rb.0-4: led column outputs
;
;=======================================================================


;-------------------------- DEVICE DIRECTIVES --------------------------

		DEVICE		SX28,OSC4MHZ,TURBO
		DEVICE		STACKX, OPTIONX
		IRC_CAL		IRC_SLOW

		RESET		Initialize

;------------------------------ CONSTANTS ------------------------------

TicksPerMs	EQU	20	; interrupts per ms
CyclesPerTick	EQU	200	; cycles per interrupt


------------------------------ VARIABLES ------------------------------
			ORG	$10

BankLeds	= $

MSTimer		DS	1
CurrentDigit	DS	1
CurrentColumn	DS	1
Digits		DS	4

CounterA	DS	1
CounterB	DS	1
CounterC	DS	1

BankEncoder	= $
EncoderState	DS 	1
temp		DS	1


ColumnPort	EQU 	rb
RowPort		EQU	rc

EncoderPort	EQU	ra 	; port for the rotary encoder
EncoderMask	EQU	$03	; which bits to use.

;---------------------------- DEBUG SETTINGS ---------------------------

		FREQ	4_000_000
	
;		WATCH	<Symbol>,<bit count>,<format>

WKED_W		equ	$0A		;Write MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising
WKEN_W		equ	$0B		;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled
ST_W		equ	$0C		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
LVL_W		equ	$0D		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
PLP_W		equ	$0E		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
DDIR_W		equ	$0F		;Write Port Direction

RA_latch	equ	%00000000		;SX18/20/28/48/52 port A latch init
RA_DDIR		equ	%11111111		;see under pin definitions for port A DDIR value
RA_LVL		equ	%00000000		;SX18/20/28/48/52 port A LVL value
RA_PLP		equ	%11111111		;SX18/20/28/48/52 port A PLP value

RB_latch	equ	%00000000		;SX18/20/28/48/52 port B latch init
RB_DDIR		equ	%11110000		;SX18/20/28/48/52 port B DDIR value
RB_ST		equ	%11111111		;SX18/20/28/48/52 port B ST value
RB_LVL		equ	%00000000		;SX18/20/28/48/52 port B LVL value
RB_PLP		equ	%11111111		;SX18/20/28/48/52 port B PLP value

RC_latch	equ	%00000000		;SX18/20/28/48/52 port C latch init
RC_DDIR		equ	%00000000		;SX18/20/28/48/52 port C DDIR value
RC_ST		equ	%11111111		;SX18/20/28/48/52 port C ST value
RC_LVL		equ	%00000000		;SX18/20/28/48/52 port C LVL value
RC_PLP		equ	%11111111		;SX18/20/28/48/52 port C PLP value

;-------------------------- INTERRUPT ROUTINE --------------------------
		ORG	$0
		
;	break Interrupt
Interrupt
; timer
	bank BankLeds
	mov w, #TicksPerMs
	dec MSTimer
	snz
	mov MSTimer, w
	sz
	jmp EndInterrupt

	mov w, #Digits
	add w, CurrentDigit
	mov fsr, w
	mov w, IND
	call Decode
	clr ColumnPort
	mov RowPort, w
	mov ColumnPort, CurrentColumn

	; next column
	clc
	rr CurrentColumn	; rotate column left
	mov w, #%00001000
	inc CurrentDigit		; increase digit counter
	snc 		; reset if digit = 4
	mov CurrentColumn, w
	snc 
	clr CurrentDigit

:EndLeds

	break ReadEncoder
ReadEncoder
        mov w, EncoderPort           ;get change between current and previous 
                            ;encoder state in w
        xor w, EncoderState    ;
        
        xor EncoderState, w    ;update state and preserve difference in w

        and w, #EncoderMask         ;check if there is change
        snz
         jmp :EndEncoder       ;no change, read encoder again

        ;if both bits changed, this will be an error, but we ignore it here
        ;xor w, #$03
        ;skpnz
        ; jmp enc_error

        ;calculate direction in temp.1
        mov temp, w       
        mov w, <<EncoderState
        xor w, EncoderState
        xor temp, w

        sb temp.1
         call EncoderIncrease       ;Encoder moved up
        snb temp.1
         call EncoderDecrease       ;Encoder moved down

:EndEncoder

EndInterrupt
	mov w, #-CyclesPerTick		
	retiw

EncoderIncrease
	inc	Digits + 3
	cjne	Digits + 3, #10, :EndInc
	clr 	Digits + 3

	inc	Digits + 2
	cjne	Digits + 2, #10, :EndInc
	clr 	Digits + 2

	inc	Digits + 1
	cjne	Digits + 1, #10, :EndInc
	clr 	Digits + 1

	inc	Digits 
	cjne	Digits, #10, :EndInc
	clr 	Digits
:EndInc
	retp

EncoderDecrease
	dec	Digits + 3
	cjne	Digits + 3, #$FF, :EndDec
	mov	Digits + 3, #09

	dec	Digits + 2
	cjne	Digits + 2, #$FF, :EndDec
	mov	Digits + 2, #09

	dec	Digits + 1
	cjne	Digits + 1, #$FF, :EndDec
	mov	Digits + 1, #09

	dec	Digits
	cjne	Digits, #$FF, :EndDec
	mov	Digits, #09
:EndDec		
	retp

Decode
	and w, #$0F
	jmp PC+w
	retw %00000101 ;0
	retw %11011101 ;1
	retw %10000110 ;2
	retw %10010100 ;3
	retw %01011100 ;4
	retw %00110100 ;5
	retw %00100100 ;6
	retw %10011101 ;7
	retw %00000100 ;8
	retw %00010100 ;9
	retw %00001100 ;A
	retw %01100100 ;b
	retw %00100111 ;C
	retw %11000100 ;d
	retw %00100110 ;E
	retw %00101110 ;F

;------------------------ INITIALIZATION ROUTINE -----------------------

Initialize
		; Configure all ports
		mov 	m, #ST_W			;point MODE to write ST register
		mov     w,#RB_ST            	;Setup RB Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_ST            	;Setup RC Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rc,w	
		mov 	m, LVL_W			;point MODE to write LVL register
		mov     w,#RA_LVL            	;Setup RA CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!ra,w		 
		mov     w,#RB_LVL            	;Setup RB CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!rb,w		
		mov     w,#RC_LVL            	;Setup RC CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!rc,w	

		mov 	w,#RA_PLP            	;Setup RA Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!ra,w		 
		mov     w,#RB_PLP            	;Setup RB Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_PLP            	;Setup RC Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rc,w	

		mov 	m, #DDIR_W			;point MODE to write DDIR register
		mov	w,#RA_DDIR		;Setup RA Direction register, 0 = output, 1 = input		
		mov	!ra,w	
		mov	w,#RB_DDIR		;Setup RB Direction register, 0 = output, 1 = input
		mov	!rb,w			
		mov	w,#RC_DDIR		;Setup RC Direction register, 0 = output, 1 = input
		mov	!rc,w			

		mov     w,#RA_latch          	;Initialize RA data latch
		mov     ra,w		
		mov     w,#RB_latch         	;Initialize RB data latch
		mov     rb,w		
		mov     w,#RC_latch          	;Initialize RC data latch
		mov     rc,w		

; zero all ram (SX28)
		clr	fsr			;reset all ram banks
: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
		incsz	fsr			;repeat until done
		jmp	:zero_ram

:init_leds	bank BankLeds
		mov CurrentDigit, #0
		mov CurrentColumn, #1

;---------------------------- MAIN PROGRAM -----------------------------

Main

	mov Digits, #1
	mov Digits + 1, #2
	mov Digits + 2, #3
	mov Digits + 3, #4
	mov	!option, #%10011111	;enable rtcc interrupt

:loop	
 	jmp :loop




	
;----------------------------- SUBROUTINES -----------------------------

;<GlobalLabel>
;<detailed description of routine>

;		<inst>	<op1>,<op2>		;