mungewell / pico-timecode

A budget friendly LTC/TimeCode device built from a RaspberryPi Pico - using the PIO blocks and MicroPython
https://github.com/mungewell/pico-timecode
MIT License
27 stars 0 forks source link

Jamming/Processing RX data - relative to the start of frame. #2

Closed mungewell closed 1 year ago

mungewell commented 1 year ago

In my world Frame XX starts with the first bit of the frame, but when we're receiving the (same) data we can't process it until the end of the frame - just before the sync word. waveforem_notation

So in-order the Jam correctly we need to automatically increase the Frame number, and apply to the TX engine.

Most of the time we would want to increase by two, as we're likely before the end of the frame. However there is a chance that we're between end of frame and start of next. We'll have to look at the timing of these points (relative to CPU clock) to see if we increase by one or two.

If we're in the 'Danger Zone', then perhaps we should just defer the Jam for another Frame/time.

mungewell commented 1 year ago

We also should use the same logic to correct the 'RX Monitor' display.

mungewell commented 1 year ago

Also, if we're too close to the star of the next frame, there is a chance that the FIFOs will not relay the data to PIO engine fast enough - missing the correct moment to sync.

mungewell commented 1 year ago

Was able to get interrupts working, so now have some reference data on start of frames - both for TX, and RX (decoding itself).

now                         tx_tick   rx_tick  
884500784 RX: 00:00:00:00   884504768 884497521
884511062 RX: 00:00:00:00   884537955 884537416
884549569 RX: 00:00:00:00   884571273 884570800
884578791 RX: 00:00:00:01   884571273 884570800
884583281 RX: 00:00:00:01   884604597 884604126
884612167 RX: 00:00:00:02   884604597 884604126
884616559 RX: 00:00:00:02   884637936 884637465
884645462 RX: 00:00:00:03   884637936 884637465
884649968 RX: 00:00:00:03   884671255 884670784
884678755 RX: 00:00:00:04   884671255 884670784
884683141 RX: 00:00:00:04   884704606 884704131
884708144 RX: 00:00:00:05   884704606 884704131
884716381 RX: 00:00:00:05   884737944 884737467
884745440 RX: 00:00:00:06   884737944 884737467
884749889 RX: 00:00:00:06   884771266 884770802
884778875 RX: 00:00:00:07   884771266 884770802
mungewell commented 1 year ago

Oh boy, Open-Source is awesome.... I can use ltcdump and Audacity to do the heavy lifting here. Record a section with Left/Right being TX/RX LTC data.

Process with:

$ ~/ltc-tools-github/ltcdump -a -c 2 jam.wav  > jam_rx_label.txt

And open in Audacity. screenshot

For the curious, without fixing anything, we have data 'off by one' frame and a delta in timing of 0.000997s.

$ grep "00:00:13:07" *_label*    
jam_rx_label.txt:10.001338  10.034649   00:00:13:07
jam_tx_start_muted_labels.txt:10.035646 10.068957   00:00:13:07
mungewell commented 1 year ago

Something is not making sense.

The 'Sync' is supposed to be triggered from IRQ into 'sync_and_read' which immediate sets the Output Pin (Pin 21) and this feeds in to the Trigger, which in turn lets all the TX machines run from their holding point.

The IRQ is from 'decode_dmc', and is set immediately after the input pin goes high/low at the start of the bit cycle (before it even knows what value the bit will be).

There is no way that this process is taking 0.000997s, which is around 38 cycles... we are clocking at 16x bit clock, so about 2.3-ish bits. And indeed that delay seems to match the observed signals.

delay_sync

Is this another issue, perhaps with FIFO data not being auto-pulled, or with microPython being late to deliver the data into the FIFO?

mungewell commented 1 year ago

I think that I found the issue here. Dispite what it says in the RP2040 datasheet, adding a delay to the IRQ(clear, 5) affects how/when the code waiting on a IRQ(block, 5) will trigger.

If I do the delay on a NOP after the IRQ it runs sooner.

def decode_dmc():
    label("initial_high")
    wait(1, pin, 0)
    irq(clear, 5)
    nop()[9]        # trigger sync engine, and wait til 3/4s mark

Without NOP: without_nop

With NOP: with_nop

This has been implement in HEAD, and I've also spend up the RX code to run at 32x bit clock.

Closing.