Autoradio Tuner List (4) : Écran LCD
2018-03-17 - 3 comments
Hardware
Ici, on a un autoradio Renault/VDO Tuner List (modèle 22DC259/62T, 77 00 434 422) et un afficheur Renault (82 00 028 364), avec un connecteur gris connecté au tableau de bord et à la radio, et un connecteur rouge connecté aux commandes situées sous le volant.
Je n'ai pas eu confiance dans les documentations que j'ai pu trouver, avec des couleurs de fils incorrectes, des brochages de connecteurs parfois à l'envers, différentes version de l'afficheur ou de l'autoradio.
Mais ce n'est pas un problème, il suffit de démonter pour vérifier qu'on ne va rien faire de dangereux. On peut rapidement identifier les pins à la masse, ceux des alimentations, et certains signaux de puissance.
Connecteur Gris :
- NTC
- GND
- NC
- NC
- GND
- Éclairage feux? (in)
- Éclairage backlight? (in)
- +12V (contact?, in)
- +12V (permanent?, in)
- NC
- GND
- LCD_ENABLE (12V, in)
- SDA (TTL, io)
- SCL (TTL, io)
- !MRQ (TTL, io, active-low)
Connecteur Rouge (TTL) :
- NC
- NC
- NC
- NC
- NC
- NC
- NC
- NC
- Commun 1
- Retour A
- Commun 2
- Retour B
- Commun 3
- Retour C
- NC
Ça permet de comprendre la majorité du câblage :
Et on peut aussi reverse-engineerer la matrice des boutons utilisés pour les commandes au volant:
Fonction | Pin commun | Pin retour |
OK | A | 1 |
VOL- | A | 2 |
VOL+ | A | 3 |
Source L | B | 1 |
Source R | B | 2 |
Pause | B | 3 |
Molette 1 | C | 1 |
Molette 2 | C | 2 |
Molette 3 | C | 3 |
Câble
Dans ce cas, la solution la plus pratique est de prendre une rallonge avec des câbles mini-ISO branchés sur l'autoradio, de couper chaque fils et de les brancher sur un connecteur à 0.1", pour y mettre des cavaliers pour une connection directe, des fils en Y pour espionner le bus ou bien des fils vers un MCU ou un analyseur logique.
Connecteur jaune C1 :
- SDA (TTL 5V)
- SCL (TTL 5V)
- !MRQ (TTL 5V)
- LCD_ENABLE (+12V)
- GND
Comme je ne voulais pas décharger la batterie ni passer plusieurs heures dans le froid, j'ai préféré démonter l'afficheur et l'autoradio pour les utiliser à l'intérieur.
Protocole
Ça nous avance bien de connaître le matériel, mais il faut encore comprendre comment l'autoradio communique avec l'écran LCD.
Pour ça, on va utiliser un analyseur logique (Cypress FX2 et sigrok/pulseview) et regarder tout ce qui passe sur le bus i2c.
On peut voir que le bus i2c fonctionne à 7.14kHz et que le signal !MRQ est constamment tiré à 0 avant que quelque chose ne soit transféré sur le bus.
En débranchant le signal MRQ de chaque côté, on peut voir que l'afficheur le force à 0 en attendant une trame de l'autoradio, mais que l'autoradio le force aussi à 0 avant d'envoyer une tram à l'autoradio. On peut aussi voir que l'autoradio est maître sur le bus i2c, et identifier l'adresse de l'écran LCD (0x23).
On peut voir plusieurs messages de 2 octets de long [0x01, 0x10] ou [0x01, 0x11], demandés au moins toutes les 500ms par l'autoradio (initié par l'afficheur qui tire le signal MRQ à 0, puis répond lorsque l'autoradio envoie une requête).
Commandes au volant
Il y a aussi une trame répondue par l'afficheur lorsqu'on appuie sur un bouton des commandes au volant, et qui permet de déduire le code de chacune des commandes au volant. L'afficheur tire le signal MRQ à 0, l'autoradio envoie une requête, puis l'afficheur envoie la trame correspondant aux boutons pressés.
Bouton | octet 0 | octet 1 | octet 2 | octet 3 | octet 4 | action |
OK | 0x04 | 0x82 | 0x91 | 0x00 | 0x00 | press |
OK | 0x04 | 0x82 | 0x91 | 0x00 | 0x40 | hold |
Source R | 0x04 | 0x82 | 0x91 | 0x00 | 0x01 | press |
Source R | 0x04 | 0x82 | 0x91 | 0x00 | 0x81 | hold |
Source L | 0x04 | 0x82 | 0x91 | 0x00 | 0x02 | press |
Source L | 0x04 | 0x82 | 0x91 | 0x00 | 0x82 | hold |
Volume + | 0x04 | 0x82 | 0x91 | 0x00 | 0x03 | press |
Volume + | 0x04 | 0x82 | 0x91 | 0x00 | 0x43 | hold |
Volume - | 0x04 | 0x82 | 0x91 | 0x00 | 0x04 | press |
Volume - | 0x04 | 0x82 | 0x91 | 0x00 | 0x44 | hold |
Pause | 0x04 | 0x82 | 0x91 | 0x00 | 0x05 | press |
Wheel up | 0x04 | 0x82 | 0x91 | 0x01 | 0x41 | |
Wheel down | 0x04 | 0x82 | 0x91 | 0x01 | 0x01 | |
Affichage
L'afficheur est rafraichi uniquement en cas de besoin, on peut l'observer en appuyant sur un bouton de l'autoradio, qui va forcer le signal MRQ à 0, puis va envoyer une trame entre 13 et 16 octets avec les caractères à afficher.
Affichage | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
98.5 | 0x0f | 0x90 | 0x7f | 0x29 | 0xff | 0x3f | 0x35 | 0x81 | 0x20 | 0x20 | 0x20 | 0x20 | 0x39 | 0x38 | 0x35 | 0x20 |
CASS [=] | 0x0f | 0x90 | 0x7f | 0x55 | 0xff | 0xff | 0x60 | 0x01 | 0x43 | 0x41 | 0x53 | 0x53 | 0x20 | 0x04 | 0x05 | 0x06 |
BAYERN 3 | 0x0f | 0x90 | 0x7f | 0x55 | 0xff | 0x3f | 0x75 | 0x01 | 0x42 | 0x41 | 0x59 | 0x45 | 0x52 | 0x4E | 0x20 | 0x33 |
Programme
On va remplacer l'autoradio par un Arduino Mega (n'importe quel micro-contrôleur avec un périphérique i2c et des IO TTL suffit), pour pouvoir écrire sur l'afficheur et lire l'état des boutons.
Avec un Atmel AVR, il faut forcer le bitrate/prescaler à environ 7kHz avec les lignes suivantes:
void conf() {
TWBR = 0xff;
TWSR = 0x01;
}
Comme c'est un programme de test qui n'a qu'une seule fonction et un MCU surpuissant pour son utilisation, il est possible d'écrire un code peu optimisé (polling au lieu d'interruptions, copy/paste).
On va initialiser l'écran en envoyant quelques trames [0x01, 0x10] et [0x01, 0x11], puis on peut écrire un peu ce qu'on veut :
void writerandom(byte *data, int len) {
while(digitalRead(2)); // polling the MRQ line
Wire.beginTransmission(0x23);
conf(); // overwrites the bitrate/prescaler after the Wire lib configures the i2c
Wire.write(data, len);
Wire.endTransmission();
}
Dans ce cas, on peut commencer par copier/coller des trames récupérées en sniffant celles envoyées par l'autoradio, puis on va reverse-engineerer le protocole complet en bouclant sur tous les caractères entre 0x00 et 0xFF, et en testant les pictogrammes.
On va aussi pouvoir lire l'état des boutons, qui sont des trames de 5 octets :
void read01() {
while(digitalRead(2)); // polling the MRQ line, pulling the MRQ line low and waiting 500us also works
conf(); // overwrites the bitrate/prescaler after the Wire lib configures the i2c
Wire.requestFrom(0x23, 5);
TWBR = 0xff;
TWSR = 0x01; // 0x00 appears to work as well
for(i = 0; i < 5; i++) {
READDATA[i] = Wire.read();
}
}
Références
- RTA 120.1 Renault Mégane/Scénic 1 1999-2003 (page 177, section essence)
- Manuel de Réparation Renault MR312-8 (pages 165-166)
- Manuel Renault/Philips MR-Radiosat-6000-10 (pages 34-36)
- TLCDEmu - Hardware, section pinouts
- HD6433834 - Datasheet Sagem/Hitachi/Renesas MCU (pages 21-27 : pinouts, pages 346-449: caractéristiques électriques)
- EEVBlog Forum - Confused about how this I2C read works, sujet de forum assez utile
- Youtube - Renault Tuner List Custom Text, proof of concept d'un autre bricoleur