735 karma · joined November 24, 2010
@msarnoff@mastodon.social @msarnoff.bsky.social
Old twitter: http://twitter.com/txsector (Inactive since 2022)
http://youtube.com/user/74hc595
http://github.com/74hc595
I didn’t even know they were a real band until I was older and knew I recognized those songs from somewhere.
X(foo, int, "set the number of foos")
X(filename, std::string, "input filename")
X(verbose, bool, "verbose logging")
which can then be used to (a) generate the fields of a config struct, define the mapping from string to field (using the stringifying macro operators), define what functions to use for parsing each field, create the help message, etc. Basically like `argparse` or `clap` but much hackier.As gross as they are, the ability to define one table of data that's used multiple ways in multiple places is handy.
I work in the embedded Linux space and recently discovered that Yocto has pretty nice Breakpad integration. Since it’s building all dynamic libraries in your system from scratch, it can generate symbol databases for each of them. At the end, you can have your build tar them all up as an artifact.
It’s pretty magical seeing a crash report that provides backtraces symbolicated all the way up to libc.
There's nothing as disappointing as starting a build, going out for a couple hours, and coming back to a terminal full of red.
But when it works, it works.
I've got a script that does all this, but it's still a pain.
I've been thinking about putting everything in a monorepo, and adding poky, the third-party layers, and my proprietary layers as submodules. Then, when the build server needs to check out the code or a new developer needs to be onboarded, they just `git clone` and `git submodule update`. When it's time to update to the latest version of Yocto, update your layer submodules to the new branch. If you need to go back in time and build an older version of your firmware image, just roll back to the appropriate tag from your monorepo.
Anyone else have another solution to this issue?
Oh yeah, and the build times. It's crazy disk I/O bound. But if you're using something like Jenkins on an AWS instance with 96GB of RAM, set up your build job to use `/tmp` as your work directory and you can do a whole-OS CI build in minutes.
The single biggest thing you can do to improve the reliability of your embedded system is to use eMMC’s built-in hardware partitioning.
- Each hardware partition is a separate block device. A firmware update cannot corrupt the device by overwriting a partition table.
- There are two small boot partitions, and they can be made permanently read-only after programming, thus preventing corruption of your bootloader. You can also use the other one read-write for your uboot environment.
- You can easily have two OS partitions for A/B firmware updates. In addition to mounting them readonly, temporary write protection can be enabled on a per-partition basis and disabled when needed for fw updates.
- If you can’t afford the capacity hit from pSLC, I believe it can be enabled on a per-partition basis. (Don’t quote me on this, it could be wrong).
All these settings can be configured with either mmc-utils or u-boot. In volumes, programming houses can take care of this for you. (You’ll have to list all the registers out very specifically in an Excel spreadsheet)
The downside is that calculating all the correct register values is not a simple process, and you’ll have to spend a bit of time reading the eMMC spec.
See the C FAQ questions 5-3 and 5-10, et al. https://c-faq.com/null/
It was originally written for the PDP-1 in the early sixties. I’ve seen it demonstrated on the Computer History Museum’s PDP-1. I always wondered how the characteristic “XOR texture” could be produced if the PDP-1’s display can only plot points and does not use a bitmapped framebuffer.
Turns out it takes advantage of the long persistence of the screen’s phosphor, and the brightness of each point decreases over time.
The CHM has a video of it running online, but it does not capture the effect of the phosphor persistence: https://www.computerhistory.org/collections/catalog/10266415...
Edit: here’s a video of it running in MAME that somewhat shows how phosphor persistence creates the XOR texture: https://youtu.be/AxJzUiaQ7xM?si=X9K47c4WyD6AisUp
It can handle a full 68000 bus no problem, but it’s cumbersome and unwieldy. (The X11 interface mentioned in the article is nifty though, I remember having the same issue with fonts.)
I love my Saleae and even the cheap USB logic analyzers work fine with Sigrok. But everything is either 8 or 16 channels.
I realize it’s a niche-of-a-niche use case, but is anyone making USB logic analyzers with 64+ channels at a hobbyist price point (or DIY)?
I made an alarm clock from some unusual Soviet 9-segment Numitrons a while ago. The code/design is in GitHub as well as a link to a video. https://github.com/74hc595/Numitron-Clock
I finally designed and built a clock for them about 3 years ago, and it sits right under my main monitor. They are captivating. I added “tasteful” (IMHO) digit cycling effects and a PIR sensor to turn off the display when no one is around to prolong the lifetime of the tubes, but your experience with the longevity of your IN-18s is remarkable.
I’ve always wondered what equipment they were originally designed for, given their size. Most likely military I imagine, or maybe public signage?
X, Y, Z for a digital readout on a CNC machine
M, G, T are SI prefixes
S, F, N, H are units
It’s also likely that they have meanings in German or another language I’m not familiar with. Large tubes like these have been used in elevators, so they could be floor designations.
It does no dynamic memory allocation, which is a plus in constrained IoT/embedded applications. But it’s really only a tokenizer. For example, if you want to parse fields out of a map, you have to write your own wrappers to iterate over key/value pairs. Since no data is copied out of the original buffer, all the “tokens” are given as byte offsets and lengths, not null-terminated strings, so you can’t just do printf(“%s”).
If you can’t (or don’t want to) malloc, it gets the job done. Not sure I’d recommend it for other applications though.
- It’s built into BusyBox and is very lightweight - Configuration is dead simple (everything is basically shell scripts in the filesystem; no special config language) - Includes logging functionality with rotation - Easily controllable from other applications using named pipes - It’s an almost perfect embodiment of the Unix philosophy: a series of small, single-purpose executables (svlogd, runsv, runsvdir, etc), with no strange config file formats or protocols.
Regarding udev, it’s entirely possible to run an embedded system without it if your device has a fixed set of peripherals, doesn’t need to handle hotplugged hardware, and uses a fixed set of kernel modules. In Yocto, you can define a dummy device manager recipe and boom, no udev. As a bonus, removing udev can shave several seconds off your boot time.
Hi John :) https://github.com/74hc595/1-Bit-AVR-Synthesizer
I also spent a good chunk of time reverse engineering and reimplementing the 6800 machine code* a while back. It’s pretty brilliant. No hardware timers, everything is software delay loops with controllable cycle counts. (Which is why it’s a bit of a challenge to emulate these sounds; there’s no fixed sample rate other than the CPU clock frequency!)
There are several algorithms. One uses a wavetable approach and then evolves the timbre of the sound by subtracting part of it gradually, until things wrap around and start going crazy. And then there’s one algorithm (which makes the coolest sounds) that is basically two pulse width modulators that interact in some very weird way that I could never figure out.
I got to talk to Sam Dicker and Eugene Jarvis about the sound code when they were at California Extreme many years ago. They brought a printout of the original source code on tractor feed paper.
*The games ran on 6809 processors but the sound boards used a 6800.