diff --git a/docs/spec.org b/docs/spec.org
index 94dab39417ae8d79f1a6baa7a735014eb27f960e..67d22dd89a1dad6d3a597b923e305cfd70e64d2b 100644
--- a/docs/spec.org
+++ b/docs/spec.org
@@ -2,28 +2,36 @@
 #+AUTHOR: Qiyang Sun
 #+EMAIL: qs2g22@soton.ac.uk
 
-* TODO [0/2]                                                       :noexport:
+* TODO [4/7] [57%]                                                 :noexport:
  - [ ] In the state diagram the * and @ are exchanged relative to the
    description text.
- - [ ] We can probably also make it such that a start marker is active
+ - [X] We can probably also make it such that a start marker is active
    only if it is the largest marker in view.
- - [ ] we can indicate with < and > in case the vision system has a
+ - [X] we can indicate with < and > in case the vision system has a
    suggested direction where to turn to, to look for markers.
- - [ ] it may be best to output another character to indicate a
+ - [X] it may be best to output another character to indicate a
    stand-by mode. What do you think about a dot (.) or a dash (-)
+ - [X] add countdown 9..0
+ - [ ] update automaton [0%]
+   - [ ] redraw latex
+   - [ ] rewrite description
+ - [ ] Fix language, and try to follow [[https://www.rfc-editor.org/rfc/rfc7322.txt][RFC7322]] [0%]
+   - [ ] check spelling and grammar
+   - [ ] add sections
+   - [ ] format export
 
 * Commit and Push Script                                           :noexport:
 
-#+BEGIN_SRC bash
-  rm ./spec.txt
-  rm ./spec.html
+#+BEGIN_SRC bash :results output silent
+  rm -f ./spec.txt
+  rm -f ./spec.html
 #+END_SRC
 #+RESULTS:
 
-#+BEGIN_SRC bash
+#+BEGIN_SRC bash :results output silent
   git add spec.org
-  git commit -S -m "Update spec, add todo"
-  #git push
+  git commit -S -m "Update spec, add state and output section"
+  git push
 #+END_SRC
 #+RESULTS:
 
@@ -59,7 +67,9 @@ can be configured.
 
 * Messaging Protocol
 
-Expected output pattern in regexp: ~[a-zA-Z\?!\*@]*~ (backslash used to
+** Synopsis
+
+Expected output pattern in regexp: ~[a-zA-Z\?!\*@<>0-9]*~ (backslash used to
 escape occurrence indicators).
 
 Characters ~a~ -- ~z~ (ASCII 97--122) and ~A~ -- ~Z~ (ASCII 65--90)
@@ -76,19 +86,10 @@ Extra messages are defined as follow:
 - ~*~ (ASCII 42): Start marker is seen.
 - ~@~ (ASCII 64): Goal marker is seen.
 - ~.~ (ASCII 46): Standby.
-- ~<~ (ASCII 60):
-- ~>~ (ASCII 62):
-
+- ~<~ (ASCII 60): Suggest left turn.
+- ~>~ (ASCII 62): Suggest right turn.
 
-If the vision module sees a Goal marker, then ~@~ is continuously
-being output until the vision module sees a Start marker and output
-~*~.
-
-A Start marker is considered to be seen *if* the Start marker comes
-into view, regardless the distance to the camera. A Goal marker is
-considered to be seen *if and only if* there are no more gates closer
-to the camera, i.e., the Goal marker is the closest valid marker in
-view.
+** State Machine
 
 The state machine diagram (similar to a finite state automaton) of the
 protocol can be found in the graph below.
@@ -115,6 +116,69 @@ at any time.
 | $n$        | No valid markers seen                                    |
 | $s$        | Sees Start marker                                        |
 
+** States and Output
+
+*** Boot Phase
+
+During the boot phase, the release version of the system may output
+countdown (~9~ -- ~0~) that indicates the boot progress. After a
+successful boot, the vision board will enter Standby state.
+
+*** Standby State
+
+After the embedded Linux successfully boot and the vision program is
+started, it enters Standby state and wait for the start marker. In this
+state, ~.~ is continuously being output.
+
+*** Start State
+
+A Start marker is considered to be seen *if* the Start marker comes
+into view, regardless the distance to the camera. If the Start marker
+is seen, then Start state is entered until the Start marker is no
+longer seen in view. In this state, ~*~ is continuously being output.
+
+*** Goal State
+
+A Goal marker is seen *if and only if* there are no more gates closer
+to the camera, i.e., the Goal marker is the closest valid marker in
+view. If the Goal marker is seen, then Goal state is entered until
+the Goal marker is no longer seen in view. In this state, ~@~ is
+continuously being output.
+
+*** Gate Seen States
+
+If a gate (a pair of ArUco tags that meets certain criteria, see
+vision program documentation) is seen, then either Lowercase state or
+Uppercase state is entered.
+
+**** Lowercase State
+
+Lowercase letters that indicate the x-coordinate of the gate is being
+output in this state. If the current gate is passed and another gate
+is seen, then Uppercase state is entered.
+
+**** Uppercase State
+
+Uppercase letters that indicate the x-coordinate of the gate is being
+output in this state. If the current gate is passed and another gate
+is seen, then Lowercase state is entered.
+
+*** No Valid Gate Seen States
+
+**** Suggest Left Turn State
+
+If a Right gate marker is seen on the left hand side, it is the
+closest gate, and no more valid gates are seen, then Suggest left turn
+state is entered. In this state, ~<~ is continuously being output.
+
+**** Suggest Right Turn State
 
+If a Left gate marker is seen on the right hand side, it is the
+closest gate, and no more valid gates are seen, then Suggest right turn
+state is entered. In this state, ~>~ is continuously being output.
 
+**** None Seen State
 
+If no markers are seen in view, or the markers in view cannot form any
+valid gates, then None seen state is entered. In this state, ~?~ is
+continuously being output.