Making Myself a USB DAC + Headphone Amp — Single-inductor DC-DC, Conclusion

Apparently I have some sort of PTSD now, after so many iterations in vain trying to get TPS65131 to behave. But without a bipolar power supply, this project cannot be considered complete, so I started finding alternatives. Well, I don’t really have to find, because when I did my teardown analysis of CEntrance DACPort Slim, I already documented its bipolar power supply:

dcdc-ms

Back then I didn’t fully understand what it was, so I asked about this on Electronics StackExchange. But of course it is not a hack that happens to work — it’s an established way to generate an “auxiliary” negative voltage from an existing boost circuit:

In fact, LMR62014 as used in DACPort’s circuit is a pin-compatible part to LT1930. Apparently this works well, at least for stable symmetric loads. In my project, all analog rails are powered throughh LDOs, and the load is indeed nearly symmetric, as measured when powering off my bench supply.

PCB

With the TPS65131-fiasco still haunting me, I decided to go safe this time. Component picks:

  • Main boost inductor: A big one — TYS6045100M-10 at L×WxH = 6×6×4.5 mm. It boasts way higher saturation current and way lower DC resistance than I could possibly need. I think a 4×4 mm profile should do just fine.
  • Rectifier diodes: Any SOD-123FL Schottky will do; the less forward voltage the better. I used MBR230S1F-7 which I already have in stock.
  • Feedback: 0603 1% resistor; 0603 5% C0G/NP0 capacitor.
  • 4.7 µF ceramic caps: 0805 5% X5R/X7R
  • CC1/2: Tantalum “B” bulk output cap. Aluminum is fine too.
  • FB1/2 (not shown on schematic): 0805 ferrite bead. Short them if you are lazy.

boost-bipolar-sch

boost-bipolar-pcb-2D

This is a reusable module, so I shared it on OSHPark. Note that it is deliberately not breadboard-friendly (but close enough) so that it fits the DAC main PCB.

Order from OSH Park

Test

It works!

Positive: (using 10 mV/div due to Rigol firmware bug messing up vertical measurements)
enter image description here

Negative: (you can see the messed up average measurement under 5 mV/div, but trigger pos is correct)
enter image description here

I think these are already good enough for powering op-amps since they have reasonably decent PSRR (at least in audio freq range). That said, I am still keeping the LDOs in between just to be safe.

Conclusion: End of the Beginning

I now have this copy plugged into my DAC-amp prototype (v4.2):

complete v4.4

Not suprisingly it works. And at this point, all basic issues have been addressed. As I merge the DC-DC and LDO halves of the power board, the last remaining unsightly jumper wires will go away…

2017-04-07 EDIT: Merged power board arrives. Works beautifully.

complete v4.5

complete v4.6

Does this mean the project is completed? Well, recalling my original goal: “To achieve good objective performance within reasonable budget”. I have not even measured the performance! But while my 8-bit scope is good enough for debugging, for proper measurement I need an audio analyzer, which I do not have and cannot afford. Without precise measurement, any further development would be blind at best — a complete waste of time. So sadly at this point I have to stop working on this project…

…and listen to some good music 😉

I will try to release design files after some extra field testing. Stay tuned.

2017-04-08 EDIT: Design files released in my Hackaday project page.

Advertisements

Making Myself a USB DAC + Headphone Amp — Debugging the DC-DC

Problem

I have always had problems incorporating switching regulators in any design, and this project is apparently no exception. I blame my ignorance — totally clueless what to measure and what to expect.

Anyway, here is the schematics for TPS65131, almost blatantly copied from the reference design in its datasheet:

TPS65131-v2.0 sch

It doesn’t work as intended, as its power rails oscillate at ∼1 kHz, like this:

TPS65131-pos-out

TPS65131-neg-out

2 Vpp, seriously?!

You might wonder how on earth does the whole system actually work. Well, because I picked some really good LDOs. Here’s what happens after them:

VCCA

VEEA

Note that the waveform is almost at the noise floor of my scope (using 5 mV/div, the lowest setting). Even taking the measured Vpp at face value we have 2.16 V to 4 mV, which is −55 dB of PSRR. So of course it works, if you don’t mind the inductor being driven by that 2 Vpp 1 kHz ripple triangle wave, radiating like crazy into, say, your headphone cable…

Problem

I don’t have proof, but I think it’s caused by inductor saturating. Comparing my parts choices to that of the reference design, the only visible difference is inductor choice.

So this time I’m going to try use a big inductor that saturates beyond the current limit of TPS65131.

(TBD)

Making Myself a USB DAC + Headphone Amp — First Complete Prototype

In the interim update post I posted the plan for integration into 2 boards: A 2-layer power board, and a 4-layer main board. Actually I have had a good copy of the main board for quite a while:

untz-v4.2-main

Story for the power board is not as good though. In the beginning I screwed up on part of the schematics. Then I mis-soldered quite a few 0.5 mm pitch QFNs. After some footprint fine-tuning, I finally made a good copy:

untz-v4.3-full1

Mount it on the main board, and voila — the system is finally standalone and working!


…with one small but annoying flaw:

DC-DC Audible Noise

While the power outputs are all clean thanks to the stronk LDOs, the DC-DC converter constantly emits a moderately-pitched audio noise.

Schematic:

TPS65131-v2.0 sch

I have some hypotheses why this is happening, but since I am not that familiar with DC-DC converters, my guess might be totally off… Anyway here they are:

  • I disabled the so-called “power saving mode” of the DC-DC chip, out of fear that they increase output ripple.
  • The current rating is too big for my application, and the actual current consumption might be near the minimal stable current limit, although I have not found such a description in the datasheet. Perhaps use TPS65131‘s little cousin TPS65130?
  • The particular inductor I chose resonates (mechanically).

Fortunately all of these are relatively easy to verify through an extra PCB iteration. Time to get to work…

2017-03-09 EDIT:

  • All 3 issues listed above were implemented on an updated PCB, but audible noise persists. The sound is smaller though.
  • The ripple on DC-DC output rails is still coupled through LDO and DAC, trashing my SNR.

2017-03-11 EDIT:

Out of curiosity I opened up my DACPort Slim again. Surprisingly (at least to me) its DC-DC section emits similar levels of audible noise. I guess this is an inevitable downside of using inductor-based DC-DC.

While I might accept the audible noise as is, I still want to address the analog power rail noise issue. It appears to me that VDAC is the weakest link, since DAC does not have as good PSRR as op-amps. Once the noise leaks onto DAC output, PSRR in later stages does not matter anymore, as the damage has been done. Back to design table then…

Making Myself a USB DAC + Headphone Amp — USB Interface

Months into the project and I was still amazed at the lack of availability of a class of ASICs: USB-I2S bridges. Well I just lied — if you are fine with USB 1.1 (12 Mbit/s, the so-called “Full Speed”) and USB Audio Class (UAC) 1.0, which severely limits your (bit depth × resolution × channel count), then there are countless chips out there, both ASIC and general-purpose microcontrollers, at various level of integration. You might not be able to source prototype quantities from Digikey/Mouser (e.g. the CM103 chip on the cheap dongle I bought on Aliexpress, or various offerings from Sabre/ESS/Via), but they’re there. Some even support 24 bit 96 kHz. A lot of them derive their audio clocks from built-in XO and PLL, sometimes shared with USB, which leads to poor quality…

So what do I care about then?

Spec

  • USB Audio Class (UAC) 2.0
  • ≥ 2 output channels
  • 24 bit 192 kHz support
  • external master clock option

Well, I betrayed myself by asking for 192 kHz, as in the very first post I explicitly said 96 kHz is way good enough. The reasoning: My DAC chip already supports 192 kHz, and I don’t want the digital source to be the bottleneck. So even if I end up using 96 kHz for best analog performance, I want the system to be capable of operating at the max data rate supported by the DAC.

MCU Picks

UAC 2.0 means USB 2.0 High Speed (480 Mbit/s). There are only a few budget and/or low-footprint choices:

  • Atmel SAM3U: Other than USB, this is just yet another Cortex-M3 chip (which is a good thing!). However it comes in bulky 100-/144-pin QFP/BGA packages.

  • Cypress FX2LP (CY7C68013/4/5/6): 8-bit 8051-derivative core (similar to Dallas Semiconductor DS80C320) running at 48 MHz. Turtle slow, few peripherals, but it comes in a tiny 56-pin QFN package (although it does require an external I2C EEPROM, available in TSSOP8).

  • XMOS XS1-U8 series: Hugely popular in the “audiophile” market. It is one of these “many small cores” niche market MCUs. Didn’t do much homework though — will explain later.

While I am very comfortable with Cortex-M3 due to past experience, its footprint is way too huge for the project at hand, so I went for CY7C68013. In fact I had known this chip for quite a long time, as it frequently appears in the BOM of budget FPGA-based designs that provides USB connectivity. Heck — even Saleae Logic is (yet another) Spartan 6 + CY7C68013! There doesn’t seem to be a good standalone minimal system board for it though, so I quickly made one:

μ-68013

I intended to attach a small CPLD for I2S output, but still there is a lot of work, especially when I have to write 8051 (!) firmware for CY7C68013 (yes, more annoying than Verilog for CPLD!) that sets up the whole UAC 2.0 streaming…

How About Easier, Sensei?

Well, the focus of this DAC project is, of course, the DAC itself and the associated analog circuits. USB-I2S is more like a necessity — an inevitable chore I have to bolt on to make the system complete. So I kept looking for ASICs, and I found one that is close enough: XMOS XHRA-2HPA. It even comes with a reference design that does exactly what I want (albeit with a crappy all-integrated DAC)! This chip is clearly based on a normal XMOS XS1-U8 with a custom bootloader, but the similarity ends here — it loads encrypted (!) firmware from external Quad SPI flash, and is therefore completely locked down (not user-programmable), so by duck typing it is an ASIC. On the other hand, I don’t have to program it. Sounds like a fair deal. While the reference design was fully integrated, I instead isolated the XHRA minimal system and made a PCB.

XHRA Hiccups — the SPI Flash Fiasco

What was supposed to be a turn-key solution turned into a prolonged attrition debugging warfare lasting well beyond 2 PCB turnarounds, just to make this thing $profanity-ing boot and enumerate! And each time, the culprit turned out to be that innocent-looking, friendly-packaged, 8-pin SOIC Quad SPI Flash.

Quick TL;DR:

  • There is a whitelist for SPI Flash ID bytes.
  • The “correct” SPI flash does not have built-in HOLD# pull-up resistor.
  • SPI clock runs at 2.4 MHz at first, but eventually switches to 100/6 = 16.667 MHz .
  • The “nibble ordering” mention in the datasheet is misleading.
  • $profanity Bus Pirate.

Apparently, being “pin and instruction compatible” is not good enough — there is a whitelist for IDs. If the wrong ID is returned, the chip drops dead. There is one vague mention of this on the datasheet, and I only realized its true meaning after I dug into a logic analyzer capture run and actually inspected the SPI transfers. Turned out that right before the chip fell silent, it had repeatedly sent command 0x9F over SPI — “read chip ID”. D’oh!

The reason I didn’t look at the logic analyzer output? 16 MHz is too fast for my old good Saleae Logic 16 streaming 6 channels at its max 50 MHz sample rate (because Nyquist). Miscaptures were frequent, but I was lucky that run.

Then there is another misleading information from the datasheet stating that the SPI flash needs to store the least significant nibble (4 bits) of a byte (8 bits) first, which sounds as if before programming we need to manually swap the nibbles for all the bytes… Turns out you don’t have to do anything other than following the datasheet, which clearly transfers MSnibble before the LSnibble on the 4-bit SPI bus. D’oh!

I once wrote a blog post on SPI flash programming using Bus Pirate — and of course I was trying to program this. Eventually I figured out that Bus Pirate is too unreliable (on top of slow) for flash programming, so I bought a dirt cheap dedicated flash programmer on Aliexpress (again), which of course is based on STM32F1, as most things coming from China do these days[citation needed]. Never felt so good about being a native Chinese speaker when I clicked through that Windows 98-inspired GUI in GBK-encoded Simplified Chinese, like a boss™.

Note that blank SPI flash chips usually come with 4-bit (quad) SPI disabled, and requires a manual write to a status register to enable it. Since this flash programmer does not do this for me, till this day I still perform this ceremony using my Bus Pirate.

BONUS: The configuration bytes / firmware image generator of XHRA, downloadable from the reference design page, takes as input a config file with .cfg extension. Public service time: It is a Python script. Have fun.

End of Rant

And here’s the minimal system board on OSHPark, and here is the raw BOM full of placeholders. {X60 = 24.576 MHz, X61 = 22.5792 MHz} can be any pin 1 active high enable, 3.2 × 2.5 mm SMD XO.

Making Myself a USB DAC + Headphone Amp — Interim Update

It’s been a while since I last wrote *ahem* lies *cough* on this project. I am currently a little bit torn whether I should keep writing it here or start posting to my new hackaday.io presence… Anyway here is a brief update:

TL;DR

I now have a working standalone unit — USB in, headphone out — although it looks like this:

enter image description here

EDIT: New output module PCB just arrived. Works on first attempt. With the bulky v2.0 PCB gone, it now looks much neater!

enter image description here

There are still 5 pairs of jumper wires for patching power together, and USB VBUS is fed directly to VDAC, but hey — no more bench supply!

Continue reading “Making Myself a USB DAC + Headphone Amp — Interim Update”

Making Myself a USB DAC + Headphone Amp — Part 3

Although I got the system working in the last post, it is powered almost entirely off my bench power supply and as a result I could only use it at my workbench. Ultimately I want it to power entirely off USB, so a power supply module is needed…

Input

  • USB VBUS: (+5 ± 0.25) V, 500 mA.
  • Optional: AC adaptor (transformer), 9V batter{y,ies}

Output

  • DAC analog power: +5 V, 40 mA.
  • Analog signal rails (for line-level): (variable but symmetric) e.g. ± 6 V
  • Analog power rails (for output buffers): use analog rails directly

Overall Plan

When I first started, I thought I could use VBUS directly for both DAC analog power and positive analog rail, then use a high current (capacitor-based) charge pump for the negative. The reason I looked into charge pumps was that they are supposed [citation needed] to be much less noisy than inductor-based converters. However this approach is flawed:

  • Voltage swing is very limited; add LDO and we can only have approx. ±4 V rails.
  • Ripple on VBUS is not specified. The positive rail could be very noisy to begin with, which would totally trash DAC performance.

So the only option is to use (inductor-based) DC-DC converter(s) to generate a higher voltage dual supply (which is predictably noisy), then use LDOs to produce regulated rails. This is so cliché that I know from the beginning that the devil is in the details. Of $profanity course!

At > 5 V power rails we’re likely using adjustible-output parts, and thanks to the output levels we’re dealing with, rails are going to be ≤ 10 V, so the specific setpoint does not matter much (yet). I picked ± 7.5 V for DC-DC output and ± 6 V for LDO output. This should give the LDOs far enough headroom for optimal PSRR performance.

Continue reading “Making Myself a USB DAC + Headphone Amp — Part 3”

Making Myself a USB DAC + Headphone Amp — Part 2

In the previous post I covered the design of my DAC + Filter module and its initial test results. Before I could actually listen to music through it though, I need at least 2 more modules: a headphone amplifier, and a USB-I2S bridge.

Headphone Amplifier

Initially I picked OPA1622 as my power op-amp chip. It is similar to TPA6120A2, but with a smaller output impedance at 5 Ω and a much smaller (yet still sufficient) output current at 140 mA. However when I first started designing DAC + Filter module, I wasn’t very sure about what circuit I want to use for the output stage, so I quickly made this breakout PCB with built-in decoupling and bulk caps:

PCB top

Continue reading “Making Myself a USB DAC + Headphone Amp — Part 2”