PDA

View Full Version : [resolved][puzzle] pass-through



kuroneko
11-10-2010, 08:04 AM
A serial port (tx/rx) is connected to the prop at pins A/B, another one at (different) pins C/D. Route traffic from the first port through the prop to the second and vice versa with the minimum amount of software possible to keep the connection alive.

Linus Akesson
11-10-2010, 12:54 PM
The first solution that springs to mind involves two cogs and two spare I/O pins. Each cog needs four registers of code to set things up, and can then go on to do other things.

Is this the solution you had in mind, or is there a better way?

kuroneko
11-10-2010, 12:56 PM
Is this the solution you had in mind, or is there a better way?

We are on the same page.

Linus Akesson
11-10-2010, 02:01 PM
Come to think of it, I actually need six registers per cog, worst case. I forgot about setting up DIRA.

By the way, if we're free to choose A/B/C/D ourselves, the puzzle can be solved with no more than three registers on a single cog. But then the cog can't do anything else.

kwinn
11-10-2010, 02:31 PM
A single cog and very simple pasm program is all you need.

Read data on port 1 rx pin
Write data to port 2 tx pin
Read data on port 2 rx pin
Write data to port 1 tx pin

If you select the pins carefully a read, shift, write, and jump instruction are all that is needed.

Sorry, forgot to include an "and" between the shift and write instruction to remove unwanted bits.

ericball
11-10-2010, 02:53 PM
With the proper port arrangement it's 6 longs total:


{ port 1 rx pin = N
port 1 tx pin = N+x
port 2 tx pin = N+16
port 2 rx pin = N+16+x
}
MOV DIRA, outmask
loop MOV outmask, INA
ROL outmask, #16
MOV OUTA, outmask
JMP #loop
outmask LONG |<(N+x)+|<(N+16)

Tracy Allen
11-10-2010, 03:22 PM
How about the ol' POSDET inverters:


ctra := (%01001 << 26) + (pA << 9) + pD
ctrb := (%01001 << 26) + (pC << 9) + pB
{pA and pC are prop tx outputs, pB and pD are prop rx inputs}

jazzed
11-10-2010, 03:59 PM
How about the ol' POSDET inverters:


ctra := (%01001 << 26) + (pA << 9) + pD
ctrb := (%01001 << 26) + (pC << 9) + pB
{pA and pC are prop tx outputs, pB and pD are prop rx inputs}
Very nice :) At a glance this seems like a reasonable solution.

Phil Pilgrim (PhiPi)
11-10-2010, 05:39 PM
The feedback is always negative, though. You would need a external inverters to restore the polarity. ('Too bad there isn't a mode with positive feedback. It would make Schmitt triggers easier! :) )

-Phil

jazzed
11-10-2010, 09:04 PM
The feedback is always negative, though. You would need a external inverters to restore the polarity. ('Too bad there isn't a mode with positive feedback. It would make Schmitt triggers easier! :) )

-Phil
Oh rats :)

kuroneko
11-10-2010, 10:22 PM
Oh rats :)

Don't be so negative! You can simply chain two cogs which sorts out polarity issues and we are back to a zero-footprint connection.

Phil Pilgrim (PhiPi)
11-11-2010, 01:09 AM
But doing the reinversion internally does use up two more pins. Does that count toward the "footprint"?

(Kuroneko, somehow I get the feeling there's a much more elegant solution that you're about to spring on us! :) )

-Phil

kuroneko
11-11-2010, 01:14 AM
With the proper port arrangement it's 6 longs total:


{
port 1 rx pin = N
port 1 tx pin = N+x
port 2 tx pin = M
port 2 rx pin = M+x
M > N
}
MOV DIRA, outmask
loop MOV outmask, INA
ROL outmask, #M-N
MOV OUTA, outmask
JMP #loop
outmask LONG |<(N+?)+|<(M)


Can you give an example arrangement? The way the pins are assigned ATM and to have it work requires a stronger restriction than M>N.

ericball
11-11-2010, 01:17 AM
Hi kuroneko,

Hmmm... thinking about it, you are correct. M = N + 16. I'll update my post.

So to pass through the standard P30/P31 serial port (P30 - Serial Tx to host, P31 - Serial Rx from host ) then P15 would be serial Tx and P14 would be serial Rx.

kuroneko
11-11-2010, 01:23 AM
But doing the reinversion internally does use up two more pins. Does that count toward the "footprint"?

Emphasis was on software overhead which is zero for this counter approach. Unfortunately it uses 2 extra pins and 2 cogs (but covers any assignment and the cogs are only borrowed). Next best thing would be the 3 instruction version suggested by Linus although it's limited to specific assignments.

As for a more elegant solution, erm, not ATM. But it's on my list of irritating limitations so maybe I come up with something at some point.

Tracy Allen
11-11-2010, 02:07 AM
I do happen to have a PCB where the one device comes in true (prop plug) and the other device is inverted (an embedded modem), due to the way the level shifters are arranged. So the single pair of cog counters works fine with that. It's a freebie when it works.

I see now this is what Linus was proposing too, in pasm, 6 instructions to set dira, dirb, outa, outb, ctra, and ctrb. And the same in another cog plus the two helper pins if you need the second inversion. Dirs and outs really only need to be done once and are probably going to be absorbed in some other code. So it really comes down to the 2 ctrx, or 4 ctrx + 2 helper pins.

Out of curiosity I tried a dedicated cog spin version that comes down to this snippet,

repeat
outa[pA] := ina[pD]
outa[pC] := ina[pB]
Which with 80MHz clock was able to keep up at 9600 baud, but with noticeable jitter on the edges. That can be a bit faster if the pins alternate in a way that allows shift & mask.

Peter Jakacki
11-11-2010, 02:11 AM
I normally just poll these pins and pass them through in this manner but bear in mind that although this sample code dedicates a cog you are still able to implement a call to this bit of code within say a normal uart cog as long as the polling rate is fast enough to update the pins which doesn't really have to be all that fast. I find that there are usually at least one of the cogs that can be patched for such operations if there aren't any spare.

This is only a functional solution and not the "elegant" solution you were asking for. But squeeze tight enough and elegant solutions just seem to pop out.



' connect an serial port to a second port in simple virtual wire mode
'
patch_init
or dira,txd1
or dira,txd2
patching
test rxd1,ina wc
muxc outa,txd2
test rxd2,ina wc
muxc outa,txd1
jmp #patching

rxd1 long |<rxdpin1
txd1 long |<txdpin1
rxd2 long |<rxdpin2
txd2 long |<txdpin2

Linus Akesson
11-11-2010, 05:06 AM
Ok, here are my proposals, as hinted at the beginning of the thread. Two cogs, two spare pins, six registers per cog:



mov DIRA, =1 << A | 1 << D
mov CTRA, =%01001 << 26 | A << 9 | C
mov CTRB, =%01001 << 26 | D << 9 | B

The above code inverts the polarity, so to get a pass-through effect you need to daisy-chain two cogs.

My second proposal is a single cog and three registers, but only if we can pick the pin numbers ourselves. This is how it could be done if A = 23, B = 1, C = 0, D = 24:



movi DIRA, #3
loop movi OUTA, INA
jmp #loop