Inside a 3.5 mm plug from old Bose headphones

28.08.2021 10:16

Some time ago my dad told me about a problem he was having with a new ham radio transceiver. The transceiver has a RS-232 serial interface in a 3.5 mm stereo socket in the back panel. Connections that would normally be used for left and right audio channels are used for data RX and TX instead. Since the transceiver didn't come with a suitable cable my dad made his own: he found an old cable with a molded 3.5 mm plug on one end and soldered the other end to a DB-9 connector he could plug into his PC. However no matter what he tried, he could not get the digital interface working.

Surprisingly, we traced the problem to his adapter cable. Even though the multimeter showed that the cable had continuity on all cores and that no lines were shorted, the digital signals that passed through it came out distorted on the oscilloscope. I was curious what was going on, so I took the cable home with me for some more investigation. I commonly re-use the 3.5 mm plugs from old headphones as well and have never came across a problem like this before.

This is the 3.5 mm plug molded onto the end of the cable in question. It has nice gold plating on the contacts and a no-expense-spared molding with a combination of hard plastic and a soft rubber-like overmold. It probably once served some higher-end Bose headphones.

The 3.5 mm stereo plug on the end of the suspect adapter cable.

First thing I did was to measure the frequency response of the cable in the audio frequency range. I connected the stimulus signal to the 3.5 mm connector and measured the gain and phase of the signal coming out of the other end of the cable. This is the resulting Bode plot:

Measured frequency response of the adapter cable.

Obviously there is something more going on in this cable than just normal copper connections. At these frequencies I would expect to see practically flat, 0 dB gain and next to no phase shift across the cable. Instead, there seem to be a -10 dB band stop filter with a center frequency of around 2 kHz somewhere inside.

I found it unlikely that the actual cable was doing the filtering, so I focused on the molded handle around the actual 3.5 mm connector. After some application of unreasonable force it still refused to fully come apart. It did reveal what looked like tops of two MLCCs molded into the plastic. However it seemed that if there is some more electronics inside removing the rest of the plastic by force would also destroy the circuit.

3.5 mm plug with the partially removed molding.

Since I heard that acetone sometimes dissolves potting compounds I put the connector into a glass of acetone-base nail polish remover. I then forgot about it, so it soaked in the acetone for about 2 months. Still, this didn't have as much effect on the plastic as I thought it would. It did make it brittle enough so that I could chip it away until I revealed a small double-sided printed circuit board with a few passive SMD components:

Circuit board inside the 3.5 mm plug handle, bottom side.

Circuit board inside the 3.5 mm plug handle, top side.

The circuit board is marked "YODA" Ver A. Apparently someone working at Bose was a Star Wars fan. If I read the date code correctly this board was produced in 2005. The circuit is symmetrical and has two identical parts for the left and right channel. Each half consists of 2 multi-layer ceramic capacitors and two chip resistors. Tracing the circuit revealed this schematic:

Schematic of the filter circuit embedded in the 3.5 mm plug.

Note that the resistances in the circuit are low enough that a typical multimeter on continuity setting will see them as a short. This is what made debugging the initial problem so frustrating.

I couldn't get a reliable measurement of the capacitors, so 10 μF was a bit of a guess here. However simulating the response of this circuit in SPICE shows that it behaves similarly to what I measured before I destroyed the connector:

Simulated frequency response of the filter circuit compared to the measurement.

Why did Bose go into the trouble of embedding this circuit into the connector? I'm guessing they wanted to improve the frequency response of their headphones. Maybe the speaker has a mechanical resonance at 2 kHz and the filter circuit damps that electrically? I don't know much about hi-end audio engineering. This article mentions passive correction filters that are placed in-line with a headphone cable to equalize the speaker response. While the circuit mentioned is a bit more complicated than the one I found, the one Bode plot they show is very similar to what I measured.

One quick test I found that is capable of detecting this specific circuit without any elaborate setup is setting the multimeter for a capacitance measurement and connecting the probes between one of the channels and ground. On a normal audio cable the multimeter reads some low capacitance, but in the case of the embedded filter it shows around 20 μF due to the two capacitors in the circuit.

In conclusion, it seems that not all connectors are merely connectors. When all other options fail it's worth doubting the most basic assumptions, like that a cable you're using is not actually behaving like a cable.

Posted by Tomaž | Categories: Analog | Comments »

Factory contents of a USB flash drive

19.08.2021 20:33

I recently bought a new USB flash drive. By chance I noticed that it didn't appear to be empty. The drive came pre-formatted with a VFAT file system that indeed did not contain any files when I took the drive out of the box. However the raw contents of the drive seemed to contain some data that was apparently written to it in the factory. Since I'm used to seeing just zeros or 0xff on new devices I was curious what was on it and whether it contains any hints on how these are tested in the factory.

ADATA S102 Pro 32 GB flash drive.

This is the flash drive in question. It's an ADATA S102 Pro 32 GB flash drive.

usb 9-3.3: New USB device found, idVendor=125f, idProduct=312b, bcdDevice=11.00
usb 9-3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 9-3.3: Product: ADATA USB Flash Drive
usb 9-3.3: Manufacturer: ADATA

This first thing I did was to dump an image of the drive in factory condition to a 32 GB file on my hard drive. I then used the binvis tool from Aldo Cortesi to visualize its contents.

The following picture shows just the first 32 MiB using the zig-zag curve. Beginning of the drive is in the top left corner. Offset increases from left to right and top to bottom:

binvis visualization of the flash drive contents.

There's mostly zeros in the first 16 MiB of the drive, with a few small isolated chunks of data and strings. At very the start there's the default partition table and the empty FAT. One of the other non-zero chunks has some recognizable strings referring to a burn-in test.

0101c000  41 44 41 54 41 20 55 46  44 20 20 08 00 00 00 00  |ADATA UFD  .....|
0101c010  00 00 00 00 00 00 56 5a  7e 33 00 00 00 00 00 00  |......VZ~3......|
0101c020  e5 73 00 74 00 20 00 66  00 69 00 0f 00 b5 6c 00  |.s.t. .f.i....l.|
0101c030  65 00 73 00 00 00 ff ff  ff ff 00 00 ff ff ff ff  |e.s.............|
0101c040  e5 42 00 75 00 72 00 6e  00 49 00 0f 00 b5 6e 00  |.B.u.r.n.I....n.|
0101c050  54 00 65 00 73 00 74 00  20 00 00 00 74 00 65 00  |T.e.s.t. ...t.e.|
0101c060  e5 55 52 4e 49 4e 7e 31  20 20 20 10 00 7b 83 be  |.URNIN~1   ..{..|
0101c070  74 52 74 52 00 00 84 be  74 52 03 00 00 40 00 00  |tRtR....tR...@..|
0101c080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

Other than that I didn't find anything interesting. This seems to be just a remnant of some filesystem metadata. Chunks are too small to contain actual test code and I didn't expect that to be on the drive anyway.

Following the first 16 MiB is a pseudo-random pattern. It starts at offset 0x1024000 and repeats every 4 MiB (4194304 bytes). Extracting just a single repetition of the pattern and plotting it with binvis reveals that it has some internal structure to it. This plot is using the gradient color map and the same zig-zag curve as before:

Visualization of the 4 MiB test pattern on the flash drive.

I also played around with different ways of distributing the pattern onto a grid using matplotlib. This is how it looks like when drawn onto a 2048 by 2048 grid. The plot is zoomed into just one corner of the pattern:

A different view of the test pattern.

I don't know the reason behind this pattern. It might just be some pseudo-random algorithm they are using and the values themselves don't matter. I don't recognize any obvious bit test patterns in it. It seems that on every 2048 byte line the byte values in the pattern increase using a different step. Histogram of byte values shows that all 256 values are represented approximately equally.

Interestingly, the test pattern does not continue throughout the entire 32 GB of the drive. It stops at approximately 3 GB. The drive just contains zeros after that. Does this mean that only the first 3 GB has been factory tested? Or maybe there was a bug in the process and only this first chunk didn't get zeroed out after the test while the rest of the drive did?

Posted by Tomaž | Categories: Life | Comments »

Wio RP2040 review

12.08.2021 7:44

I've been following the development of the ecosystem around the new RP2040 microcontroller from the Raspberry Pi Foundation. I've found the microcontroller interesting in the combination with MicroPython since it appeared suitable for development in high-level language while still offering reasonably good real-time performance. For the common low-level bit banging microcontroller stuff I'm not sure if Python beats C/C++. However as soon as any kind of networking is involved, I think using a high-level language is significantly easier. With all sorts of necessary error handling and multi-tasking, networking code quickly becomes unreadable in C.

Hence I've been curiously waiting for RP2040 development boards to appear that would integrate some kind of a network interface. The two products that were most prominent on my radar were Arduino Nano RP2040 Connect and Seeed Wio RP2040. Both were announced earlier this year, but were more or less unobtainable. In June however Seeed reached out to me and offered to send me a free sample of their Wio RP2040 development board in return for a review. Two months later I've finally got one on my desk.

Seeed Wio RP2040 mini dev board on top of its box.

Wio RP2040 itself is a surface-mount module with castellated holes suitable for machine mounting on custom PCBs. It contains just the RP2040 microcontroller, the radio and an integrated inverted-F antenna for connecting to a Wi-Fi network. Voltage supply for the module is 5 V, the GPIO pins use 3.3 V levels. There is also a 3.3 V regulator output pin available on the module, however I could not find any information on how much current you can safely draw for your own use.

To make development easier, Seeed also sells the module already mounted on the Mini Dev Board, which is what I got in the box you see above. The Mini Dev Board adds two LEDs, two buttons, a USB C connector and breaks out all the module pins to two 14 pin 100 mil headers. Schematic and PCB layout files are available for the Mini Dev Board, but not for the module itself.

Also worth noting is the declaration of an EU representative on the box. This is most likely related to the requirements of the European Radio Equipment Directive.

Wio RP2040 compared to Raspberry Pi Pico.

Compared to Raspberry Pi Pico, Wio RP2040 Mini Dev Board is slightly shorter and wider. It has a USB C connector instead of USB Micro for programming and getting power from a PC. In addition to the Pico's BOOT button, the Mini Dev Board also has a RUN button for manually resetting the microcontroller. There's also a power LED that is hard-wired to the power supply line.

Same as on Pico, the Mini Dev Board has space for 100 mil headers on its edge. The headers themselves are not included in the box, so if you want to mount this on a breadboard you need to supply and solder them yourself. GPIO 20, 21 and 22 are not available on the Wio RP2040 headers. They are probably used for communication with the wireless chip inside the module.

Curiously, I found zero information on which 2.4 GHz 802.11 b/g/n radio is used in the module. I'm yet to peek under the RF shield can, but I strongly suspect it hides an ESP8285 from Espressif. ESP8285 is a variant of the popular ESP8266 with built-in flash memory. This guess comes from the fact that the host name the module uses when obtaining an IP address from a DHCP server is espressif. The official firmware image also has a number of strings that mention ESP:

$ strings firmware.uf2|grep -i esp
o rp2040] %s | esp8285_ipconfig could'n get ip
[wio rp2040] %s | esp8285_ipconfig could'n get gateway
[wio rp2040] %s | esp8285_ipconfig could'n get netmask
[wio rp2040] %s | esp8285_config could'n get ip
couldn't init nic esp8285 ,try again please
esp8285 power off

Speaking of firmware, Seeed provides a firmware.uf2 file that contains a customized MicroPython interpreter with some added modules related to networking. Unfortunately, it's not clear at the moment what is the source used for building this file. Another problem is that the file linked from the Wiki seems to silently change without notice. Since July I've seen at least two files being distributed with the same name and URL but different contents.

The procedure for loading the firmware is the same as with Pico. Power up the module with BOOT button depressed and then copy the firmware image into the emulated USB storage device. Using rshell, this is how the module presents itself, running the firmware.uf2 downloaded on August 5:

$ rshell
Connecting to /dev/ttyACM0 (buffer-size 512)...
Trying to connect to REPL  connected
Testing if sys.stdin.buffer exists ... Y
Retrieving root directories ... 
Setting time ... Aug 05, 2021 07:43:39
Evaluating board_name ... pyboard
Retrieving time epoch ... Jan 01, 1970
Welcome to rshell. Use Control-D (or the exit command) to exit rshell.
> ls /pyboard
> repl
Entering REPL. Use Control-X to exit.
MicroPython v1.15 on 2021-07-06; Seeed Wio with RP2040
Type "help()" for more information.
>>> help('modules')
__main__          machine           uasyncio/funcs    urandom
_boot             math              uasyncio/lock     ure
_onewire          micropython       uasyncio/stream   uselect
_rp2              mqtt              ubinascii         usocket
_thread           network           ucollections      ustruct
_uasyncio         onewire           uctypes           usys
builtins          rp2               uerrno            utime
cmath             uarray            uhashlib          uzlib
ds18x20           uasyncio/__init__ uio
framebuf          uasyncio/core     ujson
gc                uasyncio/event    uos

The embedded flash filesystem is empty by default, however there are some extra importable modules available in the interpreter: network, mqtt and a few others. Again, unfortunately there is very little information on these, apart from a few examples in the Wiki. No source available as far as I can tell either. MQTT module seems similar to umqtt.simple described here with some differences - there is no check_msg() method, for example.

I didn't have much luck with using these networking Python modules. Some examples in the wiki are apparently outdated and I didn't manage to get any of them to a usable state.

Specifically, the firmware I was using seemed to have problems receiving data from the network. I could connect to the Wi-Fi network and successfully open a usocket to another host. Sending data using usocket.send() worked. However as soon as the socket received anything from the other end, the MicroPython interpreter would apparently crash and I could never get anything back using usocket.recv(). The program stopped running and the REPL would not respond. I couldn't connect to the board over USB anymore until I reset the processor using the RUN button.

I had similar problems with Seeed's MQTT example code. After fixing it to account for the fact that WLAN_UART class is not defined, Wio RP2040 connects to my MQTT broker. I can successfully publish messages and subscribe to topics from MicroPython. However as soon as some other client sends a message to the topic that the Wio RP2040 is subscribed to, the interpreter crashes. There's definitely something still alive running on the MCU because the broker keeps getting periodic MQTT pings from Wio RP2040. The Python code doesn't seem to be executing though and neither Thonny nor rshell will connect to it.

I tried to find the problem, but without the source and any kind of debug info I was pretty much stuck. I also asked my Seeed contact about it and after a week I have yet to receive a reply.

Update: On 17 August I received a MicroPython firmware image from Seeed that fixes the interpreter crashes related to the networking I describe above. They say that they will fix the image linked from the wiki at a later date.

Screenshot of Thonny with Wio RP2040 MQTT example.

It's obviously very early in the product cycle. I actually don't know if these modules have shipped in any quantity so far. Each time I check, they are out of stock and the banner on Seeed website currently says they will start shipping in September. Still, I was disappointed to see that networking, the main feature of this module, doesn't seem to be functional at the moment. It seems Seeed's customized MicroPython port still needs some work. There's also support for programming the module in C/C++ using Arduino IDE. I have not tried that, but it seems other people are not having much success with that either.

Apart from fixing the software, I hope Seeed also adds some more documentation in the future. Having examples is great, but the custom Python modules should come with a reference. If the firmware image is open source, instructions on building one would be welcome as well. I'm also missing a proper hardware datasheet with some electrical specifications for the module.

The problems I encountered are even more puzzling since Wio RP2040 seems to be focused on being a base for a product than a development board for one-off projects. Its bare-bones design doesn't include any extra sensors that Arduino is shipping on their RP2040 boards. This makes it less inviting for playing around compared to the kitchen-sink-included approach of the Arduino. On the other hand, that's obviously a feature when you're designing a custom board with only the peripherals you need. Seeed is also running a promotional campaign and gives you some free modules when using their assembly services.

Another thing worth noting is that with recently introduced EU import regulations, getting these modules shipped in small quantities from China is quite troublesome and expensive. Even when receiving this free sample I had to deal with import customs paperwork and pay approximately 20 EUR in VAT and processing fees. Add shipping costs and the 13 USD base price shown in the Seeed store effectively becomes around 50 EUR. On the other hand, I have noticed that the modules are listed on Mouser, so this might improve in the future.

In summary, this module promises to be a cheap and simple basis for small network-connected sensors and actuators. I like the simplicity of connecting to MQTT using a few lines of Python. Unfortunately, current software does no deliver on that promise and I can only recommend waiting until the quality improves.

Posted by Tomaž | Categories: Digital | Comments »