Go Down

Topic: Arduino as a CD-Changer emulator: 9-databit serial (Read 235 times) previous topic - next topic

Dec 01, 2014, 11:17 pm Last Edit: Dec 01, 2014, 11:19 pm by donny007x
I want to use my Arduino as a CD-changer emulator for my car stereo (Blaupunkt Travelpilot DX-R52). I sniffed the protocol with a logic analyzer and figured it all out. It's a 9-databit, 1 stopbit, 9800 baud (4800 during startup) RS232 signal without parity. The command structure is pretty straightforward.

Is it possible to do 9-databit serial send/receive with the Arduino; via HardwareSerial or SoftwareSerial? I've found several modified HardwareSerial libraries so far that allow some control over the databits, but none of them seem to be able to send and receive 9 bits of data.

I want to use the buttons on the head unit to control the music on my Android phone via Bluetooth (using the guts of a Bluetooth multimedia keyboard and the Arduino as a bridge). I need to convince the head unit that it's talking to a CD-changer for that to work. The Aux input stays off when no 'CD' is playing.

Here are some captures of the protocol:

A packet up close (bit level):


Head unit to CD-changer: "Load Disk 1, Track 2" (after pressing 'Next Track')



CD-changer to Head unit: "Loaded Disk 1, Track 2"


It shouldn't be hard to replicate to rest of the protocol once I figured the 9-bit communications out.

Peter_n

#1
Dec 02, 2014, 09:57 am Last Edit: Dec 02, 2014, 10:03 am by Peter_n
It should be very over-the-top hard. Since you have to read and write with 16 bits data.
Can you check once more if that is a parity ? I think I can see a change in the last bit according to the previous bits in the pictures or maybe I don't. Is your sampling frequency too low ? Why are the pulses different in timing ? Perhaps it is software generated and the 9th bit is due to timing problems.

P.S.: What makes such nice pictures ?

It's not a parity bit, the packets don't pass the parity test if I configure the decoder with parity. The limited documentation of the CDC protocol mentions the 9 databits, a few other embedded devices like this use it too.

I'm sampling at 50KHz, if I go one step lower (10KHz) it starts to skip bits.

The pictures are actually screenshots ;)

Peter_n

#3
Dec 02, 2014, 04:24 pm Last Edit: Dec 02, 2014, 04:27 pm by Peter_n
It won't be easy to write code with 16-bit buffers. Writing can be done without buffers, but I think you need a buffer for incoming data. You can use SoftwareSerial as a start, but it will be very hard.

If the 9-bits serial data is used more, is there some example code ? On this forum or in the projects section of avrfreaks.net ? When I google for it, I can find tons of pages and questions about it. It seems that the ATmega chip USART supports 9-bits.

#4
Dec 02, 2014, 10:24 pm Last Edit: Dec 02, 2014, 10:29 pm by donny007x
I've got transmitting 9-bits under control using a special command to set the 9th bit, but the signal needs to be inverted (low=logic 1, high=logic 0) with some circuitry for it to be compatible.

Code: [Select]

void setup(){
  Serial2.begin(9600);
}
void loop()
{                                         
  tx(0x0101); //100000001
  delay(5);
  tx(0x00AD); //101101010
  delay(5);
  tx(0x01FF); //111111111
  delay(100);
}
void tx(int value){
  if(value < 256){
    UCSR2B = 0b10011100; //Turn 9th bit off
    Serial2.write(value);
  }
  else if(value > 255){
    UCSR2B = 0b10011101; //Turn 9th bit on
    Serial2.write(value-256);
  }
}




I'm still clueless on the receiving end...

Peter_n


I'm still clueless on the receiving end...
So am I. You need something interrupt driven, with a 16-bit integer ring buffer. I can find many discussions about it and half-baked solutions, but not a nice example for an ATmel chip.

Well, I got it to work. The microcontroller supports 9-bit serial, with the 9th bit as an afterthought  ;).

I changed the buffers in HardwareSerial.cpp from unsigned char (8 bit) to unsigned short int (16 bit) and added the register config for 9N1 serial. The 9th bit has to be read from another register before reading the other 8 bits, and has to be set to the register before writing the other 8 bits.

Sources for the lower-level serial stuff:
http://www.appelsiini.net/2011/simple-usart-with-avr-libc
http://www.mikrocontroller.net/topic/243528

The sketch is now pretty simple. Next up is modifying the Serial.write() routine in HardwareSerial to do the same as tx().
Code: [Select]

void setup(){
  Serial.begin(115200); //pc
  Serial2.begin(9600, SERIAL_9N1);
  UCSR2B |= ( 1 << UCSZ02 );
}

int incoming = 0;
void loop()
{
  //RX Routine
  if (Serial2.available() > 0) {
    incoming = Serial2.read();
    Serial.println(incoming, HEX);
    tx(incoming);
  } 
}
//TX Routine
void tx(int value){
  if(value < 256){
    UCSR2B = 0b10011100; //Turn 9th bit off
    Serial2.write(value);
  }
  else if(value > 255){
    UCSR2B = 0b10011101; //Turn 9th bit on
    Serial2.write(value-256);
  }
}


I inverted the signals using a ULN2003A (the only thing close to a transistor that I had lying around) and successfully communicated with the head unit, writing 13:37 as the current playtime on the display:



Yellow: Head unit, Blue: Inverted signal going to Arduino, Green: Arduino repeating the same signal back:



I couldn't have done it without the logic analyzer, seeing the bits flow through the wire is a must for stuff like this.

Peter_n

I'm very impressed!
When you have working code you might make a page for it in the Playground section. I have read about many questions for 9-bit serial, but no solution yet.

MattCarp

Donny,

Do you have a reference for the Blaupunkt CDC protocol?   i.e., which commands are sent, and responses.

I'm working on a similar project, interfacing a Blaupunkt radio from 2010 (a Bremen MP78) to an old Alpine CD changer that uses Alpine's M-bus protocol.

btw, what logic analyzer did you use?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy