// Regenerate using graphviz/dotty with this command
//   dot -Tjpg ./flight/Doc/Architecture/stm32_i2c_fsm.dot > ./flight/Doc/Architecture/stm32_i2c_fsm.jpg

digraph stm32_i2c_fsm {
  label="STM32 I2C FSM"
  labelloc=t
  labeljust = l

  {
    node [ style=filled,color=lightgray ]

    stopped [ shape="doublecircle" ]
  }

  node [ style=filled,color=blue ]

  {
    rank=same
    stopped
    stopping
    starting
  }

  // start addr/w[A] data[A] stop
  //     SB       ADDR     BTF
  //      ADDR     DR
  //                STOP
  //
  // start addr/w[A] data[A] data[A] stop
  //     SB       ADDR     BTF     BTF
  //      ADDR     DR       DR
  //                         STOP
  //
  // start addr/w[A] data[A] data[A] data[A] stop
  //     SB       ADDR     BTF     BTF     BTF
  //      ADDR     DR       DR      DR
  //                                 STOP
  //
  subgraph cluster_w_last_txn {
    label="Final Write Txn"
    w_last_txn_addr
    w_last_txn_middle
    w_last_txn_last
  }

  // start addr/w[A] data[A] start
  //     SB       ADDR     BTF
  //      ADDR     DR
  //                START
  //
  // start addr/w[A] data[A] data[A] start
  //     SB       ADDR     BTF     BTF
  //      ADDR     DR       DR
  //                         START
  //
  // start addr/w[A] data[A] data[A] data[A] stop
  //     SB       ADDR     BTF     BTF     BTF
  //      ADDR     DR       DR      DR
  //                                 START
  //
  subgraph cluster_w_more_txn {
    label="Write Txn with Restart"
    w_more_txn_addr
    w_more_txn_middle
    w_more_txn_last
  }

  // start addr/r[A] [data] N stop
  //     SB       ADDR     RXNE
  //      ADDR     STOP    DR
  //               NAK
  //
  // start addr/r[A] [data] A [data] N stop
  //     SB       ADDR     RXNE     RXNE
  //      ADDR             DR       DR
  //               ACK      NAK
  //                        STOP
  //
  // start addr/r[A] [data] A [data] A [data] N stop
  //     SB       ADDR     RXNE     RXNE     RXNE
  //      ADDR             DR       DR       DR
  //               ACK      ACK      NAK
  //                                 STOP
  //
  subgraph cluster_r_last_txn {
    label="Final Read Txn"
    r_last_txn_addr
    r_last_txn_pre_one
    r_last_txn_pre_first
    r_last_txn_pre_middle
    r_last_txn_pre_last
    r_last_txn_post_last
  }

  // start addr/r[A] [data] N start
  //     SB       ADDR     RXNE
  //      ADDR     START   DR
  //               NAK
  //
  // start addr/r[A] [data] A [data] N start
  //     SB       ADDR     RXNE     RXNE
  //      ADDR             DR       DR
  //               ACK      NAK
  //                        START
  //
  // start addr/r[A] [data] A [data] A [data] N start
  //     SB       ADDR     RXNE     RXNE     RXNE
  //      ADDR             DR       DR       DR
  //               ACK      ACK      NAK
  //                                 START
  subgraph cluster_r_more_txn {
    label="Read Txn with Restart"
    r_more_txn_addr
    r_more_txn_pre_one
    r_more_txn_pre_first
    r_more_txn_pre_middle
    r_more_txn_pre_last
    r_more_txn_post_last
  }

  stopping -> stopped [ label="auto" ]
  stopped -> starting [ label="start" ]

  starting -> w_last_txn_addr [ label="SB\nop=write\nlast txn" ]
  starting -> w_more_txn_addr [ label="SB\nop=write\nmore txn" ]

  starting -> r_last_txn_addr [ label="SB\nop=read\nlast txn" ]
  starting -> r_more_txn_addr [ label="SB\nop=read\nmore txn" ]

  w_last_txn_addr -> w_last_txn_last [ label="ADDR\nlen==1" ]
  w_more_txn_addr -> w_more_txn_last [ label="ADDR\nlen==1" ]

  w_last_txn_addr -> w_last_txn_middle [ label="ADDR\nlen>1" ]
  w_more_txn_addr -> w_more_txn_middle [ label="ADDR\nlen>1" ]

  w_last_txn_middle -> w_last_txn_middle [ label="BTF\nlen>1" ]
  w_more_txn_middle -> w_more_txn_middle [ label="BTF\nlen>1" ]

  w_last_txn_middle -> w_last_txn_last [ label="BTF\nlen==1" ]
  w_more_txn_middle -> w_more_txn_last [ label="BTF\nlen==1" ]

  w_last_txn_last -> stopped [ label="BTF\nlen==0" ]
  w_more_txn_last -> starting [ label="BTF\nlen==0" ]


  r_last_txn_addr -> r_last_txn_pre_one [ label="ADDR\nlen==1" ]
  r_more_txn_addr -> r_more_txn_pre_one [ label="ADDR\nlen==1" ]

  r_last_txn_addr -> r_last_txn_pre_first [ label="ADDR\nlen>=2" ]
  r_more_txn_addr -> r_more_txn_pre_first [ label="ADDR\nlen>=2" ]

  r_last_txn_pre_one -> r_last_txn_post_last [ label="BTF\nlen==1" ]
  r_more_txn_pre_one -> r_more_txn_post_last [ label="BTF\nlen==1" ]

  r_last_txn_pre_first -> r_last_txn_pre_last [ label="BTF\nlen==2" ]
  r_more_txn_pre_first -> r_more_txn_pre_last [ label="BTF\nlen==2" ]

  r_last_txn_pre_first -> r_last_txn_pre_middle [ label="BTF\nlen>2" ]
  r_more_txn_pre_first -> r_more_txn_pre_middle [ label="BTF\nlen>2" ]

  r_last_txn_pre_middle -> r_last_txn_pre_middle [ label="BTF\nlen>2" ]
  r_more_txn_pre_middle -> r_more_txn_pre_middle [ label="BTF\nlen>2" ]

  r_last_txn_pre_middle -> r_last_txn_pre_last [ label="BTF\nlen==2" ]
  r_more_txn_pre_middle -> r_more_txn_pre_last [ label="BTF\nlen==2" ]

  r_last_txn_pre_last -> r_last_txn_post_last [ label="BTF\nlen==1" ]
  r_more_txn_pre_last -> r_more_txn_post_last [ label="BTF\nlen==1" ]

  r_last_txn_post_last -> stopping [ label="auto" ]
  r_more_txn_post_last -> starting [ label="auto" ]
}