The audio engine is responsible for transporting audio samples into and out of the MCU, codec and controllers.
When the codec transfers an input audio sample to the MCU, the sample is first shifted into the MCU's USART RX buffer. Once all of the bits of the sample are transferred, the sample is automatically transferred into the input buffer. This process repeats until the input buffer is filled.
When the input buffer is full, an interrupt is triggered and the corresponding ISR sends a BM_SERVICE_AUDIO message into the queue (which is read by the currently running controller). The message also contains a pointer to the input buffer so that the audio processing functions know where to find the input data.
Similar to the movement of input samples, the MCU takes a sample from an output buffer of processed samples and transfers it into the USART TX buffer which is then automatically transferred to the codec. Once the output buffer is emptied, the MCU moves to the next buffer of output samples and the emptied buffer is ready to be filled with input samples.
The transfer of samples between the RX/TX buffers in the USART peripheral and the input/output buffers is handled automatically by the Direct Memory Access (DMA) module. Without the DMA module, the CPU is responsible for transferring the samples into and out of the buffers, resulting in reduced efficiency.
The physical transfer of input and output samples to and from the MCU actually happens at the same time! I2S has lines reserved for both the input and output data (typically labelled as SDIN, SDOUT lines).
The codec samples audio at a frquency of 32 kHz.
In order to avoid interruptions in audio as buffers moved to different stages, BitMasher has three buffers that move between audio input, processing and output stages. This way, all stages can operate simultaneously and not wait for buffers to be transferred to them from previous stages.
The audio engine also allows configuration of various parameters in the codec (e.g. gain and EQ settings). Configuration is done through I2C.
The audio engine uses the codec driver (MW_Driver_CS42L52) which handles the low-level functions needed to communicate and transfer samples to/from the codec. The driver handles the necessary MCU peripheral configurations (e.g. USART, I2C, clocking) as well as codec setup.
The codec requires a 12.288 MHz clock signal (MCLK). To generate this signal, the MCU uses the signal from the low frequency (32.768 kHz) crystal oscillator and routes it to a phase lock loop where the frequency is increased to the required 12.288 MHz.