Bringing The Voice Assistant Home

For many, the voice assistants are helpful listeners. Just shout to the void, and a timer will be set, or Led Zepplin will start playing. For some, the lack of flexibility and reliance on cloud services is a severe drawback. [John Karabudak] is one of those people, and he runs his own voice assistant with an LLM (large language model) brain.

In the mid-2010’s, it seemed like voice assistants would take over the world, and all interfaces were going to NLP (natural language processing). Cracks started to show as these assistants ran into the limits of what NLP could reasonably handle. However, LLMs have breathed some new life into the idea as they can easily handle much more complex ideas and commands. However, running one locally is easier said than done.

A firewall with some muscle (Protectli Vault VP2420) runs a VLAN and NIPS to expose the service to the wider internet. For actually running the LLM, two RTX 4060 Ti cards provide the large VRAM needed to load a decent-sized model at a cheap price point. The AI engine (vLLM) supports dozens of models, but [John] chose a quantized version of Mixtral to fit in the 32GB of VRAM he had available.

Continue reading “Bringing The Voice Assistant Home”

A Journey Through Font Rendering

In the wide world of programming, there are a few dark corners that many prefer to avoid and instead leverage the well-vetted libraries that are already there. [Phillip Tennen] is not one of those people, and when the urge came to improve font rendering for his hobby OS, axle, he got to work writing a TrueType font renderer.

For almost a decade, the OS used a map table encoding all characters as 8×8 bitmaps. While scaling works fine, nonfractional scaling values are hard to read, and fractional scaling values are jagged and blocky. TrueType and font rendering, in general, are often considered dark magic. Font files (.ttf) are structured similarly to Mach-O (the binary format for macOS), with sections containing tagged tables. The font has the concept of glyphs and characters. Glyphs show up on the screen, and characters are the UTF/Unicode values that get translated into glyphs by the font. Three critical tables are glyf (the set of points forming the shape for each glyph), hmtx (how to space the characters), and cmap (how to turn Unicode code points into glyphs).

Seeing the curtain pulled back from the format itself makes it seem easy. In reality, there are all sorts of gotchas along the way. There are multiple types of glyphs, such as polygons, blanks, or compound glyphs. Sometimes, control points in the glyphs need to be inferred. Curves need to be interpolated. Enclosed parts of the polygon need to be filled in. And this doesn’t even get to the hinting system.

Inside many fonts are tiny programs that run on the TrueType VM. When a font is rendered at low enough resolutions, the default control points will lose their curves and become blobs. E’s become C, and D’s become O’s. So, the hinting system allows the font to nudge the control points to better fit on the grid. Of course, [Phillip] goes into even more quirks and details in a wonderful write-up about his learnings. Ultimately, axle has a much better-looking renderer, we get a great afternoon read, and fonts seem a little less like forbidden magic.

Maybe someday [Phillip] will implement other font rendering techniques, such as SDF-based text renderers. But for now, it’s quite the upgrade. The source code is available on GitHub.

The Best Kind Of Handheld Gaming Is Homemade

[CNCDan] previously dabbled with Raspberry Pi CM4-powered gaming handhelds but was itching for something more powerful. Starting in May 2023, he embarked on building an Intel NUC7i5BNK-powered handheld dubbed NucDeck.

As he goes over the feature list, it sounds like a commercially available console. A 1024 x 600 screen provides a good balance of fidelity and performance. Stereo-chambered speakers provide good front-facing sound. Two thumbsticks with gyro aim assist, two hall effect triggers, and many buttons round out the input. Depending on the mode, the Raspberry Pi Pico provides input as it can emulate a mouse and keyboard or a more traditional gamepad. A small OLED screen shows battery status, input mode, and other options. This all fits on four custom PCBs, communicating over I2C. 6000 mAh of battery allows for a decent three hours of run time for simpler emulators and closer to an hour for more modern games.

The whole design is geared around easily obtainable parts, and the files are open-source and on GitHub with PDFs and detailed build instructions. We see plenty of gorgeous builds here on Hackaday, but everything from the gorgeous translucent case to the build instructions screams how much time and love has been put into this. Of course, we’ve seen some exciting hacks with the steam deck (such as this one emulating a printer), so we can only imagine what sort of things you can do once you add any new hardware features you’d like.

Continue reading “The Best Kind Of Handheld Gaming Is Homemade”

Custom Aluminum Monitor Stand For The Home Office

Monitor stands vary wildly in price, from a few cents for a pile of books from a thrift store to hundreds of dollars. One trendy style, as [Steven Bennett] puts it, is the “General Grievous,” with adjustable arms splayed around a central pole. While effective, it is not particularly aesthetically pleasing. [Steven] set out to make his monitor stand out of extruded aluminum.

[Steven] started with a cantilever design with a VESA adapter and a c-clamp. With some 3D-printed adapter brackets, he could attach them directly to the tracks in the aluminum. Of course, the 3D printed parts, while great for prototyping, might not be the best choice for the loads he was planning on. He sent it off to a fab to get some powder-coated steel parts. After using it for a few months, he revisited the drawing board. Moving away from the cantilever with an offset center post, he switched to a single 1×4 piece of aluminum. This allowed him to create 3D-printed attachments to hold his headphones, flash drives, and cables. A build guide is available online, as well as printable add-ons.

While it doesn’t have a built-in computer like this glorious wooden stand, we can’t deny the utility or the aesthetic of the aluminum version.

Video after the break.

Continue reading “Custom Aluminum Monitor Stand For The Home Office”

Ordering Pizza While Racing

As [Matt Stele] prepared to bike a local 300-mile (~480km) race in addition to training, he had to prepare for food. A full day of riding was ahead on gravel trails, and one of the best options for him was Casey’s General Store pizza. However, as it was a race, other riders were much faster than him. So, all the hot slices were gone when he arrived. With the help of a serverless GPS tracker, some cloud lambdas, and some good old-fashioned web scraping, [Matt] had a system that could order him a fresh pizza at the precise moment he needed. Continue reading “Ordering Pizza While Racing”

WiFi, PWM Backlight, And Graphics On Updated Chumby Kernel

For some, the Chumby was a peek at what could have been. That vision never died for [Doug Brown], and he has been working tirelessly on bringing mainline Linux kernel support to the customizable smart display. He has posted several updates but recently got graphics and the PWM backlight working.

Of course, we covered when [Doug] first started working on the new kernel, so it’s high time we revisited the progress. The WiFi hardware uses a Marvell 88W8686 chipset, which talks over the SDIO bus, so it’s a matter of convincing the libertas driver to talk to it. With a USB to Ethernet adapter, [Doug] could boot new kernels over NFS, so he didn’t have to walk over to swap the SD card. After dealing with an unhandled fault when trying to read the SDHCI_HOST_VERSION register, [Doug] had access points showing up in NetworkManager but could not connect. As a nasty hack, he temporarily removed the interrupts and switched to polling in the driver. While that worked, it would never get upstreamed. A critical interrupt was being dropped, and commands went out of sequence. A second, perhaps ugly hack, read a register after acknowledging an SDIO interrupt, which seemed to work. But it was still a hack, and [Doug] wanted something cleaner. In a blind stroke of luck, he found the errata online and noticed that it mentioned that an interrupt could be missed when a signal was asserted. After following the workaround with a lot of head-scratching and deep diving, he had a fully working WiFi driver.

Graphics were a more straightforward endeavor compared to WiFi. He enabled the simpledrm driver (similar to simplefb) but using Direct Rendering Manager. He had a working panel that could run Qt apps by adding the frame buffer to the device tree with the correct compatible string, registers, and data. However, there was a Vivante GC300 graphics accelerator onboard that he wanted to use. A driver for Vivante GPUs already exists in the kernel, but after enabling it, the driver detects the GC300 and then starts complaining. He discovered that older revisions of the GC300 (like the ones found in Chumbys) mapped registered at different addresses and didn’t set some bits in their idle registers. Of course, just loading a GPU driver isn’t quite enough. He modified an x11 server that supported Vivante accelerators to support the GC300.

For hacking purposes, [Doug] set the backlight GPIO high. While easy to see, perhaps not the best for a device meant to blend in. The PAX166 comes with PWM hardware, though confusingly, it has two PWM modes for pin 84. PWM1 and PWM2 share some common clock and reset bits in a decidedly undocumented way. PWM2 doesn’t work until you configure and then turn off PWM1. However, the backlight turned off once out of UBoot and into Linux. Linux re-initialized the hardware too quickly, causing the device to freak out. This was solved using the abrupt shutdown register.

It’s a journey through debugging, Linux internals, and device tree hackery. Perhaps the most incredible thing is that these changes are submitted for upstreaming to the Linux kernel, with many landing in Linux 6.2. While it’s a shame¬†new Chumbys aren’t being made, making your own smart display has never been easier.

Accurate Cycle Counting On RP2040 MicroPython

The RP2040 is a gorgeous little chip with a well-defined datasheet and a fantastic price tag. Two SDKs are even offered: one based on C and the other MicroPython. More experienced MCU wranglers will likely reach for the C variant, but Python does bring a certain speed when banging out a quick project or proof of concept. Perhaps that’s why [Jeremy Bentham] ported his RP2040-based vehicle speedometer to MicroPython.

The two things that make that difficult are that MicroPython tries to be pretty generic, which means some hackery is needed to talk to the low-level hardware, and that MicroPython doesn’t have a reputation for accurate cycle counting. In this case, the low-level hardware is the PWM peripheral. He details the underlying mechanism in more detail in the C version. On the RP2040, the PWM module can count pulse edges on an input. However, you must start and stop it accurately to calculate the amount of time captured. From there, it’s just edges divided by time. For this, the DMA system is pulled in. A DMA request can be triggered once the PWM counter rolls over. The other PWM channel acts as a timer, and when the timer expires, the DMA request turns off the counter. This works great for fast signals but is inaccurate for slow signals (below 1kHz). So, a reciprocal or time-interval system is included, where the time between edges is captured instead of counting the number of edges in a period,

What’s interesting here is how the hardware details are wrapped neatly into pico_devices.py. The uctypes module from MicroPython allows access to MMIO devices such as DMA and PWM.¬†The code is available on GitHub. Of course, [Jeremy] is no stranger to hacking around on the RP2040, as he has previously rolled his own WiFi driver for the Pico W.