1. CPOX Design - mwgit00/cpox GitHub Wiki

The CPOX project uses multiple threads, event queues for thread communication, and event-driven state machines to implement control loops.

Event-Driven State Machines

The application is a bunch of state machines. Timeout events and task-completion events drive things. The state machines are implemented with if-then-else statements. There are other ways to make a state machine, but I like the if-then-else approach. It's similar to following along in a state machine diagram: "If I'm in state X and get event A then transition to state Y."

Main Loop

The main application loop is driven by the OpenCV frame acquisition and keyboard input handling. Here is the flow:

  1. Grab image.
  2. Run face recognition. Put its result in event list.
  3. See if any other events occurred (messages from helper tasks). Put them in event list.
  4. Update state machine timers and check for timeouts. Put them in event list.
  5. Apply event list to state machines.
  6. Check keyboard input with a 1ms wait. Put any keypress in event list (for next iteration).
  7. Go to Step 1.

Face Monitoring Mode

At start-up, the application opens a window showing the live camera view with boxes drawn around a face and eyes if they have been detected. A keypress can activate face monitoring mode. It checks for continued detection of face and eyes. If they haven't been detected for several seconds, an external action is triggered.

Listen-and-Repeat Mode

While the face monitoring state machine is running, a "Listen-and-Repeat" mode can be enabled. In this mode, the application periodically speaks phrases and waits for them to be repeated back.

Serial RX

The application can communicate with an external serial device. The protocol and device don't really matter for this demo. The code just provides a starting point for working with a serial port. For the sake of example, the serial device has a 3-character ASCII text command format with an initial header character 'C', then a command digit (0-3), and finally a value character (a-y). A response has a similar format but begins with 'R'. Here is the state machine for receiving incoming serial bytes and extracting commands from it:

Threads and Queues

There are separate application threads for the following tasks:

  • Main loop
  • UDP RX from Speech Manager
  • UDP TX to Speech Manager
  • COM port RX and TX

The threads can receive commands through a Queue and pass back events to the main app through a Queue. In the C++ console application, a message queue is implemented as a std::queue of std::string objects that uses a std::mutex for thread safety. The C# Speech Manager uses a thread-safe queue from the library.