The nRF24L01 Radio Messages

Nordic Semiconductor ® nRF24L01+ 2.4 GHz Radio Transceiver driver is contained within the MIRTOS Operating System. In addition to the system commands and concepts contained in the "N" documentation, there are few more which need to be explained and understood in order to be able to use the radios effectively.

MIRTOS will only accept a message arriving over the nRF radio if the device is logged on in Manager or Administratrive mode. Manager mode login can be done locally by typing '$' as the first character on the command line. The nRF driver must receive the string "SNPW:" followed by the unit's unique 9-byte device serial number, which IS case-sensitive. It must receive that specific string. The idea is simple: if you have its serial number, you must have had direct contact with it at some point in time, or have given it to someone.

Upon receiving that, the device enters Manager mode, just as if the '$' were typed locally, with all of the privileges that come with the Manager mode: the ability to read and change SRAM, EEPROM, and FLASH memory, the ability to run scripts and execute system commands, as well as any extensions unique to that specific device. Until that string is entered, it will not process any other command, unless the device has been logged into Manager or Admin mode locally. Logging on locally also enables the nRF radio messages. The special, suppressed, first command-line character toggle keys cannot be sent via nRF, however. When accepting commands (either by radio or locally), the "Logout" or "Logoff" system command functions like typing the '$' toggle key to log out.

The nRF protocol is a broadcast protocol. Every nRF radio configured to listen to some specific PTX device (or devices), on a specific channel, at a specific comm rate, should receive the same message. If multiple devices respond, the replies will very likely interfere with one another and the PTX not hear any of them.

Whenever commands are accepted (i.e., logged in), an optional "ID BYTE" can be transmitted to each device that can hear the message. It is recommended that this be a printable ASCII character (33 through 126), with numbers and letters ('0' to '9', 'A' to 'Z', 'a to 'z') preferred, but not required. The nRF driver then stores that ID BYTE in the remote device until logged off or changed, and every message it receives must then have that as a prefix byte before it will accept the message as valid. For example, if the PTX node sends this sequence:

>N "SNPW:Demo_PRX2"
>N "DE+ 0 32"
>N "Logout"
>N "DE+ 0 32"
>N "SNPW:Demo_PRX2"
>N "ID=Y"      ; Set the ID Byte
>N "DE+ 0 32"
>N "Logout"
>N "YDE+ 0 32"
>N "YLogout"
>N "YDE+ 0 32"
>N "SNPW:Demo_PRX2"
>N "YDE+ 0 32"
>N "YLogout"
>N "DE+ 0 32"
>N "Logout"                                                                     
Recall that the PTX node does not need to be logged in to transmit nRF messages. In this example, the "ID=Y" set the character 'Y' as the ID BYTE. The screen capture below is the response at the PRX (receiving) node to the sequence above, with nRF receive debugging enabled:
>nRF Rx [P1, 16]: 16, 1, 'SNPW:Demo_PRX2'
nRF Rx [P1, 9]: 9, 2, 'DE+ 0 32'
EEPROM contents:
0000:  10 21 00 9F 01 01 96 FF-04 00 FF FF 28 3C 50 FF  .!..........(.P.
0010:  C0 00 3F FF 00 08 03 67-FF 25 74 FF FF FF FF FF  ..?....g.%t.....
m>nRF Rx [P1, 8]: 8, 3, 'Logout'
>nRF Rx [P1, 9]: 9, 4, 'DE+ 0 32'
nRF Rx [P1, 16]: 16, 5, 'SNPW:Demo_PRX2'
nRF Rx [P1, 6]: 6, 6, 'ID=Y'
nRF Rx [P1, 5]: 5, 7, 'DE+ 0 32'
nRF Rx [P1, 8]: 8, 8, 'Logout'
nRF Rx [P1, 10]: 10, 9, 'YDE+ 0 32'
EEPROM contents:
0000:  10 21 00 9F 01 01 96 FF-04 00 FF FF 28 3C 50 FF  .!..........(.P.
0010:  C0 00 3F FF 00 08 03 67-FF 25 74 FF FF FF FF FF  ..?....g.%t.....
m>nRF Rx [P1, 9]: 9, 10, 'YLogout'
>nRF Rx [P1, 10]: 10, 11, 'YDE+ 0 32'
nRF Rx [P1, 16]: 16, 12, 'SNPW:Demo_PRX2'
nRF Rx [P1, 11]: 11, 13, 'YDE+ 0 32'
m>nRF Rx [P1, 9]: 9, 14, 'YLogout'
m>nRF Rx [P1, 10]: 10, 15, 'DE+ 0 32'
EEPROM contents:
0000:  10 21 00 9F 01 01 96 FF-04 00 FF FF 28 3C 50 FF  .!..........(.P.
0010:  C0 00 3F FF 00 08 03 67-FF 25 74 FF FF FF FF FF  ..?....g.%t.....
m>nRF Rx [P1, 8]: 8, 16, 'Logout'
>                                                                               
After the "ID=Y" command set the ID BYTE, the "DE+" and "Logout" commands did not respond in the same way that they did previously. The 'Y' prefix had to be prepended to each of them for them to respond. Once logged out at the PRX, the ID BYTE was cleared, so the commands functioned as before. After logging back in, the commands with that same 'Y' prefix were discarded. Be careful in selecting the prefix character. 'Y' was selected here because it is not used for any other standard system command.

The ID byte can apply to a single unit or can be assigned to a group. Multiple devices are grouped by giving them all the same ID byte. This is done by logging into each one in turn then sending the "ID=" command. This feature allows multiple units to execute the same command at the same time. It also permits multiple groups.

Data values can be requested from a remote node. The default PRX configurations initialize the EN_AA Register to 0, disabling the Auto- Acknowledgment feature of the nRF radios. Again, when multiple devices reply at the same time, few, if any, messages get through.

In this example, both transmit and receive debugging at the PTX node are enabled, so replies are interspersed with the commands:
>; Omit sending the comments with the "N" commands
>ES 0x20C = 32    ; Start storing data received at uVars.B[32] --> 0x2A0
>DV+              ; Shows that uVars.B[##] array has all zero values
SRAM contents:
0280:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0290:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02A0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02B0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02C0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02D0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
>N "SNPW:Demo_PRX2"
>N "N 1 = 0x3F"   ; Change EN_AA in PRX2 to reply
>NA+              ; Change PTX from to W_TX_PAYLOAD
>N "V*?"          ; Request all AI and DI values
>N "VE0?"         ; Get reply; request EEPROM values
nRF Rx [P0, 30]: 30, 9, 'V*=', 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0xEB, 0x03, 0xEB, 0x03, 0xC5, 0x00, 0x37, 0x00, 0xE0, 0x00, 0x00,
  0x00, 0x71, 0x01, 0x80, 0x30, 0x9B
>N " "            ; Receive the EEPROM data reply
nRF Rx [P0, 32]: 32, 10, 'VE0=', 0x10, 0x21, 0x00, 0x9F, 0x01, 0x01, 0x96,
  0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x28, 0x3C, 0x50, 0xFF, 0xC0, 0x00, 0x3F,
  0xFF, 0x00, 0x08, 0x03, 0x67, 0xFF, 0x25
>N "N 1 = 0"      ; Reset PRX2 EE_AA not to reply
>NA-              ; Revert to W_TX_PAYLOAD_NOACK
>N "N 23 ?"       ; Check the PRX FIFO_STATUS
>DV+              ; Values placed in SRAM 0x2A0 to 0x2B8 (25 bytes)
SRAM contents:
0280:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0290:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02A0:  1A 00 00 00 00 00 00 00-EB 03 EB 03 C5 00 37 00  ..............7.
02B0:  E0 00 00 00 71 01 80 30-9B 00 00 00 00 00 00 00  ....q..0........
02C0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
02D0:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
>N "Logout"       ; Log out of the PRX node
>                                                                               
The console output at the PRX node is shown below. Both Transmit and Receive nRF debugging were enabled:
>nRF Rx [P1, 16]: 16, 59, 'SNPW:Demo_PRX2'
m>nRF Rx [P1, 12]: 12, 60, 'N 1 = 0x3F'
m>nRF Rx [P1, 5]: 5, 61, 'V*?'
nRF Tx [31, 0xA9]: 30, 9, 'V*=', 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0xEB, 0x03, 0xEB, 0x03, 0xC5, 0x00, 0x37, 0x00, 0xE0, 0x00, 0x00,
   0x00, 0x71, 0x01, 0x80, 0x30, 0x9B
nRF Rx [P1, 6]: 6, 62, 'VE0?'
nRF Tx [33, 0xA9]: 32, 10, 'VE0=', 0x10, 0x21, 0x00, 0x9F, 0x01, 0x01, 0x96,
   0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x28, 0x3C, 0x50, 0xFF, 0xC0, 0x00, 0x3F,
   0xFF, 0x00, 0x08, 0x03, 0x67, 0xFF, 0x25
nRF Rx [P1, 3]: 3, 63, ' '
nRF Rx [P1, 9]: 9, 64, 'N 1 = 0'
m>nRF Rx [P1, 8]: 8, 65, 'N 23 ?'
0x17 (0E) -> 0x11 = B00010001
m>nRF Rx [P1, 8]: 8, 66, 'Logout'
>                                                                               
The nRF24L01 automatically ackowledges a packet received in the PRX node, before the Operating System even realizes that one has been received. The Operating System processes the command, builds a reply and places it into the nRF24L01+ Transmit FIFO buffer. The reply waits there for the next request to come from that same PTX node.

The EN_AA Register in the PRX must be enabled for transmission to the PTX node that made the request and a W_TX_PAYLOAD request packet be sent by the PTX (the "NA+" above). If a W_TX_PAYLOAD_NOACK request packet (i.e., "NA-") arrives, the message is not sent, but waits in the PRX's reply FIFO buffer. The sequence above worked as shown.

Notes:
      "N" command lines with quotes should not exceed 50 bytes; nRF messages are limited to 32.
V*? requests the 11 Analog WORDs, then the PINB, PINC, and PIND BYTEs (25 total BYTEs).
VE###? requests EEPROM data starting at address ###.
VF###? or VP###? requests FLASH data starting at ###.
VR###? or VS###? requests SRAM data starting at ###.
An ID BYTE can used prior to the value requests listed above (e.g., "YVE1?")
The SI_nRFuVIndex variable selects the starting uVars.B[##] index to store the requested data received with a "V?" command.
The BIT_REM* bits in EEbFlags_Remote may inhibit specific data requests.
  (those are: BIT_REM_ALLOW_EEPR, BIT_REM_ALLOW_PGM, BIT_REM_ALLOW_SRAM, and BIT_REM_ALLOW_READ)
The MIRTOS driver examines each outgoing nRF message and will not send its own complete serial number, but will redact it, replacing each byte with the '#' character.

See also:
      The nRF24L01+ system command, the EEfptrNRFCmdExts in SystemEEPROM.Def and EEfptrNRFValExts in SystemEEPROM.Def nRF command extensions, as well as the nRF_CommandHandler, nRF_Initialize, nRF_Read1Register, nRF_SPI_Command, and nRF_Write1Register system function calls.