On 3/26/2012 3:46 PM, Don Kinzer wrote:
> --- In AVR-Chat@yahoogroups.com, fireweaver<firewevr@...> wrote:
>> The decoder I have does its thing in about 28 cycles. As a C
>> interrupt routine, it is well over 100 cycles and may not be
>> able to keep up with the encoder.
> If you are willing to post the existing assembly code and provide an upper limit on the number of cycles that is acceptable, I expect that you would have several people rise to the challenge to make it avr-gcc compatible or re-implement it so that it is compatible.
>
> Don Kinzer
> ZBasic Microcontrollers
> http://www.zbasic.net
>
Here is the code. I don't know how this will appear since the group
forbids attachments.
Use a fixed width font like Courier to make it look right.
The general idea is to control a motor which can run up to 3000 RPM. It
has an built-in
encoder with 400 counts (at 4X) per revolution.
; SINGLE CHANNEL QUADRATURE DECODER
;*******************************************************************************;
;
;
; This is the quadrature decoder. This decoder is designed to decode
two ;
; channels to a resolution of one part in 2^24. It is designed to run
as fast ;
; as
possible. ;
;
;
; Selling
points: ;
; 1. One channel to 24-bit
precision. ;
; 2. Very fast execution time = 25 cycles worst
case. ;
; 3. Small code
size. ;
; 4. Extensible to more channels (as dedicated
encoder) ;
; Weak
points: ;
; 1. Commandeers 4 registers for its own
use. ;
;
;
;*******************************************************************************;
.include "m168Adef.inc"
;*******************************************************************************;
; Defined by original
project ;
;
ATmega168 ;
;
/----U----\ ;
; PC6 | 01 28 |
PC5 ;
; (X-axis I in) PD0 | 02 27 |
PC4 ;
; (X-axis Q in) PD1 | 03 26 |
PC3 ;
; (X error out) PD2 | 04 25 |
PC2 ;
; PD3 | 05 24 |
PC1 ;
; PD4 | 06 23 |
PC0 ;
; VCC | 07 22 |
GND ;
; GND | 08 21 |
AREF ;
; PB6 | 09 20 |
AVCC ;
; PB7 | 10 19 |
PB5 ;
; PD5 | 11 18 |
PB4 ;
; PD6 | 12 17 |
PB3 ;
; (duty cycle) PD7 | 13 16 |
PB2 ;
; PB0 | 14 15 |
PB1 ;
;
\---------/ ;
;
;
; (duty cycle) is used to see how long the routine
runs ;
;
;
;
;
; PORTD bits are laid out as
follows: ;
.equ CH_X0 = PD0 ; Channel A inphase in
.equ CH_X1 = PD1 ; Channel A quadrature in
.equ ERR_X = PD2 ; Channel A error signal out
.equ OC2B = PD3 ; Timer overflow bit (diagnostic output).
.equ Q_DEBUG = PD7 ; Duty cycle informs on CPU usage ()
;
;
; Reserved register
assignments. ;
;
;
; Encoder
management ;
.def encoder_state = R9
; X-count accumulator (dedicated to
encoder) ;
.def X_count_0 = R21 ; low byte
.def X_count_1 = R22
.def X_count_2 = R23 ; high byte
; This code is may be located anywhere in
memory. ;
;
;
; _______ ___________ _______ ___
___ ;
; A |___/ | \___|___/ | | \___|___/ | \___/ \___|___/
\___/ ;
; | | |___|___| | |___| | |___|___| | |___| |___|
|___ ;
; B \___|___/ | \___|___/ \___|___/ | \___|___/ \___/
\___/ \ ;
; -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 ? ? OK
? ? ;
;
;
; | normal operation | error
codes | ;
; ? = Error, K =
Okay ;
;
;
; The encoder is periodically sampled. Each sample is compared to the
previous ;
; sample giving one of 16 possible choices. These choices funnel into
four ;
; possible actions, depending on how the bits change between
samples. ;
; Sampling rate is required to be at least twice the rate of incoming
encoder ;
; pulses to ensure accurate
counting. ;
;
;
; These actions
are: ;
; Increment - add one to the count
register ;
; Decrement - subtract one from the count
register ;
; Idle - inputs did not change, do
nothing ;
; Error - should never happen, both inputs changed at the same
time. ;
; If the error signal comes and goes, it is a sign that
the input ;
; is changing too fast for the decoder to keep up
with. ;
;
;
; A,B
A,B ;
; Was Is Do
This ;
;
------------------------------
;
; 00 00
idle ;
; 00 01
increment ;
; 00 10
decrement ;
; 00 11
error ;
;
;
; 01 00
decrement ;
; 01 01
idle ;
; 01 10
error ;
; 01 11
increment ;
;
;
;
;
; 10 00
increment ;
; 10 01
error ;
; 10 10
idle ;
; 10 11
decrement ;
;
;
; 11 00
error ;
; 11 01
decrement ;
; 11 10
increment ;
; 11 11
idle ;
;*******************************************************************************;
.cseg
.org 0x100
Quadrature_Decoder:
; do all preparation in advance ;(cycles)
lsr encoder_state ;(1) current X,Z state becomes
previous
in ZH,PIND ;(1) sample the inputs once
; update the state of the X-input
bst ZH,CH_X1 ;(1)
bld encoder_state,1 ;(1)
bst ZH,CH_X0 ;(1)
bld encoder_state,3 ;(1) copy port bits to current
X state
;
decode_X:
ldi ZH,high( X_actions) ;(1) load once, doesn't change.
mov ZL,encoder_state ;(1)
andi ZL,15 ;(1)
subi ZL,0xFF-low(X_actions) ;(1)
ijmp ;(2) do an X action
;
X_actions:
.db low(X_idle), low(X_increment), low(X_decrement),
low(X_error)
.db low(X_decrement), low(X_idle), low(X_error),
low(X_increment)
.db low(X_increment), low(X_error), low(X_idle),
low(X_decrement)
.db low(X_error), low(X_decrement), low(X_increment),
low(X_idle)
X_error: ; both inputs changed at same time, or encoder turning too fast.
sbi PORTD,ERR_X ;(2) "X error" = 1
X_idle: ; not moving
reti ;(2)
X_increment: ; counting up
cbi PORTD,ERR_X ;(2) "X error" = 0
subi X_count_0,low(-1) ;(1)
sbci X_count_1,byte2(-1) ;(1)
sbci X_count_2,byte3(-1) ;(1)
reti ;(4) longest path = (13)
X_decrement: ; counting down
cbi PORTD,ERR_X ;(2) "X error" = 0
subi X_count_0,low(1) ;(1)
sbci X_count_1,byte2(1) ;(1)
sbci X_count_2,byte3(1) ;(1)
reti ;(4)
;*******************************************************************************;
; End of
decoder ;
;*******************************************************************************;
;AVRASM: AVR macro assembler 2.1.43 (build 48 May 30 2011 10:07:37)
;Copyright (C) 1995-2011 ATMEL Corporation
;
;D:\videos\quadrature_encoder_1_1.s(20): Including file
'D:\videos\m168Adef.inc'
;
;ATmega168A memory use summary [bytes]:
;Segment Begin End Code Data Used Size Use%
;---------------------------------------------------------------
;[.cseg] 0x000200 0x00023e 46 16 62 16384 0.4%
;[.dseg] 0x000100 0x000100 0 0 0 1024 0.0%
;[.eseg] 0x000000 0x000000 0 0 0 512 0.0%
;
;Assembly complete, 0 errors. 0 warnings
erikc