Skip to content
HN On Hacker News ↗

Converting a $20 4G wireless hotspot into a texting device

▲ 210 points • 37 comments • by bobili1234 • 4w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is human-written.

0 %

AI likelihood · overall

Human
100% human-written 0% AI-generated
SEGMENTS · HUMAN 1 of 1
SEGMENTS · AI 0 of 1
WORD COUNT 1,813
PEAK AI % 0% · §1
Analyzed
Sep 15
backend: pangram/v3.3
Segments scanned
1 windows
avg 1813 words each
Distribution
100 / 0%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 1,813 words · 1 segments analyzed

Human AI-generated
§1 Human · 0%

The motivation. I don’t organize my things well. I try to, but quite often end up with a bunch of stuff on my desk. From various aliexpress orders and projects I’m working on, all the way to gifts and stuff I didn’t have time to find a place for. That is exactly how this project came to be. At one point in time I had, lying on my desk: Various, hopefully openstick compatible, models - namely the: MF800 - one I ended up using UZ801 - OK size, but no battery or sufficienet visible GPIO USB drive form factor one I ditched because of other issues The Clicks Keyboard for iPhone 16 Pro Max (gift from my cousin - too bad I don’t have an appropriate iPhone 🥲) The Adafruit SHARP Memory Display board And of course, my caveman brain combined the 3. Okay, okay, not to lie I was probably a bit conditioned by knowing about: Beepy by sqfmi Playdate The modem. Due to the mysterious laws of supply and demand, and the magic of supply chains - somehow you can get a 4G modem with WiFi, bluetooth, a display, fully battery powered and completely unlocked - for less than $20 shipped. This, of course, is the cornerstone of our project. There are versions with and without a display. The non-display one just swaps the display for LED-s, though the PCB is the same. Display is a GC9107 powered one, but it looks like ass so i ditched it. Linux can be installed trivially, powered by the wonderful openstick project. The stock device runs Android, but adb is accessible out of the box - and from adb you can go straight to edl and reflash the thing. Just make sure to save all the important partitions. There are also pins on the pcb which you can short out to get straight to edl. Extracting the running device tree from the running android was a goldmine of information so be sure to do that. Here are a few guides or links I found helpful: OpenStick github openstick.de wvthoog.nl blog - I think I used this kernel for starters extowerk.com blog This project’s GitHub repo might also help you The real pain with openstick starts once you get to the drivers and device trees, but we will talk about that later. The keyboard. There is not much to say about the Clicks Keyboard. It feels veeery nice to use, the only issue is you need to fork over quite a few clams - made worse because you are going to have to cut it 😱. Regarding the protocol, it’s exactly what I expected with my previous experience of working with MFi devices - just a regular USB keyboard with an additional Apple proprietary endpoint which the iPhone can authorize with before allowing the keyboard to go through. So for our device this means that it’s just a regular keyboard. On a side note, there is a Clicks mobile app used for configuration/updates/whatever. The keyboard itself is powered by CH32V203 or similar. Custom code could be flashed but I don’t see any reason to to this currently. In the future I would like to have a configuration utility. The display. I think the sharp display look great with the high contrast (and it plays well into my use case of a dumb device used only for messaging). Other than that, if there wasn’t much to say about the keyboard - then there is absolutely nothing more to say here. It’s a display. You send commands. It displays. The adapter PCB. One thing became clear to me quite fast - I was going to have to add a custom PCB. I wasn’t exactly sure what the MF800 had on-board, and I never did end up opening the shield can - but I am fairly certain there is no 5V booster on-board. Because of the physical sizes, which we will go over further in the post, the USB connector will end up chopped off - so we need a way to handle that too. The final PCB ended up handling the USB host mode power, USB host/device mode switching, display power and display signal level conversion. I ordered the PCB along with assembly. And because 2 sided assembly is expensive, I made a few compromises to fit all the components on one side. The non-component side is used for the solder points for the PCB-to-PCB connections. All files can be found on GitHub, but in short the PCB consists of: TUSB320 - for the USB mode switching SN74LVC8T245 - for the level shifting MCP1640 - the 5V booster TPS22917 (one high, one low) - for swithing VBUS/VBAT USB connector and FPC connector for the display test pads used to connect the adapter PCB to the MF800 Enclosure 1. The MF800 is quite a bit bigger than other opensticks, partly because of the battery it has to include, partly because of it’s slop nature. So to fit inside a Clicks case, we either orient it verticaly and and up with a humongous abomination, or we trim the pcb to fit horizontally. Notice that my right cut (on the bottom picture) cuts off the battery connection line, so this will have to be patched up later. Cutting. Cutting the PCB went unexpectedly well. The device booted up immediately and everything seemed to work. Turns out there really were no crucial lines going through those areas of the PCB. Only things I didn’t test were the USB connection and the 4G modem. The modem I was 99% sure wouldn’t be an issue as there is no reason to route anything for it under those areas - but regarding the USB I was worried that I hadn’t maybe nicked the via. Wiring 1. I decided to reuse the pads from the old display. I don’t really know why anymore - possibly because my initial ideas was to use a rigid flex PCB and solder it similar to how the original display was. (which I decided against immediately upon seeing the prices) Looking at all this now, it seems very dumb. I should have used the labeled pads next to the unpopulated micro SD connector. Note that never did check if these were shared with the SIM card though. Since I could boot the device and I had the original android device trees, I extracted which pins were used for the display SPI. I then tested those with gpioset to make sure that I was indeed correct. Same goes for the power supplies (although I tested those by disabling them in the device tree and rebooting) and grounds. The first thing I wired and checked were the power supplies followed by the USB. This is because I could test this as an isolated unit. I was also more skeptical about this because it involved a bit of circuitry on my part as well as that iffy via. Of course, it didn’t work initially. After probing around the pads and seeing that all the voltages were OK I noticed in my laptop’s dmesg that it TRIED to enumerate - meaning something was going on. I also noticed that it says "high-speed". This caught me a bit off guard. I didn’t expect it to use "high-speed" USB. My first thought was that the wires were too long. But before shortening them, I tried a quick fix - twisting them more tightly - and it worked 😲! Immediately following this success, I tried to get the other direction working. This took some time. Turns out, not all aliexpress adapters correctly wire the CC lines. The keyboard did work immediately, though - only issue is I was afraid to test with it first in case something was wired incorrectly. Wiring 2. Before wiring the SPI lines to the display, I wanted to check if I had correctly reconfigured my device tree. I knew the pads were correct from the earlier testing, but there is quite a lot which can go wrong here. spi@78b9000 { compatible = "qcom,spi-qup-v2.2.1"; reg = <0x78b9000 0x500>; interrupts = <0x00 0x63 0x04>; clocks = <0x13 0x41 0x13 0x36>; clock-names = "core", "iface"; dmas = <0x6d 0x0c 0x6d 0x0d>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; pinctrl-0 = <0x84>; pinctrl-1 = <0x85>; #address-cells = <0x01>; #size-cells = <0x00>; status = "okay"; spidev@0 { //compatible = "linux,spidev"; compatible = "rohm,dh2228fv"; reg = <0>; spi-max-frequency = <16000000>; spi-cs-high; }; }; For example, qualcomm drivers are sketchy and the commented out compatible won’t actually export the spidev, so we scam it with this the dh2228fv compatibility. Using the spi-pipe utility running in a loop, I was able to measure voltage change on the MOSI and CLK lines - which was enough for me to conclude that something was happening. I would, of course, prefer to do this with a scope or a logic analyzer - but I didn’t have any of those at hand. Encouraged by the major success of power supplies and USB, I carelessly connected the display into the PCB (while the device was on 🤦). Immediately something happened to the display and I was sure I broke it. Fortunately nothing came of this and the display was fine. (This actually happens every time I turn on the device. I don’t yet know if I should be concerned 😬.) Once I reassured myself that nothing bad had happened, and that nothing was smoking or overheating - I proceeded with trying to get the display to work. After an hour of slopping through this with AI python code I was absolutely nowhere. There were multiple possible points of failure. Level converter, bad routing, contacts, etc… Turns out, as is quite common (IDK why), the qualcomm driver doesn’t handle the CS well (or correctly - or maybe it does but for other use cases). In any case, I tried again the same test script, but this time toggling the CS pin manually (via libgpiod) - and it actually worked. Rewiring. I was immediately dissapointed with the everything. From the "electrical" wire I used to connect the power supplies to the sketchy tiny magnet wire I used for the signals all the way to the twisted ground I wrapped around MOSI and CLK (which seemed to do nothing) - so I decided to rewire everything once more. This time i used magnet wire for both signals and power, but this one was quite a bit thicker and also kept position once bent. I didn’t rewire the USB data lines though, as the pads on the main board look very iffy. Display kernel driver. All the previous tests were done with just dumb python scripts, but the real way forward is with a kernel driver. There are quite a few drivers available, but the one I picked is ardangelo’s sharp-drm-driver. My reasons for wanting a DRM driver