On 3/27/2012 11:43 AM, Don Kinzer wrote:
> --- In AVR-Chat@yahoogroups.com, fireweaver<firewevr@...> wrote:
>> So I should write:
>> subi ZL,0xFF-low(X_actions)
>> lpm ZL,Z ;<---
>> ijmp
> Yes, if you want to load the value from the table entry into ZL. Also, I suspect that the instruction preceding the lpm should actually be
>
> subi ZL,0-low(X_actions)
>
> This subtracts the negative of the low byte of the X_actions address, effectively adding the low byte of the X_actions address.
>
> I thought you said (or perhaps I inferred) that this code was working. It doesn't seem that that is so.
>
> Don Kinzer
I screwed up and sent the wrong code. This is the version that I am
using in my DRO.
What I sent you was an attempt to compress it even further. My bad.
===begin code===
; 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 ;
;
\---------/ ;
;
;
;
;
;
;
; 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 Q_DEBUG = PD7 ; Duty cycle informs on CPU usage out
;
;
; Reserved register
assignments. ;
;
;
; Encoder
management ;
.def encoder_state = R16
; X-count accumulator (dedicated to
encoder) ;
.def X_count_0 = r26 ; low byte
.def X_count_1 = r27
.def X_count_2 = r28 ; 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 = old phase A, B = old phase
B ;
; a = new phase A, b = new phase
B ;
;
;
; Aa
Bb ;
;
------------------------------
;
; 00 00
idle ;
; 00 01
up ;
; 00 10
down ;
; 00 11
idle ;
;
;
; 01 00
down ;
; 01 01
error ;
; 01 10
error ;
; 01 11
up ;
;
;
; 10 00
up ;
; 10 01
error ;
; 10 10
error ;
; 10 11
down ;
;
;
; 11 00
idle ;
; 11 01
down ;
; 11 10
up ;
; 11 11
idle ;
;*******************************************************************************;
.cseg
.org 0x100
;
Quadrature_Decoder:
; do all preparation in advance ;(cycles)
lsl encoder_state ; 00000B0A -> 0000B0A0
in ZH,PIND ;(1) sample the inputs once
; update the state of the X-input
bst ZH,0 ; read A
bld encoder_state,0 ; 0000B0A0 -> 0000B0Aa
bst ZH,1 ; read B
bld encoder_state,2 ; 0000B0Aa -> 0000BbAa
andi encoder_state,15 ; trim encoder state
;
decode_X:
ldi ZH,high( X_actions) ;(1) load once, doesn't change.
mov ZL,encoder_state ;(1)
subi ZL,-low(X_actions) ;(1)
ijmp ;(2) do an X action
;
X_actions:
rjmp X_idle
rjmp X_increment
rjmp X_decrement
rjmp X_idle
;
rjmp X_decrement
rjmp X_error
rjmp X_error
rjmp X_increment
;
rjmp X_increment
rjmp X_error
rjmp X_error
rjmp X_decrement
;
rjmp X_idle
rjmp X_decrement
rjmp X_increment
rjmp 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 ;(4)
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)
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 code===
erikcMessage
Re: [AVR-Chat] Re: Mixing C and assembly with special requirements.
2012-03-28 by fireweaver
Attachments
- No local attachments were found for this message.