Cordless Handset LCD is I2C Device

I’m working to understand how to control the LCD on the handset of an AT&T CL84209 landline phone system, and I started by observing the behavior of its eight IO pins (plus one pin already established to be ground) using the analog mode of my Saleae Logic 8 analyzer. Two pins were immediate candidates for a serial data pin and its corresponding clock pin, so I switched my analyzer to digital mode observing those two pins specifically.

Mouse hovering over the clock line, the analyzer software told me it started at a frequency of 7.2kHz and then sped up to 100kHz during the startup sequence. 100kHz is very promising, because it matches “Standard Mode” speed of I2C. The previous LCD controller I played with used a proprietary Sanyo protocol called CCB, but I’m hopeful this unknown chip uses Philips I2C. So in the spirit of “be sure to check the easy thing first” I activated I2C protocol analyzer built in to Saleae’s software. This presented a stream of decoded bytes and no sign of error.

Good news: it is indeed I2C!

Bad news: within less than ten seconds of powerup, there are 2569 captured and decoded messages. That is a lot of raw data to wade through when I don’t datasheets to make sense of it all. But the situation isn’t quite as bad as it initially looked. While I’ve tapped pins directly connected to the LCD, that doesn’t mean all the data we see on those lines are relevant. I2C is a data bus for multiple devices to communicate, and I see multiple addresses listed in the I2C decoder output.

I wanted to filter messages by address, but I failed to find such an option in Saleae software. Instead, I copied the data output into a Jupyter notebook and wrote a bit of quick-and-dirty Python to parse them. There were ten unique I2C addresses in this output:

{'0x52', '0x51', '0x50', '0x56', '0x3E', '0x53', '0x54', '0x55', '0x4B', '0x57'}

Scrolling through the decoder output, traffic to address 0x3E stood out because they were the longest. Many of these I2C messages had only one or two bytes, but some messages to 0x3E were much longer. The long messages have a pattern, they come in sets of three: two 18-byte messages followed by one with 19 bytes.

write to 0x3E ack data: 0x80 0x81 0x40 0x20 0x43 0x4F 0x4E 0x4E 0x45 0x43 0x54 0x49 0x4E 0x47 0x2E 0x2E 0x2E 0x20 
write to 0x3E ack data: 0x80 0xC1 0x40 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
write to 0x3E ack data: 0x80 0x40 0x40 0x00 0x00 0x10 0x02 0x01 0x04 0x00 0x10 0x00 0x04 0x01 0x00 0x02 0x10 0x04 0x00 

These messages won’t have enough bits to control individual dots on the dot-matrix display. However, they might contain alphanumeric data for the LCD controller to use a font lookup table. Again, in the spirit of trying the easy thing first, I compared the first line of data against an ASCII chart.

0x800x810x400x200x430x4F0x4E0x4E0x450x430x540x49ox4E0x470x2E0x2Eox2E0x20
[?][?]@[space]CONNECTING...[space]

“CONNECTING…” is the first line displayed on the LCD! We have a winner, time to dig into traffic addressed 0x3E for this I2C LCD.

Cordless Handset LCD Power-Up in Saleae Analog Mode

I have the remnants of a cordless handset from a AT&T CL84209 landline phone system. It can still power up enough to put “CONNECTING…” on its LCD and I want to learn how to talk to that LCD myself. To do this I’ve attached wires to that LCD so I could probe its control signals with my Saleae Logic 8 analyzer.

Before I get to the digital signal analysis, though, I need to be sure I’m listening on the correct lines. This is why I connected all eight potential data lines (plus the one known ground I probed earlier) to watch them all at once with my Saleae running in analog mode. This is a secondary capability for the device and while it cannot replace a real oscilloscope it is nevertheless very useful to me as I only have a cheapo single channel oscilloscope with unreliable voltage levels. While I might buy a real multi-channel oscilloscope in the future, it is unlikely to be an eight-channel unit.

Here is the handset power-up sequence, and roughly eight seconds after power is supplied:

When I probed with a voltmeter, pin 1 (channel 0) and 5 (channel 3) were candidates for 3.3V input power. With this graph, I see square wave dips in channel 0 that indicate an enable signal, so pin 5 is +3.3V. Which makes some sense as it is adjacent to ground on pin 4.

After pin 1 enable signal stayed high, right around the 2 second mark, something significantly happens where we saw activity on channels 4-7. Here is a zoomed in view of that time period:

Pin 3 (channel 2) looks like data bits clocked by pin 2 (channel 1). I’ll look at them more closely later in digital analysis mode.

We also see the beginnings of startup on remaining four pins of unknown:

  • Pin 6 (channel 4) had 3.3V as soon as power is applied to the system, and later it jumps up to 5.2V and stays there.
  • Pin 7 (channel 5) likewise had ~3.3V immediately upon power up, and when pin 6 jumps up to 5.2V it oscillates between 3.3V and 5.2V.
  • Pin 8 (channel 6) started out flat at 0V, but would oscillate between 0V and 3.3V.
  • Pin 9 (channel 7) started out flat at 0V, but would jump up to 5.2V and stay there.

The two oscillating pins are both square waves and they move in phase. (Rise and fall at the same time.) The period from one rising edge to the next is about 125us, translating to 8kHz.

Zooming out on the timescale, I see no signs of data modulation on these pins:

I think these are voltages applied to LCD segments. It would be easy for me to replicate pin 8 square wave of 0V to 3.3V with a 3.3V microcontroller like ESP8266, but it’s not clear how I would replicate pin 7 square wave between 3.3V and 5.2V. A headache I will set aside for later.

The relationship between pins 6 and 9 is puzzling. Since pin 6 had 3.3V immediately upon powerup, and its voltage started rising before the other three pins, I thought it was the best candidate for a 5.2V power supply rail. My hypothesis was that it is connected to a boost converter external to the LCD that would pump the 3.3V up to 5.2V. The counterargument is the fact that pin 9 reached 5.2V before pin 6 did, so I’m not sure what’s going on.

While I think over the analog voltage startup behavior puzzle, I switched my logic analyzer to digital mode (what it’s designed for) for a look at the digital data and clock lines.

Preparing Cordless Handset LCD for Logic Analysis

I’ve decided to take another look at a pair of LCD units salvaged from an AT&T CL84209 landline phone system. I have a bare LCD from the base station, and an LCD still attached to the remnants of a cordless handset. I had wired those two LCDs in parallel, a crazy roll of the dice that paid off in knowledge that those two LCDs use the same communication protocol. Now I am armed with a logic analyzer (Saleae Logic 8) and intend to get more details.

The first step is to attach wires to the handset LCD so I could probe communication traffic, similar to how I attached the bare LCD earlier but with less risk and higher chance of doing something useful. I recycled the bundle of wires I had used to perform the same task on a Toyota tape deck faceplate, which had more wires that I folded out of the way for this project. Having done similar tasks a few times, I’m starting to think about buying PCBite probes that promise to let me skip this soldering task. But I’m not yet at the point where I expect to use them enough to justify the expense.

There are nine pins on this LCD, which given my lack of official datasheet I’ve arbitrarily numbered from left to right as shown in the picture above. Earlier I had probed these connection points with a voltmeter while the handset circuit board was running. All of the pins appear to be safely within Saleae logic analyzer 25V limit relative to ground, which I determined to be pin 4. That left 8 pins I don’t understand and conveniently, my Saleae has 8 inputs so I could connect them all and not have to make decisions on which pins to omit. Once connected, I could take my first look with the Saleae in analog mode.

LCD Exploration Unwinds Back to CL84209

In my electronics teardown and salvaging adventures, I kept a few segmented LCD units with the intent to learn about them later. After I watched Joey Castillo’s Remoticon presentation on LCDs, I decided it was time to take some LCDs out of my pile and start learning how to use them.

In hindsight, I undertook this adventure in backwards order. I couldn’t make heads or tails of my first attempt, and the second didn’t fare much better though it gave me enough information to infer those two LCDs both came from an AT&T CL84209 wireless landline system. The third attempt was a car tape deck I managed to power up, but it was too advanced of a system and wouldn’t help me learn LCDs basics. The fourth item was an LCD salvaged from a food thermometer, but I had problems trying to attach wires to this display. I was finally successful on the fifth try, obtaining full control over a simple segmented LCD salvaged from an electric blanket controller.

After that success, I started unwinding my stack of failures. A bit of hackery and a lot of patience allowed me to map out the food thermometer LCD on my second try.

With these two examples of low-level LCD control, I returned to the tape deck and learned how to work at a higher level with its LCD controller. I even learned a new communication protocol (Sanyo’s CCB) and programmed an Arduino Nano to speak its language.

Obtaining a full understanding of how to interface with the faceplate was very satisfying. Two key factors made it possible: the LCD controller’s datasheet, and a Saleae logic analyzer.

Armed with this experience, I will now return to where I started: to the mystery LCD units salvaged from an AT&T CL84209 landline phone system. I found nothing to identify their LCD controller, so I would have to go without a datasheet. However, I do have one valuable datapoint: a risky experiment proved that while those two LCDs were different, they do communicate with the same protocol. This is enough of a starting point for me to dive in with my logic analyzer.

Home Assistant OS in KVM Hypervisor

I encountered some problems running Home Assistant Operating System (HAOS) as a virtual machine on a TrueNAS CORE server, which is based on FreeBSD and its bhyve hypervisor. I wanted to solve these problems and, given my good experience with Home Assistant, I was willing to give it dedicated hardware. A lot of people use a Raspberry Pi, but in these times of hardware scarcity a Raspberry Pi is rarer and more valuable than an old laptop. I pulled out a refurbished Dell Latitude E6230 I had originally intended to use as robot brain. Now it shall be my Home Assistant server, which is a robot brain of sorts. This laptop’s Core i5-3320M CPU launched ten years ago, but as a x86_64 capable CPU designed for power-saving laptop usage, it should suit Home Assistant well.

Using Ubuntu KVM Because Direct Installation Failed Boot

I was willing to run HAOS directly on the machine, but the UEFI boot process failed for reasons I can’t decipher. I couldn’t even copy down an error message due to scrambled text on screen. HAOS 8.0 moved to a new boot procedure as per its release announcement, and the comments thread on that page had lots of users reporting boot problems. [UPDATE: A few days later, HAOS 8.1 was released with several boot fixes.] Undeterred, I tried a different tack: install Ubuntu Desktop 22.04 LTS and run HAOS as a virtual machine under KVM Hypervisor. This is the hypervisor used by the Linux-based TrueNAS SCALE, to which I might migrate in the future. Whether it works with HAOS would be an important data point in that decision.

Even though I expect this computer to run as an unattended server most of the time, I installed Ubuntu Desktop instead of Ubuntu Server for two reasons:

  1. Ubuntu Server has no knowledge of laptop components, so I’d be stuck with default hardware behavior that are problematic. First is that the screen will always stay on, which wastes power. Second is that closing the lid will put the machine to sleep, which defeats the point of a server. With Ubuntu Desktop I’ve found how to solve both problems: edit /etc/systemd/logind.conf and change lid switch behavior to lock, which turns off the screen but leaves the computer running. I don’t know how to do this with Ubuntu Server or Home Assistant OS direct installation.
  2. KVM Hypervisor is a huge piece of software with many settings. Given enough time I’m sure I could learn all of the command line tools I need to get things up and running, but I have a faster option with Ubuntu Desktop: Use Virtual Machine Manager to help me make sense of KVM.

KVM Network Bridge

Home Assistant instructions for installing HAOS as a KVM virtual machine was fairly straightforward except for lack of details on how to set up a network bridge. This is required so HAOS is a peer on my home network, capable of communicating with ESPHome devices. (Equivalent to the network_mode: host option when running Home Assistant Docker container.) HAOS instruction page merely says “Select your bridge” so I had to search elsewhere for details.

A promising search hit was How to use bridged networking with libvirt and KVM on linuxconfig.org. It gave a lot of good background information, but I didn’t care for the actual procedure due to this excerpt: “Notice that you can’t use your main ethernet interface […] we will use an additional interface […] provided by an ethernet to usb adapter attached to my machine.” I don’t want to add another Ethernet adapter to my machine. I know network bridging is possible on the existing adapter, because Docker does it with network_mode:host.

My next stop was Configuring Guest Networking page of KVM documentation. It offered several options corresponding to different scenarios, helping me confirm I wanted “Public Bridge”. This page had a few Linux distribution-specific scripts, including one for Debian. Unfortunately, it wanted me to edit a file /etc/network/interfaces which doesn’t exist on Ubuntu 22.04. Fortunately, that page gave me enough relevant keywords for me to find Network Configuration page of Ubuntu documentation which has a section “Bridging” pointing me to /etc/netplan. I had to change their example to match Ethernet hardware names on my computer, but once done I had a public network bridge upon my existing network adapter.

USB Device Redirection

Even though I’m still running HAOS under a virtual machine hypervisor, ESPHome could access USB hardware thanks to KVM device redirection.

First I plug in my ESP32 development board. Then, I open the Home Assistant virtual machine instance and select “Redirect USB device” under “Virtual Machine” menu.

That will bring up a list of plugged-in USB devices, where I could select the USB to UART bridge device on my ESP32 development board. Once selected, the ESPHome add-on running within this instance of HAOS could see the ESP32 board and flash its firmware via USB. This process is not as direct as it would have been for HAOS running directly on the computer, but it’s far better than what I had to do before.

At the moment, surfacing KVM capability for USB device redirection is not available on TrueNAS SCALE but it is a requested feature. Now that I see the feature working, it has become a must-have for me. Until this is done, I probably won’t bother migrating my TrueNAS server from CORE (FreeBSD/bhyve) to SCALE (Linux/KVM) because I want this feature when I consolidate HAOS back onto my TrueNAS hardware. (And probably send this Dell Latitude E6230 back into the storage closet.)

Start on Boot

And finally, I had to tell KVM to launch Home Assistant automatically upon boot. By checking “Start virtual machine on host boot up” under “Boot Options” setting.

In time I expect that I’ll learn the KVM command lines to accomplish what I’m doing today with Virtual Machine Manager, but today I’m glad VMM helps me get everything up and running quickly.

[UPDATE: virsh autostart is the command line tool to launch a virtual machine upon system startup. Haven’t yet figured out command line procedure for USB redirection.]

Home Assistant OS in TrueNAS CORE Virtual Machine

I started playing with Home Assistant in the form of Home Assistant Core, a docker container, for its low commitment. Once I decided Home Assistant was worthwhile, I moved up to running Home Assistant Operating System as a virtual machine on my TrueNAS CORE server. This move gained features of Home Assistant Supervisor and I found the following subset quite useful:

  • Easy upgrade and rollback for failed upgrades.
  • Add-on integration features, especially for ESPHome.
  • Ability to backup critical data in a compact *.tar file.

The backup situation is a tradeoff. When I ran Home Assistant Core docker container, I could map its data directory to my TrueNAS storage pool. It was a more robust data retention system, as I had configured it for nightly snapshots and regular backups to external media. However, this would take upwards of hundreds of megabytes especially when I’m flooding the Home Assistant database. In contrast, the data backup archive generated by Home Assistant Supervisor is tiny at only a few megabytes. I have ambition to eventually get the best of both worlds: a Home Assistant automation that triggers Supervisor backups, and then store those backup files on my TrueNAS storage pool. This should be possible, as people have created addons to perform automatic backups and upload to Google Drive. But right now I have to do it manually.

Unrelated to the backup situation, there were two significant downsides to running Home Assistant OS on a TrueNAS CORE virtual machine.

  1. The virtual machine does not have access to hardware. If ESPHome add-on could access USB, it could perform first-time firmware upload on ESP32/ESP8266 devices. Without hardware access, I have to perform initial upload some other way which is cumbersome. (Following uploads could be done via WiFi, a huge benefit of ESPHome.)
  2. There are various problems with the FreeBSD bhyve hypervisor running Linux-based operating systems. A category of them (apparently there are more than one) interferes with the ability for a Linux operating system to reboot itself. In practice, this means every time the Home Assistant OS updates itself and reboots, it would shut down but not restart. At one point, I could not perform manual shutdown from TrueNAS interface, so the horrible workaround was to reboot my TrueNAS server. After a few TrueNAS updates, I can now manually shut down and restart the VM. But it is still a big hassle to do this on every Home Assistant OS update.

Due to these problems, I would NOT recommend running Home Assistant OS as a TrueNAS CORE virtual machine. Issue #2 became quite annoying and, when my Home Assistant got stuck trying to reboot for an upgrade to Home Assistant OS 8.0, I decided it was time to try a different setup.

Salvage Tape Deck Faceplate Connector (Toyota 86120-08010)

I’ve successfully made a simple Larson Scanner demo from the faceplate module of a Toyota 86120-08010, the stock tape deck audio head unit of a 1998 Toyota Camry LE. It gave me confidence that I wouldn’t need the original mainboard anymore.

Nor would I expect to want to probe communication between the original mainboard and the faceplate, both separately and alone. Time for a little cleanup work, undo the tangle of wires and get to something more streamlined.

I started by detaching the wires I attached earlier.

The excellent Engineer SS-02 solder sucker helped me remove all the solder attaching the mainboard connector, freeing it for reuse.

Good news: This connector has two rows of easy-to-solder through-hole pins, with the 0.1″ pitch common to perforated prototype boards. The two rows are 0.1″ apart as well.

Bad news: The two rows are staggered, which won’t fit on a 0.1″ perforated prototype board. Reusing this connector properly will mean a custom circuit board.

In the meantime, I can still make use of that connector even if “improperly”. I had soldered wires directly to the faceplate for probing and experimentation, but I can move all of those wires to that connector even without a circuit board.

Soldering wires directly to the pins isn’t best practice, but it allows me to move and store this assembly with less worry I’ll accidentally yank something off the faceplate.

Larson Scanner Demo for Tape Deck LCD

I am happy with a sense of accomplishment after I deciphered all the information necessary to utilize this circuit board, formerly the faceplate for a salvaged car tape deck. I started this investigation when I found I could power it up under control of the original mainboard. Now, I can work with the LCD and read all knobs and buttons with an Arduino, independent of the original mainboard. My original intent was just to see if I could get to this point. I thought I would learn a lot whether I succeeded or failed trying to control this faceplate. I have gained knowledge and experience I didn’t have before, and a faceplate I can control.

Now what?

It feels like I should be able to build something nifty with this faceplate, there’s room to be creative in repurposing it. At the moment I don’t have any ideas that would creatively utilize the display and button/knob input, but I could build a simple demo. This LCD is wide and not very tall, so I thought I would make it into a simple Larson Scanner. (a.k.a. Cylon lights a.k.a. K.I.T.T. lights.)

First, I divided the LCD segments into 16 groups of roughly similar size. I started using my segment map to generate the corresponding bit patterns by hand but then decided I should make a software tool to do it instead. I’ve already written code to light up one segment at a time for generating the segment map, it took only a bit of hacking to make it into a drawing tool. I use the knob to move segments as I did before, but now I could press the knob to toggle the selected segment. Every time I pressed the knob, I print the corresponding bit pattern out to serial terminal in a format that I could copy into C source code.

I then added a different operating mode to my Arduino test program. Pressing the Volume knob would toggle between drawing mode and Larson Scanner mode. While in Larson Scanner mode, I would select two of those 16 groups based on scanner position, and bitwise OR them together into my display. This gives me a nice little demo that is completely unrelated to this LCD’s original purpose, and confidence I no longer need this tape deck’s original mainboard.


Source code for this demo is publicly available on GitHub.

Pinout of Tape Deck Faceplate (Toyota 86120-08010)

It is time to wrap up investigation into the workings of a tape deck faceplate, salvaged from the stock audio head unit of a 1998 Toyota Camry LE. I believe I’ve deciphered all the information necessary to reuse this faceplate independently from the rest of the tape deck. Summarized in this pinout report with links to more details.

The faceplate circuit board is largely built around a Sanyo LC75853N chip, which communicates via a Sanyo proprietary protocol called CCB (Computer Control Bus). An external microcontroller (I used an Arduino Nano in experiments to date) can dictate what is displayed on the LCD (see segment map here) and scan pressed/not-pressed state of buttons (see button map here).

Some faceplate components are independent of LC75853N:

From right-to-left, functionality I observed on these pins are:

LabelFunction
ACC5VPower supply for digital logic.
+5V relative to GND
LCD-DOCCB digital data out.
LC75853N address 0x43
Single 4-byte transmission to microcontroller.
LCD-DICCB digital data in.
Microcontroller to LC75853N address 0x42.
Three 7-byte transmissions to LC75853N.
LCD-CLKCCB clock signal.
Active-low generated by microcontroller.
LCD-CECCB enable.
Active-high generated by microcontroller.
CD-EJEEject button.
Normally open, shorts to GND when “Eject” button is pressed.
ILLIllumination power supply (positive).
+5V to +14.4V (~60mA) relative to ILL- for variable button backlight brightness.
LCD-BLLCD backlight power supply (positive).
+6V (~60mA) relative to BL-
VOL.CONVolume control potentiometer.
Voltage between ACC5V (full clockwise) and GND (full counterclockwise)
PULS-AAudio mode quadrature encoder knob – A
ACC5V or GND, will be opposite of B when at a detent.
A and B briefly identical during transition between detents.
PULS-BAudio mode quadrature encoder knob – B
ACC5V or GND, will be opposite of A when at a detent.
A and B briefly identical during transition between detents.
GNDDigital logic power (negative).
Relative to ACC5V
ILL-Illumination power supply (negative)
Relative to ILL
BL-LCD backlight power supply (negative)
Relative to LCD-BL
RESETUnknown. Observed 0V relative to GND.
LC75853N has no reset pin.
Seems OK to leave it unconnected/floating.
Unknown. Observed 0V relative to GND.
Seems OK to leave it unconnected/floating.

Source code for this investigation (and accompanying demo) is publicly available on GitHub.

Button Presses on Tape Deck Faceplate (Toyota 86120-08010)

I’ve mapped out all LCD segments on a Toyota 86120-08010 tape deck faceplate, allowing me to control what is displayed from an Arduino. Constrained by the nature of a segmented LCD, of course. These segments were customized for a tape deck, doing what it needs and no more. Any projects trying to repurpose it would have to get creative. This will be even more difficult than abstract Nyan Cat on a VCR VFD!

But I have more than just the LCD, I have the entire faceplate which gives me option for user interactivity. Two knobs which I still have, and buttons which are now gone but their electrical traces are still present. I can find something conductive to bridge these traces like the buttons used to do, or I can solder wires connecting to switches elsewhere. Either way, I needed to write code for my Arduino to read key scan data from the Sanyo LC75853N chip. Just like LCD segment control data, my goal is to emulate the original mainboard as closely as I can. I will be guided by the datasheet and what my logic analyzer captured.

Thanks to lessons learned from doing LCD segment control CCB communication, reading keyscan data over CCB was relatively straightforward and I could dump control data out to Arduino serial monitor.

I will follow the KD1-KD30 numbering system used in the datasheet timing diagram.

Button map for Toyota 86120-08010 faceplate. (Click to view full size)

This key map shows the KD number for almost all of the buttons on the faceplate, including the push action on both knobs. The lone exception is the “Eject” button, which has its own dedicated wire and is not part of LC75853N key matrix. These numbers may look odd at first glance, but they make sense once we look at how they would be wired to the LC75853N:

These fifteen buttons make use of KS3-6 and KI2-5, learning only KD14 unused in its matrix. If I wanted to add in a single button, I will try to find KS3 and KI4 traces on the faceplate to wire in KD14. If I want to add more buttons, I might need to solder directly to the unused IC pins KI1, KS1, and KS2 as I wouldn’t expect any traces for those unused pins on the faceplate circuit board.

Feeling good that I’ve figured out the input & output of this faceplate, it’s time to wrap it all up.


Source code for this investigation is publicly available on GitHub.

Segmented LCD on Tape Deck Faceplate (Toyota 86120-08010)

Thanks to well-labeled connectors and an online datasheet, I can write Arduino code to control faceplate LCD of the stock tape deck audio unit from a 1998 Toyota Camry LE. (86120-08010). However, knowledge of the digital wiring doesn’t tell me anything about the physical location and shape of each segment in the LCD. I will build a segment map with the help of a knob already on the faceplate. The Sanyo LC75853N chip could control up to 126 segments. I edited my Arduino program to turn on all of them, so I could take this picture to see where segments even existed.

It reflected the custom nature of a segmented LCD. Some of these digits would only ever display numbers, so they had the standard 7 segments for numeric display. Others have a secondary use to display letters for a few audio settings, and those digits had more than 7 segments. But they can’t display arbitrary letters, only exactly what was needed and no more.

With the full set of available segments in hand, I changed the program to turn on just one segment at a time interactively selected via the “Audio Mode” knob. Since each segment is a single bit, I could print out my control bits to Arduino serial monitor to see current active segment’s programmatic address.

I’m using the same numbering system as used in the datasheet, D1 to D126. From there, I generated this segment map:

LCD segment map for 86120-08010. Click to view full size.

When I first started my Arduino program, I saw nothing for the first few turns of the dial. I thought perhaps my program was faulty, but a few turns later I saw my first result for D13. From there on it was relatively straightforward, working from bottom-to-top and right-to-left. Some notes:

  • D24 is missing, a mysterious gap.
  • There were a few segments that I had thought were separate but were actually the same segment. For example, two visually distinct segments were actually just D54. This was disappointing, because it restricted the number of letters we could show. (Example: a good looking “M” would be possible, but a good looking “N” wouldn’t.)
  • Along the same lines, some numeric segments looked like separate segments purely for the sake of preserving the 7-segment aesthetic. The three segments D101, D102, and D105 together could display either “1” or “2” but visually looked like 6 segments instead of 3.
  • The leftmost large numeric digit puzzled me. It could only display 1, which is fine. But given that, why are the two segments D91 and D92 individually addressable? I can’t think of a reason why we’d want to display only the top or bottom half of a “1”.

Here is a table from the LC75853N datasheet mapping segment numbers to pins. I colored in the segments that were seen and a clear pattern emerged: This LCD allocation avoided using the first four pins (S1-S4) leaving the option of using them as general-purpose output wires. (P1-P4) At the end, stopping at D105 meant they didn’t have to wire up the final seven output pins. (The final two S41 and S42 would have had to been reallocated from key scan duty KS1 and KS2, if used.)

None of this explains why D24 is missing. The answer to this mystery must lie elsewhere.

Now that I know what is on this LCD available to display, maybe I can think of a creative way to reuse it. While I think that over, I’ll proceed to work through how to read input from this faceplate.


Source code for this investigation is publicly available on GitHub.

Reading Faceplate “Audio Mode” Knob

Once I got a retired faceplate’s LCD up and running, I realized I was wrong about its backlight circuitry. Now that it’s been sorted out, attention returns to the LCD. I want to map out all the segments, which means I need to get some way to interactive select individual segments. Recently I’ve used ESPHome’s network capabilities for interactivity, but this project uses an Arduino Nano for its 5V operating voltage. I can wire up my own physical control, but the faceplate already had some on board. Earlier probing established Power/Volume knob is a potentiometer, and Audio Mode knob is a quadrature encoder with detent.

The encoder is perfect for selecting individual segments. I can write code to activate one segment at a time. When the knob is turned one way, I can move to adjacent segments in one direction. When the knob is turned the other way, segment selection can follow suit. However, this knob does have one twist relative to my prior experience: Each detent on this encoder is actually two steps. When the knob is at rest (at a detent) the A and B pins are always different. (High/low or low/high). Intermediate values where A and B pins are the same (high/high or low/low) occur between detents.

This places timing demands for reading that knob. For encoders where each detent is a single step change and turned by human hands, polling once every hundred millisecond or so would be fast enough. However, since this knob can flash through a step very quickly between detents, I need to make sure those steps do not get lost.

There are many quadrature encoder libraries available for the Arduino platform. I selected this one by Paul Stoffregen, who I know as the brains behind the Teensy line of products. When working with interrupt-capable pins, this library will set up hardware monitoring of any changes in encoder state. This makes it very unlikely for encoder steps to get lost. According to Arduino documentation for attachInterrupt(), all ATmega328-based Arduino boards (including the Arduino Nano I’m using) have two interrupt-capable pins: 2 and 3. Using those pins resulted in reliable reading of knob position for mapping out segments of this LCD.


Source code for this investigation is publicly available on GitHub.

Two Separate Sets of Faceplate Illumination (Toyota 86120-08010)

I’ve successfully programmed an Arduino to interface with LCD controller on the faceplate of a retired car tape deck. When under the control of its original mainboard, the LCD segments and the LCD backlight always turned on and off in lockstep, leading me to think LCD backlight was under control of the LCD segment controller. But now that I have active LCD segments but no LCD backlight, I know my assumption was wrong. I’ll need to look elsewhere.

Looking at my notes from measuring voltage of each pin relative to data ground, two candidates stood out because their voltage levels changed when the LCD was active vs. inactive. When the LCD is on, there is ~6V difference between them. And when the LCD is off, there is ~0.5V between them. One candidate’s label was cropped at the bottom. Earlier I guessed maybe it said “CD-BL” but now that I look closer, I think the vertical bar to the left is part of the text: a “L” with its bottom cropped. That label is possibly “LCD-BL” which I optimistically expand to “Liquid Crystal Display Back Light”. The other candidate pin is labeled “BL-” which would be the negative terminal. Notably, “BL-” fluctuated relative to “GND” so these two pins, if they are our targets, have their own voltage planes.

The first test was with my backlight LED tester, which quickly shot up to the preset current limit of 20mA at less than 1V while the backlight stayed dark. I then measured with an Ohm meter, which indicated just 10 Ohms between these two pins. If that is a LED current-limiting resistor, it is the smallest I’ve ever measured. Might this backlight be some technology other than LEDs? I don’t know how a compact fluorescent light would look like under an Ohm meter. (I do know a filament bulb usually shows up as a short a.k.a. direct connection with no resistance.) I can’t see the actual light source, as it is buried within the metal case of the LCD assembly.

Well, this is a piece of salvaged electronics and I have little to lose. Especially since I believe the backlight is on its own circuit. So if I accidently destroy the backlight, I still have the rest of the faceplate to play with. I soldered wires to “LCD-BL” and “BL-” and connected it to my bench power supply. Gradually turning up the voltage, I start seeing a dull glow at just under 5V and got brighter as it reached 6V.

Illumination of this backlight isn’t great, but consistent with how it looked when I powered it up with the original mainboard.

The diffuser behind this LCD isn’t nearly as good as what we see behind, say, the screen of an Amazon Fire tablet. But it works well enough for us to see the LCD segments in the dark, and that’s all it needed to do in a car. These LEDs do not need to be daylight visible, as the LCD is readable in the presence of ambient daylight without backlight help.

At 6V this backlight drew almost 70mA, which is LED territory after all. If this was a piece of cheap consumer electronics, I would say 70mA indicates three heavily-driven LEDs. But this is from a Toyota, a brand with reputation for engineering for longevity. So I’m going to assume it actually represents four (or more) lightly driven LEDs. I increased the voltage until 9V, at which point it drew 80mA and was still pretty dim and uneven. I guess “bright enough to be legible at 6V” is all we’re going to get out of this backlight.


Since I had the bench power supply set up for testing LEDs anyway, I connected wires to two other pins “ILL” and “ILL-” which I had already determined to be on their own independent voltage plane as well. These wires are connected to the in-car dashboard illumination circuit, which has a dimmer knob. Being on a separate power plane explains the behavior I remember from using this tape deck in the car: lights illuminating faceplate buttons would change in brightness as I moved the dimmer knob, but the LCD backlight LED stayed at constant illumination. When I powered them directly on ILL/ILL-, I start seeing a tiny bit of glow at just over 5V (<10mA) and brighter as the voltage is increased.

I stopped at 14.4V (80mA) which is the maximum recommended voltage level for automotive lead-acid batteries, and thus likely to be the ceiling for automotive electrical systems like this one.


Between these two sets of lights, it means any project to repurpose them will need to generate multiple voltages. Up to 14.4V for button backlights (variable if we want dimming), 6V for LCD backlight, and 5V for digital logic including physical controls like the Audio Mode knob.

Successful Arduino Test of LC75853N Control

Using a Saleae Logic 8 Analyzer, I’ve examined the communication protocol between the mainboard and faceplate of a car tape deck. These signals match expectations of a Sanyo LC75853N LCD controller which uses Sanyo’s proprietary CCB (Computer Control Bus) protocol. CCB has some resemblance to SPI and I2C but is neither, though close enough to SPI for me to use the SPI analyzer mode on a Saleae analyzer.

But “close enough” won’t be good enough for the next step: take an Arduino Nano and write code to talk to the LCD controller via CCB, copying the data waveform behavior I saw as closely as I can. Arduino has a library for SPI that assumes control of the enable pin, which has different behavior under CCB so that would not work here. I investigated using the shiftIn() and shiftOut() routines, which is part of the standard Arduino library. They are software implementations of a clocked serial data transfer routine, but unfortunately their clock signal behavior is different from what I saw of CCB under the logic analyzer. (Active-low vs. active-high.) In order to emulate behavior of the tape deck mainboard, I would have to write my own software implementation of CCB serial data transfer.

On the hardware side, I could no longer avoid soldering to small surface-mount connector pins on the back of the faceplate. I started simple by soldering the four data communication wires: LCD-DO, LCD-DI, LCD-CLK, and LCD-CE. Probing the circuit board with my meter, the only alternative soldering points were directly to the LC75853N, and those pins are even smaller. However, I found alternatives for ACC5V and GND: those were directly connected to the volume control potentiometer, which has nice big through-hole pins for me to solder to. I soldered these wires to a small prototype board with header pins, which then plugged into a breadboard alongside my Arduino Nano.

As a “Hello World” for CCB, I wrote code to replicate the control signals as closely as I could. I won’t try to replicate the exact timing of every pulse captured by my logic analyzer because (1) Arduino doesn’t make that level of control easy and (2) the CBB spec has no explicit requirement for precise timing anyway. However, I aim to make sure relationship between every clock, data, and enable pin high/low transition is preserved. I can verify this by capturing my Arduino output and compared the output to what I captured from the tape deck mainboard, look for where they are different, and fix differences over several iterations. Finally, I was satisfied the data waveforms look the same (minus the timing caveat above) and connected the faceplate.

These are almost the same LCD segments that are visible when I captured the data communication between mainboard and faceplate.

The only difference I see is “ST” in the upper right, which lights up when the FM tuner has a good enough signal to obtain stereo audio. Since this tape deck didn’t have an antenna attached, “ST” blinks on and off. Apparently, I had taken this picture when “ST” was on, and the recorded control signal I played back on an Arduino was when it was off. This is close enough to call my first test a success.

The other visible difference was the backlight: illuminated when I captured the data control message, but dark when I played it back. I had hoped the backlight was under LC75853N control somehow, but it looks like those LEDs are actually separately controlled.


Source code for this investigation is publicly available on GitHub.

Logic Analyzer on Sanyo LC75853N Key Scan Input

I’m learning to understand control communications for a Sanyo LC75853N, which drives the LCD in the stock tape deck head unit of a 1998 Toyota Camry LE. My goal is to control the faceplate independent of the rest of the head unit, which means learning about Sanyo’s proprietary CCB (computer control bus) protocol. CCB resembles some parts of SPI and some parts of I2C but is neither of them. I was primarily focused on the LCD output, but in setting up my logic analyzer to look at LCD output control, I also have everything to examine keypress input.

Here is the Saleae logic analyzer output for the chip reporting that the volume knob was pressed, which is designed as the on/off toggle for this tape deck. The controller toggled LCD-CLK 32 times during this data transmission. Datasheet says the first 30 bits represent state for each of the scanned keys, followed by one bit representing sleep state, and one bit of padding whose state is irrelevant. Here the 0x08 represents the single scanned key that corresponds to the knob being pressed.

Before that happened, though, were several events of note. When a CCB peripheral wants to report data to the controller, it pulls the DO line low. (Spec sheet says DO has a 1k – 10k pull-up resistor.) It then waits for the controller to emit a peripheral address and then raise CE.

  • If the controller emitted the peripheral’s address, then it can start using DO to report bits upon each CLK pulse.
  • If the controller emitted another peripheral’s address, then it releases DO (letting it be pulled high again) and wait until CE is low, at which point it pulls DO low again.

When I read this part of the spec, I was confused at how the LC75853N would know whether to transmit or to receive when its address was called. Eventually I found the answer: it has two different addresses! Address 0x42 receives LCD data from the controller, and address 0x43 reports key scan data to the controller. I had missed the difference when I looked at the logic analyzer output earlier, 0x42 looked a lot like 0x43 when I was skimming through output. But it’s plainly there once I was paying attention. Address is transmitted on DI from the least significant bit first: 1100 0010.

Counting buttons on this faceplate, I don’t think it wired up all 30 possible key scans. But aside from the power button (pressing volume knob) logged here, I don’t know what they are. I might map them once I can perform CCB communication to read these key press reports. And if I fail to do that… I guess I wouldn’t care anyway. Onward to the Arduino!

Logic Analyzer on Sanyo LC75853N LCD Control

My Saleae Logic 8 analyzer is now tapped into communication between the mainboard and face plate of a tape deck. A quick examination of the captured data looks reasonable, now it is time to dig into the data, compare against the LC75853 datasheet, and understand what is going on with LCD output control.

Within the ~3/4 second of the faceplate getting power, this sequence is transmitted repeatedly approximately once every 5 milliseconds. Zooming in, I see they are three consecutive CCB transmissions to address 0x42:

Address1234567
0x420x000x000x000x000x000xC00x10
0x420x000x000x000x000x000x000x80
0x420x000x000x000x000x000x000x40

Guided by the datasheet, I interpret them as:

  • Most of the 0x00 bits indicate the corresponding LCD segment is to be turned off.
  • Some of the 0x00 bits in the second and third set are fixed data.
  • In the first set, the two bits in 0xC0 maps to S0 and S1, which controls sleep mode. S0 =1 and S1=1 is one of three available sleep modes.
  • Also in the first set, the single bit in 0x10 translates to SC, the segment on/off control data. SC=1 means display state is off.
  • For the second and third set, they each have a single bit that appear to be fixed within the section labeled as DD (direction data) and their values written into the timing diagram.

After that initial ~3/4 of a second, the pattern makes a minor change and repeats less frequently: once every 50 milliseconds:

Address1234567
0x420x000x000x000x000x000x000x10
0x420x000x000x000x000x000x000x80
0x420x000x000x000x000x000x000x40

The two bits associated with sleep mode are now zeroes. Sleep flags S0=0 and S1=0 means “Normal operation”, so the chip is awake. SC is still 1, though, so LCD is still off.

Then I pressed the power button. This triggered a set of events (probably related to key scan reporting) that I will investigate later. Right now, I am focused on how the LCD control message changed to display “FM 1 CH 1 87.9”

Address1234567
0x420x000x000x000xD00xDD0x020x00
0x420x700x550x000x000x000x000x80
0x420x060x040x0B0x000x000x000x40

The end of first set changed from 0x10 to 0x00. This cleared the SC flag, so now LCD is on. There are other control bits in the first set of bytes and they are all zero.

  • K0 and K1 set to zero means none of the key scan pins were reassigned to segment control duty, so the chip retains ability to scan up to 30 keys.
  • P0 and P1 set to zero means none of the segment pins were reassigned to digital output duty, so the chip can control a maximum of 120 segments.
  • DR set to zero means 1/3 bias drive voltage.

The display backlight is also illuminated now, but which of these bits are responsible? For now, that is still an unknown. Until I get more information otherwise, I’ll proceed on the assumption that all remaining bits are LCD segment control.

To get more information, I pressed the “Mode” knob changing the display to “BAS 0” and its control message to this:

Address1234567
0x420x000x000x000x000xC00x020x00
0x420x0D0x800xDC0xF40x2F0x020x80
0x420x000x000x000x000x000x000x40

That’s a lot of changes!

For a smaller delta, I turned the knob one step so it now shows “BAS 1”.

Address1234567
0x420x000x000x000x000x800x020x00
0x420x000x800xDC0xF40x2F0x020x80
0x420x000x000x000x000x000x000x40

This is a more manageable set of changes. A single step changes “0” to “1”, which on a 7-segment display means turning off four segments. A change from 0xC0 to 0x80 turns off one bit, and from 0x0D to 0x00 turns off three bits. This matches expectation of deactivating four segments.

I didn’t take pictures for the next experiment: While in FM radio mode, I press the tuner up button once. This moved it off the first preset so “CH 1” disappeared and now the display shows “FM 1 88.1”:

Address1234567
0x420x000x000x000x100xD10x020x00
0x420x7F0x550x000x000x000x000x80
0x420x000x000x0B0x000x000x000x40

Then I pressed it again, so it now displays “FM 1 88.3”:

Address1234567
0x420x000x000x000xD00xD90x020x00
0x420x7F0x550x000x000x000x000x80
0x420x000x000x0B0x000x000x000x40

All changes are in the first part of the control message. Changing from 0x10 to 0xD0 turns on two bits, 0xD1 to 0xD9 turns on one bit. These added up to the three activated segments, matching expectation of going from a “1” to “3” on a seven-segment numeric display.

These observations give me confidence that we are indeed looking at control bits corresponding to individual segments on screen. Not enough information to map out all the segments to their corresponding bits, but I am postponing that task until I have individual control through code. It would be much easier to map out segments when they are under my control. And if I fail to obtain control, I wouldn’t care about the segment map anyway.

With some confidence I understand the output side, now to look at the input side.

Sanyo CCB Close Enough to SPI For Logic Analyzer

I’m examining the control signals for a Sanyo LC75853N LCD driver chip, which uses a Sanyo proprietary protocol they call CCB. (Computer Control Bus.) It’s popular enough that I could find CCB reference material online, but it’s not popular enough to be natively understood by Saleae’s Logic Analyzer software. Beyond Saleae’s set is a list of Community Shared Analyzers but Sanyo CCB didn’t make the cut there, either. Those additional analyzers were written using Saleae’s Protocol Analyzer SDK so there is the option to write one for CCB. For the purpose of initial experimentation, though, their default SPI analyzer is close enough.

Before we even try using the SPI analyzer, we can look at the raw data. CCB transmits the peripheral address before raising CE. Here I can see 0x42 hexadecimal, or 0b01000010 binary. (The white binary numbers were not part of Saleae software, I drew it in afterwards.) In an unfortunate bit of coincidence, this binary value is symmetric so it alone couldn’t tell us if CCB transfer least-significant bit first or most-significant-bit first. According to spec, it is least-significant-bit first. Seeing this gave me the confidence I’ve wired up everything correctly for further probing.

The clock pulses measured out to be in the ballpark of 400kHz, which I can probably work with. But more importantly, I was relieved to see that the clock pulse widths varied somewhat between transmitted bits. This is encouraging because it meant the protocol is graceful under irregular clock pulses, making it more likely I can successfully communicate using CCB in software. Which is great because I don’t have dedicated CCB communication peripheral hardware.

The next step was to activate SPI analyzer with the following parameters. The biggest difference between CCB and SPI is the behavior of CE line, and thankfully Saleae’s SPI analyzer can be configured to ignore CE. (“Enable” set to “None”.) I set the SPI analyzer options to the following values to decode all the values regardless of CE status:

SPI Analyzer OptionValue
MOSILCD-DI
MISOLCD-DO
ClockLCD-CLK
EnableNone
Significant BitLeast Significant Bit First
Bits per Transfer8 Bits per Transfer
Clock StateClock is High when inactive
Clock PhaseData is Valid on Clock Trailing Edge
Enable Line(Doesn’t matter when “Enable” is “None”)

Now the software can decode data for us. This time, the decoded values 0x42, etc. in this image was drawn by the software.

This was the start of the very first data transmission after I applied power to the tape deck. Which is why CLK started as low even though it is normally high when inactivity. When Enable is set to None, I see all the data regardless of CE status.

First question to answer: the B in CCB is “Bus”. How many devices are on this bus? Taking advantage of the difference between CCB and SPI, I can tell the SPI analyzer to decode just the CCB address by saying CE is Active Low:

SPI Analyzer OptionValue
EnableLCD-CE
Enable LineEnable is Active Low

The decoded values on LCD-DI were all 0x42, which tells me the LCD control chip is the only peripheral on this bus, which makes things simpler. I won’t have to worry about reading data intended for the wrong device. And once I decided I didn’t have to worry about different addresses anymore, I can switch the SPI Analyzer over to Active High CE. This will cause the analyzer to ignore addresses (since I expect them to all be 0x42) transmitted while CE is low and decode just the data.

SPI Analyzer OptionValue
EnableLCD-CE
Enable LineEnable is Active High

Within the ~3/4 second of the faceplate getting power, something is transmitted repeatedly approximately once every 5 milliseconds. Zooming in, I see they are three consecutive CCB transmissions to address 0x42:

Address1234567
0x420x000x000x000x000x000xC00x10
0x420x000x000x000x000x000x000x80
0x420x000x000x000x000x000x000x40

Next: compare this captured data to the LC75853N datasheet to see if they make sense.

Sanyo LC75853N LCD Driver Archaeology

I’ve soldered wires to the connector between the mainboard and faceplate of the stock tape deck audio head unit from a 1998 Toyota Camry LE. (86120-08010) My goal is to learn enough to control the faceplate with my own creation independent of the mainboard. Since these two circuit boards can still be powered up, I can probe their voltages and listen to communications between them. A skilled electronics hacker can make sense out of the waterfall of bits, but I don’t have that level of skill yet. I need a little more information, and I started with this very prominent chip on the faceplate.

I couldn’t find where Sanyo hosts their electronic component datasheets, I kept stumble into unrelated areas like their consumer electronics site. This is a common problem when dealing with products made by huge companies with diverse product lines. There’s also the problem that Sanyo has been acquired by Panasonic in 2011 (Wikipedia) so it’s quite possible the relevant divisions have been merged or shut down and their website disappeared.

Seeking another source, I searched for this chip at Digi-Key. Their database did not list this exact item, but there were a few other LC7583 variants listed as “Obsolete” and without datasheet. I ultimately resorted to going through one of those internet sites that archive old PDFs. I find it annoying to have to wade through a bunch of “Click here to download!” ads that try to trick you into downloading irrelevant things that may or may not hide malware. It’s always a hunt for the actual link to the PDF we want, which may or may not have been modified maliciously. But eventually I ended up with Sanyo datasheet for “LC75853NE, 75853NW” which is hopefully close enough. The PDF was also slathered with the annoying site’s watermark, but I hope that’s all the annoyances in that file.

Here is the summary and high-level block diagram:

1/3 duty LCD display drivers that can directly drive up to 126 segments and can control up to four general-purpose output ports. These products also incorporate a key scan circuit that accepts input from up to 30 keys

Digging further into the datasheet, I learned of caveats with that summary. It is not possible to have simultaneous control 126 segments, four output pins, and scan 30 keys. In order to get 126 segments, we have to reallocate two key scan pins cutting the number of scannable keys by 10. And in order to use four output ports, we have to reallocate four segment pins cutting the number of addressable segments by 12. I’m sure such flexibility is useful for adapting to different usages, but it also means I will have to figure out the specific configuration used by this faceplate.

The operating voltage range is listed as 4.5V to 6V, so if I am to build a project to control this faceplate I might have an easier time with 5V parts like Arduino ATmega328P or PIC16F18345. Using parts like ESP32 would require voltage level shifters.

When I examined the connector labels, I noticed enable (LCD-CE), clock (LCD-CLK), data input (LCD-DI), and data output (LCD_DO) pins. I optimistically hoped it meant this chip communicated via SPI, but the datasheet said it actually used a Sanyo proprietary protocol called CCB (Computer Control Bus). I found no official Sanyo documentation here, either, but fortunately CCB was used in enough products that some electronics hackers had preserved a copy of CCB documentation. Like this page, where the author reverse engineered a different car audio head unit (Kenwood KDC-MP6090R) that used a different Sanyo CCB controller (LC75808) so they could control it from a STM32.

CCB have similar pinout as SPI, but its electrical behavior is different. Each device has a hard-coded address similar to I2C. There is a variation of CCB that merges DI and DO into a single half-duplex line, making it even closer to I2C but not still the same. I’m pretty certain I couldn’t use hardware SPI or I2C peripherals to talk to this chip, but in the CCB specification there’s a line “Using software or serial I/O facilities” which implied the creators explicitly supported doing CCB in software. (bit-banging) Looks like some people have claimed success doing so in Arduino so their precedents might be worth a look when I aim to do the same. But before I do that, I need to learn what normal CCB communication looks like.

Probing Voltage Range of Tape Deck Faceplate Interface

I have on hand electronic circuit boards of the factory stock tape deck unit 86120-08010 from a 1998 Toyota Camry LE. There is a connector between the main board and the faceplate, and I’ve soldered a row of wires so I can take a peek into its inner workings. I thought it might be fun to reuse the faceplate for my own project, creating something that could stand in for the main board.

Thankfully, the faceplate side connector was mostly labeled, including the ground pin which gave me a reference point for measuring all the other wires with a voltmeter. Here’s what I found:

[UPDATE: This was my first draft, see the wrap-up post for final draft.]

PerfboardConnectorVoltage
AACC5VSteady 5V
BLCD-DOSteady 5V
CLCD-DIFluctuates
DLCD-CLKFluctuates
ELCD-CEFluctuates
F(CD-EJE?)5V
GILL0V when mainboard ILL is 0V (lights off)
12V when mainboard ILL is 12V (lights on)
H(CD-BL?)7V when radio is on
8V when radio off.
IVOL.CONVolume knob potentiometer
0V counterclockwise limit
5V clockwise limit
JPULS-AQuadrature encoder for settings knob.
5.1V – 0.1V – 5.1V as knob is turned.
KPULS-BQuadrature encoder for settings knob.
0.1V – 5.1V – 0.1V as knob is turned.
LGND0V reference
MILL-0V when lights off
0.7V when lights on
NBL-0.7V when radio on
7.5V when radio off
ORESET0V
P?0V

Notes:

  • One connector, which I wired to breadboard column P, has no label. It doesn’t seem to do much, either. Possibly unused?
  • The bottom ~1/3 of two labels were cropped off this silkscreen design. The one I wired to perfboard F might be “CD-EJE”, and H might be “CD-BL”. But it may as well be “CD-BI” or similar letters with the same top 2/3.
  • I was surprised that LCD-DO appears to hold steady at 5V, I expected it to fluctuate during data transfers. [UPDATE: This is expected for Sanyo CCB protocol in absence of event notification.]
  • LCD-DI, LCD-CLK, and LCD-CE fluctuates as expected.
  • There are two knobs on this control panel. They can be both turned and pressed. Turning the volume knob affects VOL.CON, but the press (radio power on/off) seems absent from this connector.
  • Similar story with the settings knob. Turning it affects PULS-A and PULS-B but pressing (select) is absent from the connector.
  • I know there is an LCD controller chip on this faceplate circuit board with additional feature to scan for button presses. Perhaps in addition to faceplate buttons it is responsible for reading presses on volume and settings knob? [UPDATE: Hypothesis confirmed.]
  • If the LCD controller chip lacks ADC (analog-to-digital conversion) and quadrature decoding, that would explain why the connector has VOL.CON, PULS-A, and PULS-B so something on the mainboard can interpret knob motion.
  • Several LEDs scattered throughout the faceplate turn on when ILL is high. Varying ILL between 9V and 12V controls brightness of these LEDs.
  • ILL does not control LCD backlight LEDs, whose brightness remains constant. Might the LCD control chip responsible for the backlight as well?
  • ILL- is a voltage plane that can be 0.7V higher than the GND plane. Have to keep this in mind when wiring up components, in case a 0.7V difference is problematic. Or ILL and ILL- could be wired separately from digital logic aspect of the circuit.

Next step: find more information on the traffic moving on LCD-DI/DO/CLK/CE pins.

Wires to Probe Toyota Audio Head Unit (86120-08010)

Successfully mapping out the segments for a food thermometer LCD had a nice side effect of improving my soldering skills. Armed with this experience, I feel more confident tackling the task of deciphering LCD controller communication protocol. Earlier I had successfully reassembled and powered up the circuit boards from a 1998 Toyota Camry LE stock tape deck. Now I intend to go beyond looking at pretty lights and see if I can control its front panel.

That front panel connects to the main board through this connector, which has labelled most of its contact points. Since I want to probe their behavior in a running system, I wanted to preserve the ability to plug it back into the mainboard. I had the soldering iron all warmed up ready to solder to the visible surface-mount contacts above and below this connector, but then I thought of a better idea.

Its mating connector is soldered to the mainboard, and it is a through-hole connector which meant there are exposed pins on the bottom of the mainboard. These pins are finer pitch than the 0.1″ I usually work with, but through-hole pins are still more familiar to me than surface mount pads. So I soldered my wires to these pins.

These wires are then brought out to another strip of perforated prototype circuit board, and a row of 0.1″ pitch headers.

Which then plug nicely into a breadboard for easy probing and experimentation. Thanks to the labeled connector, I already know which wire is ground so I connected a bare loop for my instruments to use as reference. Next step is to probe the remaining pins to determine their voltage range.