Parallel pin read in PASM2
ke4pjw
Posts: 1,155
So, I am having a bit of "writer's block" / procrastination with writing my first block of inline PASM2. I am not sure if I want to use smart pins to manipulate a series of byte reads from the parallel bus on the W6100 or just do it the old fashioned way, with INA. I looked to some code I wrote 10 years ago, a modification of the FullDuplexSerial I called FullDuplexParallel.
' Receive receive jmpret rxcode,txcode 'run chunk of tx code, then return test rxmask,ina wz ' Is RXF# low? Set Z flag if it is if_nz jmp #receive ' If Z not set, jump to receive label xor outa, rdmask ' Set RD# low mov rxdata, ina ' Read pins set for input or outa, rdmask ' Set RD# high shr rxdata, datapin ' Shift data so that the LSB corisponds with D0 ' Save received byte and inc head rdlong t2,par ' Assign the value of rx_head to t2 add t2,rxbuff ' Increment t2 by the address location of rxbuff wrbyte rxdata,t2 ' Write byte from the rxdata into the address located at t2's value (rx_head + rxbuff) sub t2,rxbuff ' Decrement t2 by the address location of rxbuff ' Increment rx_head add t2,#1 ' Increment t2 by 1 bit (same as rx_head + 1) and t2,#$FF ' Perform AND operation on t2's value with $FF (if > $FF then rollerover) wrlong t2,par ' Write long value of t2 in to the address location of par jmp #receive ' byte done, receive next byte '
How would you handle that when it is INB, 8 pins at pins 32+? Maybe have a value at setup that checks the pin mask and sets a variable with $01FE for P31..P0 or $01FE for P63..P32 and mov from the variable?
Or is the old way dumb, and I should use smart pins?
I am stuck and can't start I hate feeling like this, LOL.
Thanks,
Terry
Comments
Your existing code is certainly an option. It could probably be optimised but it'll go faster just by the higher internal clock frequency available.
Smartpins won't help you with data over parallel pins. They are primarily for single pin functions.
A streamer likes to do parallel data though. So that's an option if you're keen for some mental gymnastics. There is no hardware synchronising so it's up to the software to coordinate between bit-bashing, or maybe a smartpin, and triggering the DMA at the right time.
Maybe something like this (based on interpreter pinread() code).
This doesn't allow reading across the ina/inb boundary.
If your pins are always on a multiple of 8, you can use getbyte/altgb on the INA/INB ports.
will move 8 pins worth of pins into
data
. Note thatpingroup
is the base pin divided by 8.That's so begging to be a macro.
Thanks for your examples guys. I had a copy of the PASM2 manual printed and bound so I could thumb through it. I am going to use WRBYTE to get this data into the HUB. Hopefully there will be more documentation on the FIFO and streamer available to mere mortals soon!
Time for me to just get to the business of making it happen. Hopefully I will see a speed increase!
Thanks all!
--Terry
How is pingroup expressed? A 32 bit bitfield of the pins of interest or a value created with ADDPINS?
Nevermind. Sometimes I am just thick. You already answered that.
So, swapping over to PASM made a big improvement for the read. So much so, that it was reading the pins was faster than valid data could arrive, so I had to add a waitx in there after pulling the RD line low. It requires 4 clocks at 100Mhz for the data to be valid, I calculate that as 40ns. So we are at super fast speeds!
I know there are other places that need improvement in other objects, so I am going to tackle those as well.
One odd thing that occurred, that I did not expect, was I had to assign a local variable for the pingroup in altgb. I could not use a constant, nor could I use a literal. I used constants for drvl and drvh, such as
DRVL ##RDn
where RDn was defined as a constant. Not sure if this is a bug or a design choice.Another question, is it possible to use altsn for a two bit nibble (a crumb)?
Thanks!
Terry
Design choice. Frees up a bit in the instruction encoding. There is very few instructions that have immediate mode D-operand instruction encodings. And the ones that do are either single operand instructions or sacrifice status flag control.
Nope, there's no two-bit ops like that.
Err, actually, there is quite a lot of instructions that do provide immediate mode D-operand. The compromises are still correct though. Most of them sacrifice control of Z flag.
Is the write operation of
Like this?
Having weird results, as in it hoses video display cog.
A quick squiz at your opening post ... nitpicking I know but the name probably shouldn't be full-duplex, as that implies a dual channel with one going each way concurrently. Half-duplex is a single channel with turnaround for bidirectional comms. Simplex is unidirectional data flow.
That reads byte data from INA/INB and places it in
tmpdata
The value in
datapin
is a pin-group number, so a 0 for pins P0-P7, a 1 for P8-P15, and so on up to 7 for P56-P63.That was just a section of the library I wrote for the FT-245. It is full duplex communication to the FT-245 and a modification of FullDuplexSerial.
https://github.com/parallaxinc/propeller/tree/master/libraries/community/p1/All/FullDuplexParallel
That's certainly going to write data to OUTA or OUTB. What appears on the pins depends on DIRA/DIRB and
datapin
as well as the data inLADDRH
Something more like this is what we are looking for? In this case, I want the value in LADDRH written to the datapin group.
Ah, I got it. Had to change the direction from input. Thank you @evanh !
Triple back-tick on separate line for posting code blocks. Single back-tick, ', for code strings in a sentence.
/me goes checks ... "USB to parallel FIFO bidirectional" - Half-duplex then. Often just called a data bus.
Ah!!! I would have never figured that out! Kinda miss the old markup. Thank you!
You are technically correct. That's the best kind of correct
I can't think of a better name now. Calling it HalfDuplexParallel doesn't help anyone. LOL,