Semtech SX1278 FSK packet mode decoding with Arduino

 sunnuntai, 25. kesäkuu 2017
Semtech SX1278 FSK packet mode decoding with Arduino

Short data transmission at 420.0125 MHz which repeats once every minute and is heard in (at least) Pori (town in Finland) central area is probably DMR control channel.

Arduino Uno & Dragino Lora Module (SX1278) http://www.dragino.com/products/module/item/102-lora-shield.html


 



#include <SX1278.h>

#define SERIAL_SPEED        9600
#define FREQ                420.0125
#define BPS                 9600
#define STATE_STANDBY       1
#define STATE_FSRX          4
#define STATE_RX            5
#define S_DELAY             10
#define L_DELAY             100
#define RX_BUFFER_LEN       64
#define SX_BEGIN            "SX.begin"
#define SX_BITRATE          "SX.readBPS "
#define SX_FREQ             "SX.readFreq "
#define RSSI_THRESHOLD      160             // -rssi/2, 160 = -80 dBm
#define CH_FILTER_BW        B00001101       // 12.5 kHz
#define SYNC_VALUE          0x01

#define RegRssiConfig       0x0e
#define RegRxBw             0x12
#define RegPacketConfig1    0x30

#define RegFifo             0x00
#define RegOpMode           0x01
#define RegPaRamp           0x0a
#define RegRssiThresh       0x10
#define RegOokPeak          0x14
#define RegPreambleDetect   0x1f
#define RegSyncConfig       0x27
#define RegSyncValue1       0x28
#define RegSyncValue2       0x29
#define RegSyncValue3       0x2a
#define RegPacketConfig2    0x31
#define RegPayloadLength    0x32
#define RegIrqFlags1        0x3e
#define RegIrqFlags2        0x3f

bool rx = false;
byte b;
byte RegIrqFlags1_value;
byte RegIrqFlags2_value;
byte rxBuffer[RX_BUFFER_LEN];

void setup() {
  Serial.begin(SERIAL_SPEED);
  if (SX.begin()) {
    Serial.println(F(SX_BEGIN));
    delay(S_DELAY);
    SX.startModeFSKOOK();
    b = SX.SPIread(RegOpMode);
    bitClear(b, 6);
    bitClear(b, 5);
    SX.SPIwrite(RegOpMode, b);

    // Channel filter bandwidth control
    SX.SPIwrite(RegRxBw, CH_FILTER_BW);

    SX.setFreq(FREQ);
    Serial.print(F(SX_FREQ));
    Serial.println(SX.readFreq(), DEC);
    SX.setBPS(BPS);
    Serial.print(F(SX_BITRATE));
    Serial.println(SX.readBPS(), DEC);

    // Bits 7-6: AutoRestartRxMode, 01 à On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 =>  Off, 1 =>  On
    // Bit 5: Sets the polarity of the Preamble. 0 à 0xAA, 1 à 0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = SX.SPIread(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitSet(b, 4);
    bitClear(b, 5);
    bitClear(b, 2);
    bitSet(b, 1);
    bitClear(b, 0);
    SX.SPIwrite(RegSyncConfig, b);
    SX.SPIwrite(RegSyncValue1, SYNC_VALUE);
    SX.SPIwrite(RegSyncValue2, SYNC_VALUE);
    SX.SPIwrite(RegSyncValue3, SYNC_VALUE);

    // Bits 6-5: Defines DC-free encoding/decoding performed: 00->none, 01->manchester, 10->whitening
    // Bit 7: packet format, 0 = fixed length, 1 = variable length
    // Bit 4: crc calc/check, 0 = off, 1 = on
    // Bits 2-1: Defines address based filtering in Rx: 00  None (Off)
    // Bit 3: Defines the behavior of the packet handler when CRC check fails:
    // 0 => Clear FIFO and restart new packet reception. No PayloadReady interrupt issued.
    // 1 =>  Do not clear FIFO. PayloadReady interrupt issued.
    b = SX.SPIread(RegPacketConfig1);
    bitClear(b, 6);
    bitClear(b, 5);
    bitClear(b, 7);
    bitClear(b, 4);
    bitClear(b, 3);
    bitClear(b, 2);
    bitClear(b, 1);
    SX.SPIwrite(RegPacketConfig1, b);

    // Bits 6-5: FSK data shaping:
    // 00 -> no shaping, 01 -> Gaussian filter BT = 1.0
    // 10 -> Gaussian filter BT = 0.5, 11 -> Gaussian filter BT = 0.3
    // Bits 3-0: Rise/Fall time of ramp up/down in FSK:
    // 1001 à 40 us
    b = SX.SPIread(RegPaRamp);
    bitClear(b, 6);
    bitClear(b, 5);
    bitSet(b, 3);
    bitClear(b, 2);
    bitClear(b, 1);
    bitSet(b, 0);
    SX.SPIwrite(RegPaRamp, b);

    SX.SPIwrite(RegPayloadLength, RX_BUFFER_LEN);

    // Data processing mode: 0 => Continuous mode, 1 => Packet mode
    b = SX.SPIread(RegPacketConfig2);
    bitSet(b, 6);
    SX.SPIwrite(RegPacketConfig2, b);

    // RSSI smoothing.
    // Defines the number of samples taken to average the RSSI result. 010 -> 8 samples
    b = SX.SPIread(RegRssiConfig);
    bitClear(b, 2);
    bitSet(b, 1);
    bitClear(b, 0);
    SX.SPIwrite(RegRssiConfig, b);

    SX.SPIwrite(RegRssiThresh, RSSI_THRESHOLD);

    // Bit 5: enables the Bit Synchronizer:
    // 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
    b = SX.SPIread(RegOokPeak);
    bitSet(b, 5);
    SX.SPIwrite(RegOokPeak, b);

    // RegPreambleDetect (0x1f). Enables Preamble detector when set to 1.
    // The AGC settings supersede this bit during the startup / AGC phase.
    // Bit 7: 0 -> turned off, 1 -> turned on
    // Bits 6-5: Number of Preamble bytes to detect to trigger an interrupt.
    // 00 à 1 byte, 10 à 3 bytes, 01 à 2 bytes
    b = SX.SPIread(RegPreambleDetect);
    bitSet(b, 7);
    bitSet(b, 6);
    bitSet(b, 5);
    SX.SPIwrite(RegPreambleDetect, b);

    clearFifoAndFlags();

    SX.setState(STATE_FSRX);
    delay(L_DELAY);
    SX.setState(STATE_RX);
    RegIrqFlags1_value = SX.SPIread(RegIrqFlags1);
    RegIrqFlags2_value = SX.SPIread(RegIrqFlags2);
    Serial.print("RegIrqFlags1_value ");
    Serial.println(RegIrqFlags1_value, BIN);
    Serial.print("RegIrqFlags2_value ");
    Serial.println(RegIrqFlags2_value, BIN);
    rx = true;
  }
}

void loop() {
  if (rx) {
    byte r1 = SX.SPIread(RegIrqFlags1);
    byte r2 = SX.SPIread(RegIrqFlags2);
    if (r1 != RegIrqFlags1_value) {
      RegIrqFlags1_value = r1;
      Serial.print("RegIrqFlags1_value ");
      Serial.println(RegIrqFlags1_value, BIN);
    }
    if (r2 != RegIrqFlags2_value) {
      RegIrqFlags2_value = r2;
      Serial.print("RegIrqFlags2_value ");
      Serial.println(RegIrqFlags2_value, BIN);
    }
    if (bitRead(r2, 2) == 1) {
      b = SX.SPIread(RegPayloadLength);
      if (b > 0) {
        Serial.print("RegPayloadLength ");
        Serial.println(b, DEC);
        b = SX.dataReceived(rxBuffer, b);
        if (b > 0) {
          for (int i = 0; i < b; i++) {
            Serial.print(rxBuffer[i]);
          }
          Serial.println();
        }
      }
    }
  }
}

void clearFifoAndFlags() {
  // Flag(s) and FIFO are cleared when this bit is set
  b = SX.SPIread(RegIrqFlags2);
  bitSet(b, 4);
  SX.SPIwrite(RegIrqFlags2, b);
  delay(S_DELAY);
}

Comments

Popular posts from this blog

Mods for SDR# TETRA demod plugin 1.0.14.0 - 2

Modifying old SDR# TETRA demod plug-in