I'm working on a project that should be able to play "retro games". The base of the system is a homemade proto-board with Atmega 1284P, using the MightyCore Arduino core.
Currently I have all the hardware modules ready and now i'm trying to put together all the software.
The project should prduce some music, i'll used the "arduino-music-player" project to make it possible:
Shortly, this project reads a prepared file from the program memory (which is converted from .mod / .it / .xm files on PC) and computes the PCM samples to output. While this computation happens in the regular loop(), outputting the samples must be precisely timed, so it happens in a timer interrupt.
I modified this code to use an SPI DAC (MCP4921) instead of parallel resistor ladder. Saves IO pins, improves quality. I attached the DAC on the hardware SPI pins, and it works without any problems, music plays just fine.
After this I tried to connect the "display" to the system, which is a homemade LED matrix made from 200 pieces of SK9822 (~APA102) RGB LEDs. These leds are programmable chips, also using an SPI like interface, but not featuring a chip-select line.
I'm using the FastLED library to drive the LEDs, and at first I tried to use their bit-banging mode (software SPI), since the hardware SPI is already taken by the DAC, and it is not trivial (at least for me) to connect both peripherials to the hardware controller:
- SK9822 has no chip select; this may be worked around using some logic gates
- LEDs must be driven from loop(), while the DAC is driven from an interrupt; what happens if the two transmissions interfere?
Though the software SPI worked fine, the LEDs were running OK, but the audio output became unrecognizable distorted. It looks that updating the LEDs in the loop() takes too much cycles, and the audio player cannot fill the sample buffer quickly enough.
I was quite hopeless at this point, but then i realized that the 1284P has additional USART controllers which can be configured to operate as SPI masters. FastLED even supports this out of the box. I only needed to define the USART pins for it and I could drive the LEDs much faster! The audio is now recognizable, but still jittering annoyingly. As I lower the LED count, the jittering becomes less and less.
At this point I'm thinking of the following things:
switch the two peripherals: the LEDs go to the hardware SPI, DAC to the USART. I'm not sure, from what I could learn, their speed should be comparable. And in theory, the DAC produces more traffic (only 2 bytes but outputted at 22050 Hz vs. ~ 200*3 bytes at ~30 Hz), so it should be connected to the faster lane?
replacing the current 16 MHz external crystal to a 20 MHz one. 1284P should run fine with it, and it is a ~25% speed gain, could be enough?
reducing the audio sample rate: easiest to try, definitely would help, but I do not want to drastically reduce the audio quality
What do you think about this design? Do you have some ideas for me to try?
Thanks in advance!