Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: [AVR-Chat] Re: Mixing C and assembly with special requirements.

2012-03-28 by fireweaver

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===

erikc

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.