Difference between revisions of "Reading Rotary Encoders"
From Just in Time
Line 4: | Line 4: | ||
The main program just loops and does nothing. The first vp communicates directly with the second. | 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. | ||
;======================================================================= | ;======================================================================= |
Revision as of 23:26, 5 September 2006
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> ;