Hack of COMPACT DISK 723
The target of this hack is to intercept data between the control card and drive
to change for instance the output format of the drive’ s DAC interface:
In program:
Link control
card - Drive
First of all, it is necessary to begin studying the link between control card
and drive, as described in the doc of SAA737X. This is the chip that controls
everything at the drive level. In the case of the ECO-MKIII drive, definite
reference of the chip it is SAA7378GP. However his datasheet is untraceable on
the net, so I used that of SAA7377. It is almost the same chip, the only
difference is the configuration by default.
The used protocol is called 4 Wire bus. It derives from what existed on
the more ancient chips such SAA7345. The 4 wires being discussed are:
In this protocol, the micro controller on the control card is the
master and the drive’s SAA7378GP is the slave. From the point of
view of the SAA7378GP, RAB,
SILD and SICD are entries. They are therefore driven by the micro
controller (on the control card). Only SDA is bi-directional. A write
corresponds therefore to the control card sending data to the drive, a reading
being obviously the opposite. This protocol allows several working modes:
However in the case of ECO-SL-MKIII the RAB input is forced to ground.
This has the effect of allowing only the use of Servo Commands. It has
also to be noted that only 3 wires are used (and heck with "4 wires")...
Physically, the connection is made using an 8-wire, black-blue flat cable which
connects the drive to the control card.
THREAD |
COLOUR |
SIGNAL |
1 |
Blue |
Sicl |
2 |
Blue |
Gnd |
3 |
Blue |
Sicd |
4 |
Blue |
Data |
5 |
Black |
Reset |
6 |
Black |
Tray-sw |
7 |
Black |
Tray + |
8 |
Black |
TRay- |
This information
is taken from the datasheet of ECO-SL-MKIII,
found on the site of Daisy-laser. The wires Tray-sw,
Tray +, Tray- are related to the tray and therefore we are not interested to
them. Reset is the drive reset and is provided by the control card.
The protocol of
Servo Commands
The
doc of SAA737X reports the Servo Commands protocol, of which some basics are described
here (if you want more information, you’ll obviously have to browse through the
datasheet):
Writing of a byte
At
idle state the lines SICD and SICD are set to 1, DATA (SDA) is high impedance.
The transmission of a byte begins with MSB and finishes with the LSB. The state
change of the DATA line is made on SICL’ s falling edge. After the transmission
of 8 bits, the ACK (returned by SAA7378) is tested. As for the timing, every
bit is separated from the following one at the very least by 1,4µs and every
byte is separated from the following one at least by 70µs.
Reading of a byte
The
difference between a read and a write is determined at the level of the first
bit. If SICL goes back to 1 without SICD being at 0 then it is a write,
otherwise it is a read. This time the DATA state change is made at SICL’ s
rising edge. During a read there is not ACK. Timing is identical to that of a
write.
Dispatch of one command
The
dispatch of a command begins with the dispatch of the command number followed
by N byte of data. N depends only on the command. The engineers at Philips were
clever, since N is established by the command number itself. N is equal to
the command’ s lower nibble.
So,
command *17h have 7 bytes of data, order *33h have 3 bytes of data, order *B1h
have 1 byte of data, etc...
Several identical data
If
several bytes are identical it is possible not to re-send the byte, just
setting SICD to 0 without touching either SICL or DATA. However, one should not
forget to respect the timing, which stipulates that every byte (=impulsion on
SICD) must be separated at the very least by 70µs
Receiving data
Data receiving starts dispatching the command number and then reading N
bytes of data. Contrary to a write, N is not fixed. N maximum is given
by the command number, but nothing obliges us to recover all data. The end of a
reading is given either by the reception of all data, or writing a byte (which
will be will be the number of the next command).
To supplement theory, I used a micro controller intercepting the RESET, DATA,
SICD and SICL lines (in this order on pictures) to make some measurements:
|
|
|
I
noted the presence of glitches on SICD. This is very important because it means
that we cannot rely only on SICD to spot a byte, but it is also necessary to
use SICL. Knowing that a vertical scale represents 10µs, we can also have a
rough idea about the real timing. So SICL goes to 1 for 2-3µs and stays at 0 for
7-9µs and 2 SICD pulses are spaced at the very least by 130µs. We are therefore
far from the minimum values, and that’ s better!
Servo Commands
They are given in the SAA737X doc:
ORDER |
NUMBER |
BYTE |
PARAMETER (S) |
Write
commands |
|||
Write_focus_coefs1 |
#17h |
7 |
foc_parm3, foc_int, ramp_incr, RAMP_HEIGHT, RAMP_OFFSET, FE_START,
foc_gain |
Write_focus_coefs2 |
#27h |
7 |
defect_parm, rad_parm_jump, vel_parm2, vel_parm1, foc_parm1,
foc_parm2, CA_drop |
Write_focus_command |
#33h |
3 |
foc_mask, foc_stat, shock_level |
Focus_gain_up |
#42h |
2 |
foc_gain, foc_parm1 |
Focus_gain_down |
#62h |
2 |
foc_gain, foc_parm1 |
Write_radial coefs |
#57h |
7 |
rad_length_lead, rad_int, rad_parm_play, rad_pole_noise, rad_gain,
sledge_parm2, sledge_parm_1 |
Preset_Latch |
#81h |
1 |
chip_init |
Radial_off |
#C1h |
1 |
'1CH ' |
Radial_init |
#C1h |
1 |
'3CH ' |
Short_jump |
#C3h |
3 |
tracks_hi, tracks_lo, rad_stat |
Long_jump |
#C5h |
5 |
brake_dist, sledge_U_max, tracks_hi, tracks_lo, rad_stat |
Steer_sledge |
#B1h |
1 |
sledge_level |
Preset_init |
#93h |
3 |
re_offset, re_gain, sum_gain |
Write_decoder_reg |
#D1h |
1 |
decoder_reg_data |
Write_parameter |
#A2h |
2 |
param_ram_addr, param_data |
Read
commands |
|||
Read_Q_subcode |
#0h |
until 12 |
Q_sub1.. 10, peak_l, peak_r |
Read_status |
#70h |
until 5 |
foc_stat, rad_stat, rad_int_lpf, tracks_hi, tracks_lo |
Read_hilevel_status |
#E0h |
until 4 |
intreq, dec_stat, seq_stat, motor_start_time |
Read_aux_status |
#F0h |
until 3 |
re_offset, re_gain, sum_gain |
However, as their description
is very succinct, a little of imagination is necessary to guess their
utilization...
Hack 1/2 (study)
Now that the theory is known, let us switch to the
practice!
Due to the lack of available information, it is necessary to begin by spying on
the target. As we are clever, it is necessary to start at looking at what
interests us. As what interests us is the decoder,
only the following commands are to be watched (underlined in the previous
table):
*As a matter of fact, looking in the doc at the various
possibilities of param_ram_addr, we find:
One problem is that param_data is not detailed in the doc and a
bit of reverse engineering will therefore be necessary...
In
practice, here is what I used for spying:
According to the doc of
SAA737X:
Oversampling Rate |
Frequency |
1
xFS |
2.1168
Mhz |
2
xFS |
4.2336
Mhz |
4 xFS |
8.4672
Mhz |
Interception scheme
Here
is what this resembles in reality...
The big thing to the left it is the frequency meter, the small thing to the right
it is the Atmel development card.
I began looking at the command numbers (after filtering) sent in several cases.
However, it came out quickly that only the command Write_decoder_reg (*D1h) was
indeed interesting. Here what they intercept (not exhaustively) as orders in
the decoder in different cases (the identification of orders envoys towards the
decoder is given in the datasheet of SAA737X):
2 points are
remarkable:
Hack 2/2 (action)
The first tries consisted in intercepting the command #D1h #30h
present at initialisation and to replace it with #D1h #3Xh, with X according to
the required output format:
Unfortunately this is definitely not enough. In
effect it allows only to change the output format during the first play (and
still). From the second play on the format switches back again to the default value
(0000b, therefore Sony 16 bits 4xFS). It was therefore necessary to use another
technique, much more subtle.
The technique is linked to the second remark about the commands. It consists in
replacing a superfluous command with the desired one.
Given that during a play there is a persistent #D1h #01h command, this seems
very much suitable for our hack! It is necessary to hack it at every new play,
but it is not healthy to do it continuously during a play. It is therefore
necessary to successfully identify the beginning of a play in a reliable way.
In order to do that, we consider that the beginning of a play is linked to a #D1h
#01h sequence. Arbitrarily, I chose to let pass through 2of them and then to
hack the 3rd one. Finally, it is also necessary to re-initialise the process at
every new play. In order to do that, the solution chosen consists in testing
the presence of a #D1h #00h command, present at every end of a play and track
change.
All this brings us to write down a small program; here is a simplified diagram
thereof:
It begins with an initialisation routine of I/O and
variables, then reading the configuration to be able to choose the output format
without changing program. Then the program begins by waiting for a command number:
o
If we must hack the data, we drive DATA for the time of a byte
o
Otherwise we retrieve the byte:
If it is #00h we authorise a new hack. If we can hack and detect 2 consecutive #01h
(test of the beginning of a play) then it will be necessary to hack the next command.
Implementation
The program
was written in assembler for the AT90S1200 using AVR Studio 4 (available for free
on the site of Atmel).
(Click on program to access the said project).
Note: The program is not compatible with AT90S2313 because the
stack pointer (SP) initialisation is missing, as it does not exist on the AT90S1200.
To program the micro controller I used the ATMEL development
card, provided with the kit STK-200. Otherwise, there is a number of small,
easy to build programmers available at the usual shops or on the net. Finally,
it is always possible to arrange something sending me a mail
(delete nospam_ from the address)...
Contrary to spying, where I had used AT90S2313, here I preferred AT90S1200
because it is the cheapest micro controller available from Atmel. In effect, it
has less "gadgets", but what is present is more than enough for the task.
It is available without problem from all the habitual suppliers (Selectronic,
Conrad, RS, Farnell etc.). The components required for this set up are not many:
Schema of " Hacker "
The scheme is very straightforward!
The reset is integrated into the micro controller, therefore it is not
necessary to provide for an external one. There is a small quartz as clock with
the 2 usual, 27pf small capacitors. The quartz frequency does not have big
importance and any value between 4Mhz and 10Mhz fits the bill. The lower the frequency
and the more the micro controller consumption will decrease, therefore I
recommend rather 4Mhz than 10Mhz. PB0 drives directly a signalling led. PB1-4 are
used to configure the desired output format. The presence of internal pull-ups limits
the number of component necessary at this level. The lines SICL, SICD and DATA come
directly from the control card. The card’ s supply is picked up directly from
the control card. Finally, there is a small capacitor of 100nf for the de-coupling
of the micro controller.
The integration in the player is made as follows:
Connection
between the hacking card and the control card
Connections
to the control card
The various signals can be taken at the level of the control card. Signals
SICL, SICD and DATA are to be taken at the level of the flat cable going to the
drive. They are in this order (from bottom to top if you orientate the control
card as on the image):
·
SICL (in blue on the image)
·
GND
·
SICD (in red on the image)
·
DATES (in yellow on the image)
·
etc...
GND (in green on the image)
is taken on the side of the flat cable going to the analogue card. It is the
second wire starting from the right (if you orientate the control card as on
the image). Finally +5v (in violet on the image)
is taken just next, at the output of the diode on the 1st wire of the same cable.
It is possible to assemble it without problems on a breadboard, given the low
component count. On the contrary, it is a good idea to think of using a socket
for the micro controller. In effect this can be practical if you need to
re-program it for instance...
|
|
Operation,
listening
The operation is very simple:
With the player disconnected, we choose the desired output format using
the bridges:
STRAP |
EFFECT |
STRAP |
EFFECT |
|
Without oversampling |
|
Output format Sony 16 bits |
|
Oversampling
2xFS |
|
Output format Sony 18 bits |
|
Oversampling
4xFS |
|
Output format I²C 16 / 18bits |
Then we connect the player, put a CD in (if there is
not one already) and press play. As soon as play begins, a few seconds after
the CD starts rotating, the led of the hacker switches on meaning that
everything is ok. The led goes off as soon as the play is stopped.
If you want to change format it is necessary to switch off the player and then to disconnect
it.
In the following it will always be necessary to disconnect the player before taking
any action, except of course, if you want to play a CD ;-)
What do we get sound-wise?
I made a short comparative listening session using a modified CD 713 (mods are described
here)
with oversampling (4xFS) and without (1xFS). On all the listened pieces, I preferred
the version without oversampling. The difference is very much evident on the
trebles. The trebles are distinctly improved (more refined,
silkier). Theoretically, abolishing the oversampling, we should also lose a
little of level at the extreme high. Personally, I absolutely did not feel this
gap (the opposite, even). I also noted that the sound image was more definite.
For the rest, I did not find any difference.
At the end of the story, although small, the difference is net and in favour of
the version without oversampling.
I also tested this implementation on my drive-modified CD4000
(mods are described here).
The suppression of the oversampling gets rid of 0.5db attenuation at the level
of the volume control. As this attenuation has an influence on the numerical output,
there is a possible benefit. Having quickly tried some CDs, I did not definitely
remark any difference...
On the contrary, as it allows to exactly extract the digital stream on the
SPDIF output, it is consequently possible to play CD DD and DTS.
I verified it burning a test CD with samples found on this site:
http: // www.sr.se /
multikanal / english / e_index.stm
Whew, I did not work for nothing:-)
The
bug of the CD723
Fiddling around with the player I noticed the existence of a bug:
Actually if, during the
first start-up of the player and after plugging it in, we start a play
directly by pressing on " Play " without previously switching on the
player (using the "stand by" button), the internal digital output is not
oversampled. It is really weird, but very handy if you want to try listening
without oversampling without changing anything. As soon as the play is stopped,
the output switches back to the normal mode (therefore oversampled 4 times). To
perform again the test it is then necessary to switch off the player, then to unplug
it and to start again the initial procedure.