Auto serial baud rate calc (4) option?

So I was dealing with a troublesome connection where my uart was actually fluctuating serial baud rate as boot was happening on this chip and the old buspirate - i used the (4) option to auto calc…is 5 missing this option perhaps I am just not a cool bus pirat(sp) user.

1 Like

Good question. The PIC in Bus Pirate v3.x had autobaud detect hardware. The RP2040 in 5+ do not. There is some mention of autobaud via the PIO online, but I have never been able to find the actual code used.

Another option is to use the Bus Pirate as a logic analyzer with pulseview, I believe the decoder will detect the baud rate.

Interesting question. I saw Adafruit did something here a few years back, but the code doesn’t seem to have been released. So I searched how this would be done…

  1. Sample the shortest spike in the communication line (typically when a 010 bit pattern is sent).
    • This will detect ANY baud rate, not just the standard ones.
    • Viewed another way, it works even with broken clocks.
    • If periodically feeding the result to another program, could automatically adjust even if the other side changes baud rate.
    • Both CR and LF have a 010 and/or 101 bit pattern, so typical ASCII output will find the shortest pulse rapidly.
    • For binary data, initial results may be an integer multiple of the baud rate (e.g., 001100 for 2x, 000111000 for 3x, …) … so don’t just accept the first result!
    • May also want to filter spikes that are outside “reasonable” ranges, to filter noise.
  2. Now that the shortest pulse is found, get a bitstring interpretation of the data using that presumed baud rate.
  3. Interpret that bitstring to discover the actual combination used:
    • Data Bits: 7 or 8
    • Parity Bits: 0 or 1
    • Stop Bits: 1 or 2
    • Total configurations to test: Eight
  4. As a heuristic (option when appropriate), check if the data is primarily ASCII.

Table of Time to Baud Rate

Time Baud Rate
3333µs (3.3ms) 300
833µs 1200
416µs 2400
208µs 4800
104µs 9600
69µs 14400
52µs 19200
34µs 28800
26µs 38400
17.3µs 57600
8µs 115200

Source: UART Automatic Baud Rate Detector


What is the maximum baud rate detectable using a RP2040 @ 125MHz clock (e.g., without overclocking)?


detecting shortest `101` bit pattern

Note: this is written without any testing, so consider it pseudo-code…

EntryPoint:
    ; Must start with pin high
    JMP PIN WaitForPinToGoLow
    JMP EntryPoint

LowLength_Found:
    IN X ; push the count into the output buffer, autopush enabled

WaitForPinToGoLow:
    JMP PIN WaitForPinToGoLow; loop while pin high
    ; Pin transitioned from high -> low
    ; Reset count to zero (or any other value)
    SET X = 0x00000000

.wrap_target ; Reduces need for last instruction to jump here
LowLength_Loop:

    JMP PIN LowLength_Found ; branch taken when input is high

    ; Next two lines: unconditional decrement of register X
    ; See https://github.com/raspberrypi/pico-sdk/issues/1042
   JMP X-- LowLength_DecHack
LowLength_DecHack:

    ; loop back to check the pin state again
    ; Uncomment next instruction if not using .wrap_target
    ; JMP LowLength_Loop

From transition high → low:

Cycle Instruction
0 JMP in WaitForPinToGoLow fails
1 SET X = 0
2 First JMP to detect pin going high (fails)
3 DEC X pseudo-instruction
2*N Next JMP to detect pin going high (success)
2*N + 1 IN X puts counter into ISR
2*N + 2 … back to cycle 0

This just constantly detects the length. Something else must read from the ISR FIFO, throwing away the first (ISR queue depth) samples, and then reading some number of ISR entries (discarding if really large negative values), and taking the smallest reasonable result. Or maybe average the values close to the smallest reasonable result? If the smallest sampled value is close to a standard baud rate, time to try it out!

1 Like

The above shows how to detect the length of low signals. However, decoding serial requires both high and low. Thus, adjust the above PIO program to outputs the length of BOTH the high and low signals.

Essentially, could be identical to prior program, but duplicated for high and low length detections. Use distinct start values for high and low (e.g., 0xFFFFFFFF and 0x7FFFFFFFF)? Positive values would reflect how long the signal was high, while negative values would reflect how long the signal was low (or vice-versa … one of those is better for idle time detection). Change the pseudo-DEC to not be unconditional (to detect idle time) … thus pushing zero into the OSR implying idle time? Maybe use register Y to store X & 0x7FFFFFFF, and use that for detecting idle?

Thank goodness for the DEC X pseudo-instruction. Else, there would be no way to count time passing. With it, PIO becomes much more useful.

Given a stream of high/low timings being pushed to the ISR, a program could read them (discarding idle time) and then decode the data after N values received, using the shortest time, thus supporting arbitrary baud rates? If it detects the baud changed, it could also re-process historic data…

Not perfect, but likely a “good enough” heuristic for automagic baud detection and sync?

2 Likes