I was curios about some old school R2R DACs namely the BurrBrown PCM56P. They where used in the late 80's in some of the better CD players like SonyES222/DenonDCD1500/MaranzXY whatsoever. There is some discussion in certain forums about their more or less superior sound quality, compared to this and that chip bla bla... I simply needed to experience one myself.
So why not use one of these oldies with modern equipment ? Read on...
That is probably not exactly a step by step "instructable" you can just follow. Parts used are somewhat special and it's pretty advanced stuff I suppose. On the other hand all components used are big and handy through hole parts, making it easy to solder.
I would call this instructable "experience sharing". Hope you can find some ideas for your own projects or at least have fun reading.
Cheers, Mario :)
Opening Hifi equipment might expose you to dangerous high voltage ! You should know what you do !
This kind of hacking can damage your superduper hifi equipment, especially speakers then used with that thing, Better run tests with cheap old stuff or old headphones !
What you need...
An old CD player, a RaspberryPi (with accessible P5 header), soldering iron, breadboard, handfull of logic chips, some wires, patience, an idea how TTL/CMOS logic works, and an oscilloscope could help to track down signals.
It plays sound nicely. For an internet radio this sounds really good. I have heard over my headphones so far, there the hights seem a little sharp, on the other side it plays a nice bass and clear mid. Not bad for a ~25 year old device.
Sound quality might have a bit of potential when using a modern and Elko free output stage, see last page for improvements.
Added Pictures and schematic for I2S converter and how to hook up everything.
Added Pictures and schematic of the 6x clock multiplier.
Added annotated picture of CD player.
Slight changes in text.
Fixed Bug in I2Sconv schematic, LRout was connected to V+ instead of Q2
Step 1: ...searching a CD Player...
My idea was to look for an old CD player with the desired DACs and see how I could modify it to connect with the RPi. In theory a DAC is interfaced with a pretty common synchronous serial connection similar to I2S (no not I2C). It is a 4 wire bus, it's signals can be seen in any DACs data sheet - take a look at http://www.ti.com/product/pcm56.
So lets g"gle a bit... maybe "CD player DAC list"? Yeah there is a link to http://wzone.vegalab.ru/faq/cd_transport_list/y a list of CD players from ventor Y.. and what DAC they use, remove the y and you find more lists with other vendors/players. I looked for my PCM56 or better two of them and then search for that particular player on ebay.
A bit later I got a Kenwood DP 2010, who's drive did not work.
Next step is reverse engineering the PCB and schematics. It helps very very very much to have a service manual and/or the data sheets of all the chips found in the player. I stumbled upon a service manual for a Kenwood DP-3010 on the net, it is more or less the same as the DP-2010 (apart from the head phone level poti :) as far as i can tell, well the 3010 seems to use a different oversampling chip as well, anyway it will be extremely helpful.
The most interesting chips found in the player are the PCM56Ps of course, next to them is a bit of logic (7474 (flipflops) and 7402 (nor, inverter)) and most interesting what's this.. a SM5807 ...searching g... reveals it's an oversampling circuit, great, i just interface this one then. The oversampling circuit does all the cumbersome signal conversion for the pcm56 and it pushes the 44.1kHz up to 176.4kHz. Some talk about NOS DACs meaning Non-OverSampling is the greatest, but I don't get what advantage this should have. The oversampler moves the requirements for the past DAC low pass filter to a simple 12bB filter and smooths the signal by interpolating. That makes perfect sense to me, I go for the oversampling DAC (feel free to convince me about NOS advantages).
Step 2: ...prepare the Player...
I clued a bit of plastic foil over the power switching and transformator PCBs so they will not fry me when accidentally touched.
Take out the PCB...
I also made the cable to the transformator plug able with pinheads. The headphone amp can be detached by opening the connector on it. After removing some screws the PCB is free.
Find signals to hack in...
Find the oversampling circuit, follow it's pins 5,6 and 7, they all go to 330Ohm resistors and from there to the TA9200 (CD signal processor)
I removed these resistors and inserted pin headers at their places. Also added a pin header for GND (next to the LR resistor is an empy hole to the ground plane, or just tab at bin 7 of the 74hc04) and 5V+ at pin 14 of the 74hc74.
If the player would still work, some sort of switch could be implanted to toggle between CD signal and external.
Step 3: ...wire It Up...
- BCLK pin
- LRCK pin
- DATA pin
- GND pin
It is not exactly "I2S" because this has a different timing, anyway I will refers to these 4 digital audio connection signals as I2S.
Hook it up...
Lets connect the RPI and the player via SPI.
A level converter can be omited, the logic build here can handle the 3.3V inputs.
I followed the instructions over at "Hifiberry" to install the pcm5107 driver on the RPi. This driver uses the I2S available on the RPIs optional 8 pin header. And the HDMI and analog outputs will be disabled.
The DAC outputs something (tested with high impedance phones on the PCM56 pin 8)...
The player has a muting circuit, It turns off sound output whenever the player thinks it's not playing useful things. Find the mute pin (it has a big measure point with description on the PCB) and plug it to 5V. The mute signal controls transistors shortly after the output filter circuit. These transistors simply shortcut the output to ground, resulting in silence. The base of these transistors points towards the mute control signal.
There is something, loud and noisy which could be related to the played music :-)
That "sounds" like the bits on the data line are not correctly aligned with the LRCK, thus the lowest bits slips into the highes (MSB) of the next data word leading to heavy noise.
...adjust the data timing...
Step 4: ...adding an I2S Converter...
Looking at the datasheets again I noticed that the I2S output (actually I look at the chip documentation used in the HifiBerry project whose driver I'm using, the chip is a pcm5102) of the RPI is slightly different from what the oversampler chip expects. In general the "standard" I2S signal delays the data one clock behind the LR signal. How to compensate this ?
There are two ways to address this:
1. Program a kernel driver which does not delay the data. The pcm5102 driver explicitly sets the data delay to 1 in the TXC_A register of the BCMs PCM engine (documentation here page 119+). Changing this to 0 should do it. But I dont like to compile a RPI Kernel now...
2. Build some vintage logic to do it, YEAH that's the way I like it :)
Here is a schematic...
The idea is to delay the data by 1 and the LR signal by 2, this moves the data forward in time (relative to the LR signal) so they line up as wanted. To do that, we need 3x D-Flipflops and an inverter for the clock. I found 2x 4035 and 4001 in my vintage chip collection, these will do (Could also be build with 7474 / 74174 and some other ICs).
The 4035 is a versatile 4bit shift register (this has 4 flip-flops in a line) 4001 is a 4x NOR which acts as the inverter then the inputs are tight together.
I use one 4035 to shift the data and another one to shift the LR. The outputs Q1-Q4 will show the input delayed by 1-4 clocks (the input is shifted through the register, that's that shift registers do). So the oversampler gets it's new data from Q1 of the data shifter and LR from Q2 of the LR shifter. Simple isn't it? The oversampler gets the inverted clock (sort of delayed by 1/2 clock cycle) this is necessary because the shifter needs some time to clock in the data and provide a stable output.
The Images show original and delayed LR signal, clock signal, analog output with cracking.
Yes that sounds like music.
Still a bit cracky (~50Hz tock tock) - might be a clock drift, investigate later...
How does it sound?
A bit loud around the mids and hights - could be the headphone, the build in headphone amp is a bit to loud for my taste and my headphone. Investigating...
Lowered the HP volume, did I mention that the PCB has a space for a volume pot. I inserted 4 resistors which turn down the volume a bit.
That by itself is an old school hack, introduced to overcome limitations of old 14bit DACs. It works a bit like the Dolby noise suppression, when recording you add noise, when playing you remove it and the transmission noise disappears with it - something like that.
Cut of pin 36 of the TA9200 and connected the now open trace to a switch to GND/5V so I can toggle it manually. The default setting was better when the hacked one, so it should go to 5V to deactivate emphasis. This switch toggles a transistor as in the mute section but this one changes the response of the output filter by turning off/on parts of the filter network - tricky analog circuit design.
I think the cracks come from a clock drift. The RPi pushes out the data with his 44.1 kHz*32 bit clock, the oversampler processes that with his own clock (also 44.1kHz*32 (*12 gives the 16.9MHz) ) Both clock drift away until one data bit jumps to it's neighbor bit effectively scaling it up by 2 which produces the peak in one single sample.
Solution 1 - pull data out of the RPi with the over samplers clock. This would make the DAC and OS the master clock. It would involve changing the driver module (or using another)
Solution 2 - Be crazy hardware hacker and construct a clock multiplier. This could multi the data clock (44100*2*16 per sec) by 6 or 12 to produce the clock for the oversampling circuit. This will eliminate the second clock and their will be nothing to drift away since all clocks are derived from one common clock.
One way to achieve that could be the use of a delay line. Another involves PLLs - new for me too. Thinking...
Step 5: Building a 6x Clock Multiplier
The thing is called "Clock multiplier with delay line". It is sort of simple. Delay the original clock signal by 1/6th period and do a bit of logic with these delayed signals results in a new clock 6 times as fast as the original.
Problem: Finding a well defined delay line.
Solution: Trial and error!!! I found the 40098 CMOS inverters to have round about 150 ns propagation delay. This is quite close to the desired 708ns/6 118ns (44100 samples with 16 bit and 2 channels -> 44100*16*2 is 1.4112 MHz SCLK that is a ~708ns clock period)
A bit more or less delay will still give the same frequency just not as smooth, the ups and downs will have different length.
From earlier projects I know the Xilinx ISE tools, which are freely available to do FPGA and CPLD programming. They can do logic simulation using schematic, VHDL or Verilog design entry. Schematic might be good for beginners but it's quite painful to change things in it. A hardware description language is much more flexible but of course more to learn.
Anyway, the simulation is just for me to see if the idea works and to check what logic would do the trick. If interested, you can find the simulation project attached, unzip it and open the "ClockMult.xise" with ISE. Once you made it so far you may burn it into a CPLD, no way, you want some vintage fun! :)
The result can be seen in the images. The clock goes through the 40098 5 times (6th inverter unused), at each output you see the previous input inverted and delayed. the signals are called clk_Xp and clk_Xn for positive and negative (a bit irritating here because all outputs of the 40098 are called p although they toggle... Each output and the original clock run through a second (fast) inverter which is a 74hc04 so that each delayed signal is available as positive(non inverted) and negative(inverted).
After inversion I pick two signals who can be AND'ed to form a single pulse with the 1/6th length of the clock period.
The pulses are then OR'ed together giving the final 6x clock.
The AND's are actually NAND's because I got 74hc00 ICs (that's a AND with output inverted) making the pulse negative. To get the same result these must be (N)AND'ed instead of OR'ed. NAND or AND doesn't matter because I don't care about the final clocks polarity, or at laest I can simply invert it again with the 74hc00 or 74hc04.
Ok, this really works, in theory ;-)
To make use of the new 8.4672 MHz clock the Kenwood's PCB must be changed a bit. The SM5807 runs with 16.9344 MHz, which is twice as much as the 6xCLK but the data sheet says it also runs with the 8.4..MHz when pin 3 (CKSL) is connected to 'L' instead of 'H'. Of course the original clock signal must be removed from pins 1. Our nice new clock is then fed into this pin.
Let's get the PCB out again and change pin 3 of the SM5807 to GND and add a pinheader for the clock.
From the DP3010 service manual it seems best to remove the 16.9344 crystal and add the pin header instead (the pin facing pin 5 of the 7402) then the clock will be inverted once more, doesn't matter, just makes modification simple. Pin 2 and 3 of the SM5807 seem unconnected, so I just add a bridge from pin 3 to ground. That should do it. Pretty simple.
Works, no clicks anymore, cool.
That was fun :-)
Well the breadboard is not the most reliable piece of tech, touch here and there makes the whole thing go crazy. Maybe the CPLD on a simple soldered PCB isn't such an bad idea after all.
Step 6: And Now?
Well, I will try to install a internet radio on my pi and tune into exotic stations. MPD does the job quite nicely. It can be controlled by a number of Android clients or just over a command line. There are many documentations with RaspberryPi and MPD around the net.
Throw away all that logic chips and write a kernel module for the SM5807 ? Mhm maybe not. make a soldered PCB using a CPLD for the logic - could make things more solid and reliable.
The sound quality is more interesting, the output filter of the kenwood is a bit strange, all that analog emphasis switching... I think I measure the frequency response and eventually build a simple 12dB or 24db low pass filter by myself. But that could be an instruct able of its own.
Thanks for reading, Cheers.