Pi OS for Zynqberry: Adafruit RFM69 Radio with CircuitPython

Adapting Adafruit's CircuitPython to use the RFM69HCW Radio FeatherWing on the Zynq-7000 series FPGAs.

One of my most commonly used Raspberry Pi shields I discovered a few years ago is the 433 MHz RadioFruit RFM69HCW Transceiver Radio Bonnet from Adafruit. The RFM69HCW is a transceiver module with a wide operating frequency range, and all of its major RF communication parameters are programmable. Most of these RF parameters can be dynamically set via the transceiver's SPI interface from an external source. This transceiver has the more unique feature of programmable narrow-band and wide-band communication modes. This is in thanks to the parameters that can be dynamically set via the transceiver's SX1231 based SPI interface such as those controlling the power amplifier, filter settings, automatic frequency correction, and so on. Having a radio transceiver option like the RFM69HCW is a nice option to have along side more popular wireless options of Wi-Fi and Bluetooth because they are capable of much longer range communication. It's also much easier to get two transceivers such as the RFM69HCW communication with each other since there is no scan, pair, or associate process.

While it is possible to grab the datasheet for the RFM69HCW and start sending raw bits to the SX1231 SPI module to set the configuration and control registers of the radio, there are a couple of really good libraries that have written and proven in on a large array of platforms. The RadioHead library provides a complete object-oriented library for sending and receiving packetized messages. A CircuitPython module for the RFM69 wraps this library in a way that allows for a user to easily write Python code to send and receive packets of data with the radio.

In my last project post, I laid the ground work for porting CircuitPython over to the Zynq-7000 platform for the Zynqberry given its shared formfactor with the Raspberry Pi, and creating a ‘Pi OS' for the Zynqberry. The RadioFruit RFM69HCW Transceiver Radio Bonnet also has an SSD1306 OLED, which is the same OLED on the PiOLED with the same pinout on the 40-pin GPIO header as well. Starting with the Vivado and PetaLinux projects for the Zynq hardware design and embedded Linux image I created in my last post, I'll be adding the necessary hooks to use the RFM69HCW radio bonnet and install the RFM69 CircuitPython module.

There are several options for SPI interfaces in FPGA hardware, to save programmable logic space/resources I opted to use the SPI1 interface routed via EMIO in the Zynq processing system.

CircuitPython uses the SPIdev kernel which is called out as ‘User mode SPI device driver support' in PetaLinux's kernel configuration editor. This must be enabled as a minimum and there are other debugging kernel options for SPI that can be enabled if so desired.

So that the kernel knows to use the SPIdev driver with SPI1 of the Zynq PS, a node in the device tree specifying Zynq's SPI1 and the appropriate SPIdev parameters is needed:

&spi1 {
status = “okay”;
num-cs = <1>;
is-decoded-cs = <0>;

spidev0: spidev@0 {            
    compatible = "spidev"; 

    /* Max SPI clock frequency via Zynq EMIO is 25MHz */    
    spi-max-frequency = <25000000>; 

    /* slave number - CS */
    reg = <0>; 

    /* Set SPI mode = 0 */        
    spi-cpol = <0>;         
    spi-cpha = <0>;     


I went over the Zynqberry.GPIO package I created to make the 40-pin header of the Zynqberry appear to CircuitPython modules the same as a Raspberry Pi's 40-pin header which applies the same in this project.

I also went over how the main steps of porting CircuitPython over to the Zynqberry were in editing the Adafruit Platform Detect and Adafruit Blinka packages. While I simply had copied the same spi.py script into the Zynqberry hooks in Adafruit Blinka from the Raspberry Pi hooks for the SPIdev interface in CircuitPython, I found that the SPIdev version in the kernel generated from PetaLinux is slightly different from the one generated for the embedded Linux images for the Raspberry Pi such as Raspbian. Specifically how the readinto() function pulled in data from a device, I had to edit it to pull in more of the buffer at once and adjust how it was indexing that buffer. At first I though this was a specific issue with the RFM69 SPI interface, but then I retested the unedited version of this script on a Raspberry Pi and it worked just fine.

Source: Pi OS for Zynqberry: Adafruit RFM69 Radio with CircuitPython

About The Author

Muhammad Bilal

I am highly skilled and motivated individual with a Master's degree in Computer Science. I have extensive experience in technical writing and a deep understanding of SEO practices.

Scroll to Top