Receive Interrupt
This proof of concept (PoC) was to confirm I could configure the Semtech 127X then handle the received messages using a TinyCLR GpioPinValueChangedEventHandler.
public sealed class Rfm9XDevice
{
private SpiDevice rfm9XLoraModem;
private GpioPin InterruptGpioPin = null;
private const byte RegisterAddressReadMask = 0X7f;
private const byte RegisterAddressWriteMask = 0x80;
public Rfm9XDevice(int chipSelectPin, int resetPin, int interruptPin)
{
var settings = new SpiConnectionSettings()
{
ChipSelectType = SpiChipSelectType.Gpio,
ChipSelectLine = chipSelectPin,
Mode = SpiMode.Mode0,
ClockFrequency = 500000,
DataBitLength = 8,
ChipSelectActiveState = false,
};
SpiController spiCntroller = SpiController.FromName(FEZ.SpiBus.Spi1);
rfm9XLoraModem = spiCntroller.GetDevice(settings);
// Factory reset pin configuration
GpioController gpioController = GpioController.GetDefault();
GpioPin resetGpioPin = gpioController.OpenPin(resetPin);
resetGpioPin.SetDriveMode(GpioPinDriveMode.Output);
resetGpioPin.Write(GpioPinValue.Low);
Thread.Sleep(10);
resetGpioPin.Write(GpioPinValue.High);
Thread.Sleep(10);
// Interrupt pin for RX message & TX done notification
InterruptGpioPin = gpioController.OpenPin(interruptPin);
resetGpioPin.SetDriveMode(GpioPinDriveMode.Input);
InterruptGpioPin.ValueChanged += InterruptGpioPin_ValueChanged;
}
private void InterruptGpioPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
if (e.Edge != GpioPinEdge.RisingEdge)
{
return;
}
byte irqFlags = this.RegisterReadByte(0x12); // RegIrqFlags
Debug.WriteLine($"RegIrqFlags 0X{irqFlags:x2}");
if ((irqFlags & 0b01000000) == 0b01000000) // RxDone
{
Debug.WriteLine("Receive-Message");
byte currentFifoAddress = this.RegisterReadByte(0x10); // RegFifiRxCurrent
this.RegisterWriteByte(0x0d, currentFifoAddress); // RegFifoAddrPtr
byte numberOfBytes = this.RegisterReadByte(0x13); // RegRxNbBytes
// Get number of bytes in the message
byte[] messageBytes = this.RegisterRead(0x00, numberOfBytes);
string messageText = UTF8Encoding.UTF8.GetString(messageBytes);
Debug.WriteLine($"Received {messageBytes.Length} byte message {messageText}");
}
this.RegisterWriteByte(0x12, 0xff);// RegIrqFlags
}
...
class Program
{
static void Main()
{
Rfm9XDevice rfm9XDevice = new Rfm9XDevice(FEZ.GpioPin.D10, FEZ.GpioPin.D9, FEZ.GpioPin.D2);
// Put device into LoRa + Sleep mode
rfm9XDevice.RegisterWriteByte(0x01, 0b10000000); // RegOpMode
// Set the frequency to 915MHz
byte[] frequencyWriteBytes = { 0xE4, 0xC0, 0x00 }; // RegFrMsb, RegFrMid, RegFrLsb
rfm9XDevice.RegisterWrite(0x06, frequencyWriteBytes);
rfm9XDevice.RegisterWriteByte(0x0F, 0x0); // RegFifoRxBaseAddress
rfm9XDevice.RegisterWriteByte(0x40, 0b00000000); // RegDioMapping1 0b00000000 DI0 RxReady & TxReady
rfm9XDevice.RegisterWriteByte(0x01, 0b10000101); // RegOpMode set LoRa & RxContinuous
rfm9XDevice.RegisterDump();
Debug.WriteLine("Receive-Wait");
Thread.Sleep(Timeout.Infinite);
}
}
The output in the output debug window looked like this
'C:\Users\BrynLewis\source\repos\RFM9X.TinyCLR\ReceiveInterrupt\bin\Debug\pe\..\ReceiveInterrupt.exe', Symbols loaded.
The thread '<No Name>' (0x2) has exited with code 0 (0x0).
Register dump
Register 0x00 - Value 0X88
Register 0x01 - Value 0X85
Register 0x02 - Value 0X1a
..
Register 0x41 - Value 0X00
Register 0x42 - Value 0X12
Receive-Wait
RegIrqFlags 0X50
Receive-Message
Received 15 byte message HeLoRa World! 0
RegIrqFlags 0X50
Receive-Message
Received 15 byte message HeLoRa World! 2
RegIrqFlags 0X50
Receive-Message
Received 15 byte message HeLoRa World! 4
RegIrqFlags 0X50
Receive-Message
Received 15 byte message HeLoRa World! 6
RegIrqFlags 0X50
Receive-Message
Received 15 byte message HeLoRa World! 8
RegIrqFlags 0X50
Receive-Message
Received 16 byte message HeLoRa World! 10
RegIrqFlags 0X50
Receive-Message
Received 16 byte message HeLoRa World! 12
Next steps will be wiring up the transmit done interrupt, then building a full featured client based on my Windows 10 IoT Core library.