Coursework 2 for ELEC60013: Embedded Systems at Imperial College London - a music synthesizer with keys to cover one octave and the ability to daisy chain multiple devices to expand to cover more octaves
Go to file
Benjamin Ramhorst 9bf12dcfae
Added new lines
2022-03-25 18:16:21 +00:00
docs Minor cleanup 2022-03-25 11:21:21 +00:00
include Initial commit 2022-03-23 10:15:23 +00:00
lib Core features possibly done 2022-03-25 17:16:43 +00:00
src Core features possibly done 2022-03-25 17:16:43 +00:00
test Initial commit 2022-03-23 10:15:23 +00:00
.gitattributes Initial commit 2022-03-23 10:15:23 +00:00
.gitignore Initial commit 2022-03-23 10:15:23 +00:00
platformio.ini Catch up to P1S5 2022-03-23 17:52:33 +00:00
README.md Added new lines 2022-03-25 18:16:21 +00:00

ELEC60013 Embedded Systems - Music Synthesizer Documentation

The following document outlines the design, implementation and real-time dependecies of a music synthesizer for the 2nd coursework of the Embedded Systems module.

System tasks

The sytem at hand executes several real-time tasks, including:

  • Reading the key matrix
  • Updating the display
  • Generating sound

Reading the key matrix

Purpose:

  • Decode the key matrix, obtaining the states of the keys, knobs and joysticks
  • Obtain the currently selected note from the decoded key matrix
  • Select the appopriate step size for the currently selected note
  • Transmit the currently selected note, along side its state (pressed or released) using CAN
  • Obtain any changes in the knobs from the decoded key matrix, corresponding to volume, octave or waveform

Function: code(void scanKeysTask(void *pvParameters))
Implementation: Thread, executing every 50ms
Minimum initiation time: TO BE COMPLETED.
Maximum execution time: TO BE COMPLETED.
Priority: Highest (1), as playing the appropriate sound is more important than updating the display.

Updating the display

Purpose:

  • Display the currently selected note (string)
  • Display the current volume (int)
  • Display the current octave (int)
  • Display the current waveform (XMB icons)

Function: code(displayUpdateTask(void *pvParameters)
Implementation: Thread, executing every 100ms. While a refresh rate of 10Hz does not sound impressive; the display is largely static. Therefore, 100ms was perfectly accetable, without any noticeable delays.
Minimum initiation time: TO BE COMPLETED.
Maximum execution time: TO BE COMPLETED.
Priority: Lowest (2).

Generating the sound

Purpose:

  • Adds the sample rate to the accumulated value, corresponding to the desired frequency
  • Sets the output voltage, by using the accumlated value and the desired volume
  • Writes to analogue output, generating the desired sound

Function: code(sampleISR())
Implementation: Interrupt executing with a frequency of 44.1kHz
Minimum initiation time: TO BE COMPLETED.
Maximum execution time: TO BE COMPLETED.

CAN

Purpose:

  • TO BE ADDED

Function:
Implementation:
Minimum initiation time:
Maximum execution time:
Priority:

Critical instant analysis of the rate monotonic scheduler

TO BE ADDED - After system is completed.

CPU Resource Usage

TO BE ADDED - After system is completed; see this link: https://edstem.org/us/courses/19499/discussion/1300057

Shared data structures

Shared data structures:

  • code(currentStepSize), safe access guaranteed using code(std::atomic<uint32_t>)
  • code(keyArray), each element within the array is of type code(std::atomic<uint8_t>)
  • msgInQ, handled by FreeRTOS
  • code(RX_Message), handled by code(std::atomic_flag)

It was desiced to use C++ code(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."(https://en.cppreference.com/w/cpp/atomic/atomic)

TODO - Expand on the memory model for std::atomic.
TODO - Explain how FreeRTOS handles msgInQ.
TODO - Once CAN is completed, expand on the protection of RX_Message

Analysis of inter-task blocking dependencies