trouble with 9 bit math; controlling overflow
nick bernard
Posts: 329
hail
the project:
in a continous rotation drive one encoder returns command (where do i want the drive to point), another returns feedback (where the drive is pointing). the controller compares the 2 encoders w/ a simple algorithm and turns the drive so that the feedback matches the control.
the algorithm:
if command = feedback then dont move
if command - feedback < feedback - command then turn clockwise
if command - feedback > feedback - command then turn counterclockwise
the trouble:
the encoders have 512 bits of resolution, to simplify the project i ignored the lsb and voila. the algorithm applies directly to the sx because the byte sized variable wraps around itself. that is
1 - 255 = 2
255 - 1 = 254
so go clockwise.
but i think i can do better! i can do this with 9 bits.... ok i cant because i'm stuck on this snippet
; btw testcw = cmd
mov w, feedback0 ; testcw = cmd - fbk
sub testcw0, w
mov w, feedback1
sc
movsz w, ++feedback1
sub testcw1, w
the result is true 16bit and wraps around 65535, but i need it to wrap around 511. my previous sub wrapping script would dec the variable in a loop and detect for overflow. but thats way to slow.
does anyone have any experiance with this?
any help would be well received.
i attached 2 files,
apec256 is the working 8b program and is well commented
apec512 is the partial program in question and is poorly commented
future thanks for your generous reply
nickB
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
engineer, fireman, bowler, father, WoW addict [noparse];)[/noparse]
the project:
in a continous rotation drive one encoder returns command (where do i want the drive to point), another returns feedback (where the drive is pointing). the controller compares the 2 encoders w/ a simple algorithm and turns the drive so that the feedback matches the control.
the algorithm:
if command = feedback then dont move
if command - feedback < feedback - command then turn clockwise
if command - feedback > feedback - command then turn counterclockwise
the trouble:
the encoders have 512 bits of resolution, to simplify the project i ignored the lsb and voila. the algorithm applies directly to the sx because the byte sized variable wraps around itself. that is
1 - 255 = 2
255 - 1 = 254
so go clockwise.
but i think i can do better! i can do this with 9 bits.... ok i cant because i'm stuck on this snippet
; btw testcw = cmd
mov w, feedback0 ; testcw = cmd - fbk
sub testcw0, w
mov w, feedback1
sc
movsz w, ++feedback1
sub testcw1, w
the result is true 16bit and wraps around 65535, but i need it to wrap around 511. my previous sub wrapping script would dec the variable in a loop and detect for overflow. but thats way to slow.
does anyone have any experiance with this?
any help would be well received.
i attached 2 files,
apec256 is the working 8b program and is well commented
apec512 is the partial program in question and is poorly commented
future thanks for your generous reply
nickB
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
engineer, fireman, bowler, father, WoW addict [noparse];)[/noparse]
Comments
rotosub_9bit
cjb value1, result1, r9_no_overflow ; if v > r then overflow
cjb value0, result0, r9_no_overflow
; on overflow r = r + 512 - v
or result1, #$02 ; r = r + 512
r9_no_overflow
mov w, value0 ; r = r - v
sub result0, w
mov w, value1
sc
movsz w, ++value1
sub result1, w
ret
edit - that doesnt work the conditional jumps fail. try,
rotosub_9bit
cja xvalue1, xresult1, r9_overflow ; if v > r then overflow
cjb xvalue1, xresult1, r9_no_overflow ; if v > r then overflow
cja xvalue0, xresult0, r9_overflow
jmp r9_no_overflow
r9_overflow ; on overflow r = r + 512 - v
or xresult1, #$02 ; r = r + 512
r9_no_overflow
mov w, xvalue0 ; r = r - v
sub xresult0, w
mov w, xvalue1
sc
movsz w, ++xvalue1
sub xresult1, w
ret
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
engineer, fireman, bowler, father, WoW addict [noparse];)[/noparse]
Post Edited (nick bernard) : 9/28/2005 7:55:35 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
my algorithm goes like so
if valHi > valLo then
result_cw = valHi - valLo
result_ccw = 512 - (valHi - valLo) = 512 + valLo - valHi
yours states mask = $01
result_cw = valHi - valLo
result_ccw = valLo - valHi // 512 = [noparse][[/noparse]calculator] ((65536 + valLo - valHi) / 512 - 127) * 512
66536 + valLo - valHi - 65024 = 512 + valLo - valHi
512 == 512 *SUCCESS*
so you can also div by the wrap around value to do circular arithmatic! i honestly did not think it was that simple
many thanks tracy
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
engineer, fireman, bowler, father, WoW addict [noparse];)[/noparse]
Post Edited (nick bernard) : 9/29/2005 2:04:13 PM GMT