Added cm401 and wile posts
All checks were successful
Build and deploy Hugo website / build-and-deploy (push) Successful in 9s

This commit is contained in:
2025-06-20 11:28:41 +02:00
parent 4ff4ecb4f3
commit fbcf2b78dc
19 changed files with 177 additions and 0 deletions

33
content/posts/cm401-01.md Normal file
View File

@ -0,0 +1,33 @@
+++
title = "CM401 IC Reverse Engineering Part 1"
date = 2022-11-10
tags = ["reverse engineering", "IC", "ALU", "NMOS"]
+++
Not very long ago I stumbled upon [this](https://www.reddit.com/r/chipdesign/comments/yhy0yx/ussr_cm401_alu/) reddit post in r/chipdesign which showed a die image of a USSR era Bulgarian 4-bit (?) ALU created on an NMOS process made by Ryan Cornateanu (the pictures are posted on his [twitter](https://twitter.com/ringoware) as well). As a long time lurker on this subreddit and have seen some nice die pictures come by I thought lets give reverse engineering a try! How hard can it be….
Another kind redditor let the world know this IC was used in the Elka-50M calculator and provided a [link](https://electronicsdeli.net/2021/08/09/elka50m-refurbish/) which shows the calculator and contains some PCB shots. From these photos we can conclude that the output of the ALU is NOT plain binary since the output pins are directly connected to 13 7-segment displays so we can expect 13 display select outputs and at least 7 segment outputs. Looking at the die image we can find 21 beefy output transistors at the top half directly connected to the pads suggesting we indeed have 13 select lines and 7+1 segment outputs. Taking an even closer look we can find that the leftmost 13 ouput transistors are interconnected with some logic as are the other 8, suggesting that the leftmost 13 are the select line outputs.
![topleft](/images/blog/cm401/topleft.jpg)
![topleft_layersonly](/images/blog/cm401/topleft_layersonly.jpg)
Okay… we know this, and now? This being my first full IC to reverse engineer I just opened up Inkscape and KiCad next to eachoter and just started tracing. Since the top left part had the 13 select lines it seemed like a nice place to start. I quickly found the GND and VCC pads and traced them over the full die and there I went, tracing the metal layer and the underlying 2 other layers (the red and green ones in the die picture as is shown on the left).
Tracing the shapes we can see is all nice and dandy but the goal is of course to find the transisors themselves and create a schematic from the image. Having seen other NMOS ICs I was expecting to see polysilicon gates, thus a coloured area with a strip in between forming the transistor. After looking around a bit I just could find areas which looked like vias inbetween two red areas so the conclusion quickly landed on: that is a transistor! The last unidentified things were the long green snake-like traces and they could just be one thing: resistors. And looking to where these traces connect it actually makes sense (most, if not all, are connected at one side to the VCC or GND traces thus acting as pull up or pull down resistors which are required in NMOS logic).
Giving the metal layer a blue colour (with GND a dark teal and VCC a light teal colour), the aluminium on top of the N+ regions (or something alike… To be honest I am not exacly sure how the layer stack is created but this layer acts as routing traces AND source and drain of the transistors) are coloured red and as last the resistor lines are coloured green (again I am not sure of what material this is…).
![topleft_transistors](/images/blog/cm401/topleft_transistors.jpg)
![topleft_all](/images/blog/cm401/topleft_all.jpg)
Then I gave all the vias a black square and all the via-like structures inbetween two red areas a yellow square indicating a transistor (which got a square around them). Up until now it was a very relaxing and quite doable job. Not much thinking was required. Some music, some coffee and go! In fact, this was so relaxing and fun to do that at the time of writing roughly a third of the IC is fully traced…
![schem_01](/images/blog/cm401/schem_01.png)
Then the more difficult and involving task started… Numbering the transistors and resistors and creating a schematic. With a pencil and a notebook next to me I numbered each transistor, put it in my notebook and followed the traces to the next transistor (and ignoring the repetitive part in the center for now since I suspected this was some kind of PAL/PLA structure (as did Ryan as well looking at his twitter posts about this IC). After finding out a good way to order everything I transfered it to KiCad and went to town on placing a lot of mosfets.
After 130-ish named mosfets (and the bunch in the PAL/PLA structure which stayed unnamed) and around 60 resistors a full schematic of the top left quadrant of the IC is created. It is far from done! Not only the rest of the IC must be done this way but interpreting the schematic would be a massive task as well (alas a fun one!).
This was part one! Probably more parts will come with interpretation of specific parts. No real conclusions can be made up untill this point except for that reverse engineering this IC is not only possible but quite doable. I put up this post mostly to document the workflow I used and a little bit to pressure myself in trying to finish this project. The github repository linked at the top and bottom contains the traced silicon and the schematics.
In [part 2](/posts/cm401-02) I take a look at the schematics of the part shown in the images.

62
content/posts/cm401-02.md Normal file
View File

@ -0,0 +1,62 @@
+++
title = "CM401 IC Reverse Engineering Part 2"
date = 2022-11-11
tags = ["reverse engineering", "IC", "ALU", "NMOS"]
+++
# CM401 IC Reverse Engineering Part 2
Its time for part 2! Last time I was left with a schematic of the first region. Part of that is the PAL/PLA-like structure with some circuitry underneath it of which the schematic is shown on the right (Figure 1). After taking some looks I found out it is not that difficult to find out what exactly is happening here.
One of the first things we can see is that the big beefy output transistors (which are clearly visible in [part 1](/posts/cm401-01)) are in an open-drain configuration, pulling the output to ground when active. Before the output transistor is an inverter which input is connected to a row of the matrix. The image below (Figure 2) is one of those rows.
![Figure 2, matrix row](/images/blog/cm401/region1_or_matrix_row.png)
The row of transistors in the matrix together with the resistor on the left form a (in this case) four-input NOR gate and with the inverter behind it together form a four-input OR gate. Altogether, this select line output will be tied to ground with `A+D+E+G`. Below is a table of all the active combinations:
| Output | Active Inputs |
|--------|--------------------|
| S0 | `A+C+F+H` |
| S1 | `B+D+F+H` |
| S2 | `A+C+E+H` |
| S3 | `B+C+E+H` |
| S4 | `A+D+E+H` |
| S5 | `B+D+E+H` |
| S6 | `A+C+F+G` |
| S7 | `B+C+F+G` |
| S8 | `A+D+F+G` |
| S9 | `B+D+F+G` |
| S10 | `A+C+E+G` |
| S11 | `B+C+E+G` |
| S12 | `A+D+E+G` |
![Figure 1, total schematic](/images/blog/cm401/region1_matrix_and_driver.png)
![Figure 3, column latch](/images/blog/cm401/region1_matrix_driver_latch.png)
After that I took a look at the column drivers at the bottom of the matrix (of which the schematic is shown to the left, Figure 3). When redrawing the part a little bit it becomes clear that the two top transistors form an SR-latch with the set and reset inputs at the bottom. Since the side with the one transistor is connected to the A1 signal and shares it with all other column latches, we can assume this is the reset input, making the other side the set input and the outputs as shown on the top. On the set side the two transistors form an AND gate (well, technically a NAND gate but in this case functions as AND), making the second shared signal A0 a kind of enable signal, with the bottom transistor being the input from another stage.
Altogether, it is clear that the matrix activates the select line outputs for different states of the four latches at the bottom. Now it being an OR matrix may sound strange since one could expect outputs to be active for specific combinations and not any form of a combination, but here come the logic rules: `(!A)(!B) = !(A+B)`, so when calling the Q and !Q outputs !Q and Q respectively and assuming the open-drain output is externally inverted, one gets a big matrix that has active outputs for specific combinations of latch states (which sounds more usable and reasonable).
##### A new section
![Figure 4, silicon of new section](/images/blog/cm401/region1_longtail_silicon.jpg)
![Figure 5, masks of new section](/images/blog/cm401/region1_longtail_mask.jpg)
![Figure 5, schematic of new section](/images/blog/cm401/region1_longtail_schematic.png)
Just below the completed section, right under the power strips, there are 4 long sections which serve as input to the set lines of the latches described above. One of those sections looks like Figure 4 (with the extracted masks shown in Figure 5). Extracting the schematic resulted in the monstrosity shown in the right picture (Figure 5) — and yeah, everything is tilted on its side, I wanted to roughly keep the layout of the silicon intact.
On the silicon, two round/circular tracks with two transistors can be found which I suspected to be SR latches again — and looking at the schematics, I was right. I will expand them both in their own schematics as done before.
![Figure 6, top part of the section](/images/blog/cm401/region1_longtail_top.png)
![Figure 7, bottom part of the section](/images/blog/cm401/region1_longtail_bottom.png)
The top half of the section contains a latch with set and reset sections which are enabled with a global signal (A10), and a section which sets and resets the latch according to a data line: when the data line is inactive and the enable signal is active (A11), the latch is reset (and the same for setting the latch). The D signal comes from the circuitry under this section. The set and reset lines come from the right and are shared between multiple sections which look like the one shown.
The output of this latch is fed into the set and reset lines (`pQ` and `p!Q`, respectively, in Figure 7) of another latch which is shown on the right. The inverted output of this latch is routed to the top part and is used as the set signal in the circuitry explained in the first section. Again, this latch has a global enable signal (A12), and there is some output circuitry: a NOR gate with the Q output and A13 (a signal shared with all four blocks), whose output again is fed into another NOR gate with A14. Following the output of this gate, it is used as one of the columns in another PAL/PLA section right below.
Altogether, we end up with four sets of 3 latches with some set and reset circuitry and a big OR matrix for the select line outputs. How this all plays together with the rest of the IC I do not know yet, so we shall see! These two parts finish the left top quadrant of the IC and roughly a fifth/sixth of the total area of the IC. Still a long way to go, but we are one step closer to the end!
![Region 1, the finished area of the IC](/images/blog/cm401/done-1.jpg)
*Note: the schematics of this region can be found on my [GitHub](https://github.com/Jojojoppe/CM401_reveng)*

82
content/posts/wile-01.md Normal file
View File

@ -0,0 +1,82 @@
+++
title = "WiLE: A WiFi-Based Low Energy Mesh Network"
date = 2022-12-01
tags = ["WiFi", "BLE", "Mesh Network", "ESP32"]
+++
Home automation, a fun gimmick or very useful… Doesn't matter what your opinion is on this subject, but one cannot deny that designing smart appliances yourself is a fun activity. This is the reason that some of my lights are controlled by a small ESP32-based board, which in turn are controlled by ArtNet over WiFi (ArtNet being DMX with some extensions over UDP).
This works pretty well and since it uses UDP, it can be controlled by any ArtNet controller somewhere on the network. This works as long as the boards are constantly connected to a power source. Running from a battery is less ideal since maintaining a WiFi connection on an ESP32 (and pretty much, if not all, other MCUs as well) is quite a power-hungry task.
Other types of networks do exist as well: think of ESP mesh, WiFi mesh, BLE mesh (all supported by the ESP32), or Zigbee and others. But what's the fun in that…? Since this project is only going to be used in my own house, it seemed more fun to design a custom mesh network from the ground up!
Of course, this wasn't my idea from the start… I just thought "Let's use BLE mesh or plain WiFi and it's done." Until I read an interesting paper: [Wi-LE: Can WiFi Replace Bluetooth?](https://doi.org/10.1145/3365609.3365853) by Abedi et al. It talks about using the 802.11 beacon frames for information exchange (commonly known as beacon stuffing). They found that the transmission of one beacon frame takes much less energy (and way less time) than first connecting to a WiFi network and then sending out a UDP packet. They also found that the energy per data-containing packet is in the same order of magnitude as a BLE packet, hence calling this method WiLE or WiFi Low Energy.
### A bit about BLE
Before diving into my ideas, lets first take a short look at Bluetooth Low Energy.
In BLE, each device periodically sends out beacons and periodically listens for beacons (or listens continuously, which consumes quite a bit of energy). After some waiting, a device sends out three beacon frames, each on a different advertisement channel, with a small random time between them, and then waits until the next beacon period.
If another device is listening on that specific advertisement channel at the right time, it receives the beacon frame and delivers the information to the application. Since there's quite a bit of chance involved in receiving a beacon frame, the receiver will probably be on for most of the time. This means that devices needing to receive data must stay awake continuously — which isn't ideal for low-power devices like light switches.
This made me wonder: can I create a network that allows devices to sleep between beacon periods *and* still receive data? This is where WiLE comes into play. On an ESP32 using ESP-IDF, we can control both beacon transmit times and the receiver state via `esp_wifi_80211_tx`, allowing us to synchronize devices and exchange data using custom-crafted beacon frames.
Bluetooth Mesh builds on BLE and uses its beacons (GAP) to exchange data (though it can use GATT too). It routes messages by flooding and encrypts with two layers: a network key (to identify valid members of the mesh) and an application key (for application-specific data, e.g., turning on a light). Devices are provisioned into the network using a device key.
### The main idea
![Figure 1, basic WiLE mesh beacon timing](/images/blog/wile/wile_timing0.png "Figure 1, basic WiLE mesh beacon timing")
The basic principle is a time-synchronized mesh where devices send application-specific beacons within a short interval. Outside of this beacon interval, devices can sleep to conserve energy.
A full cycle might look like this:
- **Wakeup period**: A device wakes, turns on WiFi, and starts listening.
- **Active period**: Synchronized devices each send their beacon (at a random moment to avoid collisions).
- **Inactive period**: WiFi is disabled and the device sleeps until the next cycle.
If all devices share the same cycle period **T**, and the same start/end times **t1** and **t2**, they can remain synchronized.
Extensions are easy. For instance, low-power devices (LPDs) dont need to wake every cycle. Instead, each LPD is assigned a “friend device” that stores messages for it. When the LPD wakes (e.g., due to a button press), it waits for the next cycle, sends a beacon, and stays active slightly longer to receive P2P data from its friend.
Messages are encrypted similarly to BLE mesh: network + application keys. P2P (e.g., provisioning) can use device-specific keys.
### Time synchronization
Until now, we assumed all devices are synchronized. Unfortunately, this doesnt happen magically. NTP is not feasible here — no internet, and only one beacon per cycle.
Luckily, I found [this 2004 technical report](http://disc.ece.illinois.edu/publications/clocksync-tech.pdf): **A Distributed Self-Stabilizing Time Synchronization Protocol for Multi-hop Wireless Networks** by So & Vaidya. It discusses MTSP, a protocol that adjusts local clocks based on beacon reception.
Each device keeps a microsecond-resolution timer (doesn't mean microsecond *precision*). Its state contains:
- A parent ID
- TTL counter for parent and children
Each beacon includes:
- Time of transmission
- Sources **t1**
- Sources parent ID
If a device receives a beacon with a *newer* time, it sets that device as parent and adjusts its own time at the end of the cycle. If it receives a beacon from a *child* with an *older* timestamp, it resets the TTL counter for that child.
If TTL expires (e.g., after a few missed cycles), the device resets to unsynchronized state.
### Basic frame layout
![Figure 2, frame layout of normal frames](/images/blog/wile/nframe_layout.png "Figure 2, frame layout of normal frames")
Figure 2 shows the layout of normal 802.11 management frames used in WiLE. Each includes:
- Standard MAC header and beacon format
- Custom data in vendor-specific field (ID 211)
- A "magic" string + frame type ("N" for normal)
- Time sync data: timestamp, **t1**, and parent ID
- Application data payload
The SSID length is set to 0 so nodes remain invisible. These beacons wont interfere with surrounding networks, and connection attempts will fail as WiLE ignores packets without the magic string.
---
**_Work in progress…_**

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB