Half-duplex synchronous serial tested.
Seairth
Posts: 2,474
in Propeller 2
Here's a quick little demo of the synchronous TX and RX communicating with the DS1620. (sorry, no exciting pictures.) For those not familiar with the DS1620, here are the key points:
* Synchronous serial (up to about 1.75MHz)
* Half-duplex (single DQ line)
* For read operations, send 8-bit command on DQ, then receive 9-bit response on DQ
* For write operations, send 8-bit commnad on DQ, then send 9-bit value on DQ
* For non-parameter operations, just send 8-bit command on DQ
* /RST line is pulled high to execute a single command, then pulled low.
In the attached code:
* /RST is implemented using good old SETB/CLRB on OUTA.
* CLK is implemented using the "transition" smart cell mode.
* DQ is implemented using a single smart cell that is switched back and forth between synchronous transmit and receive
Two quick notes:
1. A logic analyzer helps! (I used SPLAT. Thanks, Peter!) It turns out that the the timing of the DQ line relative to the CLK line was different than what I was expecting. In the end, I followed the timing used by the DS1620 SPIN code (in the OBEX) instead of the DS1620's datasheet timing diagram(s). Remember that the first bit of the TX buffer is already on the pin before you even start clocking, so depending on how you have your clock configured, you can accidentally clock out the next bit before the other end has even registered the first bit!
2. On the RX modes, don't forget to set Output Enable OFF (field %D = 0 in PINSETM mode configuration). I wasted a LOT of time on this one, as I was expecting the read modes to implicitly do this. (@cgracey: maybe consider switching the synchronous (and asynchronous?) modes to be a single 5-bit opcode, then use the %D field to distinguish between TX and RX.)
(Note: while I was testing this with v7z, this should still work with any version that uses the new PINSETM mode layout.)
* Synchronous serial (up to about 1.75MHz)
* Half-duplex (single DQ line)
* For read operations, send 8-bit command on DQ, then receive 9-bit response on DQ
* For write operations, send 8-bit commnad on DQ, then send 9-bit value on DQ
* For non-parameter operations, just send 8-bit command on DQ
* /RST line is pulled high to execute a single command, then pulled low.
In the attached code:
* /RST is implemented using good old SETB/CLRB on OUTA.
* CLK is implemented using the "transition" smart cell mode.
* DQ is implemented using a single smart cell that is switched back and forth between synchronous transmit and receive
Two quick notes:
1. A logic analyzer helps! (I used SPLAT. Thanks, Peter!) It turns out that the the timing of the DQ line relative to the CLK line was different than what I was expecting. In the end, I followed the timing used by the DS1620 SPIN code (in the OBEX) instead of the DS1620's datasheet timing diagram(s). Remember that the first bit of the TX buffer is already on the pin before you even start clocking, so depending on how you have your clock configured, you can accidentally clock out the next bit before the other end has even registered the first bit!
2. On the RX modes, don't forget to set Output Enable OFF (field %D = 0 in PINSETM mode configuration). I wasted a LOT of time on this one, as I was expecting the read modes to implicitly do this. (@cgracey: maybe consider switching the synchronous (and asynchronous?) modes to be a single 5-bit opcode, then use the %D field to distinguish between TX and RX.)
(Note: while I was testing this with v7z, this should still work with any version that uses the new PINSETM mode layout.)
Comments
It now captures X[31:16] during PINSETX and compares that value to the repeating down counter which runs from X[15:00] to $0001. If the down counter is > X[31:16], a high is output, else a low is output.
This means that by leaving X[31:16] at zero, you still get one pulse, as you do now, but by putting other values in there, like $0001 for example, the output would be high only when the down counter is greater than $0001, but low when the counter is $0001. This generates full clock cycles which can be any number of clocks (2+) with a selectable transition point. Want a 3-clock cycle with 2 highs and 1 low? Do a PINSETX ##$0001_0003,pin. Want a 3-clock cycle with 1 high and 2 lows? Do a PINSETX ##$0002_0003. Before, only mode %00101 would give you N transitions, but they were all of the same duration, limiting its use as a clock source to only even numbers of system clocks and 50/50 duty cycle.
Now, I've just got to get the OUT bit gating some behavior for the OUT-override modes, so that you can do things like start a bunch of pulses at the same time.
Sounds great !
Sounding good, can this also act as a leading edge delay, so that multiple pins can be preset, then start with varying delays.
PWM modes are good, but they control only one edge.
Sounds like finer phase / multiple pins cases of output generate modes are coming along.
That leaves the input capture modes
Looking at this, I see the B field is spare on many modes where both A&B are not used.
In those, A is the Count or Count Enable, and B can become the Capture Control.
%BBBB = x100 gives present operation, TimeBaseX paced captures.
All other values, use the selected pin change to capture, and can use X <> 0 to Count pin edges.
If X=0, the modes are software paced.
Then, a single boolean is needed for One-Shot/Armed or Continual captures.
%AAAA: ‘A’ input selector, EdgeCount or Count Enable
0xxx = true (default)
1xxx = inverted
x000 = this pin’s read state (default)
x001 = relative +1 pin’s read state
x010 = relative +2 pin’s read state
x011 = relative +3 pin’s read state
x100 = this pin’s OUT bit from cogs
x101 = relative -3 pin’s read state
x110 = relative -2 pin’s read state
x111 = relative -1 pin’s read state
%BBBB: ‘B’ input selector, or Capture Selector.
0xxx = true (default)
1xxx = inverted
x000 = this pin’s read state (default)
x001 = relative +1 pin’s read state << Capture on Pin+1 edge, X counted if X > 0
x010 = relative +2 pin’s read state
x011 = relative +3 pin’s read state
x100 = this pin’s OUT bit from cogs << Capture on TimebaseX.TC ? (SW if X=0)
x101 = relative -3 pin’s read state
x110 = relative -2 pin’s read state
x111 = relative -1 pin’s read state
These simple MUX extensions will allow reading of sensors that use Duty Cycle data (uses 2 pin cells) and Reciprocal Counting
Both these measurement tasks need TWO capture values, that is external signal phased.
- ability to time N high-to-high cycles of signal
- ability to count highs during entire N-cycle measurement
By dividing both the resultant N-period count and high count by N, we could get very accurate (averaged) frequency AND duty cycle measurements. Is this what all this reciprocal-counter stuff you talk about amounts to?
For both Duty Cycle and Reciprocal Frequency, two numbers are needed to be captured, and they need to related to the same PinIn edges.
So you capture dT and dC, as 32b values. In frequency counter, dC is external PinIn Cycles, and in Duty Cycle dC is the gated-hi value (in SysCLKs), so is always a % of dT.
Same capture rules for both, but just a clock-source change on one counter, covers both modes.
That N you give above, needs to be either user-fixed (OK for narrow range apps) or SW captured (for more general Frequency Counting), which is why I suggested the B Field and X counter allowing either fixed-X or X=0 for SW captured.
When SW captured, those values still need to be PinIn edge aligned, hence the boolean for OneShot arming.
Usually 10ms~100ms~1s type SW sampling rates are used, and you arm, then get one reading pair, then process, then wait and re-arm etc
I think it is ok to use two pin cells to do this pair-capture.
I thought above you meant a phase-preload, but here I think you are talking about another adder.
That adjust phase offset at any time is certainly nice to have, but is there time for 2nd add, and is the area cost low enough ?
It amounts to a 16-bit adder. This would let us do phase modulation, since we are never resetting the core phase, except in reset.
While mode 01100, time accumulator mode, is perfectly adequate for the job I can see how one might want to have synchronous sampling based around the fixed modulation frequency of the PWM signal.
Mode 10001 - Time A-input high and low states, does achieve this but of course without more buffer stages the inevitable buffer overrun will occur on short states. EDIT: This mode would need extended to contain high vs low identity.
Another variant is use two Smartpins, one in mode 10011 - Time A-input positive edges, generating an interrupt in-phase with the modulation frequency, and the other Smartpin in mode 10010 - Time A-input high states, to provide the latest duty length.
Is there value in extending beyond this? Dunno. I'll leave that up to you, Chip.
EDIT: Actually, using two Smartpins shouldn't a big deal really. After all, most other synchronous activities use a second pin for the synchronous clock.
A SW triggered/Armed version, can easily check if no result is ready, since last ARM, and signal Static State (or more likely, connection failure)
Most Sensor Systems avoid Static levels, so that can be used for wired failure.
The synchronous serial mode probably already has a similar trigger for its shifter.
Yes, with my suggestion of using B channel MUX for qualifier signals, on A counting that may be possible, depending on the details.
Because I have taken the clock as always on IP.A, and the qualifier as B, that would mirror to be
Ctr.clk = A-input positive edges
Ctr.ce = B High
- as you say, for external ADC streams that have CLK+Data both incoming.
Other B qualifier uses are capture, via X, or SW.
Thinking some more about the OneShot/Arm, another way to tackle this, that may be easier to explain is a
Capture mode boolean that allows either
a) Hold First Capture, (any later captures are discarded)
or
b) Overwrite capture, so last capture is the one read
If the software always reads faster then capture, these modes morph to similar.
If the input frequency is high, or if multiple co-operating pins are involved, mode a) becomes important.
EDIT: That's certainly something to get a clear performance number on - The number of clocks from end-of-measured-signal arriving at the Smartpin until an ISR can apply the mask control.
May be a fiddle to reset after each trigger though.