mynet43
03-17-2009, 09:09 AM
I'm modifying some code I wrote a while back, to make part of it assembly code, for speed.
I have a bug in the assembly code that I can't figure out. It looks right, but it doesn't work...
I've isolated it to a 'djnz' command in the code, that never finishes looping.
If I eliminate the line with the 'djnz', then it works fine, and outputs the correct debug data.
If the 'djnz' is in there, it gets stuck in the loop and never returns.
I'm sure I'm doing something dumb, so please help me find it.
Here's the important code:
'' ************************************************** ****************************
'' * "HC595.spin" 74HC595 SPIN Object *
'' * Version 1.2 *
'' ************************************************** ****************************
''
'' Calling sequence
'' OBJ
'' SReg : "HC595"
''
'' code segment
'' SReg.InitSer595 ' to initialize driver
'' more code
'' DataByte := toSend ' set up data to send to chip
'' SReg.WriteSer595(DataByte) ' send data to chip
'' more code
''
CON
_PinHigh = 1
_PinLow = 0
CLK = 0 ' pin number of CLK pin on chip (AKA SCK)
SER = 1 ' pin number of SER pin on chip
CLR = 2 ' pin number of SCLR pin on chip
RCK = 3 ' pin number of RCK pin on chip for LED arrays
GPN = 4 ' pin number of G pin on chip
RCK1 = 5 ' pin number for Vel digits
RCK2 = 6 ' pin number for Pwr digits
RCK3 = 7 ' pin number for Rep digits
RCK4 = 8 ' pin number for Wgt digits
clkmsk = 1 '1<<CLK ' set bit for CLK pin
sermsk = 2 '1<<SER ' set bit for SER pin
rckmsk = 4 '1<<RCK ' set bit for RCK pin
VAR
long cog, cmd, bitout, datalong
PUB InitSer595 ' initialize 74HC595 for startup
' set the control lines as outputs
dira[CLK] ~~
dira[SER] ~~
dira[CLR] ~~
dira[RCK] ~~
dira[GPN] ~~
dira[RCK1] ~~
dira[RCK2] ~~
dira[RCK3] ~~
dira[RCK4] ~~
outa[CLK] := _PinLow ' init main clock line to low
outa[RCK] := _PinLow ' init latch line to low
outa[RCK1] := _PinLow ' init latch line to low
outa[RCK2] := _PinLow ' init latch line to low
outa[RCK3] := _PinLow ' init latch line to low
outa[RCK4] := _PinLow ' init latch line to low
outa[GPN] := _PinHigh ' set outputs to 3-state
outa[CLR] := _PinLow ' set to clear register on chip
outa[GPN] := _PinLow ' turn on the chip and clear pins
outa[CLR] := _PinHigh ' return CLR pin to high after clear
if cog
cogstop(cog~ - 1)
cmd := 0 ' init for cognew
cog := cognew(@HC595_write, @cmd) +1
waitcnt(clkfreq/4 + cnt) 'wait 1/4 sec for cog to start
PUB WriteSer595(Data) | ix ' Data is long with 24 bits of data in bits 23 - 0
' Write 24 bits of data. ' Data is output MSB first.
datalong := Data
cmd := @datalong ' start the assy routine
repeat while cmd ' wait for assy routine to finish
return datalong ' debug output
DAT
''
''************************************
''* Assembly language 74HC595 driver *
''************************************
org
'************************************
HC595_write rdlong bit_addr,par wz ' wait for command
if_z jmp #HC595_write
rdlong bit_data,bit_addr ' get the data bits to shift out
mov bit_count,#24 ' shift out 24 bits
:bloop test bit_data,bit23 wz ' see if bit set
if_z andn outa,sermsk ' if bit zero, set pin to zero
if_nz or outa,sermsk ' if bit one, set pin to one
shl bit_data,#1 ' shift for next bit
or outa,clkmsk ' set clk high to toggle
andn outa,clkmsk ' set clk low to finish toggle
djnz bit_count,#:bloop ' loop for 24 bits
or outa,rckmsk ' now toggle RCK to latch the data
andn outa,rckmsk ' complete the bit toggle
mov t1,par 'reset sample pointer
add t1, #8 'add offset, t1 now points to datalong
mov t2,bit_count
wrlong t2,t1 'write sample to datalong
wrlong zero, par ' tell the calling routine we're done
jmp #HC595_write ' back to look for next data
'************************************
' Initialized data
'
bit23 long %1000_0000_0000_0000_0000_0000 'constants
zero long 0
fofo long $F0F0F0F0
'************************************
' Uninitialized data
'
bit_addr res 1 ' address of datalong passed in
bit_count res 1 '
bit_data res 1 ' LED array bit data to shift out
bit_out res 1 ' bit to send out to port
t1 res 1
t2 res 1
Thanks for the help.
Jim
I have a bug in the assembly code that I can't figure out. It looks right, but it doesn't work...
I've isolated it to a 'djnz' command in the code, that never finishes looping.
If I eliminate the line with the 'djnz', then it works fine, and outputs the correct debug data.
If the 'djnz' is in there, it gets stuck in the loop and never returns.
I'm sure I'm doing something dumb, so please help me find it.
Here's the important code:
'' ************************************************** ****************************
'' * "HC595.spin" 74HC595 SPIN Object *
'' * Version 1.2 *
'' ************************************************** ****************************
''
'' Calling sequence
'' OBJ
'' SReg : "HC595"
''
'' code segment
'' SReg.InitSer595 ' to initialize driver
'' more code
'' DataByte := toSend ' set up data to send to chip
'' SReg.WriteSer595(DataByte) ' send data to chip
'' more code
''
CON
_PinHigh = 1
_PinLow = 0
CLK = 0 ' pin number of CLK pin on chip (AKA SCK)
SER = 1 ' pin number of SER pin on chip
CLR = 2 ' pin number of SCLR pin on chip
RCK = 3 ' pin number of RCK pin on chip for LED arrays
GPN = 4 ' pin number of G pin on chip
RCK1 = 5 ' pin number for Vel digits
RCK2 = 6 ' pin number for Pwr digits
RCK3 = 7 ' pin number for Rep digits
RCK4 = 8 ' pin number for Wgt digits
clkmsk = 1 '1<<CLK ' set bit for CLK pin
sermsk = 2 '1<<SER ' set bit for SER pin
rckmsk = 4 '1<<RCK ' set bit for RCK pin
VAR
long cog, cmd, bitout, datalong
PUB InitSer595 ' initialize 74HC595 for startup
' set the control lines as outputs
dira[CLK] ~~
dira[SER] ~~
dira[CLR] ~~
dira[RCK] ~~
dira[GPN] ~~
dira[RCK1] ~~
dira[RCK2] ~~
dira[RCK3] ~~
dira[RCK4] ~~
outa[CLK] := _PinLow ' init main clock line to low
outa[RCK] := _PinLow ' init latch line to low
outa[RCK1] := _PinLow ' init latch line to low
outa[RCK2] := _PinLow ' init latch line to low
outa[RCK3] := _PinLow ' init latch line to low
outa[RCK4] := _PinLow ' init latch line to low
outa[GPN] := _PinHigh ' set outputs to 3-state
outa[CLR] := _PinLow ' set to clear register on chip
outa[GPN] := _PinLow ' turn on the chip and clear pins
outa[CLR] := _PinHigh ' return CLR pin to high after clear
if cog
cogstop(cog~ - 1)
cmd := 0 ' init for cognew
cog := cognew(@HC595_write, @cmd) +1
waitcnt(clkfreq/4 + cnt) 'wait 1/4 sec for cog to start
PUB WriteSer595(Data) | ix ' Data is long with 24 bits of data in bits 23 - 0
' Write 24 bits of data. ' Data is output MSB first.
datalong := Data
cmd := @datalong ' start the assy routine
repeat while cmd ' wait for assy routine to finish
return datalong ' debug output
DAT
''
''************************************
''* Assembly language 74HC595 driver *
''************************************
org
'************************************
HC595_write rdlong bit_addr,par wz ' wait for command
if_z jmp #HC595_write
rdlong bit_data,bit_addr ' get the data bits to shift out
mov bit_count,#24 ' shift out 24 bits
:bloop test bit_data,bit23 wz ' see if bit set
if_z andn outa,sermsk ' if bit zero, set pin to zero
if_nz or outa,sermsk ' if bit one, set pin to one
shl bit_data,#1 ' shift for next bit
or outa,clkmsk ' set clk high to toggle
andn outa,clkmsk ' set clk low to finish toggle
djnz bit_count,#:bloop ' loop for 24 bits
or outa,rckmsk ' now toggle RCK to latch the data
andn outa,rckmsk ' complete the bit toggle
mov t1,par 'reset sample pointer
add t1, #8 'add offset, t1 now points to datalong
mov t2,bit_count
wrlong t2,t1 'write sample to datalong
wrlong zero, par ' tell the calling routine we're done
jmp #HC595_write ' back to look for next data
'************************************
' Initialized data
'
bit23 long %1000_0000_0000_0000_0000_0000 'constants
zero long 0
fofo long $F0F0F0F0
'************************************
' Uninitialized data
'
bit_addr res 1 ' address of datalong passed in
bit_count res 1 '
bit_data res 1 ' LED array bit data to shift out
bit_out res 1 ' bit to send out to port
t1 res 1
t2 res 1
Thanks for the help.
Jim