ASM CMP vs TEST INA
Hello,
Question How to test a pin in propeller asm?
I want to test pin 11 for 1 or 0 in assembler
I was thinking cmp ina,Pin_11, #1 would work but seems not
so I think that is has to be done with a test instruction
Test Value1,Value2 (and compare)
so I would define a mask,
:Pin_11_Bitmask long %00000000_00000000_00001000_00000000
Test ina,P_11, Pin_11 then jump on flags
but this does not work, (ie, I can't get this to work)
regards
Jeff
Question How to test a pin in propeller asm?
I want to test pin 11 for 1 or 0 in assembler
I was thinking cmp ina,Pin_11, #1 would work but seems not
so I think that is has to be done with a test instruction
Test Value1,Value2 (and compare)
so I would define a mask,
:Pin_11_Bitmask long %00000000_00000000_00001000_00000000
Test ina,P_11, Pin_11 then jump on flags
but this does not work, (ie, I can't get this to work)
regards
Jeff

Comments
Use: TEST <mask>,INA wc,wz ' or whatever combination of flags you want
The reason is that INA is a read-only register and must be specified in the source field of an instruction. If you put it in the destination (first) field of an instruction, what you're really referencing is the COG RAM location (shadow memory) corresponding to the INA register's address. This is also true of other read-only registers like CNT.
This is the asm code: The idea is to read bits off pin 11, write the data to an array and then write the array to spin for processing
:test_init mov addr,par ' get par address add addr,#28 ' offset by 28 longs rdlong _RX_data,addr 'set or reset RX_data pointer mov RX_Counter,RX_counter_rst 'reset counter jmpret Init_P39_ret_P8, #Init_P39_P8 'TX on pin 39 :read_RX test RX_Test_Msk, ina wz if_ne jmp :off_bit mov _RX_data,#1 'set high jmp skip_low :off_bit mov _RX_data,#0 'set low :skip_low mov addr,#4 djnz RX_Counter,#:read_RX ' loop until the number of subgroups is zero mov addr, par ' set address of par add addr, #28 'offset to RX array wrlong _RX_data,addr 'transmit back to spin jmp#:test_initProbably a little messy, but I'll see if it works
regards
Jeff
-- As Tom pointed out, the cog sees the hub as an array of bytes, not longs, so you need to update that line, e.g., add addr, #(28 * 4)
-- jump labels need to be preceded with #, e.g., jmp #skip_low
-- It appears you want to move the state of the rx pin into rxdata -- I would do this:
:read_rx test rxmask, ina wc ' move rx pin to c mov rxdata, #0 ' clear rxdata muxc rxdata, #1 ' set rxdata to rx inputThe second line is a little redundant; if you do it at initialization it doesn't need to be in this loop. You just need to set rxdata to zero before you use this loop.
Finally... the colon proceeding a label makes it local to the previous simple label; this allows you to use the same generic names in a listing -- like this:
flash16 mov flashes, #10 mov timer, cnt add timer, p16ontix :loop or outa, p16mask waitcnt timer, p16offtix andn outa, p16mask waitcnt timer, p16ontix djnz flashes, #:loop flash17 mov flashes, #5 mov timer, cnt add timer, p17ontix :loop or outa, p17mask waitcnt timer, p17offtix andn outa, p17mask waitcnt timer, p17ontix djnz flashes, #:loopThe point is: use colons to denote local labels; using them otherwise is an easy way to introduce errors (IMHO).
ok,
on the spin side: rxdata is an array
on the assembler side:
mov addr,par 'wrlong _rt,addr add addr,#4 mov _Trapz_num,#1 wrlong _Trapz_num, addr add addr,#4 rdlong _Sub_grp_size,addr add addr,#4 rdlong _Sub_grp_num,addr add addr,#4 rdlong _Sub_grp_time,addr add addr,#4 rdlong _Sub_grp_current,addr add addr,#4 rdlong _Trapezoid_time,addr add addr,#4 rdlong _RX_data,addr (_RX_data res 1 - last line of the assembler code)so my intention was to capture the status of Pin 11, every 100us, write the status (high or low) to the RX data (which is an array), on both sides. (when I did arrays in assembler on other machines, it was set the absolute base address of the array, load a value, then relative offset the width of the array type (long, int and so on)) to the next position, and in this case loop 128 times and stop.
then on the spin side print the array.
so I cleaned up the code, but I'm not sure about the bytes, vs long, when I pass parms to and from asm i use rdlong and wdlong, but updating a array in assembler I use bytes? even if the array is long?
run_init39 mov time, cnt add time, Period100us 'xor outa, Pin10_Pin39 'Make pin 39 high TX transmission mov dira, dira_rx 'dira_RX long %00000000_00000000_00001000_00000000 'or outa,Pin11_Pin26RX or outa, Pin17_Trap2 'Turn on led just to check where we are in code :test_init mov addr,par ' get par address add addr,#28 ' offset by 28 longs rdlong _RX_data,addr 'set or reset RX_data pointer mov RX_Counter,RX_counter_rst 'reset counter to 128 jmpret Init_P39_ret_P8, #Init_P39_P8 'TX on pin 39 :read_RX ' now start waiting for a reply test RX_Test_Msk, ina wz 'test against mask 'RX_Test_Msk long %00000000_00000000_00001000_00000000 if_ne jmp #:off_bit 'jump on z flag (a zero bit) mov _RX_data,#1 'set high set array long high jmp #:skip_low 'already set so skip :off_bit mov _RX_data,#0 'set low :skip_low add addr,#4*4 'offset in bytes (a long is 4 bytes, the rx_array is a long array, 16 bytes waitcnt Time, Period100us ' Wait 100us, then load 100 us djnz RX_Counter,#:read_RX ' loop until the number of subgroups is zero mov addr, par ' set address of par add addr, #28 'offset to RX array wrlong _RX_data,addr 'transmit back to spin - only do it once :wait_on_spin jmp#:wait_on_spin 'loop forever and check spin sideI originally did this in spin but the timing was not precise enough... so I moved on to asm.
regards
Jeff
I think this can be done in Spin if you structure your code properly. Have a look at the attached test program. It captures the RX pin to a byte array every 100us -- the timed portion of the code (capture loop) took 12824 microseconds. That very small error has to do with initializing t and starting the loop; the time between samples is 100us (using waitcnt and constant).
pub capture (n, p_buf) | t t := cnt repeat n waitcnt(t += constant(US_001 * 100)) byte[p_buf++] := outa[TX] := ina[RX]Spin certainly isn't as fast as PASM, but for a 100us loop with very little to do, it's no problem.
pub capture | t, n t := cnt repeat n from 0 to 127 waitcnt(t += constant(US_001 * 100)) capbuf[n] := outa[TX] := ina[RX]The last line has changed -- and it's 1.4us faster than the version using pointer and post incrementing (maybe that's where the speed is coming from). Anyway, when one is worried about microseconds, these things matter.
One of the [many] things I love about the Propeller is that I can use it to explore code style versus performance.
var long rxpin long txpin long tix100 long bufpntr byte capbuf[128] pub capture rxpin := RX txpin := TX tix100 := clkfreq / 1_000_000 * 100 bufpntr := @capbuf cognew(@cap128, @rxpin) ' wait for rxin == 0 to signal finished repeat while (rxpin) dat org cap128 mov t1, par ' start of parameters rdlong t2, t1 ' get rxpin mov rxmask, #1 shl rxmask, t2 add t1, #4 rdlong t2, t1 ' get txpin mov txmask, #1 shl txmask, t2 test rxmask, ina wc ' sample rx muxc outa, txmask ' copy to tx or dira, txmask ' make tx output add t1, #4 rdlong smpltix, t1 ' get sample period add t1, #4 rdlong hub, t1 ' get buffer pointer mov timer, smpltix ' start timer add timer, cnt ' sync with system mov cycles, #128 :loop waitcnt timer, smpltix ' wait sample time, reset timer test rxmask, ina wc ' capture rx to c muxc outa, txmask ' copy to tx mov t1, #0 muxc t1, #1 ' t1 = ina[RX] wrbyte t1, hub ' write to array add hub, #1 ' advance to next element djnz cycles, #:loop mov t1, #0 wrlong t1, par ' clear rx pin (signal done) cogid t1 ' self-shutdown cogstop t1 t1 res 1 t2 res 1 rxmask res 1 txmask res 1 smpltix res 1 hub res 1 timer res 1 cycles res 1 fitthanks, code works fine, there is a little offset because my clock is a 6.25, but that is minor.
regards
Jeff
But I noticed a few things that might help you understand the prop a little better...
DAT org 0 run_init39 mov time, cnt add time, Period100us 'xor outa, Pin10_Pin39 'Make pin 39 high TX transmission mov dira, dira_rx 'dira_RX long %00000000_00000000_00001000_00000000 'or outa,Pin11_Pin26RX or outa, Pin17_Trap2 'Turn on led just to check where we are in code :test_init mov addr,par ' get par address add addr,#28 ' offset by 28 longs rdlong _RX_data,addr 'set or reset RX_data pointer mov RX_Counter,RX_counter_rst 'reset counter to 128 'jmpret Init_P39_ret_P8, #Init_P39_P8 'TX on pin 39 call #Init_p39_P8 ' rename your return address Init_P39_P8_ret :read_RX ' now start waiting for a reply test RX_Test_Msk, ina wz 'test against mask 'RX_Test_Msk long %00000000_00000000_00001000_00000000 {{ replace the following... BTW TEST is performing and AND RX_Test_Msk with ina so Z (eq) means the bit is zero so you have it wrong way around if_ne jmp #:off_bit 'jump on z flag (a zero bit) mov _RX_data,#1 'set high set array long high jmp #:skip_low 'already set so skip :off_bit mov _RX_data,#0 'set low }} if_z mov _RX_data,#0 'set low (for a zero bit) if_nz mov _RX_data,#1 'set high set array long high (for a one bit) :skip_low add addr,#4*4 'offset in bytes (a long is 4 bytes, the rx_array is a long array, 16 bytes waitcnt Time, Period100us ' Wait 100us, then load 100 us djnz RX_Counter,#:read_RX ' loop until the number of subgroups is zero mov addr, par ' set address of par add addr, #28 'offset to RX array wrlong _RX_data,addr 'transmit back to spin - only do it once :wait_on_spin jmp #:wait_on_spin 'loop forever and check spin side