TransferFullDuplex vs. Read Write
For testing the initial versions of my .Net Core 5 dotnet/iot SX127X library I’m using a Uputronics Raspberry PiZero LoRa(TM) Expansion Board which supports both standard Chip Select(CS) pins (switch selectable which is really useful) and an M2M 1 Channel LoRaWan Gateway Shield for Raspberry PI which has a “non-standard” CS pin.
The spiDevice.ReadByte() and spiDevice.WriteBye() version worked with a custom chip select pin(25) and CS0 or CS1 selected in the SpiConnectionSettings (but this CS line was “unusable” by other applications). This approach also worked with standard select line (CS01 or CS1) if the SpiConnectionSettings was configured to use the “other” CS line and the selected CS pin managed by the application.
namespace devMobile.IoT.SX127x.ShieldSPIWriteRead
{
class Program
{
private const int SpiBusId = 0;
private const int ChipSelectLine = 1; // 0 or 1 for Uputronics depends on the switch, for the others choose CS pin not already in use
#if ChipSelectNonStandard
private const int ChipSelectPinNumber = 25; // 25 for M2M, Dragino etc.
#endif
private const byte RegisterAddress = 0x6; // RegFrfMsb 0x6c
//private const byte RegisterAddress = 0x7; // RegFrfMid 0x80
//private const byte RegisterAddress = 0x8; // RegFrfLsb 0x00
//private const byte RegisterAddress = 0x42; // RegVersion 0x12
static void Main(string[] args)
{
#if ChipSelectNonStandard
GpioController controller = null;
controller = new GpioController(PinNumberingScheme.Logical);
controller.OpenPin(ChipSelectPinNumber, PinMode.Output);
controller.Write(ChipSelectPinNumber, PinValue.High);
#endif
var settings = new SpiConnectionSettings(SpiBusId, ChipSelectLine)
{
ClockFrequency = 5000000,
Mode = SpiMode.Mode0, // From SemTech docs pg 80 CPOL=0, CPHA=0
};
SpiDevice spiDevice = SpiDevice.Create(settings);
Thread.Sleep(500);
while (true)
{
#if ChipSelectNonStandard
controller.Write(ChipSelectPinNumber, PinValue.Low);
#endif
spiDevice.WriteByte(RegisterAddress);
byte registerValue = spiDevice.ReadByte();
#if ChipSelectNonStandard
controller.Write(ChipSelectPinNumber, PinValue.High);
#endif
byte registerValue = readBuffer[writeBuffer.Length - 1];
Console.WriteLine($"Register 0x{RegisterAddress:x2} - Value 0X{registerValue:x2} - Bits {Convert.ToString(registerValue, 2).PadLeft(8, '0')}");
Thread.Sleep(5000);
}
}
}
}
The spiDevice.TransferFullDuplex worked for a standard CS line (CS0 or CS1), and for a non-standard CS line, though the CS line configured in SpiConnectionSettings was “unusable” by other applications “.
namespace devMobile.IoT.SX127x.ShieldSPITransferFullDuplex
{
class Program
{
private const int SpiBusId = 0;
private const int ChipSelectLine = 0; // 0 or 1 for Uputronics depends on the switch, for the others choose CS pin not already in use
#if ChipSelectNonStandard
private const int ChipSelectPinNumber = 25; // 25 for M2M, Dragino etc.
#endif
private const byte RegisterAddress = 0x6; // RegFrfMsb 0x6c
//private const byte RegisterAddress = 0x7; // RegFrfMid 0x80
//private const byte RegisterAddress = 0x8; // RegFrfLsb 0x00
//private const byte RegisterAddress = 0x42; // RegVersion 0x12
static void Main(string[] args)
{
#if ChipSelectNonStandard
GpioController controller = null;
controller = new GpioController(PinNumberingScheme.Logical);
controller.OpenPin(ChipSelectPinNumber, PinMode.Output);
controller.Write(ChipSelectPinNumber, PinValue.High);
#endif
var settings = new SpiConnectionSettings(SpiBusId, ChipSelectLine)
{
ClockFrequency = 5000000,
Mode = SpiMode.Mode0, // From SemTech docs pg 80 CPOL=0, CPHA=0
};
SpiDevice spiDevice = SpiDevice.Create(settings);
Thread.Sleep(500);
while (true)
{
byte[] writeBuffer = new byte[] { RegisterAddress, 0 };
byte[] readBuffer = new byte[writeBuffer.Length];
#if ChipSelectNonStandard
controller.Write(ChipSelectPinNumber, PinValue.Low);
#endif
spiDevice.TransferFullDuplex(writeBuffer, readBuffer);
#if ChipSelectNonStandard
controller.Write(ChipSelectPinNumber, PinValue.High);
#endif
byte registerValue = readBuffer[writeBuffer.Length - 1];
Console.WriteLine($"Register 0x{RegisterAddress:x2} - Value 0X{registerValue:x2} - Bits {Convert.ToString(registerValue, 2).PadLeft(8, '0')}");
Thread.Sleep(5000);
}
}
}
}
The output when the application was working as expected
Loaded '/usr/lib/dotnet/shared/Microsoft.NETCore.App/5.0.4/Microsoft.Win32.Primitives.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Register 0x06 - Value 0X6c - Bits 01101100
Register 0x06 - Value 0X6c - Bits 01101100
Register 0x06 - Value 0X6c - Bits 01101100
Register 0x06 - Value 0X6c - Bits 01101100
Register 0x06 - Value 0X6c - Bits 01101100
Register 0x06 - Value 0X6c - Bits 01101100
The program 'dotnet' has exited with code 0 (0x0).
Summary
Though the spiDevice.TransferFullDuplex code was slightly more complex it worked with both standard and non-standard CS pins.
Pingback: .NET Core 5 SX127X library Part2 | devMobile's blog