After debugging Windows 10 IoT Core & .NetMF nRF24L01P libraries I figured a port to a Wilderness Labs Meadow device shouldn’t be “rocket science”.
I couldn’t source an nRF24L01 feather wing so built a test rig with jumpers

//---------------------------------------------------------------------------------
// Copyright (c) Feb 2020, devMobile Software
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//---------------------------------------------------------------------------------
namespace devMobile.IoT.nRf24L01
{
using System;
using System.Text;
using System.Threading;
using Meadow;
using Meadow.Devices;
using Meadow.Hardware;
public class MeadowApp : App<F7Micro, MeadowApp>
{
const byte SETUP_AW = 0x03;
const byte RX_ADDR_P0 = 0x0A;
const byte R_REGISTER = 0b00000000;
const byte W_REGISTER = 0b00100000;
ISpiBus spiBus;
SpiPeripheral nrf24L01Device;
IDigitalOutputPort spiPeriphChipSelect;
IDigitalOutputPort ChipEnable;
public MeadowApp()
{
ConfigureSpiPort();
SetPipe0RxAddress("ZYXWV");
}
public void ConfigureSpiPort()
{
try
{
ChipEnable = Device.CreateDigitalOutputPort(Device.Pins.D09, initialState: false);
if (ChipEnable == null)
{
Console.WriteLine("chipEnable == null");
}
var spiClockConfiguration = new SpiClockConfiguration(2000, SpiClockConfiguration.Mode.Mode0);
spiBus = Device.CreateSpiBus(Device.Pins.SCK,
Device.Pins.MOSI,
Device.Pins.MISO,
spiClockConfiguration);
if (spiBus == null)
{
Console.WriteLine("spiBus == null");
}
Console.WriteLine("Creating SPI NSS Port...");
spiPeriphChipSelect = Device.CreateDigitalOutputPort(Device.Pins.D10, initialState: true);
if (spiPeriphChipSelect == null)
{
Console.WriteLine("spiPeriphChipSelect == null");
}
Console.WriteLine("nrf24L01Device Device...");
nrf24L01Device = new SpiPeripheral(spiBus, spiPeriphChipSelect);
if (nrf24L01Device == null)
{
Console.WriteLine("nrf24L01Device == null");
}
Thread.Sleep(100);
Console.WriteLine("ConfigureSpiPort Done...");
}
catch (Exception ex)
{
Console.WriteLine("ConfigureSpiPort " + ex.Message);
}
}
public void SetPipe0RxAddress(string address)
{
try
{
// Read the Address width
byte[] txBuffer1 = new byte[] { SETUP_AW | R_REGISTER, 0x0 };
Console.WriteLine(" txBuffer:" + BitConverter.ToString(txBuffer1));
/*
// Appears to work but not certain it does
Console.WriteLine(" nrf24L01Device.WriteRead...SETUP_AW");
byte[] rxBuffer1 = nrf24L01Device.WriteRead(txBuffer1, (ushort)txBuffer1.Length);
Console.WriteLine(" nrf24L01Device.WriteRead...SETUP_AW");
*/
byte[] rxBuffer1 = new byte[txBuffer1.Length];
Console.WriteLine(" spiBus.ExchangeData...RX_ADDR_P0");
spiBus.ExchangeData(spiPeriphChipSelect, ChipSelectMode.ActiveLow, txBuffer1, rxBuffer1);
Console.WriteLine(" rxBuffer:" + BitConverter.ToString(rxBuffer1));
// Extract then adjust the address width
byte addressWidthValue = rxBuffer1[1];
addressWidthValue &= 0b00000011;
addressWidthValue += 2;
Console.WriteLine("Address width 0x{0:x2} - Value 0X{1:x2} - Bits {2} Value adjusted {3}", SETUP_AW, rxBuffer1[1], Convert.ToString(rxBuffer1[1], 2).PadLeft(8, '0'), addressWidthValue);
Console.WriteLine();
// Write Pipe0 Receive address
Console.WriteLine("Address write 1");
byte[] txBuffer2 = new byte[addressWidthValue + 1];
txBuffer2[0] = RX_ADDR_P0 | W_REGISTER;
Array.Copy(Encoding.UTF8.GetBytes(address), 0, txBuffer2, 1, addressWidthValue);
Console.WriteLine(" txBuffer:" + BitConverter.ToString(txBuffer2));
Console.WriteLine(" nrf24L01Device.Write...RX_ADDR_P0");
nrf24L01Device.WriteBytes(txBuffer2);
Console.WriteLine();
// Read Pipe0 Receive address
Console.WriteLine("Address read 1");
byte[] txBuffer3 = new byte[addressWidthValue + 1];
txBuffer3[0] = RX_ADDR_P0 | R_REGISTER;
Console.WriteLine(" txBuffer:" + BitConverter.ToString(txBuffer3));
/*
// Broken returns Address 0x0a - RX Buffer 5A-5A-5A-5A-59-58 RX Address 5A-5A-5A-59-58 Address ZZZYX
Console.WriteLine(" nrf24L01Device.WriteRead...RX_ADDR_P0");
byte[] rxBuffer3 = nrf24L01Device.WriteRead(txBuffer3, (ushort)txBuffer3.Length);
*/
byte[] rxBuffer3 = new byte[addressWidthValue + 1];
Console.WriteLine(" spiBus.ExchangeData...RX_ADDR_P0");
spiBus.ExchangeData(spiPeriphChipSelect, ChipSelectMode.ActiveLow, txBuffer3, rxBuffer3);
Console.WriteLine("Address 0x{0:x2} - RX Buffer {1} RX Address {2} Address {3}", RX_ADDR_P0, BitConverter.ToString(rxBuffer3, 0), BitConverter.ToString(rxBuffer3, 1), UTF8Encoding.UTF8.GetString(rxBuffer3, 1, addressWidthValue));
}
catch (Exception ex)
{
Console.WriteLine("ReadDeviceIDDiy " + ex.Message);
}
}
}
}
After lots of tinkering with SPI configuration options and trialing different methods (spiBus vs.SpiPeripheral) I can read and write my nRF24L01 device receive port address
Creating SPI NSS Port...
nrf24L01Device Device...
ConfigureSpiPort Done...
txBuffer:03-00
spiBus.ExchangeData...RX_ADDR_P0
rxBuffer:0E-03
Address width 0x03 - Value 0X03 - Bits 00000011 Value adjusted 5
Address write 1
txBuffer:2A-5A-59-58-57-56
nrf24L01Device.Write...RX_ADDR_P0
Address read 1
txBuffer:0A-00-00-00-00-00
spiBus.ExchangeData...RX_ADDR_P0
Address 0x0a - RX Buffer 0E-5A-59-58-57-56 RX Address 5A-59-58-57-56 Address ZYXWV
I need to investigate why the first byte of the buffer returned by nrf24L01Device.ReadBytes and nrf24L01Device.WriteRead is wrong.