Custom RFM69 Packet

Hello,

I'm using the Adafruit RFM69HCW radio module with a Pi Pico, and want to send a custom data packet over FSK. Using RadioHead and other RFM69 libraries, they all write data to the RFM69's onboard FIFO buffer over SPI which then packetises the data in the form seen below, from page 51 of the data sheet found here:

This format is laid out nicely in the packet_mode_rx example provided by jlmurdoch - which provides a really nice and straightforward way to interface with the RFM69 and specific registers.

/*
   * Packet Mode:
   * - Preamble (x bytes) = 0x55
   * - Syncword (2 bytes) = 0x2DD4
   * - Length (1 byte) = 0x1C
   * - Address (1 byte) = 0x8D or 0x0D
   * - Payload (<length> bytes)
   * - CRC-16 (2 bytes - appears to be broken)
*/

However, I would like to use the RadioHead Library, as it includes the functionality of the addressed packets and works very reliability for me, but I want to send out data in my own packet format.

I can send out my own data packet within the 60-64 payload bytes (depends on AES Encryption which I am not using) to send out a custom packet but seems very wasteful and not very efficient.

Is it possible to send data to the FIFO and have it not be packetised and still work within the RadioHead library by changing the format in the RF69.cpp/h files or even transmit data by sending it directly to the DIO2 pin, which I have been doing with success, by viewing the output using my RTL-SDR, but I have had no success in receiving any of the transmitted data with a second RFM69.

Here is the code I used to transmit the FSK packet using DIO2, it actually reads a serial input from the pico which converts it into bits to transmit as the long term view is I want to transmit data received from the UART port of the pico in the future.

/*
 * Generic Radio Example
 */

#include <SPI.h>

#define RFM69HCW_G0_IRQ   17   // E - PayloadReady/CrcOk
#define RFM69HCW_CS       21   // D - SPI Chip Select
#define RFM69HCW_RST      20   // C - Reset
 #define RFM69HCW_G2_DIO2  14  // A - Data
// #define RFM69HCW_G1_DIO1  13  // 13 - DCLK if Gaussian FSK needed

//#define MODULATION    OOK
#define MODULATION    FSK
#define FREQ          433.92
#define BITRATE       1000
#define BANDWIDTH     DCCFREQ_4 << 5 | RXBWMANT_16 << 3 | RXBWEXP_0
#define AFC_BANDWIDTH DCCFREQ_4 << 5 | RXBWMANT_16 << 3 | RXBWEXP_0
#define BIT_SYNC      0x60 // Bit Sync off, as pulses are asymmetrical
#define FREQDEV       4700

// RFM69HCW clock speed - do not change
#define FXOSC 32000000.0

enum { FSK, OOK };

uint8_t spi_cmd(uint8_t addr, uint8_t value) {
  uint8_t status;

  digitalWrite(RFM69HCW_CS, LOW);
  SPI.transfer(addr);
  status = SPI.transfer(value);
  digitalWrite(RFM69HCW_CS, HIGH);

  return status;
}

// Set the wnr bit to write (Section 5.2.1) 
uint8_t spi_write(uint8_t addr, uint8_t value) {
  return spi_cmd(addr | 0x80, value);
}

// Pass nothing when reading
uint8_t spi_read(uint8_t addr) {
  return spi_cmd(addr, 0x00);
}

void rfminit() {
  // Read the version register, if it's not 0x24, something is wrong
  if(spi_read(0x10) == 0x24)
    Serial.println(F("RFM69HCW SPI Working"));
  else
    Serial.println(F("RFM69HCW SPI Failed"));

  // RegOpMode: Standby Mode & wait
  spi_write(0x01, 0x04); 
  while(!(spi_read(0x27)) & 0x80);

  // RegDataModul: Continuous w/ bit-sync and no other shaping 
  uint8_t modulation = MODULATION;
   spi_write(0x02, BIT_SYNC | modulation << 3); 
  //spi_write(0x02, 0x00); 

  uint16_t freqdev = FREQDEV / (FXOSC / 524288);
  spi_write(0x05, (freqdev >> 8) & 0x3F);
  spi_write(0x06, freqdev & 0xFF);



  // RegFrf*: Frequency across 3 bytes
  uint32_t freqrf = (FREQ * 1000000) / (FXOSC / 524288);
  spi_write(0x07, (freqrf >> 16) & 0xFF);
  spi_write(0x08, (freqrf >> 8) & 0xFF);
  spi_write(0x09, freqrf & 0xFF);

  // RegBitrate*: Bitrate needed for Bit Synchronizer
  uint16_t bitrate = FXOSC / BITRATE;
  spi_write(0x03, (bitrate >> 8) & 0xFF);
  spi_write(0x04, bitrate & 0xFF);

  spi_write(0x0A, 0x88); // Calibrating the oscillator
  while (!(spi_read(0x0A) & 0x08));

  Serial.println(F("Oscillator Cal done"));

  // ClkOut set to Off to save some power
  spi_write(0x26, 0x07);

  /*
   * TX- Settings
   */ 
  // High Power toggles
  spi_write(0x5A, 0x5D); // Section 3.3.7 PA1 on for +20dBm
  spi_write(0x5C, 0x7C); // Section 3.3.7 PA2 on for +20dBm

  // Power Settings for Tx
  spi_write(0x13, 0x0F); // Default = 0x1A. Disable OCP = 0x0F
   spi_write(0x11, 0x7F); // Default = 0x9F. 23dBm = 0x1F, PA1+2 on = 0x60
  //spi_write(0x11, 0x08); // Low Power Mode
  // spi_write(0x12, 0x09); // Default = 0x09. Ramp time for FSK

  // Sleep
  spi_write(0x01, 0x00);
  while(!(spi_read(0x27)) & 0x80);
}

void setup() {
  // Setup pins other than SPI, VDD and ground
  pinMode(RFM69HCW_CS, OUTPUT);
  pinMode(RFM69HCW_RST, OUTPUT);
  pinMode(RFM69HCW_G2_DIO2, OUTPUT);
  // pinMode(RFM69HCW_G1_DIO1, OUTPUT); // For DCLK

  // For flashing the LED on emitting
  pinMode(LED_BUILTIN, OUTPUT);

  Serial1.setTX(0);
  Serial1.setRX(1);

  // Serial console: e.g. cu -s 115200 -l /dev/ttyACM0
  Serial.begin(115200);
  Serial1.begin(9600);

  delay(5000);

  // Section 5.2.1 - SPI Interface
  digitalWrite(RFM69HCW_CS, HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  Serial.println(F("SPI connection open"));

  // Section 7.2.2 - Manual Reset
  digitalWrite(RFM69HCW_RST, HIGH);
  delayMicroseconds(100);
  digitalWrite(RFM69HCW_RST, LOW);
  // Spec says 5ms, but takes longer
  delay(6);

  // Configure the receiver
  rfminit();
}

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);

  // Section 3.2.2 - Async output is on DIO2  
  digitalWrite(RFM69HCW_G2_DIO2, HIGH);
  
// Transmit
  spi_write(0x01, 0x0C);
  while(!(spi_read(0x27)) & 0x80);


  Serial1.println("55");
  if (Serial1.available()){
    String hexString = Serial1.readStringUntil('\n');
    hexString.trim();
    uint8_t hexValue = strtol(hexString.c_str(),NULL,16);
    Serial.println(hexValue, HEX);

    for (int  i=7; i>=0;i--){
        int bitValue = (hexValue >> i) & 1;
        Serial.println(bitValue);
        digitalWrite(RFM69HCW_G2_DIO2, bitValue);
        delayMicroseconds(1000);
      }

  }

  delayMicroseconds(1000);
  
  // // Sleep
  spi_write(0x01, 0x00);
  while(!(spi_read(0x27)) & 0x80);

  delay(3000);

  digitalWrite(LED_BUILTIN, LOW);
}

Thank you, any help is appreciated :slight_smile:
-Harvey

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.