PDoA Node Source Code Guide
PDoA Node Source Code Guide
Version 1.1
TABLE OF CONTENTS
1 INTRODUCTION .................................................................................................................................................... 4
6 APPENDIX A ........................................................................................................................................................30
7 BIBLIOGRAPHY ....................................................................................................................................................43
TABLE OF FIGURES
1 INTRODUCTION
This document, “DWM1002 PDoA Node Source Code Guide” is a guide for an embedded software developers
to the application source code of Decawave’s Phase Difference of Arrival (PDoA) evaluation kit node application,
running on the Nordic Semiconductor ARM Cortex M4 MCU on the PDoA node hardware platform. The code
and the document is organized on the same manner as the “PDoA Tag Source Code Guide” [3]. The Node
project is supplied as Segger Embedded studio project with Nordic SDK15.
The application source code employs a real-time operating system (FreeRTOS), however it is possible to use
another RTOS or potentially remove the operating system and implement the node application using a Round
Robin scheduling with interrupts technique (main super loop).
On start-up the PDoA node listens for Blink messages from tags and when a Blink message has received, the
PDoA node responds to the tag with a Ranging Config message. The Ranging Config message provides
information to the tag describing how to perform ranging with the PDoA node. This information includes the
PAN ID, the short address of the PDoA node, a short address assignment for the tag, and timing parameters
for the ranging phase. Upon receiving the Ranging Config message, the tag changes to ranging mode where it
periodically initiates ranging exchanges with the PDoA node.
The PDoA node has two antennae and two DW1000 ICs (one for each antenna). Each ranging exchange starts
with the tag sending a Poll message, while the PDoA node listens with only one DW1000 IC active. When the
PDoA node receives the Poll message, it replies with a Response message, and the tag completes the ranging
exchange by sending a Final message. The PDoA node turns on both DW1000 ICs to receive the Final
message. This enables it to determine the phase difference (PDoA) between their arrival times at each
antennae. The PDoA node then calculates X and Y coordinates of the tag which it reports via USB/UART for
displaying by the PC GUI application.
• Section 2 provides a description of the architecture and structure of the PDoA node platform and
application.
• Section 3 provides a description of the operation of the core tasks.
• Section 4 describes the operation of the top-level applications.
• Section 5 gives a brief overview of how to build and debug the code.
• Section 6 Appendix A details the ranging method and the ranging messages, and provides a flowchart
of the interaction between the major software blocks, and gives a list of the project files.
NODE TCFM
TCWM
RX CALC
Top-level USB2SPI
IMU applications
FreeRTOS
Default
Flush Control
Core tasks
DW1000 SPI/USB/UART
Device Driver Drivers
Target HAL
Physical interfaces
This is the top level of the software defining the operation of the node unit. It has four separate applications /
modes of operation. The main mode, named “NODE” is the normal PDoA node functionality as introduced in
section 1.1 above, while the three other operational modes are for testing purposes. These are: TCFM – Test
Continuous Frame transmission Mode; TCWM – Test Continuous Wave transmission Mode; and, USB2SPI
test mode, allowing external test software direct access to the DW1000 SPI’s.
The top-level applications cannot run concurrently since they use the same resources: e.g. NODE application
configures the DW1000s to do two-way ranging, while TCWM application initializes selected DW1000 to run a
Continuous Wave mode test.
The core tasks are always running once the RTOS kernel has been started. These core tasks are described in
section 3.2. The core tasks are:
• The Default core task is responsible for starting one of the top-level applications. It receives events
from the Control task to switch to a particular mode of operation and starts corresponding top-level
application. This is described in detail in section: 3.2.1
• The Control core task is responsible for reception and execution of commands from external IO
interfaces USB and UART. The Control task can also pass data from those I/O interfaces to the top-
application layer. This is described in detail in section: 0, 3.2.3.
• The Flush core task is responsible for transmitting of any output data to the external I/O interfaces
USB and UART. This is described in detail in section 3.2.4.
2.1.3 Drivers
The drivers are responsible for translating of higher-layer requests and the specific sequences to control
particular peripherals.
To control the DW1000 UWB radio transceivers the DW1000 API and the device driver is incorporated as a
library. Other physical interfaces have corresponding drivers, namely UART, USB, etc.
2.1.4 FreeRTOS
The PDoA node platform runs under the FreeRTOS operating system control. This is a CMSIS compatible
RTOS, thus the PDoA node software is portable to other CMSIS-RTOS if needed. The CMSIS-RTOS is a
common API for Real-Time operating systems. It provides a standardized programming interface that is
portable to many RTOS and enables therefore software templates, middleware, libraries, and other
components that can work across supported the RTOS systems.
The PDoA node software has two layers of operation: RTOS tasks, which run concurrently, and bare-metal
functions, which run under the operation of the RTOS based application. Potentially it is possible to remove
RTOS tasks, and implement their functionality using Round Robin technique (super loop), however this may
lead to a complex times management and complexity in the code (spaghetti-code).
Some of the bare-metal functions, such as SPI driver are running below the RTOS priority, which means that
they cannot be interrupted by the RTOS or use RTOS mechanisms for communications. This is done to
increase the performance of running applications.
Folder Description
name
nRF_Libraries
nRF_Log
nRF_Segger_RTT
At the startup, the main() loads the saved configuration from the FConfig, which is the Non Volatile Memory
(NVM) of the MCU (in the target ARM it’s organized as a part of Flash memory), into the RAM segment,
called bssConfig. On the run-time the application uses the configuration parameters from bssConfig only.
The bssConfig parameters may be updated by the Control task and saved to the Fconfig section of NVM.
NOTE: the application has two configuration sections in the NVM memory, called defaultConfig and FConfig,
and one section in the RAM memory, called bssConfig. The defaultConfig NVM segment stores the default
data configuration and this cannot be changed but can be used to restore the initial configuration. The FConfig
NVM segment stores the current configuration, which can be updated by the Control task. The bssConfig
RAM segment holds the actual run-time working parameters copied from FConfig during the startup.
All globally accessible variables are defined in the global “app” structure.
app_t app; /**< All global variables are in the "app" structure */
load_bssConfig();/**< load the RAM Configuration parameters from NVM block */
app.pConfig = get_pbssConfig();/* app.pConfig is pointed to the RAM (bssConfig)*/
After loading of the configuration parameters, the main() code initialises the core tasks and enables the Real-
Time kernel (scheduler), see Figure 3. After starting of the RTOS kernel, the core tasks will begin to run “in
parallel”, each executing its dedicated role.
• The Default task, which is coded in the DefaultTask(), is responsible for starting individual top-level
application tasks which operate in a mutually exclusive way with the DW1000’s because they cannot
share this unique resources for their operation, i.e. only one of these top-level tasks is enabled to run at
any one time. This is described in more detail in section 3.2.1.
• The Control task, which is coded in the CtrlTask(), is responsible for reading of the input from USB and
UART, translating it to the appropriate command and executing of that command, see 0.
• The Flush task, coded in the FlushTask() is attempting to output all data to USB and UART from the
common circular report buffer Report.buf, which used as a common data storage for all output information
coming from any running processes, see 3.2.4.
There is one more special core task, called the Idle() task, which is created automatically when the RTOS
scheduler is started. It is created at the lowest possible priority to ensure it does not use any CPU time if there
are higher priority tasks in the ready state. The power-saving mode of the MCU is implemented as a part of
this task.
The Default task waits for a global event xStartTaskEvent, which instructs it to enable a particular top-level
application task, depending on the requested operation mode. This event can be received from Control task or
as a part of parsing of initial configuration, see 0 below.
On reception of non-empty xStartTaskEvent, the Default task stops all running top-level tasks and their
corresponded processes, and then starts the requested top-level application from its initial condition.
Alternatively, if the xStartTaskEvent is empty, the Default task periodically executes the USB_VBUS driver, by
running it every USB_DRV_UPDATE_MS.
For more details about events and tasks interconnection mechanisms see section 3.3.
The Control task awaits an input on a USB and/or UART interfaces. The task has two modes of operation,
Command mode and Data mode.
The Control task in Command operational mode, see Figure 4, parses and executes a command, and can set
an event to xStartTaskEvent, which will be received by Default task. More details of Command mode of
operation of Control task is given in the paragraph 3.2.3.
NodeTask
Command parser EVENT Usb2SpiTask
TcfmTask
Data parser TcfmTask
Figure 4 Control task (in command mode) sends EVENT to the Default task
Importantly, on the reception of a USPI command from a PC, see Table 2, the Default task will be instructed to
start the special Usb2Spi top-level application, which requires a raw data input from the I/O interface (USB or
UART connection to the “DecaRanging” PC application).
The start of the Usb2Spi top-level application switches the Control task to run in transparent mode, called
“Data parser” mode, where the Control task will not parse commands and will not attempt to execute them.
Instead, the Control task will send the SIGNAL and pass the data input directly to the Usb2Spi top-level
application, which will process the incoming traffic from USB and UART inputs. This is illustrated in Figure 5
below. For more information about Usb2Spi top-level application see 4.2.
Run
Data parser SIGNAL usb2spi
process
Figure 5 Control Task (in data mode) sends signal to the Usb2Spi application
The command mode of Control task includes parsing and execution of a number of different input command
sets. In this section a more advanced description of this mode will be given.
On reception of a valid command by the Control task, the command is processed and corresponding reply is
sent for output. The Flush task is then actually sending of the output to the USB/UART.
There are three types of commands, which can be parsed in the node: anytime commands, state changing
commands and run-time parameters access commands, which all can be named as “generic commands” set,
and a set of commands to control the PDoA Node top-level application.
The generic commands set described in subsections 3.2.3.1, 3.2.3.2, 3.2.3.3, and Node’s application set - in
subsections 3.2.3.4 below.
Where <Command> is the command string from the Table 1, Table 2 and Table 3 below, [<SPACE><Val>]
is optional and <CR> is representing the carriage return (can be any of <CR>, <LF>, <CRLF>, <LFCR>).
The anytime commands listed in Table 1 can be executed anytime except of the USPI mode of operation, i.e.
when binary data parser is running (see 0). The only exception is a STOP command, which can be executed
in all modes.
STAT Reports the status. Gives a dump of software version info, configuration
values and the current operation mode (NODE, TCFM, TCWM or STOP).
STOP Stops running any of top-level applications and places the node to the STOP
mode, where only core tasks are running.
The commands to change mode of operation can be executed only after the STOP command (otherwise the
command parser will output the string “error incompatible mode”). They are used to send an appropriate event
request to the Default task to start a particular top-level application.
On reception of a command to change the mode the Control task sets an event for to the xStartTaskEvent
which is then received by the Default task, as described on Figure 4 above. For a complete list of commands
to change the mode of operation see Table 2 below.
NODE <val> Run the Node top-level application. The chip configuration <val> is optional and
can be specified to “0” (default) or “1”. This will select the DW1000 chip, which will
act as “master” in the Node application. If <val> is not specified, the default chip
will be used.
TCWM <val> Run the Test Continuous Wave transmission Mode top-level application. The
DW1000 chip can be selected by optional <val> variable, which can be specified to
“0” (default) or to “1”. If <val> is not specified, the default chip will be used.
TCFM <val> Run the Test Continuous Frame transmission Mode top-level application. The
DW1000 chip can be selected by optional <val> variable, which can be specified to
“0” (default) or to “1”. If <val> is not specified, the default chip will be used.
USPI <val> Run the USB-to-2SPI conversion top-level application. The DW1000 chip can be
selected using optional <val> variable, which can be specified to “0” (default) or to
“1”. If <val> is not specified, the default chip will be used.
The USB-to-SPI conversion mode gives an external host/PC direct access to the
SPI bus of DW1000 (one from two ICs). Can be used for testing of DW1000 ICs
and their RF performance.
The commands to change run-time parameters, listed in Table 3, can be executed only when a top-level
application is not running, i.e. the STOP command is needed to place the PDoA node into its STOP mode
before accessing these parameters. All parameters are a part of the bssConfig, and all changes will be
applied at the start of a top-level application. The SAVE command can be used to store changed parameters
to the FConfig that they also will be used after the reboot of the device.
ADDR <val> Set the PDoA node’s short address to decimal <val>. The default is 1 (which is
decimal for PDoA node’s address 0x0001).
PANID <val> Set the PDoA node’s PAN ID to decimal <val>. The default is 57034 (which is
decimal for 0xDECA).
NUMSLOT <val> Set the number of slots been used in the superframe to decimal <val>. The default
is 20. This specifies the maximum number of tags in the superframe. This value
should be equal or bigger than MAX_KNOWN_TAG_LIST_SIZE, see 4.1.1.
SLOTPER <val> Set the slot’s window period to decimal <val>, milliseconds (ms). The 5 ms slot
window is used in the system.
SFPER <val> Set the superframe period to decimal <val>, milliseconds (ms). Superframe period
shall be at least of time duration to fit all slots, i.e. SFPER ≥ NUMSLOT*SLOTPER.
The suerpframe period defines the maximum ranging rate of tags in the system.
The default is 100 ms means that all tags in the system can range to the node 10
times a second each.
REPDEL <val> Set the Reply delay to <val>, microseconds (µs). This value is a parameter in the
Ranging Config message that is sent to each discovered tag to begin ranging. This
value is both tag and node hardware dependent. The tags have their
MIN_RESPONSE_CAPABILITY_US, and if REPLYDEL is less than tag supports,
tag will not start ranging to the node.
P2FDEL <val> Set the Poll-to-Final delay to <val>, microseconds (µs). Default is 1500 µs. This
value is a parameter in the Ranging Config message that is sent to each
discovered tag to begin ranging. This value is mostly tag hardware dependent. The
tags have their MIN_POLL_TX_FINAL_TX_CAPABILITY_US, and if P2FDEL is
less than tag supports, tag will not start ranging to the node.
RCDEL The <val> is the delay in microseconds (µs) between tag’s completion of sending a
Blink and start of tag’s reception of Ranging Config response from the node. Both
nodes and tag have this configuration parameter and it should be the same for all
the devices in the system. Default is 1000 µs.
UART <val> “0” (default) - Disables the UART. The PDoA node will not output data to UART.
“1” - Enables the UART. This enables the PDoA node to use both USB and UART,
which means the top-level application will use both output. In this case the location
report rate in Node top-level application will be limited, since UART speed is limited
to 115200 b/s. It is recommended to switch off JSON TWR output to maintain
maximum location output rate (set PCREP to 2 or 3).
AUTO <val> Used to start default Node top-level application automatically after Reset/Power
on. May be configured to “0” to stay in STOP mode of operation.
By default is configured to “1”, which after reset leads to start the Node top-level
application with first DW1000 chip in a “master” role. Also can be configured to “2”,
which will enable another DW1000 chip to act as a “master” in the Node top-level
application.
ANTTXA <val> Sets the TX antenna delay value to specified val (INT16) decimal value, in device
time units of 1/499.2e-6/128 (approx. 15.65 ps). Applied to the TX antenna delay
configuration of the currently configured “master” chip.
ANTRXA <val> Sets the RX antenna delay value to specified val (INT16) decimal value, in device
time units of 1/499.2e-6/128 (approx. 15.65 ps). Applied to the RX antenna delay
configuration of the currently configured “master” chip.
PDOFF <val> Phase difference mean value, externally collected and send back to the node on
phase calibration process. The known tag, placed in the known coordinates is
used to find the PDoA offset.
RNGOFF <val> Distance mean value, externally collected and send back to the node after on
range calibration process. The known tag, placed in the known coordinates is used
to find the range offset.
PCREP <val> Select granularity of report used for output. By default “1” (JSON). Used to replace
JSON format in report with simple short one to achieve higher locations throughput
over UART. If “0” then reports switched off. <val> can be “0”, “1”, “2”.
RESTORE Restore node’s configuration to default. This command copies the defaultConfig
section of NVM to the bssConfig. SAVE command shall be used thereafter if user
wants to save the FConfig section.
When PDoA Node top-level application is running, it can be controlled externally by USB/UART and accepting
specific commands, which belongs specifically to the Node top-level application.
The PC to the PDoA Node communication commands, listed in Table 4, can be executed at any time and will
have immediate effect to the Node’s top-level application, if it is running. The node is replying onto that
commands, using JSON formatted output, wrapped to TLV format, see 3.2.3.5.
For autonomous mode, e.g. when Node application is not connected to the PC GUI application, but working
standalone, (e.g. when installed on a mobile robot), the known tags list (KList) can be saved to the FConfig
NVM segment, using the SAVE command for this.
DECA$ Node will reply with Info JSON object with version string, see Table 5
GETDLIST Node will reply with KList JSON array of discovered (harvested) tags list, see
Table 5
GETKLIST Node will reply with DList JSON array of known tags list, see Table 5.
DELTAG <addr64> Formatted input string. This will delete the tag of with <addr64> from KList.
<addr64> is address of the tag, hexadecimal, must be 16 characters;
The <addr64> may contain a short address of the tag, followed 12 zeroes. In
this case the tag also will be correctly deleted by its short address.
Example:
Tag long 64-bit address is 0x001122334455667788. And assigned short
address is 0x1234
Following commands will identically correctly delete the tag from the KList:
“DELTAG 0000000000001234” or “DELTAG 001122334455667788”.
The PDoA Node top-level application outputs to the PC using JSON formatted output. The JSON object is
encapsulated in TLV format (Type-Length-Value) to easier the implementation of parser on the PC side. The
reader may find a description of JSON format in the RFC 4627, [https://tools.ietf.org/html/rfc4627].
Example:
JS0088{"Info":{
"Device":"PDoA Node",
"Version":"1.0.0",
"Build":"Sep 18 2017 14:06:47",
"Driver":"DW1000 Device Driver Version 04.00.07"}}
{"slot":<int>,"a64":<string>,"a16":<string>,"F":<int>,"S":<int>,"M":<i
nt>}”
Example:
JS001F{"DList":["10205F4910002E5C"]}
JS005D{"KList":[
{
"slot":1,
"a64":"10205F4910002E5C",
"a16":"012A",
"F":1,
"S":64,
"M":1
}
]}
JS0022{"TagDeleted": "10205f4910002e5c"}
Example:
JS0034{"SN": {"a16":"0001","V":0,"X":-15,"Y":-5,"Z":-985}}
Example:
JS006A{"TWR": {"a16":"4096","R":53,"T":5126,"D":112,"P":-
161,"Xcm":112,"Ycm":0,"O":336,"V":0,"X":0,"Y":0,"Z":0}}
Any functions, including ISR functions, or RTOS tasks can produce and request to send data to the terminal
output (USB and/or UART). In the data sending function port_tx_msg(), the data is copied to the intermediate
Report Buffer, which is then flushed by the Flush task. This is illustrated on the Figure 6 below.
The Flush task is coded as FlushTask() in the task_flush.c source code file.
The Report buffer is a circular buffer, which is statically allocated in the usb_uart_tx.c as txHandle.Report. The
port_tx_msg() function is copying data to the txHandle.Report.buf and then sets the app.flushTask.Signal to
the Flush task to start immediate transmitting of data via USB/UART.
The Flush task is emptying the Report buffer onto the USB and the UART. The Report buffer is a statically
allocated area of REPORT_BUFSIZE, which is defined to 0x2000 bytes. The size of Report buffer is sufficient
that any task/function can send a chunk of data for background output without delaying its throughput, even
during an ISR, see Figure 6 below.
REPORT
BUFFER
Process USB2SPI
protocol commands
Start a TWR timer for slots
Port_tx_msg SPI to DW1000
Discovery phase
Listen for a Tags in a range and
report unknown tags ID to the
output
Ranging phase
Perform TWR to known tags; report
Range and PDoA to the output Run Test Continuous
Frame mode
SPI to DW1000
SPI to DW1000
Command parser
Read IMU Sensor & Run Test Continuous
sets/clear Data parser
Wave mode
Stationary flag
SPI to DW1000
SPI to IMU TWR timer for slots
For locking and signalling, the following mechanisms are used: mutexes, events and signals. Mutexes are
used to protect task execution from being killed in the Default task while they still in the running state.
The EventGroup mechanism, is used to send relatively slow events between tasks. This method is used to
instruct the Default task to start a particular top-level application.
As a fast and simple alternative to EventGroup, the fast task notification mechanism can also be used. In the
CMSIS-RTOS this defined as signals. The signal is delivering a simple message to the specific task. This
mechanism is faster that EventGroup and in the application is used to organize interconnection from ISR level
functions to a RTOS-based tasks. For more information please refer to the FreeRTOS documentation
[www.freertos.org].
For the purposes of unification, all tasks (top-level applications and sub-levels), which are capable to receive
signals are defined as task_signal_t structures in the global app structure. Example of the code is below.
In the code, in the app structure, task handlers and signals are defined as follows:
4 TOP-LEVEL APPLICATIONS
There are four top-level applications, listed in the Table 6, which can run in the dedicated mode on the node
platform. Every top-level application consists from a task (or a number of tasks) and a set of non RTOS based
functions to implement an application’s functionality.
As described in section 1.1, the PDoA node hardware employs two DW1000 IC. The same physical clock is
provided to both DW1000 to enable their receivers to operate using the synchronous timings. One of the
DW1000 is used in the role of “Master” where it is in the reception state most of the time. The “Master” chip is
also used to transmit, as “Responder” in the Two-Way-Ranging process, see 6.1. The other DW1000, the
“Slave”, is in the reception state only for the reception of the Final message in TWR exchange process,
otherwise it is in the idle state.
The PDoA node supports more than one tag ranging to it. To prevent interference between these tags, a
Time-Division Multiple Access method (TDMA) is employed to separate the tags’ ranging exchanges into
individual “slots” within a repeating "superframe" structure, specified by the PDoA node, see 4.1.3.
Initially each tag sends only blink messages to advertise itself and be discovered by the PDoA node. For the
tag, see [3], this is called the Discovery phase. After sending the blink, the tag awaits a Ranging Config response
from the PDoA node, and upon its successful reception, the tag configures itself, as instructed by the Ranging
Config response, to range to the PDoA node in a designated slot.
The PDoA node only ranges to tags that appear in its KList, which is a list of known tag IDs (and their
configuration parameters) that are authorised to communicate to the PDoA node.
When the PDoA node receives a blink from a tag which is not in the KList, it reports this via the “newTag” report,
sent over the USB/UART (e.g. to the to the connected PC application). The new tag may be added to the KList
using the “ADDTAG” command. When a blink is received from a tag that is in the KList, the PDoA node
immediately responds with a Ranging Config response, assigning a slot to the tag for its future TWR exchanges.
The SAVE command which saves the PDoA node configuration also saves the current KList. The “DELTAG”
command, can be used to remove a tag from the KList. See Table 5 for more details.
As noted above, after sending a blink, receiving of a Ranging Config and been configured, the tag is going to
the Ranging phase and starts periodic ranging exchanges to the node in its dedicated time slot. Every ranging
exchange the tag starts with sending of a Poll message (addressed to the PDoA node address, specified in the
Ranging Config message), awaits of a Response message from the PDoA node, and upon its successful
reception, replies with a Final message to complete the ranging sequence.
For reception of the Final message from the tag, the PDoA node configures both “Master” and “Slave” chips for
a reception. On successful reception of the Final, the node reads data from both chips, calculates distance and
phase difference between received Final messages, and reports result to the output. Figure 7 below shows a
high-level view to the Node application flow and more detailed description is giving in the section 4.1.2.
Is the tag in NO
the Klist?
YES
Final Blink NO
Is this a BLINK
message?
Poll
NO Is a tag the
one we are Setup and send to
ranging to? the tag a Ranging YES
Config response
YES
Is the tag in the YES
Setup and send to the
Read data tag a Reply Dlist?
from Master Response, using
and Slave Master DW1000.
DW1000s;
Calculate TOF In the tx_callback(), NO
and PDOA and setup delayed RX for
report it to Master and Slave Add addr64 to the DList
output DW1000s
Report to the output that a new
tag with addr64 has been
discovered
Before the PDoA node starts ranging to a tag, the tag needs to be added to a list specifying tags to which the
node is allowed to range with. This list of tags is called “known tags list” or KList.
Every record in the KList has all necessary information about each tag including: its 64-bit address, assigned
16-bit (short) address, assigned slot number, etc. This information is supplied to the tag in the Ranging Config
reply that the PDoA node sends in response to receiving the tag’s blink message. The KList can be saved and
it will then be available for use during autonomous working mode of the Node (i.e. after start up).
The user-commands “ADDTAG” and “DELTAG”, described in Table 5, are used to add and remove tag
information to/from the KList. The “GETKLIST” command is used to retrieve the KList information, e.g. by the
PC GUI application so that it can update the list of known tags in the system on its start up.
When the PDoA node receives a blink from a tag that is not present in the KList, the tag’s 64-bit address is
stored in a temporary “discovered” tags list, called DList. The “GETDLIST” command is used to periodically
retrieve the discovered tags information, e.g. by the PC GUI application, so that it can update its list of tags in
the system.
Note: The “GETDLIST” command also clears the discovered tags list in the PDoA node.
The maximum sizes for KList and DList can be found in the tag_list.h header file:
There is a set of RTOS tasks (threads) to implement the PDoA Node’s functionality above. On reception of the
Ev_Node_Task event, the Default task executes the node_helper() function, which configures all the HW to
operate for the Node top-level application, i.e. wakes up and configures the DW1000s chips to run with
configured UWB parameters and starts following sub-tasks: RxTask and CalckTask.
IRQ level
DW1000 IRQ:
rx_callback()
twr_responder_algorithm_rx()
Please note, the core tasks, i.e. Control, for input handling, and Flush, for output handling, are always running,
see sections: 2.1.2, 3.2.3, 3.2.4.
On reception of a UWB blink message in the RxTask it checks whether the sender is in the KList. If it is, the
RxTask sends to the tag the appropriate Ranging Config response, which describes to the tag its personal
run-time parameters, for it to use during the Ranging phase.
If the sender is not in the KList and is not yet in the DList, the RxTask reports that a new tag has been
discovered in the range (see the “NewTag” object in Table 5) and stores the tag’s 64-bit address in the
discovered tags list DList, that it will not be reported as “NewTag” to the output anymore, but only if the control
application will request for a “GETDLIST”, see Table 5.
Once a tag has been sent a Ranging Config response, it is expect that it will start ranging to the PDoA node,
i.e. it will periodically send a Poll message to initiate the ranging exchange in its configured time slot.
On reception of Poll message from a known tag, the PDoA node begins range to that particular tag, also node
send back to the tag a correction value in microseconds, of how far is the tag from its assigned slot, that the
tag can correct its internal processes and will range next time closer to the assigned slot, see 4.1.3 and 6.5.
On reception of Final message from the tag, the Node’s rxTask sends the mail using mailbox RTOS
mechanism to the lower priority calcTask, which will calculate and report the estimated distance, PDoA and X-
Y coordinates of the tag with respect to the Node.
4.1.3 The superframe, the wakeup timers and the tag’s slot correction
To ensure non-overlapping ranging exchanges for multiple tags, the PDoA node uses Time-Division Multiple
Access method (TDMA), to assign to every tag its own dedicated slot, of T_Slot duration, within the PDoA
node’s superframe period, see Figure 9.
Node s Superframe (n) Superframe (n+1)
Tag0 s Superframe
Slot 0 Slot 1 Slot 2 Slot 3 Slot 4 Slot 5 ... Slot N Slot 0 Slot 1
T_Slot T_Slot
rx delay
TX TX
Poll Final
R R
Node TX
Resp-
onse
Poll2Final
On the picture above, the R represents the RMARKER, which is the event nominated by the IEEE 802.15.4
UWB PHY standard for message time-stamping. The time the first symbol of the PHR launches from the
antenna (defined as the RMARKER) is the event nominated as the transmit time-stamp, see 6.1, 6.2, 6.3, [4].
The Poll2Final configuration value defined the rough time between transmissions of RMARKERS for Poll and
Final messages from the tag. Rx_delay is the time between tag’s end transmission of the Poll and its start of
reseption of a Response from a Node, see P2FDEL and RCDEL parameters in Table 3 above.
Note, the slot number zero is reserved and may be used for future enhancement of the system, for example
Node can beacon in this slot and Tag can listen for the beacon and be instructed to transmit only on allowed
time.
The PDoA node specifies the superframe period in the Ranging Config message which the tag saves in its
framePeriod_ms variable The PDoA node counts its local superframe period using a RTC wakeup timer,
configured to expire every pSfConfig->sfPeriod_ms. On expiry, the timer saves the clock value to the
gRtcSFrameZeroCnt, which indicates the start of Node’s internal superframe and is used in the slot
correction process, as described below.
The RTC in the PDoA node and the RTC in the tag have a small drift with respect to each other, so to
maintain the tag ranging in its assigned slot, every time the node receives a Poll from tag, it checks its receive
time against the expected receive time and includes in the ranging Response message a correction factor, the
slotCorr_us, which indicates the difference between the start of tag’s dedicated slot with respect to node’s
current start of superframe – gRtcSFrameZeroCnt and the actual arrival time of the Poll. Using this
slotCorr_us information, the tag adjusts its wakeup timer for the next period to send its Poll in the assigned
slot. For more details about slot correction method see section 6.5.
When the Control task receives the command “USPI <val>”, see Table 2, it sets the Ev_Usb2Spi_A_Task or
Ev_Usb2Spi_B_Task to the xStartTaskEvent. The Default task consumes the event, safely ends all running
tasks and starts Usb2Spi top-level application. There are two DW1000 chip on the PDoA node hardware. The
optional <val> parameter can be empty or “0”, or be set to “1”, and specifies the chip to run the Usb2Spi
application.
Once Usb2Spi top-level application has started, the Control task is switched to the “Data parser” mode, see 0,
where it passes the whole incoming USB/UART stream into the Usb2Spi task, which has the implementation
of the Usb2Spi protocol to control the DW1000 from an external application. This illustrated on the Figure 10
below.
USB_RX_IRQ:
CDC_Receive_FS()
[SIGNAL to Ctrl]
IRQ level [Signal]
APP level
APP level
Usb_process_run()
Usb_uart_rx()
NO is STOP in Data
mode received?
NO
Need to reply to
Data the PC?
Command mode [Signal to Usb2Spi]
or Data mode?
YES
YES
Command
port_tx() Set EventGroup event
Add reply to the
Report.Buf
Ev_Stop_All.
Command parser
This will be receiver by
Default task and will stop
all top-level applications
End
End
It would be possible to modify the system to include power save features and put DW1000 to sleep for the
periods of time when there no tag ranging is expected. This is out of the scope of current document.
The IMU task, see Figure 11, is started by node_helper() function and it uses a third SPI (i.e. different to
others, used to talk to the DW1000 ICs) to read the IMU sensor’s state periodically and determine whether the
PDoA node is moving or stationary. This task does not conflict with any top-level applications and can run at
the same time as any of them, if needed. This illustrated on the Figure 11.
If the PCREP configuration parameter is set to “1”, the PDoA node is reporting to the output the “SN” JSON
object, indicating whether the device is stationary or moving as well as accelerometer normalized values per
all 3 axis. The accelerometer readings are normalized to 1000 milli-g per axis. If PDoA node is not moving, it
sends last report, indicated PDoA node is stationary and after that it does not send reports to the output
unless the IMU task will detect movement again.
Wait IMU_READ_DELAY_MS
IMU task is NO
ON?
YES Imu_enabl
NO
ed ?
NO
Imu_enabl
ed ? YES
YES Stop_imu()
Stationary = run_imu();
imu_report(Stationary) to
the output.
Imu_enabled = start_imu()
This project is created using the Segger Embedded Studio IDE with Nordic SDK15. The Segger IDE
includes a full license to develop, debug and run applications targeting nRF52832 ARM MCU, which
is the MCU used onto the Decawave’s DWM1001 hardware platform.
Download and install the Segger Embedded Studio IDE from the following web site:
https://www.segger.com/products/development-tools/embedded-studio/
Unpack the source code to the, for example, “dw_pdoa_tag” folder. In the Segger IDE, choose File-
>Open Solution and select the project dw_pdoa_tag.emProject, located in the
examples\dw_pdoa_tag\ folder.
Connect the board to the PC. You may require to install J-Link drivers, which could be found on the
Segger web site:
https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack
Install J-Link Software and Documentation pack, which includes drivers and J-Flash Lite tool
needed for reprogramming new FW binary into tag.
To check if the target board is working select Target->Connect J-Link from the menu. To start the
TDOA Tag application select Build->Build and Run from menu.
If it was the first time you start your app you shall be asking for the licence. License is free for Nordic
MCU’S, please refer to the Appendix A – Installing a license for Nordic MCU for details.
6 APPENDIX A
6.1 Two Way Ranging algorithm
The tag (Initiator) periodically initiates a range measurement, while the node (Responder) listens and
responds to the tag and calculates the range. The ranging method uses a set of three messages to complete
two-round trip measurements from which the range is calculated. As messages are sent and received, the
message send and receive times are retrieved from the DW1000. These transmit and receive timestamps are
used to work out a round trip delay and calculate the range, see [4].
In the ranging scheme shown in Figure 12 below, the tag sends a Poll message which is received by the
PDoA node. The PDoA node replies with a response packets Resp, after which the tag sends the Final
message.
Tround1 Treply2
Tag time
Poll Resp Final
TX RX TX
RMARKER
Tprop Tprop Tprop
Node
Poll Resp Final
Master RX TX RX
Treply1 Tround2
Final
Slave RX
The Final message communicates the tag s Tround and Treply times to
the Node s Master, which calculates the range to the tag as follows:
Since the PDoA node also calculates the phase difference on the reception of the Final message between
Master and Slave chip, this means that the tag can be located relative to the node after just a single ranging
exchange.
The range and measured phase difference used by the node to work out tag’s X-Y position.
6.2 UWB configuration and TWR timing profile used in the PDoA system
The PDoA node and tags hardware and software are designed to operate on one UWB configuration. This
includes antenna designs, data rate and message timings, used in the TWR exchange. This specified in the
Table 7 below.
UWB Channel Data Preamble PRF Preamble SFD PHR PAC Smart Tx
Config Rate Length Code mode power
In the PDoA TWR timing profile, see Figure 13, there are two timing parameters, pollTxToFinalTx_us and
delayRx_us. The pollTxToFinalTx_us parameter, specifies the rough time between RMARKER of Poll
and RMARKER of the Final Tx messages for the tag, see 6.1. The delayRx_us parameter specifies the
rough time, the Tag shall activate its receiver after transmission of the Poll in order to receive the Response
from the PDoA node, see Figure 13.
Preamble Data
delayRx_us
Node s State
Response
2450
RX ON – FRAME RX
Chip B IDLE IDLE
The significant event making the TX and RX times is specified in IEEE 802.15.4 [4] as the “Ranging Marker
(RMARKER): The RMARKER is defined to be the time when the beginning of the first symbol of the PHR of
the RFRAME is at the local antenna. The time stamps should reflect the time instant at which the RMARKER
leaves or arrives at the antenna. However, it is the digital hardware that marks the generation or reception of
the RMARKER, so adjustments are needed to add the TX antenna delay to the TX timestamp, and, subtract
the RX antenna delay from the RX time stamp. This is done automatically by DW1000, as long as the TX and
RX antenna delays are configured.
The PDoA node uses configurable antenna delay values (which are initially defined in the default_config.h
file). The values have been experimentally set by adjusting them until the average reported distance is the
measured distance. This can be re-programmed in the FConfig by using a corresponding control command
interface, see 3.2.3.3.
Note:
The messages follow IEEE message encoding conventions, but these are not standardised RTLS messages.
The reader is referred to the ISO/IEC 24730-62 international standard for details of standardised message
formats for use in RTLS systems based on IEEE 802.15.4 UWB. This may be changed in future software
revisions.
Initially a tag transmits Blink messages using the shortest IEEE blink message format. This is an optimized
blink message which also can be used for TDOA (Time Difference of Arrival) location methods. The encoding
of the blink message is as per Figure 14 below.
0xC5 - -
During initial blinking the tag has only long 64-bit address. To maintain shortest timings, the PDoA node
assign to the tag a temporary short address using Ranging Config response. Thus, for Ranging Config
message to be delivered to the tag, the short-long addressing mode is used. This is shown on the Figure 15
below.
The PAN ID of the PDoA system and the PDoA node’s 16-bit addresses are in the MAC header, and the rest
is in the Ranging Config Data field: tag’s new 16-bit address and its configuration parameters. The description
of Ranging Config Data part of a range_init_msg_t structure is given in the Table 8.
During the Two Way Ranging, the tag and node use short (16-bit) addressing modes. The format of the
ranging frames, which are Poll, Response and Final is shown in Figure 16 below.
Frame buffer indices: 0, 1 2 3, 4 5 to 6 7 to 8 9 and up
The content of the Two Way Ranging Data portion of the frame, defined by a first octet, identifies the type of
the Ranging message: Poll, Response or Final, as per Table 9 below.
The Poll message structure defined in the code as a structure of type poll_msg_t. This sent by the tag to
initiate a Ranging sequence. Table 10 describes the individual fields within the Poll message.
The Response message structure is defined in the code as a structure of type resp_msg_t. This sent by the
node as a Response to a Poll from the tag. Table 11 describes the individual fields within the Response
message.
The Final message is a structure of type final_msg_t and it sent by the tag after receiving the PDoA node’s
Response message. Table 12 lists and describes the individual fields within the Final message.
The tag’s RTC timer is intended to keep the tag transmitting in its assigned TDMA slot. Every time the tag is
starting a Poll frame, the timer is configured to expire every wakeUpPeriodCorrected_ns, which holds the
value, of the duration of the tag’s superframe – note this is in the tag’s time and not in the PDoA node’s time
domain (the value is close to the PDoA node’s superframe period, but may vary). If the tag is not intended to
range on the next expiration of the timer (i.e. when the tag is configured to range less frequently than every
superframe), the timer will keep expiring every wakeUpPeriodCorrected_ns until tag decides it is time for
the next ranging exchange.
On the reception of the Response message from the PDoA node, the tag receives the slotCorr_us, which
specifies the time where the PDoA node has expected the reception of the tag’s Poll with respect to the start
of the node’s superframe (gRtcNode), see Figure 17. Upon reception of the Response, the
nextWakeUpPeriod_ns is calculated as follows:
The method above includes the correction of the time needed for the tag to wake up and initiate transmit the
Poll message, so that for the next transmission the RTC should wake up the MCU at the correct time for the
pollTask to execute and transmit the Poll message.
TAG
Set the standard nextWakeUpPeriod_ns gRtcTag
Wakeup time to the
gRtcTag ~SF Period Expected PollRxRtcNode_us
pollTxRtcTag pollTxRtcTag
TX
pollTxFinalTx_us
respRxRtcTag
RX
ReplyDelay_us
NODE: chip A
gRtcNode gRtcNode
Expected
pollRxRtcNode
TX
Next poll
Assigned slot to shall be
earlier this Tag s Poll
the Tag s Poll:
time. within the
slot missed or not
slotCorr_us assigned slot
very accurate
Actual
pollRxRtcNode
RX
With the reference to the figures, the main blocks are as follow:
1. Initialization of the hardware and peripherals. This includes initialization of MCU peripherals (like
UART, SPI, I2C etc), initialization of DW1000 chips, loading configuration data from NVM into RAM.
2. RTOS based functionality. This includes the FreeRTOS kernel, and all files with prefix “task_”. This
separates the functionality of the applications, and aids in the management of MCU time more
effectively and makes the code design cleaner at the expense of a small increase in latency. This
adds an “application” layer, sitting on the top of bare-metal implementations.
3. Bare-metal implementation of functionality: callbacks, tx_start, usb_uart_rx, usb_uart_tx, etc.
The source files are organized to match the architecture of the application, see section 2.2 and section 6.7.
SETUP THREADS - Extract rxPckt from buffer; - On reception of Final msg: - Calculate the tag s slot correction time,
- Execute twr_responder_algorithm_rx(); . Check if tag is in known_tag_list using PollRx_RTC_ts, tag s slot number and
- Default thread. .If Final message received, send a mail to . Read phase and range data from chip gRtcSFrameZeroCnt;
1.1
- Control thread. calculate distance and pdoa; . Report to application app - Send Delayed response Tx;
- Flush thread.
Signal get_tag64_from_knownTagList()
Calculation Thread (calcTask) - If the tag s addr64 is not in the KList, then:
START SCHEDULER . Add the addr64 to the DList;
- Wait for the mail with raw data to . Signal to the output that a NEW_TAG has
AP-DWM1002-PDoA-Node-Source-Code-Guide-
calculate Distance & PDoA. been discovered;
. Return NULL;
Src/bare/node.c
Page 38
IMU Task Src/bare/node.c
EVENT: start User app Call RX callback from DWT_ISR()
- Program IMU sensor;
- Periodically read IMU data; twr_tx_node_cb()
- Report to PC GUI that Node is
stationary or moving; - Save TxTimestamp and RTC Tx Time for Response;
DW1000 power manager()
- set Delayed Rx time for both DW_A and DW_B chip
Src/task/task_imu.c Manually put DW1000 to for expected receive of Final;
1.1
Src/task/task_usb2spi.c
RTC
cdc_acm_user_ev_handler()
Report Buffer flush Task (Callback from USB driver)
RTC: resolution 30.5175 us;
- Wait signal to empty the Report Maximum count 16777216.
Buffer;
- Periodically check and empty the - Add chunk of data from
Src/bare/usb_uart_tx.c driver to the USB RX buffer;
Report Buffer
- Signal USB Received.
AP-DWM1002-PDoA-Node-Source-Code-Guide-
Src/task/task_flush.c - Check USB TX circular buffer;
TCFM user application Task Blocking transaction. In general, RTOS CAN interrupt this.
USB CDC TX
- Kill all tasks which can interact to If calling from Application level, must be protected by RTOS Mutexes.
shared resource: DW1000. Src/bare/tcfm.c If calling from ISR level – not need to be protected.
- Run CFM test mode; Transmit 64 bytes
- Init CFM test mode process;
- Run CFM test mode process;
Src/task/task_tcfm.c
- Stop CFM test mode process; port/Deca_usb.c
Page 39
Dw1000_spi.c
DWM1002 PDoA Node Source Code Guide
Table 13 List of core files and directories in the node ARM application
7 BIBLIOGRAPHY
Ref Author Title
[1] Decawave DW1000 Data Sheet
[2] Decawave DW1000 User Manual
[3] Decawave PDoA Tag Source Code Guide
IEEE 802.15.4‐2011 or “IEEE Std 802.15.4™‐2011” (Revision of
IEEE Std 802.15.4-2006).
IEEE Standard for Local and metropolitan area networks— Part 15.4: Low-
[4] IEEE Rate Wireless Personal Area Networks (LR-WPANs). IEEE Computer
Society Sponsored by the LAN/MAN Standards Committee.
Available from http://standards.ieee.org/
8 DOCUMENT HISTORY
Table 14: Document History
9 FURTHER INFORMATION
Decawave develops semiconductors solutions, software, modules, reference designs - that enable real-time, ultra-
accurate, ultra-reliable local area micro-location services. Decawave’s technology enables an entirely new class of easy
to implement, highly secure, intelligent location functionality and services for IoT and smart consumer products and
applications.
For further information on this or any other Decawave product, please refer to our website www.decawave.com.