How to write to a group of pins in PASM2?
jrullan
Posts: 177
in Propeller 2
I need to write to 8 sequential pins at the same time by moving a byte of data to them.
If I start @ pin 0, its easy enough:
But if I want to start at an arbitrary pin by specifying a pinfield it seems there is no single instruction that can do this.
I came up with this 9-instructions approach but I wonder if there is a correct way of doing this or a more efficient way:
Can this be done in less than 9 operations?
If I start @ pin 0, its easy enough:
MOV OUTA, data
But if I want to start at an arbitrary pin by specifying a pinfield it seems there is no single instruction that can do this.
I came up with this 9-instructions approach but I wonder if there is a correct way of doing this or a more efficient way:
CON
_clkfreq = 160_000_000
VAR
long stack[40]
long pinfield
PUB main()
pinfield := 16 addpins 7
COGINIT(COGEXEC_NEW,@go,@pinfield)
DAT
ORG 0
go
RDLONG pin_f, PTRA
DIRH pin_f 'Set pins to outputs
MOV base, pin_f 'Get base of pinfield
AND base, #$3F
'9 operations to move the data byte into an arbitrary position in OUTA
MOV shifted, OUTA 'Get current value of OUTA
MOV mask, #$FF 'Create a mask for 8 bits
SHL mask, base 'Align mask with base pin position
NOT mask 'Invert the mask
AND shifted, mask 'Get everything but our pins
MOV newval, data 'Get the data to send to the pins
SHL newval, base 'Shift the new data to base pin position
OR shifted, newval 'Combine data with the rest of the pins data
AND OUTA, shifted 'Finally push the new value to OUTA
data long 21
pin_f long 0
base long 0
mask long 0
shifted long 0
newval long 0
Can this be done in less than 9 operations?

Comments
' PINW(pins,val) (9 longs, must be in regs) ' pinw_ ror y,#6 wc 'y=pins, w=val (begins at pop2 in LUT) bitc .reg,#9 'select outa/outb for writing bmask v,y 'make mask rol y,#6 rol v,y 'justify mask rol w,y 'justify val setq v 'mux val into outa/outb using mask .reg muxq outa,w _ret_ dirh y 'enable outputsThanks @Tubular, honestly I would love to learn how to use the streamer. The benefits of it could out weight the arbitraryness of the requirements but I've tried to read the available documentation and I haven't been able to put it all together in my head. There seems to be several moving parts which I haven't identified so far.
Thanks @JonnyMac, it didn't occur to me to see the under the hood approach of other instructions. Seems like the "right way" approach to do what I want. But.. there are a few things to unpack and understand from that snippet:
bitc .reg, #9 .... .reg muxq outa, wIsn't .reg a symbol pointing to the muxq operation? It seems like bitc is hacking the encoding of muxq to modify its destination address (if that's true it's a pretty neat trick!) That seems to overcome the problem of limiting the arbitraryness to either within OUTA or within OUTB.
It still cost 9 operations but it is more versatile than my code. Wow so much to learn!
As always, thank you all, such a great community of like minded people!!
YES! I can confirm, finally understood the snippet, it in fact modifies the bit #9 of the MUXQ instruction using the carry from the ROR on the pinfield. If base pin is >= 32 the carry == 1 so it changes OUTA address from $1FC to $1FD (which is the address of OUTB) effectively selecting between the two with the carry. WOW!
THIS IS THE WAY!