Assembly I/O with 8-bit bus with variable basepin
in Propeller 2
For a TFT driver I'm working on, want to have an 8-bit bus with a basepin provided by the top level .spin2 file, not a constant in the low level file.
When the basepin is a CON value, it's easier to move data to the right position using outa+something constant.
But, when basepin is a variable, I'm not seeing an easy way to do it.
Looks to me like I have to self-modify the code that reads or writes to the 8-bit bus pins.
Or, am I missing something?
Comments
You want ALTSB/ALTGB (which you need, anyways, since the byte number in GETBYTE/SETBYTE must be constant). 2 cycles extra though.
That sounds good, thanks.
I guess that’s an easier form of self modifying code.
Still need to do something to pick between porta and portb.
Probably need to look at alts or altd for that, right?
https://forums.parallax.com/discussion/comment/1539934/#Comment_1539934
PS: For parallel data throughput, the better way is to employ the streamer.
I needed 8 parallel outputs for a project so I looked at the Spin2 interpreter code for pinw(). This little inline method simulates that. Of course, in your driver you only need to do the top part once.
pub wr_bus(base, value) | mask, outs org testb base, #5 wc ' outa or outb bitc wr_bits, #9 mov mask, #$FF ' make mask shl mask, base mov outs, base ' make pins group mov pr0, #7 shl pr0, #6 or outs, pr0 shl value, base setq mask wr_bits muxq outa, value _ret_ dirh outs end
No, altgb/altsb index between longs, too.
mov x,#5 altsb x,#outa setbyte #255
will set pins 40..47 high
@Wuerfel_21 Ok, that sounds perfect then.
@evanh I can see the streamer is being the best way, but would like there to be an easy way to deal with timing.
Be nice to do a "xcont" or something and have the data show up immediately and have it stay there indefinitely, without having to worry about the streamer running out of data and doing something undefined.
Streamer just holds the last value when it runs out of data. No funny business like P1 waitvid.
Here's the generic timing solution for streamer + clock smartpin to phase align the clock and data output:
rdfast #0, hubaddr setxfrq ratio mov pb, datapins and pb, #$38 'confine to group base pin, strip ADDPINS shl pb, #17 or pb, ##X_RFBYTE_8P_1DAC8 | X_PINS_ON or pb, bytecount 'timing critical code dirh PIN_CLK 'clock smartpin cycle period starts from now waitx phasedelay 'can be tuned to either SPI clock mode 0 or mode 3 xinit pb, #0 'data pins are registered - adds one sysclock latency to data wypin bytecount, PIN_CLK 'start pulses on next smartpin period 'end of critical code
The value in
phasedelay
depends on ratio, pin registration and SPI clock mode0/3 choice. But not affected by sysclock frequency when transmitting, sysclock frequency affects receiving only.PS: The value in PB can be predefined in another register. I mainly left it that way for clarity on setting up the XINIT.
PPS: Clock smartpin mode is something like:
pinstart( PIN_CLK, P_PULSE | P_OE | P_INVERT_OUTPUT, ratio | (ratio>>1)<<16, 0 ) 'CPOL=1 ratio := $8000_0000 / ratio 'convert to suit SETXFRQ
@evanh
Ok that is the fancy, fully automated way. This particular thing doesn’t need to be that fast. I think 15 MHz is the limit. Think can just xcont or something with actual data instead of having it automatically read from hub, right?
Transfers may also be small, maybe just one byte. So, the fully automated way is overkill I think …
Is is not refreshing a whole LCD?
So, this particular lcd has memory so does not have to do full refresh.
That can be useful if low on hub ram.
Okay, if only wanting to write single bytes from the cog then ALTSB+SETBYTE is fine.
I’ll keep this streamer info in mind though for some other LCDs that don’t have memory.
Ok, thanks for the help, think have it now...
In the beginning, calculate "BusAlt" from Base pin, "PinBus", and then use it on DIRA like this:
mov BusAlt,PinBus shr BusAlt,#3 altsb BusAlt,#dira setbyte #$FF
Then later on, use "BusAlt" to apply byte in "garg1" to OUTA like this:
altsb BusAlt,#outa setbyte garg1
Excellent example. Shows the flexibility and tidiness at once.
This altgb/altsb combined with getbyte/setbyte is great. Sure I knew about this a couple years ago and then forgot...
As I remember now, you can actually use this to index a large table of bytes in hub ram, not just for putting 8-bits on a bus with arbitrary base pin.