This is a four-layer PCB. I spent at least two days stressing about the power and grounding scheme, and my work just about paid off. With a slightly revised power supply design, the audio performance of this board would be excellent. Even with my inevitable mistakes and oversights, it’s as good as I’d hoped it would be.
Right in the centre of the board, just above the hole, is a Cirrus CS4272 audio codec, which converts stereo analogue audio to digital so it can be processed, and the processed digital audio to analogue so we can hear it. Apparently it has a dynamic range of 110dB. It also turns out to be fairly fragile: I’ve blown up four of them so far, all while working on the power supply. In this application, the codec runs at 64kHz. I have found in the past that these codecs are not quite transparent at 48kHz, but it is not necessary to go as high as 96kHz.
The biggest chip on the board is an ARM Cortex-M7. This zips along at about 216MHz and has one job: to process audio. The physical size is down to the amount of memory the chip contains alongside the processor. It turns out it’s bigger than it needs to be: I chose one with 2 megabytes of FLASH storage before making the breakthrough that means everything I’ve written fits neatly into 32 kilobytes. If we ever go commercial with this, I’ll save three or four pounds and a few square millimetres by making a more parsimonious decision next time.
In my first attempt in January, I found that this chip could process two channels of the simulation at 96kHz, but only just. If it’s decided that we need a 5.1-channel version we should be able to deploy two chips to process three channels each at 64kHz.
The large blue trimming resistors are to fine-tune the common mode rejection ratio of the balanced inputs. Perhaps they’re a little extravagant: if you don’t understand the opening sentence of this paragraph, you’re almost certainly not using them.
Up at the top left, near the rear panel switch, is the other biggish chip. This is an ARM Cortex-M0, which is the cheapest and most basic core that ARM makes. It’s about £1.50 worth of microcontroller, and its job is to do everything else. Interfacing with the USB, driving the screen, doing all the power sequencing and setting up the codec on start-up, connecting to the head tracker, and deciding when you’ve flicked a switch. While the massive ARM chip could do all this, it wasn’t very expensive to keep its load entirely predictable.
Above the headphone jack is a relay. This unplugs the headphones from the interface until it’s powered up. The design of the amplifier means that there’s a lot of low-frequency stuff happening on start-up as the power rails stabilise, and that would be very unpleasant to listen to. It’s quite an expensive component and there are cheaper ways of doing this, but it’s all about fidelity.
The headphones are driven by operational amplifiers running in parallel through 2-ohm resistors. It loosely follows the approach of NwAvGuy, whose work was recommended to me; he appears to know what he’s doing. I’ve used LM833 amplifiers throughout because they’re cheap, the specs are good, and they do what I need them to do. They are driven from a 12.5V single-rail power supply that is derived from whatever you happen to plug in.
Our screen is a 96×64 pixel passive-matrix OLED. These things are typically tricky to mount, which is why I designed my own custom clips and had them 3D printed. Only certain kinds of screws had slender enough heads to fit the design. I forget how much research went into this thing, but it didn’t fit together by accident.
Volume is controlled in the analogue domain by a stereo Vishay potentiometer. They’re pretty good. Better potentiometers are available, but only with great difficulty and at enormous expense. The template I designed fits three different potentiometers, just in case we had problems getting hold of the right part.
Just above the volume pot you can see two small slide switches. These were added for development. The one on the left can bypass the codec and connect the stereo analogue input straight to the headphone output. This is to satisfy me that I cannot hear the effect of the codec in the circuit if I flick the switch when the simulation is turned off (I can’t). The one on the right optionally adds 10dB of attenuation in case the headphone amplifier is too hot to be useful (it isn’t).
The break-off board is a contigency in case I ever want to experiment with designing a USB audio interface to fit to the amplifier. There’s a template for placing another Cortex-M0 that can be dedicated to streaming and sample-rate-converting audio from a computer should this ever be necessary. But I’m hoping it won’t be.