RPI-5 PIOLib available

211 views
Skip to first unread message

pa3gsb

unread,
Mar 22, 2025, 3:01:09 PM3/22/25
to Radioberry
Hi All,



Someone interested in making a new firmware radioberry using this new lib? Enabling the power of the RPI-5  RP1 for the radioberry.


73 Johan
PA3GSB

Paulh002

unread,
Mar 24, 2025, 4:42:28 AM3/24/25
to Radioberry
I don't know did not see any benchmark for the GPIO speed for the pi5.
Why not swap the FPGA for a Infinion FX3 USB 3.0 chip ? That would be interesting.
A bit like the web-888 SDR receiver

73, Paul
Op zaterdag 22 maart 2025 om 20:01:09 UTC+1 schreef pa3gsb:

Ed Marciniak

unread,
Mar 24, 2025, 9:22:26 AM3/24/25
to Paulh002, Radioberry
The digital filtering, decimation and digital downconverter functions all have an extremely hard realtime requirement. Coupled with something other than a realtime operating system, that’s a losing deal, especially without a FIFO even for a receive only system.

Using an FX3 gets you a FIFO but it’s still a fools errand even if you can make it work.

And that’s for RX only.

While receive only, glitches and lost data lead to some corruption, including out of band noise, clicks, pops, etc leaking into your receiver….something other than a phase continuous drop free signal leads to spurious emissions on transmit. That’s a deal killer.

The RTL dongles, used as they were intended to, have hardware FEC, synchronization recovery and all other functions necessary to simply specific an RX frequency and be delivered a bitstream to decode. Used the way they’ve been hacked to, they’re a tuner, with AGC, and effectively a 9 bit ADC(8 bit IQ) receiving around 30MHz IF from tuner, kneecapped to provide up to a few mega samples per second before they start dropping samples.

It is reasonable to ask whether the IO coprocessor and state machines in the RP1 found on the Pi5 can be used for a more efficient transport similar to the role the juice board or an Ethernet MAC transport provide.

Then again in a “nice” world, something like an Lattice ECP3 versa (or its successors) PCIe native interface with scatter gather DMA either running the whole thing, or just offloading IO to hardware would be nice. Scatter gather DMA essentially allows you to specify in virtual address space where you want the data to appear or be pulled from, and the hardware/driver does the translation and data just streams into/out of a circular buffer. Wrap in a circular buffer and all you’re left to do is handle the DSP and user interface while the transport uses almost zero processor cycles. The problem is a chip like that used to run around 75 USD and need a four layer board.

There have been a few examples on kickstarter or crowd supply implementing such methods. They’re all costly, low volume products. They might be less costly if they achieved high volume.

Then again think about how many RTL2832 USB tuner dongles running SDR are out there precisely because they are cheap, or how USB won out over FireWire for a difference in patent royalties of maybe a third to a half USD per unit. It’s unfortunate, because FireWire “400” actually has a clock of 393.216 MHz which is divisible exactly by 48KHz (and multiples) and that depending on sample rate, clock leakage aliases to DC or Nyquist null(96KHz for example) and that multiple units can by synchronous to same clock…avoiding buffer cross runs. It’s unfortunate, but is reality.

Texas Instruments for HDAudio codec interfaces running at 24MHz or USB interfaces can use 250x oversampling to get the same benefit.

Bottom line, if I were running a Pi 5, I’d use a Juice or plug the radioberry into a Pi4 or similar board where the GPIO is closely coupled to the AXI bus.

Maybe someday we’ll have a better option on the Pi5 but we’re not there yet.

For the record, I have no hate on the FX3…just don’t try to eliminate the FPGA unless you want to eliminate the platform appeal.

I do wish there was a more expensive but still reasonably affordable radioberry type device with a 16 bit ADC. The Hermes lite sucks because it’s not and it’s not all that cheap. The Anvelina SDR isn’t quite what I’m after, and the Apache Angelia board is nearly ideal for my desires except that I’d really want to use 1st Nyquist to provide a high performance 144-148MHz transceiver to drive microwave transverters for amateur radio.

There’s more to digest here than is obvious, but I’ll leave these thoughts to consider.




From: radio...@googlegroups.com <radio...@googlegroups.com> on behalf of Paulh002 <paul.hol...@gmail.com>
Sent: Monday, March 24, 2025 3:42:28 AM
To: Radioberry <radio...@googlegroups.com>
Subject: Re: RPI-5 PIOLib available
 
--
You received this message because you are subscribed to the Google Groups "Radioberry" group.
To unsubscribe from this group and stop receiving emails from it, send an email to radioberry+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/radioberry/359a3530-516c-4a16-9f0d-20bba751c66en%40googlegroups.com.

Paulh002

unread,
Mar 24, 2025, 11:30:27 AM3/24/25
to Ed Marciniak, Radioberry
I was looking at the FX3 because there are some SDR's (receivers only) based on it, so for a PC it seems to be possible.
For the hobbyist it is easier to implement DSP code in C / C++ than in FPGA Verilog or so. 
But developing a complete lowcost SDR is quite a challenge and also costly.
The beauty of the radioberry is its cost effectiveness, there is no SDR transceiver beating that (maybe Tayloe based).
 For now I am happy with my radioberry, I also have build an Tayloe SDR with a hifiberry card (192 Khz 24 bits audio) Is also a lot of fun and you don't break the bank.




Op ma 24 mrt 2025 om 14:22 schreef Ed Marciniak <edr1...@gmail.com>:

pa3gsb

unread,
Mar 24, 2025, 3:16:58 PM3/24/25
to Radioberry
Hi guys

i defined a statemachine in the pio and did some math

.program rx_iq_sample
.side_set 1

; Pin 6: Clock pin (side-set)
; Pin 25: Sample available pin
; Pins 23, 20, 19, 18, 16, 13, 12, 5: Data pins (23 = MSB)

.wrap_target
sample_loop:
    wait 1 pin 25          ; Wacht tot samples beschikbaar zijn
    set pins, 1 side 1 [1] ; Zet de klok hoog
    in pins, 8         [1] ; Lees 8 data bits (23 = MSB)
    set pins, 0 side 0 [1] ; Zet de klok laag
    in pins, 8         [1] ; Lees 8 data bits (23 = MSB)
    push block
    jmp sample_loop
.wrap

State machine of 18 cycles.



1. **IQ sample size**: Each IQ sample consists of **48 bits** (or 6 bytes).
2. **Cycles per IQ sample**: As calculated earlier, it takes **18 PIO cycles** to read one IQ sample (48 bits).
3. **PIO clock speed**: We're assuming the PIO runs at **125 MHz**.

### Calculations:

1. **Sample rate**:  
   As previously calculated, the **sample rate** for 18 cycles per IQ sample is:  
   Sample rate = 125 MHz / 18 ≈ 6.94 MHz  
   This means **6.94 million samples per second**.

2. **Bit rate**:  
   Each sample is **48 bits** (6 bytes). The bit rate is then:  
   Bit rate = 6.94 MHz × 48 bits/sample = 332.8 Mbps

### Conclusion:
The **bit rate** for the IQ sample stream is **332.8 Mbps** at a **sample rate** of 6.94 million samples per second, with each sample being **48 bits** and a **PIO clock speed of 125 MHz**.


Pretty good throughput.... now making a program .......

73 Johan
PA3GSB


Op maandag 24 maart 2025 om 16:30:27 UTC+1 schreef paul.hol...@gmail.com:

Ed Marciniak

unread,
Mar 24, 2025, 10:06:37 PM3/24/25
to pa3gsb, Radioberry
You should be able to save 1 clock cycle with auto push every 32 bits.

I *think* you should be able to save an additional cycle by putting the wait before the wrapped loop.

With a scratch register containing 0x00, an input from the scratch could give the fourth byte to give 32 bit aligned 24 bit samples.

Unrolling the loop to grab two samples at a time because they always occur in pairs also makes sense.

The side set executes concurrently with the input.

The execution can be far less than 18 cycles.

There’s also an interesting note on the pi2040 datasheet section 3.5.6.3 about input synchronizers are a two clock cycle delay.

In principle DDR input sampling in rising and falling clock edge could toggle the clock every other cycle while grabbing a byte every clock cycle. Unrolling the loop for a fixed size burst you could grab 6 bytes every eight cycles while producing 32 bit word aligned data. If my math isn’t broken, you could fit about 3 samples in a loop. With the wrap setting the program counter to the beginning of the loop, and a jump instruction that exits the loop if there are no more samples to be read, that’s 25 cycles for 18 bytes, 26 instructions. I think that comes out to be 90 megabytes per second raw, though it’d load 120 into memory with alignment.




From: radio...@googlegroups.com <radio...@googlegroups.com> on behalf of pa3gsb <pa3...@gmail.com>
Sent: Monday, March 24, 2025 2:17 PM

pa3gsb

unread,
Mar 31, 2025, 1:42:39 PM3/31/25
to Radioberry

Just to let you know....

A little baby step is set.... tool environment setup.

Making a led blink....

73 Johan
PA3GSB




/**
 * radioberry using rpi-5 and rp1 io chip using pio module.
 *
 *
 */

#include <stdio.h>
#include <signal.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"

// Our assembled program:
#include "rb-firmware.pio.h"


#define HELLO_PIO_LED_PIN 21

volatile bool running = true;

void handle_sigint() {
    running = false;
}


int main() {

signal(SIGINT, handle_sigint);

uint pin_hello = 21;

    // initialize pio library
    stdio_init_all();
    PIO pio = pio0;
    uint sm = pio_claim_unused_sm(pio, true);

uint offset = pio_add_program(pio, &hello_program);
    hello_program_init(pio, sm, offset, pin_hello);


    printf("Using gpio %d\n", HELLO_PIO_LED_PIN);

    while (running) {
        // Say hi
        pio_sm_put_blocking(pio, sm, 1);
        sleep_ms(500);
        // Say low
        pio_sm_put_blocking(pio, sm, 0);
        sleep_ms(500);
    }

pio_sm_unclaim(pio, sm);

}


// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //

#pragma once

#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif

// ----- //
// hello //
// ----- //

#define hello_wrap_target 0
#define hello_wrap 2
#define hello_pio_version 0

static const uint16_t hello_program_instructions[] = {
            //     .wrap_target
    0x80a0, //  0: pull   block
    0x6001, //  1: out    pins, 1
    0x0000, //  2: jmp    0
            //     .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program hello_program = {
    .instructions = hello_program_instructions,
    .length = 3,
    .origin = -1,
    .pio_version = hello_pio_version,
#if PICO_PIO_VERSION > 0
    .used_gpio_ranges = 0x0
#endif
};

static inline pio_sm_config hello_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + hello_wrap_target, offset + hello_wrap);
    return c;
}

static inline void hello_program_init(PIO pio, uint sm, uint offset, uint pin) {
    pio_sm_config c = hello_program_get_default_config(offset);
    // Map the state machine's OUT pin group to one pin, namely the `pin`
    // parameter to this function.
    sm_config_set_out_pins(&c, pin, 1);
    // Set this pin's GPIO function (connect PIO to the pad)
    pio_gpio_init(pio, pin);
    // Set the pin direction to output at the PIO
    pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
    // Load our configuration, and jump to the start of the program
    pio_sm_init(pio, sm, offset, &c);
    // Set the state machine running
    pio_sm_set_enabled(pio, sm, true);
}

#endif



//end of source

Op zaterdag 22 maart 2025 om 20:01:09 UTC+1 schreef pa3gsb:
Hi All,

Paulh002

unread,
Mar 31, 2025, 2:20:06 PM3/31/25
to pa3gsb, Radioberry
Did you ever thought about using the i2s bus? Will require some changes but is it directly on the cpu?

Op ma 31 mrt. 2025 19:42 schreef pa3gsb <pa3...@gmail.com>:
--
You received this message because you are subscribed to the Google Groups "Radioberry" group.
To unsubscribe from this group and stop receiving emails from it, send an email to radioberry+...@googlegroups.com.

Ed Marciniak

unread,
Mar 31, 2025, 2:24:17 PM3/31/25
to Paulh002, pa3gsb, Radioberry
The I2S bus is nowhere close to the required performance. “Normal” I2S is good for about one 192 ksps stereo pair at 24 bit sample depth (they’re  24 bits stuffed into 32 bit words). I suppose you’d get twice that with 16 bit words stuffed with 12 bit samples.


Sent: Monday, March 31, 2025 1:19:52 PM
To: pa3gsb <pa3...@gmail.com>
Cc: Radioberry <radio...@googlegroups.com>

Subject: Re: RPI-5 PIOLib available

pa3gsb

unread,
Apr 1, 2025, 2:14:29 AM4/1/25
to Radioberry
Paul,

The PIO way of workong will offload the processing from the CPU ; we will use DMA so the bitbanging we are using now, which uses the cpu will be completely eliminated. 

73 Johan
PA3GSB

Op maandag 31 maart 2025 om 20:20:06 UTC+2 schreef paul.hol...@gmail.com:
Reply all
Reply to author
Forward
0 new messages