From e7680dc598f546a0733b29f32839c943808a74ad Mon Sep 17 00:00:00 2001 From: DavidAmor-Segan <59933971+DavidAmor-Segan@users.noreply.github.com> Date: Fri, 25 Mar 2022 23:09:27 +0000 Subject: [PATCH] Update README.md --- README.md | 7 ++++++- docs/DependencyGraph.png | Bin 0 -> 22462 bytes 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 docs/DependencyGraph.png diff --git a/README.md b/README.md index 96ea151..3a1a3e0 100644 --- a/README.md +++ b/README.md @@ -124,11 +124,14 @@ Therefore, total latency is slightly over 23.07ms. The exact latency could not b The total CPU usage is calculated by dividing the total latency by the highest initiation time. In this case the CPU usage is ~25%. -## Shared data structures +## Shared data structures & dependencies * `currentStepSize`, safe access guaranteed using `std::atomic`, stores the step size of the most recently pressed key, to be used within `sampleISR()` * `keyArray`, each element within the array is of type `std::atomic`, stores the current state of the key / encoder matrix * `msgInQ`, handled by FreeRTOS, pointer to the next item in the received CAN message queue +* `latestKey`, guarded by `std::atomic`, ensures that the current note is maintained as an integer value +* `selectedWaveform` is an int (`std::atomic`) corresponding to the currently selected Waveform type, that determined if the output is a Sawtooth, Square, Triangle or Sine wave. +* `octave` is modified when the key is changed and the message displayed on the screen needs to be displayed, stored as an int. It was decided to use C++ `std::atomic`, as it is easier to use and implement, while providing the same functionality as a mutex. According to the documentation: *"Each instantiation and full specialization of the std::atomic template defines an atomic type. If one thread writes to an atomic object while another thread reads from it, the behavior is well-defined (see memory model for details on data races). In addition, accesses to atomic objects may establish inter-thread synchronization and order non-atomic memory accesses as specified by std::memory_order.*" - [CPP Reference "std::atomic"](https://en.cppreference.com/w/cpp/atomic/atomic) @@ -136,6 +139,8 @@ It was decided to use C++ `std::atomic`, as it is easier to use and implement, w `msgInQ` is used as a FIFO buffer for CAN messages, to supplement the small buffer of the CAN system and allow for more messages to be retained, increasing the required minimum initiation time. +![Dependency Graph](docs/DependencyGraph.png) + ## Analysis of inter-task blocking dependencies ## Advanced features diff --git a/docs/DependencyGraph.png b/docs/DependencyGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..d597b79e3bf022044fab278cfdb6fe4649d4b35d GIT binary patch literal 22462 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 jj