Hardware
The electrical design here was pretty straightforward. For NFC, I relied heavily on the Adafruit PN532 breakout board for layout and design cues (thanks Adafruit, saved me from having to spend a lot of time tuning my antenna!).
For audio, I wanted to keep things pretty simple, so I opted for the MAX98357A 3W integrated DAC and class-D amplifier. This amp has a PCM or I2S interface that can be controlled directly from a microcontroller. On past projects I've tried to do a discrete DAC feeding an amplifier and have always run into some noise issues. The MAX98357A made life easy! In order to store audio files, I used an SD micro card connected over SPI to my microcontroller. This interface ended up being the most challenging aspect of the project, but more on that in the software section.
For visual feedback, I created a ring of DotStar RGB LEDs from Adafruit. DotStars are really nice compared to the ubiquitous NeoPixels, because they are more robust and have a higher refresh rate (useful if you're multi-tasking).
I am a big fan of STMicro's line of 32-bit ARM microcontrollers. For this project, I needed an I2S interface for audio as well as 2 SPI ports for the NFC and SD Card interfaces. These requirements drove me to the STM32L052C8T6, which is a low cost, low power, and full-featured ARM M0+. I attached an I2C accelerometer to the micro to automatically put everything to sleep if the toy is not being used (great trick for irresponsible 3 year olds who don't remember to toggle the power switch!).
Schematic and layout was done in KiCAD and the PCB was ordered through PCBWay (Tip: PCBWay manufactures in China so shipping is higher cost than OSH Park, but for medium to large size boards the significantly lower base cost makes it the best option). I usually try to hand solder PCBs when possible, but I have some tiny, leadless parts in this project so I opted to order a stencil from OSH Stencils. Solder paste and a hot air gun made assembly a breeze.
Software
All code was written in Visual Studio Code (if you're still using anything else it's time to convert!). I used Atollic TrueStudio from STMicro and a SEGGER J-Link EDU mini debugger to program the microcontroller over SWD. The code for controlling the NFC reader and DotStars was borrowed from Adafruit (thanks again!) Arduino libraries, which I modified to use STMicro's STM32Cube framework. This was a little tricky, because Adafruit uses C++, but TrueStudio does not natively support this (ping me if you need details for how to get around this).
As I mentioned earlier, the interface to the SD card was the most challenging aspect of this project. I found several libraries for FatFs through internet searches that claimed to work out of the box with STM32. I had nothing but issues. I ultimately ended up using Chan's FatFs library (link) but still spent many hours with a logic analyzer and the SD Card specification, tinkering with the code to get it to work. If you want to interface to an SD Card over SPI with an STM32 part I suggest you start with my code on GitHub.
The one other challenging part of this project was the timing of the audio interface. There is not enough RAM in the microcontroller to buffer an entire audio file. As such, I had to read files in chunks and then stream the chunks out over I2S. I implemented this function with a ping pong buffer where an audio chunk is read into one section of RAM, and then a DMA engine starts streaming the chunk out over I2S while the next chunk is read into a different section of RAM. The DMA I2S and SD Card reads then swap RAM sections. It took some tinkering to figure out the optimal RAM chunk size and to get the DMA function and handoff fast enough to not experience a small audio delay between chunks.