What started off as a little exploration led me deeper to try and better understand what was going on with the Keweisi KWS-V20 USB Tester. Even though I don’t have any specialist bus sniffing gear, I decided to just wing it with the Serial Decoding features of the Picoscope 2205A and see what I could get.
As usual, the disclaimer applies – I can’t guarantee this is all correct, and can’t be held responsible if you damage anything through attempting to use what is written here.
The first step was to try and get a good connection to the buses in question. As there were two buses in question, a total of five connections were made to the IC including ground.
The connections aren’t pretty by any measure, and the mixture of lead and lead-free solder creates the frosted brittle-looking joints that function well enough. After all, this only had to last long enough for me to see what was going on.
I decided to start by taking a look at the LCD bus in more detail, as it was the one with a constant stream of data.
The first thing I realized is that the LCD bus data “bursts” once every 4ms, or a frequency of about 250Hz. This now explains the “CLOCK?” signal I saw – this is not I2C (as pointed out by a reader in the previous article merely hours before I got to writing up this one). This is in fact SPI, and the CLOCK? signal is the slave select line, activating in synchronism with the bursts of data. There may also be an explanation for pin #14 which appears unconnected – maybe it’s the matching hardware MISO pin, as most SPI drivers have four connections, and the LCD doesn’t really need to talk back to the host at all.
Looking closer at one of the bursts, it seems that the bus frequency is about 263khz, and a total of 18 bytes (or 144 bits) are sent. Because of the way the bursts start and stop, there wasn’t an easy way to trigger it reliably with the oscilloscope especially as there was no way I could think of to properly configure it to avoid triggering “mid-stream” on a downward clock transition. As a result, I decided to trigger once the signal exits the window for a specified amount of time – basically triggering after the end of the burst and “ignoring” the idle time between bursts. This sort-of-worked, with the exception that it was slow and missed many updates, and due to the “jitter” in the trigger, the data jumped around a bit but at least the issue of “fragmented” data was solved.
Leaving it for a while, I managed to get the following bytes of data, deduplicated:
Because I couldn’t exercise the display and have all values varying, some of the bytes listed as static may actually not be static at all. I couldn’t see any easy correlation between the values and the data – maybe the values sniffed are inverted, maybe they are bit-mapped to segments and packed together.
That got me thinking – just how many segments are there on the display? I took a photo of its brief “reset” test and counted …
In many cases, the symbols for V, A, T and mAh are single segments that are fixed to stay on and are not really “segments”. Likewise, the colon is likely a single segment rather than two. The numbers listed are being as generous as possible, and tallying them up, I arrive at 116 segments. However, it’s more likely to be 109 segments based on the above reasoning.
If the display was bit-mapped, 15 bytes would be enough for 120 segments. As a result, there’s probably a little over 3 bytes of data used for other purposes – possibly configuration of LCD drive parameters (e.g. contrast), segments which don’t exist in this particular panel, or timing. It’s still relatively close to the number of segments, so I expect the data to be bit-mapped to a segment in some way. I just don’t have the inclination to decompose all the bits and work out which is which, but I suppose if one were really interested, they could desolder the IC and then try talking to the display directly feeding different bytes to see how it liked it.
Time to divert our attention to the I2C EEPROM communications. The first thing I did was to try and ascertain what happened whenever the unit stored updated values to the EEPROM.
It was found that the I2C bus operated about 147khz, so around “standard” rate but a little faster. Whenever 30 seconds would pass and the unit was integrating, a burst of bus activity occurred with some wait between each burst to allow time for chip processing. Because the Picoscope did not reliably capture every burst, I let it sit around for a while and filtered out any duplicate accesses to addresses. The resulting data appears as follows:
It seems to be a classical EEPROM write to addresses 0x00 through 0x04 (5 bytes). By checking with the display after an hour of time, I confirmed that address 0x03 contains the decimal hours, and 0x04 contains the decimal minutes. Because of this, I expected addresses 0x00, 0x01 and 0x02 to store a pair of digits each for the integrated mAh. Contrary to expectations, this didn’t seem to be the case – the value for 0x00 was seen to use raw unsigned binary storage of the mAh value – having a value of 0xAE at the end to signify 174mAh. As a result, I believe the three bytes 0x00, 0x01, 0x02 form a 24-bit storage for the integrated mAh value even though I haven’t seen any data stored in 0x01 and 0x02 during the short testing (as the integrated mAh value wasn’t high enough).
When the device is plugged in, it needs to restore the data from the EEPROM to the display. This gives us a good chance to witness exactly what is being read out.
As expected, the read-out checks the data in addresses 0x00 to 0x04, a total of five bytes. Based on this analysis so far, no wear levelling is employed and even though the EEPROM has storage for 256 bytes, only the first few are used. Based on a 1 million cycle endurance and a 30 second timer, the EEPROM is expected to expire at about 347 days of continuous operation. Sadly, no additional data seems to be stored or restored.
However, when it came to clearing the EEPROM, there was a curious quirk:
As a result, I now believe that the chip connections are as follows:
Sometimes I like putting posts up as I go, and this was one of the cases of that. As a result, the last post did have some loose ends which weren’t tied up. Initially, I didn’t really feel like exploring it, but then, I had a change of heart and decided to just try it anyway. At least, now I know a little more about this device … although it’s probably not data that’s really useful to me right now, it was worth the try just to learn more about snooping about on buses and getting the scope set-up right to capture and decode the data.