aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-05-10 20:28:24 +0200
committerlonkaars <loek@pipeframe.xyz>2022-05-10 20:28:24 +0200
commitcbf90c6983e2dfe90a9c5f607a5978d76565fefe (patch)
tree4ed715fc48538042a829445da5f9010967a58b02
parentaaf6d7963314c1fcb86b84442cd3d960bc87297b (diff)
added updated protocol spec
-rw-r--r--protocol.md317
-rw-r--r--robot/readme.md8
2 files changed, 233 insertions, 92 deletions
diff --git a/protocol.md b/protocol.md
index 0317d05..f5bb0cc 100644
--- a/protocol.md
+++ b/protocol.md
@@ -2,13 +2,11 @@
under construction!
-## client/robot
-
the included wixel is used for bidirectional wireless serial data transfer. it
has built-in error correction and other features that make sure data gets to
the robot losslessly, so data loss is not accounted for.
-### important constants
+## important constants
|property|value|unit|
|-|-|-|
@@ -16,148 +14,297 @@ the robot losslessly, so data loss is not accounted for.
|max byte timeout|5|ms|
|byte order|big-endian|-|
-### commands
+## commands
-each command consists of an opcode, and then a payload. each opcode defines
-logic to handle payload length, so certain commands might expect a fixed-length
-payload, a variable-length payload, or none at all.
+each command consists of a start byte, opcode, and a payload. each opcode
+defines logic to handle payload length, so certain commands might expect a
+fixed-length payload, a variable-length payload, or none at all. the start byte
+is `0xff`, and because most data sent is in binary format, if the data contains
+an `0xff` byte, it will be escaped by replacing it with two `0xff` bytes. this
+is converted to a single `0xff` on the receiving end, so these duplicated bytes
+and the starting byte don't count towards message length.
-opcodes are picked sequentially, but bit 0 is reserved to indicate a transfer
-from robot to client. this means that the opcode for a sensor data request
-would be `0x14`, but the response opcode would be `0x15`. a c header is
-provided that contains consts of these opcodes for code readability.
+opcodes are picked sequentially, but the direction bit (LSB) is reserved to
+indicate a transfer from robot to client. this means that the opcode for a
+sensor data request would be `0x12`, but the response opcode would be `0x13`.
+these opcodes are stored as enum constants inside consts.h for code
+readability.
|code|name|implemented|directions|full name|
|--:|---|:-:|:-:|---|
-|`0x00`|[BOMD](#bomd)|no|`r <=> c`|<u>b</u>ack<u>o</u>rder <u>m</u>o<u>d</u>ify
-|`0x00`|[CORD](#cord)|no|`r <=> c`|<u>co</u>o<u>rd</u>inate
-|`0x00`|[EXFL](#exfl)|no|`r <-- c`|<u>ex</u>ecution <u>fl</u>ow
-|`0x00`|[SRES](#sres)|no|`r <-- c`|<u>s</u>oft <u>res</u>et
-|`0x00`|[EXPT](#expt)|no|`r --> c`|<u>ex</u>ce<u>pt</u>ion
-|`0x00`|[SPED](#sped)|no|`r <-- c`|<u>spe</u>e<u>d</u>
-|`0x00`|[DIRC](#dirc)|no|`r <-- c`|<u>dir</u>ect <u>c</u>ontrol
-|`0x00`|[DISP](#disp)|no|`r <-- c`|<u>disp</u>lay control
-|`0x00`|[SENS](#sens)|no|`r <=> c`|<u>sens</u>or data
-|`0x00`|[MAPS](#maps)|no|`r <-- c`|<u>map</u> <u>s</u>end
|`0x00`|[PING](#ping)|no|`r <=> c`|<u>ping</u>
-|`0x00`|[PLAY](#play)|no|`r <-- c`|<u>play</u> midi
-|`0x00`|[CLED](#cled)|no|`r <-- c`|<u>c</u>ontrol <u>led</u>s
+|`0x02`|[EXPT](#expt)|no|`r --> c`|<u>ex</u>ce<u>pt</u>ion
+|`0x04`|[MODE](#mode)|no|`r <=> c`|<u>mode</u>
+|`0x06`|[SPED](#sped)|no|`r <-- c`|<u>spe</u>e<u>d</u>
+|`0x08`|[DIRC](#dirc)|no|`r <-- c`|<u>dir</u>ect <u>c</u>ontrol
+|`0x0a`|[CORD](#cord)|no|`r <=> c`|<u>co</u>o<u>rd</u>inate
+|`0x0c`|[BOMD](#bomd)|no|`r <=> c`|<u>b</u>ack<u>o</u>rder <u>m</u>o<u>d</u>ify
+|`0x0e`|[SRES](#sres)|no|`r <-- c`|<u>s</u>oft <u>res</u>et
+|`0x10`|[MCFG](#mcfg)|no|`r <-- c`|<u>m</u>ap <u>c</u>on<u>f</u>i<u>g</u>
+|`0x12`|[SENS](#sens)|no|`r <-> c`|<u>sens</u>or data
+|`0x14`|[INFO](#info)|no|`r <-> c`|<u>info</u>
+|`0x16`|[DISP](#disp)|no|`r <-- c`|<u>disp</u>lay control
+|`0x18`|[PLAY](#play)|no|`r <-- c`|<u>play</u> midi
+|`0x1a`|[CLED](#cled)|no|`r <-- c`|<u>c</u>ontrol <u>led</u>s
+
+the DISP, PLAY, and CLED commands have low implementation priority, and should
+be considered extra features
+
+a double stroke arrow means that the command can be initiated from either the
+robot or the client, while a single arrow indicates a request-response
+structure.
+
+### PING
+
+#### ping (`r <=> c`) (2 bytes)
+
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x00 + 0` or `0x00 + 1`)|
+|`uint8_t`|ping id|
+
+**ping** sends back an identical message either way with the direction bit
+toggled. _ping id_ is a random 8-bit value that makes sure the same ping
+doesn't keep bouncing back and forth indefinitely.
+
+### EXPT
+
+#### exception (`r --> c`) (3+ bytes)
+
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x02 + 1`)|
+|`uint8_t`|error code|
+|`uint8_t`|length|
+|`uint8_t[length]`|message contents|
+
+the **exception** instruction is used by the robot to send errors, warnings,
+and other messages back to the client. an error can also optionally contain a
+message between 0 and 255 characters long. message length is sent before the
+message, and can be 0 in case of no message.
+
+### MODE
+
+#### set mode (`r <-- c`) (2 bytes)
-#### BOMD
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x04 + 0`)|
+|`uint8_t`|mode code|
-##### backorder append
+when initiated from the client, the **mode** command forces the robot to change
+execution mode. the mode codes are undetermined as of now.
-- length: 2 bytes
-- client to robot
+#### get mode (`r --> c`) (2 bytes)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 0`)|
-|`uint8_t`|action|
+|`uint8_t`|opcode (`0x04 + 1`)|
+|`uint8_t`|mode code|
-_action_ is a byte containing `0bXXXXXXYY` where X+1 is the amount of times
-action Y gets repeated. Y can be:
-- 0: move 1 tile forward
-- 1: move 1 tile backward
-- 2: turn right 90°
-- 3: turn left 90°
+the **mode** command is send by the robot when it switches into another mode.
+the mode codes are undetermined as of now.
-examples:
-- move forward 4 tiles: `0b00001100` (`0x10`)
-- turn 180°: `0b00000110` (`0x06`) or `0b00000111` (`0x07`)
+<!-- TODO: mode codes in client and robot -->
-##### backorder index
+### SPED
-- length: 9 bytes
-- robot to client
+#### set speed modifier (`r <-- c`) (2 bytes)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 1`)|
-|`uint32_t`|backorder buffer length|
-|`uint32_t`|backorder buffer index|
+|`uint8_t`|opcode (`0x06 + 0`)|
+|`uint8_t`|speed modifier|
-#### CORD
+scales motor output power from 0% (0x00) to 100% (0xff).
-##### set position
+### DIRC
-- length: 6 bytes
-- client to robot
+#### set motor speed (`r <-- c`) (5 bytes)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 0`)|
+|`uint8_t`|opcode (`0x08 + 0`)|
+|`int16_t`|left motor speed|
+|`int16_t`|right motor speed|
+
+directly set left and right motor speed values. only works in direct control
+mode (unimplemented!). motor values range from -255 to 255. speed is sent as a
+signed 16-bit integer (`short`).
+
+### CORD
+
+#### set position (`r <-- c`) (6 bytes)
+
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x0a + 0`)|
|`uint32_t`|position|
|`uint8_t`|orientation|
-_position_ = y * width + x
+manually correct robot position and orientation in grid portion of the map.
+
+_position_ = y * width + x
_orientation_:
- 0: west
- 1: north
- 2: east
- 3: south
-##### get position
-
-- length: 6 bytes
-- robot to client
+#### get position (`r --> c`) (6 bytes)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 1`)|
+|`uint8_t`|opcode (`0x0a + 1`)|
|`uint32_t`|position|
|`uint8_t`|orientation|
-_position_ = y * width + x
+sent by the robot in the grid portion of the map when a transition to a new
+_position_ is finished.
+
+_position_ = y * width + x
_orientation_:
- 0: west
- 1: north
- 2: east
- 3: south
-#### EXFL
+### BOMD
+
+#### append order (`r <-- c`) (9 bytes)
+
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x0c + 0`)|
+|`uint32_t`|order identifier|
+|`uint32_t`|position|
+
+add a new order to the backorder list (queue).
+
+_position_ = y * width + x
+
+#### order status (`r --> c`) (6 bytes)
+
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x0c + 1`)|
+|`uint32_t`|order identifier|
+|`uint8_t`|status|
+
+sent by the robot in the grid portion of the map when the status of an order
+changes. also used to confirm orders are received successfully.
+
+_status_ is one of:
+- 0: received
+- 1: processing (begin)
+- 2: reached
+- 3: finished
+
+### SRES
+
+#### soft reset (`r <-- c`) (2 bytes)
-##### set execution flow
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x0e + 0`)|
+|`uint8_t`|type|
+
+_type_ is one of:
+- 0: reinitialize all global state
+- 1: reset emergency mode
+
+### MCFG
-- length: 2 bytes
-- client to robot
+#### configure map (`r <-- c`) (4+ bytes)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 0`)|
-|`uint8_t`|action|
+|`uint8_t`|opcode (`0x10 + 0`)|
+|`uint8_t`|width|
+|`uint8_t`|height|
+|`uint8_t`|length|
+|`feature[length]`|features|
+
+> _feature_ is a struct containing:
+>
+> |type|description|
+> |-:|-|
+> |`uint16_t`|position|
+> |`uint8_t`|kind|
+>
+> where _position_ = y * width + x
+> and _kind_ = 0bXXYYYYYY where X = _orientation_ and Y = _type_
+>
+> _orientation_:
+> - 0: west
+> - 1: north
+> - 2: east
+> - 3: south
+>
+> _type_:
+> - 0: entrance / exit
+>
+
+sends the map layout to the robot. the map is an automatically generated grid
+of the specified size, starting at coordinates (1, 1) to keep a margin around
+the grid for the maze-grid transition.
+
+example hexdump of 5x5 map with a north-facing entrance/exit at (3, 0) for
+later reference:
+```
+10 05 05 01 00 03 40
+```
+
+### SENS
+
+#### request sensor data (`r <-- c`) (1 byte)
-_action_ is:
-- 0: suspend all operation
-- 1: resume operation
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x12 + 0`)|
-#### SRES
+requests sensor data
-##### soft reset
+#### sensor data response (`r --> c`) (??? bytes)
-- length: 1 byte
-- client to robot
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x12 + 1`)|
+|`???`|???|
+
+sensor data response. contains all sensor data (distance, ir, buttons) in one
+packet. format yet to be determined.
+
+### INFO
+
+#### request robot info (`r <-- c`) (1 byte)
|type|description|
|-:|-|
-|`uint8_t`|opcode (`0x00 + 0`)|
+|`uint8_t`|opcode (`0x14 + 0`)|
-#### EXPT
-#### SPED
-#### DIRC
-#### DISP
-DCLR display clear
-DPOS display cursor position
-DWSR display write string
-DWBM display write bitmap
-#### SENS
-#### MAPS
-#### PING
-#### PLAY
-#### CLED
+requests robot info
+#### robot info response (`r --> c`) (41 bytes)
-## client/websocket
+|type|description|
+|-:|-|
+|`uint8_t`|opcode (`0x14 + 1`)|
+|`uint8_t[32]`|build string|
+|`uint8_t`|errcatch module cycle time (ms)|
+|`uint8_t`|io module cycle time (ms)|
+|`uint8_t`|sercomm module cycle time (ms)|
+|`uint8_t`|modes module cycle time (ms)|
+|`uint32_t`|total robot uptime (s)|
+
+robot info response
+
+<!--
+### DISP
+- DCLR display clear
+- DPOS display cursor position
+- DWSR display write string
+- DWBM display write bitmap
+-->
-TBD
diff --git a/robot/readme.md b/robot/readme.md
index fa5774c..ebf2e3c 100644
--- a/robot/readme.md
+++ b/robot/readme.md
@@ -100,7 +100,7 @@ global todo:
- [ ] clear global timer at start of cycle instead of just for mode selection
module (for last ping time measurement)
- [ ] calibrate (line-detecting) light sensors in setup.c, or manually by
- placing the robot and pressing a button
+ placing the robot and pressing a button (maybe make this a seperate mode)
### hypervisor
@@ -109,9 +109,6 @@ provides all other modules with a central place for defining global variables.
### pc communication
-> this mode can't be implemented until the pc-communication protocol spec is
-> finished
-
the pc communication module sends messages in a binary format over the serial
connection provided by the wixel modules. this module should also send a 'ping'
command each cycle to check if the connection is still intact. the pc will also
@@ -190,9 +187,6 @@ implementation details for this mode are yet to be determined.
### emergency stop
-> this mode can't be implemented until the pc-communication protocol spec is
-> finished
-
the emergency stop mode stops the robot from doing anything until the user
determines it is safe to resume execution.