Skip to content

TDMA over ESB #135

@Eirenliel

Description

@Eirenliel

This is a design document of implementing TDMA (Time-Division Multiple Access) for nRF trackers that I do in tdma branches of both dongle and tracker. The branches require our SDK fork, see post below on how to build it.

Here I collect current state, plans and TODOs. This will be used in the future to write documentation on how the protocol works.

General Info

  • Hardware ID - 6 bytes unique device address (not guaranteed, see datasheet (link?)) fetched from FICR DEVICEADDR registers
  • Tracker ID - 1 byte, unique incremental ID of a tracker connected to each dongle. Trackers on different dongle can share this ID, it's just a dongle-specific shortcut
  • Address - ESB address, 4 bytes. Devices on the same address and channel can talk to each other. We use 2 addresses: one shared for pairing, another unique for each dongle based on dongle's Hardware ID.
  • Pipe - ESB pipe, we only use 2. Pipe 0 for pairing, search and dongle broadcast, Pipe 1 for data exchange. Other pipes might be used in the future or could be used for debugging. Pipes 1 to 7 share addresses, Pipe 0 has the same address for all devices 0x62, 0x39, 0x8A, 0xF2.
  • Address Prefix prefix for all ESB packets. 8 bytes, 0xFE, 0xFF, 0x29, 0x27, 0x09, 0x02, 0xB2, 0xD6

Pairing

  • TODO: Pairing packets are not implemented in tdma yet, right now it uses old packet structure.
  • If dongle clears pairing and then we start re-pairing trackers, previously paired trackers could start interfering with the process by sending packets to the same tracker id. (See below in TODO).
  • If two dongles are on the same channel as the tracker and you try to pair, both dongles will accept the pairing request and save the tracker, though a tracker will only send packets to one of them

Pairing packet is sent to Pipe 0 on a shared address 0x62, 0x39, 0x8A, 0xF2. They all share preamble 0xCD.

Packet 1 - request from tracker:

Bytes 0 1 2 3-9 10-16
Information 0xCD 0x01 0x00 Tracker Hardware ID Tracker Hardware ID
Packet 2 - pairing accepted from dongle:
Bytes 0 1 2 3-9 10-16
Information 0xCD 0x02 Tracker ID Dongle Hardware ID Tracker Hardware ID
Bytes 2-8 are set to Tracker's Hardware ID when sent to Dongle, but to Dongle's Hardware ID when it's returned. Dongle should keep Tracker Hardware ID to make sure the tracker receives its own packet.

Timing And Channels Hopping

Air time and packets exchange is split onto Slots. Every slot is 32 cycles long (1/32768th of second), which can be timed by calling to k_cycle_get_32() & 0x7FFF. There are 1024 slots in every second.

  • TODO: Will test having more slots in the near future. We now have more precise timer and may be able to double the slots amount, or at least x1.6
    • At least try to reach 122 packets/s for each tracker to have 120Hz of tracking data +2 status packets
    • At worst try to reach 101 packets/s for each tracker to have 100Hz of tracking data +1 status packet (can just reduce advertisement section by 10 slots)
  • Unpaired trackers, or trackers that lost connection should move to Channel 0 and wait for dongles broadcast on Slot 0 to know which channel to use to continue or to pair to
  • Just booted dongles should listen for 2 seconds to Channel 0 to detect other dongles
  • If they detect Dongle State (3) packet, they should advance their channels bundle to not interfere with other dongles in the area. After 2 seconds Dongle starts normal operation in Slot 0.
  • A dongle should free the window from a tracker if it didn't receive packets from it in 1 minute or so and send Disconnected to the server.

Slots 0-23

Dongle moves to Channel 0 and broadcasts on Pipe 0 its current status without ACK.

Packet 3 - Dongle State

Bytes 0 1 2-8 9[0:0] 9[1:1] 10[0:3] 10[4:7]
Information 0xCD 0x03 Dongle Hardware ID Accepts new trackers? Force pair Channels bundle Next channel offset
  • Accepts new trackers? - 0/1 bit, 1 if the dongle has empty slots to accept new tracker pairings
  • Force pair - 0/1 bit, tells unconnected trackers to pair to this dongle even if they have pairing information saved
  • Channels bundle - 4 bits - which channels bundle this dongle hops on
  • Next channel offset - 4 bits - which channel bundle this dongle will move next after this broadcast

The dongle sends the state packet 10 times and then continues to Slots 24+ according to the time left.

  • Measure the time it takes to actually do all the switching and reduce the amount of slots used for this to free more space for the trackers and to have less stutter during these 24ms gaps

Slots 24-1023

On slots 24 to 1023 the dongle accepts and replies to packets received from trackers. The dongle will try to process any packet it receives, even if it's not in the correct slot.

Every tracker is assigned a window 0 to 9 when they it can send packets to the dongle. If dongle receives a packet from a tracker that doesn't have a window assigned at the time, the dongle will try to allocate a free window to it. If there are no empty windows, it will reply with No Windows (4) packet.

Each tracker is allocated 100 slots according to their window, one window every 10 slots starting with slot 24. Current window by the time can be calculated as (t >> 5 - 24) % 10 where t is the current time in cycles.

Packet 4 - No Windows

Bytes 0 1
Information 0xCD 0x04
  • A tracker that received No Windows (4) packet could try looking for another dongle (TBD).

If a tracker already has or just received a window, the dongle will reply with Window Info (5) packet that includes information about the tracker's window and dongle's timer to synchronize the clock between the dongle and the tracker.

Packet 5 - Window Info

Bytes 0 1 2 3-6 7
Information 0xCD 0x05 Window Timer Packet Number
  • Window - 1 byte, trackers assigned window

  • Timer - 4 bytes, time in cycles passed from Slot 0 start

  • Packet Number - 1 byte, packet sequence that this packet is a reply to (only for data packets with packet number)

  • If the tracker didn't miss the window, dongle can send other information to it, like in Data Packets section. The dongle will always try to correct the window first before sending any data.

After receiving Window Info (5) packet, the tracker must adjust its timings to better hit the window. It does so by adjusting its timer offset to better match Dongle's Slot 0 with its own, but it will only move the offset by half the calculated difference. See NTP for details of the algorithm.

The tracker can apply static offset equal to the time it requires to initialize the data sending to better hit the start of the slot.

Data Packets

  • Rework data packets
    • Add header prefix
  • Why do we send packet 0 so often? Reduce to 1/second + once on reconnect
  • Statistics tracking on dongle and on server - missing packets Packet loss SlimeVR-Server#1687

TODO

  • Track trackers that went to sleep or lost connection
    • Report when trackers reboot for any reason so we could ask user to reset
    • Show it in the server, free dongle windows, etc.
  • Ghost trackers (related to address reports sent?)
    • Related to the fact that the server receives tracker 0 packet from somewhere, maybe some other tracker is secretly paired to the dongle and sends something?
    • Tracker 0 sometimes doesn't display battery, ping and signal quality on the server, blinking on and off
  • No way to fail properly when the tracker has no windows remaining but the tracker is paired to it
    • Paired slots should be equal to window slots. Why do we need to be able to pair more devices to the dongle than we have window slots?
    • Communicate with the tracker before allocating windows to it and start sending packets. Check that it's paired to this dongle. Reply with Not Paired if the tracker isn't paired and there are no windows or slots
      • If the tracker doesn't have a window, ask it to send us info about it to check if it's paired.

Metadata

Metadata

Assignees

Labels

UrgentThis needs to be fixed ASAP.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions