The entire WWW summed up in three pictures

“For Wales? Why Richard, it profit a man nothing to give his soul for the whole world. . . but for Wales!”

― Robert Bolt, A Man for All Seasons

(Way to trashtalk an entire country, Bob. You really slipped that one under the net.)

With that quote in mind, here are the pictures I promised you …

Contestant number 1:

Validate me

Contestant number 2:

Y’all my bitches now

Contestant number 3:

I’m here to discuss the modalities

In other words: narcissists, gatekeepers, and scammers. I was going to include SJWs, but I figured they were just a sub-category of narcissists.

I was going to just show the first picture, but realised that I needed three to display the whole gamut.

So, let’s talk about the first picture, shall we? It is what prompted this post in the first place.

The lady in question is Scarlett Dixon. Doxxing people is usually considered completely uncool dude, but her name is a matter of public record already. It’s from the Twitter account scarlettlondon, which no longer seems active. Presumably the blowback she received from it ruined her credibility. The picture was posted in 2018, so I’m way late to the party.

What really grinds my gears is the sheer fakeness of it. The sheer emptiness. For Listerine White. Like, I have to plaster on this phony smile to avoid the realisation that my life amounts to absolutely nothing. Scarlett says:

The best of days start with a smile and positive thoughts. And pancakes, And strawberries. And bottomless tea.

Holy shit.

I do give you a little insight into how I start my day in a positive way.

Hold that thought. I’ll be pouring scorn on it shortly.

Adforum picks up the news:

… a plate of tortillas conspicuously disguised as pancakes sits next to her … Shortly after Dixon put the photo on Instagram, someone posted it on Twitter, pointing out that it looks nothing like “anybody’s normal morning,” and announced that “Instagram is a ridiculous lie factory made to make us all feel inadequate.”

Further down:

As Dixon notes in her statement, her posts are intended to be exaggerated: “Sometimes my photos are whimsical and OTT [over the top] and a little too pink, but I’m not presenting this as an ‘idealistic’ version of life that young girls should aspire to” (brackets added).

See, I’m not going to give her a pass on this. For starters, she said that “I do give a little insight into how I start my day.” She presents it as a truthful statement, which she then retracts. Secondly, she presents it as an aspiration for young girls. This is terrible! No wonder the youth is so messed up. They are presented with images that no well-balanced person could emulate.

Turning to the Gemini protocol …

My Gemini site (OK, “capsule”, if you insist) is coming along to my satisfaction. I intend to migrate my former website over to it. I’m in no rush, though. I might make it public at some stage. We’ll see. Gemini “capsules” (grrr) contain a lot of meta-discussion about Gemini itself. My capsule won’t be about that though. It will contain technical information that I’m accumulating. I won’t bother mirroring it over http, either. It’ll be something exclusive to Gemini. It will represent over 20 years of accumulated information that I have.

Update 1: 2022-05-21

There was more I wanted to talk about, but just could find the stuff that I found on Gemini. I actually found what I was looking for by perusing my $HOME/.config/lagrange/visited.2.txt site.

Gemini has a search engine, but alas I couldn’t find the content I knew I had seen. I’m not the first one to notice that the Gemini could use a decent search engine. And I wonder if Gemini capsules should establish a set of conventions for things like blogs. Not standards, but conventions. At first this might seem like semantic nitpicking, but allow me to explain. By “standard”, I mean “baked into the protocol”. That would be too restrictive. “Convention” is to be understood as “best practises.” Informal extensions. On practise I would like to see is that pages should be dated by their creation and update date. On one level, I am always fascinated by the history of these documents. And on another level, it gives context to the page. Information can become stale. Dating articles can be useful from that perspective.

But I have digressed too far already …

The article that I had in mind was at gemini://idiomdrottning.org/web-sluts. The page referenced “scantily-clad women”, and at first I thought that the article must have been based on a post I made recently about Gemini and the WWW. However, that article predates my own, so I know that it was purely coincidental.

I wanted to reproduce some of their text because it amused me no end.

I’m first and foremost protesting the “Gemini is good because we don’t as many scantily clad Babylonian whores” misogynist rhetoric.

Also:

Instead we’re saying that visual media are being associated with women and text media are being associated with men. That’s not necessarily based in actual reality (as you correctly observe with the voracious readers in your own life) but that’s how it is being coded, which is pretty wack.

That’s a kind of odd way of stating things, in my view. Yeah, I kinda get where s/he is coming from, although you need a bit of context for it, which I might not be representing properly.

I really love the next bit, though:

Plain text is seen as sober, thoughtful, chaste, male, clay, ribcage, wands, clubs, odd, 陽, I bless Ra, the fierce sun burning bright.

The web is seen as intoxicated, impulsive, slutty, snake, apple, cups, hearts, even, 陰, I bless Isis—Luna in the night.

Plain text is seen as the honest truth.

The web is seen as Babylonian, tarted up, performed.

That’s a mythology that can get kinda pretty messed up very quickly, can create an environment where the proverbial bitches can’t hang with the proverbial streets.

Sir, you are a true wordsmith! May the light of Ra always shine upon you.

Posted in Uncategorized | Leave a comment

Gemini: a www alternative

So, do think that watching scantily-clad young ladies twerking in their bikinis on OnlyFans is a bunch of bullshit? Concerned that Google, Microsoft and Facebook are becoming the gatekeepers of the internet? Annoyed that most sites have become bloated pieces of garbage more interested in harvesting your eyeballs than in providing interesting content?

Then I have a suggestion for you: Gemini. Gemini is an internet protocol, similar to HTTP and gopher (Wikipedia). It also defines a file format, similar to HTML. Gemini derives its name from the Gemini space program, which was conducted between Mercury and Apollo. In the analogy, Mercury is the equivalent of the Gopher protocol, Apollo is the equivalent of the World Wide Web, and Gemini occupies an intermediate ground between the two.

In terms of a facetious editor analogy: Gopher is Ed, Gemini is Vim, and HTML is a 1GB Eclipse IDE download.

The Gemini markup language seems to be inspired by markdown, but with a formal specification rather than ad hoc extensions that markdown often has. Whilst HTML is basically infinitely extensible, Gemini is deliberately constrained. You can’t run riot with JavaScript and all that baloney.

This makes writing client software well within the scope of one man hacking away in his bedroom. As opposed to a browser like Firefox. A lot of the clients I’ve tried were rather flaky, or just plain failed to compile. Fortunately, someone pointed me to a nice one called Lagrange. It seems to be one recommended a lot, and is “feature-complete”. So that’d be the the one to try in the first instance. You can compile it from source, if you feel you must. Or, you can do what I did, and just download and run an AppImage. I think there is a Flatpak package too, but I can’t be doing with all that nonsense.

Lagrange has fantastic font rendering. Really gorgeous. Although maybe it’s just Helvetica (?) It has a default “dark”” theme, which you can change. One reviewer said it was depressing, but I think it is very stylish and the whole rendering is pleasantly aesthetic. A really nice touch is a sidebar in which you can display a table of contents. What an ingenious idea! Gemini docs (GMI’s) can have headings and subheadings, so it is easy for the browser to generate it. It is an interesting demonstration as to how sometimes simpler can be more powerful.

Comparing Gemini to Vim is a very apt one, I think. Although folks have developed plugins for Vim (but you can’t do that with Gemini), in a way, I think that’s the wrong way of thinking about Vim. You should do things the Vim way, bend your thinking to its way of thinking, rather than the other way around. Vim is not Emacs. It’s a different mindset.

I had tried kicking the tyres of Gemini about half a year ago, and found them to be a bit flat. With the discovery of Lagrange, I have a renewed interest. There’s a combination of factors. Github announced that it was upping its login arrangements. Google is doing something similar too. It looks like we’ll be jumping through more hoops to get Thunderbird to work. Even worse, it is my understanding that regular 2FA (2-factor authorisation) won’t work. It’s some kind of Google propitiatory bullshit.

Then there’s WordPress. It’s pretty bloated, and often a fiddle to use. I write a lot of technical content. Writing preformatted code in WordPress can be a bit of a wrestling match. When I first used WordPress, the process was somewhat tiresome. Then there was a phase where it actually did the right thing. Now it seems back to crap again.

I had investigated a bunch of blogging platforms that had been recommended. I was disappointed. Most of them seemed overfussy, and I was dubious that they would be an improvement over WordPress. I had heard that Tumblr was making a comeback. I checked out the site, but figured that it wasn’t suitable for the kind of content I was interesting in posting. I have said this before, and I’ll say it again: I’m seeing a lot of sites which have what I call the “Generation Z aesthetic” (I’m defining Gen Z as people born in the late 90’s to 2010’s). Or you could call it “Plastic Pop”. Something about them says “influencer”, you know? “This is me being the best version of myself”, and all that stuff.

I decided that probably the best way forward would be to cobble something together with Jekyll. I have never used Jekyll before. A quick try proved that it was simple enough. I could make something clean and simple, without gimmickry.

I had also discovered a small server written in golang called markdir. It served markdown pages rather than HTML.

So there was bunch of ideas floating around in my head. I was trying to form a cohesive idea out of them. The pieces looked that they may come together in the form of Gemini. I could create pages in a simple markup language. What’s more, I didn’t need any server software if I just wanted to use something internally. The browser could pull up links as required. So at least at first glance I had some kind of solution that I was looking for.

Interestingly, I have read articles suggesting that gopher is making a bit of a comeback. According to an article in 2018:

… one of the gopher sites where I post shows new members weekly: 2% growth per week. … Gopher represents the ability to bring an interconnected browsing experience to low-computing-power environments.

That’s a good point, actually. In fact, I see at least two benefits of simple protocols like gopher and Gemini:

  • bandwidth requirements are really low, so they can be used in rural areas or developing countries where internet connection is poor and slow
  • being mostly plain text, they are very accessible to visually impaired viewers
  • being simple, client software is easy to write for obscure Operating Systems like Aros (a free AmigaOS clone)
  • resource usage is light. They should run on even the lowest-specced machine. Hell, you could probably write a gopher client for an ESP32 microcontroller.

I had a quick play with gopher yesterday. It was quite interesting. I noted that it was surprisingly useable. I think I’ll stick to Gemini just now, though.

I’ve explored Gemini sites just a little bit. There’s quite a sub-cultural and retro feel to it. I mean that in a good way. Even reading some of their blogs (I think they call them phlogs) is quite interesting. Smallish snippets of ideas.

There’s a feeling that Gemini, like Gopher, is stepping back to the internet of 1991 (in a good way!). There’s something mysterious and fresh about it, with unexpected discoveries around the corner.

It’s worth mentioning that Gemini is not intended to be a replacement for the WWW. That ship has long sailed. Nor Gopher, for that matter, Rather, it is an adjunct of the two.

Anyway, I reckon I’ve said enough about all this. Go check it out if it seems interesting to you.

Peace.

Posted in Uncategorized | Leave a comment

Microcontroller API design: separate out concerns

My tip: try to separate out device-specific code from SDK-specific code.

By “device”, I mean any physical piece of hardware like a DS3231 real-time clock, or an SSD1306 OLED display. Something that you attach to your mcu (microcontroller).

By “SDK” I mean whatever API may be used to implement a protocol such as I2C, SPI, etc.. Every mcu likely has a selection of APIs to choose from: Arduino, mbed, CMSIS, ST HAL, libopencm3, etc..

Ideally, keep these two sides separate. Otherwise, you will have a difficult time porting code between different mcus.

I’m not here to pour scorn on Arduino code, but you will see that, time and time again, libraries to control devices are intertwined with protocol code. This makes things hard to port.

The protocol code written for the Arduino generally does a good job, but it is not always consistent. You need to use the TinyWire library for an ATtiny85, whereas for an Uno a hardware library is used.

So ideally, to program a device you would be to write a library that initialised variables, returned initialisation code, and ways to interact with the specific device. It shouldn’t know how I2C works, for example, although it will need to be designed to be easy to use with I2C. Then, as a separate piece of code, write adapters for calling I2C.

I searched for “poor microcontroller api design”. The second match was “7 Tips for Developing Great APIs”. I won’t link to the website because I don’t want to publicise such shoddy writing.

My first problem is with the headline itself. It uses the word “Great”. The use of superlatives and hyperbole is a red flag that the article is mostly going to be fluff. This has no place in technical writing. Save that garbage for buzzfeed articles.

Anyway, I’m off for a walk. My apologies for any broken formatting. WordPress is turning into an unfixable dumpster fire.

Posted in Uncategorized | Leave a comment

Is it my imagination, or is the #rp2040 more reliable than the #stm32?

Maybe I’m doing things wrong, but I wonder if people have found the RP2040 to work better than STM32’s? Just some of the peculiarities I’ve noticed:

  • I couldn’t quite get an oled display working with an STM32L432KC, and resorted to bit-banging
  • although the L432 has NSSP for SPI, the STM32F411 does not. The NSSP setting enables the clock pin to high between each byte/word of transmission. Some devices require this. So you may not be able to use SPI DMA (depending on device). The RP2040 just works.
  • I could get my oled to work on the STM32 using libopencm3. It works OK until I enable systick. I did some LED flashing using systick, and the mcu used to freeze, or something, after about 20 minutes. I’m not sure about the precise nature of the problem. I don’t think there’s any data races introduced, so that couldn’t be the cause of the problem. I tried using a timer instead, with similar results. I then simplified the systick/timer to only increment a tick count. The MCU then froze after approx 2h30m. Bizarre. The same project on my RP2040 is still going, even after 3h30m. A lot of the code is shared.

I must presume that I’ve been doing something wrong somewhere. I mean, the chips can’t be as unreliable as I’m making out, right?

Update 2022-05-11: I rewrote my oled/ds3231 code using the stm32 hal. My libraries remained the same, I just used the HAL to initialise the I2C and wrote a simple 2-line replacement for libopencm3’s i2c_transfer7() function. The MCU is still working after 2h54m. Hmm, I wonder what’s going on here. A bug in my code, perhaps, but basically nothing changed in it. Perhaps a bug in the way libopencm3 calls the standard library? Some subtle software or hardware bug in libopencm3 itself? It’s difficult to know what to say about that.

Posted in Uncategorized | Leave a comment

Time to break out the tinfoil and make myself a hat

So, Google Mail is going to switch to 2FA (two-factor authentication). It seems that somewhere along the chain a phone number is required. I am not happy.

Microsoft’s Github is going to switch on 2FA before the end of 2023. Although I haven’t figured out all the details, it looks like I can authenticate with command-line tools on Linux.

I am running out of a lot of trust with Google. They are too aggressive at trying to get my phone number. I am thinking seriously about hosting my own email. Fortunately, my ISP provides me with a sub-domain that I can use. I may just switch to some other free email provider, like AOL.

I’m also transitioning my Github stuff over to Gitlab. I might try their 2FA to see if I can get it working with my system after I have fully transitioned to Gitlab.

My other concern is with taxes. I have an app that generates one-time passwords on my Nexus, running Android. I use the official HMRC app. What’s annoying is that they keep wanting me to upgrade the app. It’s a 10M download. I think it just uses TOTP (Time-based One Time Password). It’s a massive download for what is actually a simple tool. It doesn’t reveal the secret key, though, so I don’t know how I’m going to transition away from the Nexus.

The Nexus is from 2012, it’s not a smartphone, so I am a bit worried about how long Android will support it. HMRC allows you to change how you log in to do your taxes, but the process seems impossible. Like, they require a valid passport. Mind has expired. Or I could submit a Northern Ireland driving license. Northern Island? I’ve never been to Northern Island. What the hell?

They do have an API for me to look at. I’m not sure I want to go down that particular rabbit-hole. Like I say, I suspect authentication is pretty straight-forward and standard if I could just get hold of the secret key.

I might try to install Android on VirtualBox for my PC, or for my Raspberry Pi. I had tried Android on my Pi a few years ago, IIRC, and walked away with the conclusion “needed some work.”

I’m not ultra-convinced that TOTP is such a great idea. We already have public-key encryption for things like ssh. And we have things like login passwords where the password is irrecoverable. If you do the TOTP stuff, then both the server and the client must store the actual key. If there’s a compromise, then the whole mechanism is useless. And sites seem to get compromised all the time.

There are always weak links in these schemes. Devices might break, be unavailable, be non-upgradeable, lost, and all manner of things. Then you risk being permanently locked-out.

There are apps out there that can help you. But one must be extra cagey about these things. How do you know you can trust them? How do you know how long they will be around? Some guy was talking about an app for Android. He said he moved off of it, because if his Android was stolen, and it wasn’t properly secured, then the whole 2FA thing is compromised anyway. As the saying goes, a chain is only as strong as the weakest link.

Vendor-lockin. This is a big issue. Companies just love to lock you in. Look at “Do no evil” Google. The temptation is just too strong. Vendors just love setting policy, too. “It’s either our way, or the highway.” I choose “highway.” Time and time again we see that vendors just can’t be trusted. We need to stop with the attitude of “It’ll be alright on the night.”

Lambs to the slaughter.

Posted in Uncategorized | Leave a comment

A quine in the Daft programming language

“Will Hare replace C? Or Rust? Or Zig? Or anything else?” (link)

Zig, Nim, Rust, Odin, and occasionally D, as languages that appear on Hacker News.

It inspired me to start mucking around with a silly exercise. It is based on a soup of ideas: bootstrapping C implementations, quines (self-replicating code), Forth, and Val Schorre’s paper on Meta II (link)

So I came up with Daft, a minimalist language that can produce a quine of itself. Here is a quine in Daft:

S>S2TT
>S2TT

What the hell, and what’s the point?

Meta II is a “meta-circular compiler”, which means that it can compile itself. The problem is that it needs it’s own assembly instructions to do it. You have to write that assembler. So we have the classical chicken-and-egg problem.

My idea is to dispense with writing that assembler, and instead writing a different assembler, an assembler that is much easier to implement.

Forth seems an interesting idea, but can we make it even simpler? Yes, we can. We use ASCII characters as opcodes. This is what the above “program” uses. Specifically:

S - push the current heap pointer onto a stack, read a string from stdin until the newline, putting the read string on the heap
2 - duplicate the top item on the stack
> - read the next char from stdin, and echo it to stdout
T - type the zero-terminated string pointed to by the top of the stack to stdout, then a newline, and pop the top of the stack

With just 4 instructions, we are able to produce a quine.

Now, admittedly, this isn’t enough in itself to make a general-purpose compiler. It’s just a thought experiment. There are no test conditions or jump instructions, for example, that would be needed to create a compiler.

Here is the implementation of the interpreter:

#include <stdio.h>

int stack[100];
int sidx = 0;

char heap[1000];
int hidx = 0;


int pop(void) { return stack[--sidx]; }
void push(int val) { stack[sidx++] = val; }
void dup(void) { stack[sidx++] = stack[sidx-1]; }

int main()
{
        int c;
        while((c = getchar()) >=0) {
                switch(c) {
                        case 'S':
                                push(hidx);
                                while((c = getchar()) != '\n') {
                                        heap[hidx++] = c;
                                }
                                heap[hidx++] = 0;
                                break;
                        case '2':
                                dup();
                                break;
                        case 'T':
                                puts(heap + pop());
                                break;
                        case '>':
                                putchar(getchar());
                                break;

                }

        }
        return 0;
}

40 lines of code. That’s all. The question is: what would we need to add to have the same power as Meta-II?

And what will this buy us? Well, we could create a grammar for some language that we were interest in writing. Maybe it’s not a computer language, maybe it’s a string for something like RTTTL, which is a ringtone description language. I did one of those in C using lex and yacc.

Meta II and lex and yacc require separate compilation phases. My system could potentially embed an interpreter inside the runtime itself, like Forth, but geared more towards generalised language. The whole thing is so small that you could use it in a microcontroller.

To get in and out of the interpreter, maybe you could use a symbol like “¬”. code blocks could be implemented between “[” “]” pairs, with escape sequences for strings. Bracketed pairs would be inefficient, but then it would mean that you don’t have to implement backtracking of addresses, and all that.

Anyway, just some ideas. I might see if I can develop it further.

Hey, WordPress seems to be getting worse by the month.

Link to github code.

Posted in Uncategorized | Leave a comment

Square-wave and boolean-modulated output using sampling

Abstract

Tones of a specified frequency can easily be produced on nearly all mcus (microcontrollers) using pwm (pulse-width modulation). The output is a square wave. This post explores the use of sampling to produce frequency waves. Although this is more processor-intensive method, it does allow for greater control of the output wave. This post introduces the concept of “boolean-modulation”, where the on-off states of an input square-wave signal is processed by boolean logic. It demonstrates how to produce an effect that is similar to a binaural beat. Additional harmonics are introduced into the output, giving them a “funkier” effect.

Algorithm for producing sampled square waves

Suppose the following:

  • fs is the desired sampling frequency of the wave. fs = 44100 (Hz) is a typical sample rate for many audio files
  • fw_t is the frequency of the square wave to output. fw_t = 440 (Hz) is the frequency of the note “A”. More specifically, it is usually referred to “A4”.

The following algorithm, written in D, determines whether the output should be 0 or 1:

import std.math;
import std.stdio;

const float fw = 440; // frequency of wave
const float fs = 44100; // sample frequency
const int nsamples = 60 * cast(int)fs; // reserve space for 60 secs of tone

void main()
{
        float[] samples = new float[nsamples]; // the output
        float dt = 1 / fs; // time increment is inverse of sampling freq
        float t = 0; // time
        const float fw_t = 1.0/fw; // period of output wave
        for(int i=0; i< nsamples; i++) {
                t = fmod(t, fw_t); // limit time to one wave period
                samples[i] = 0;
                if(t>=0.5*fw_t) samples[i] = 1.0; // in second-half of wave
                t += dt; // increment time

        }
        ... any extra processing, e.g. writing to file
}

It is an algorithm that can be translated easily to a microcontroller with a timer. The output is a 50% duty cycle. It can be changed easily.

Boolean modulation

Binaural beats are generated when two sine waves of similar, but non-identical, sine waves are added together. This method is not especially suited to microcontrollers because the output is of variable amplitude rather than a simple on/off of a GPIO pin.

However, all is not lost. The inspiration behind binaural beats can be modified to use simple boolean logic. The strategy is to generate two square waves of slightly different frequency. Their on/off states are OR’d together to produce the output state.

Here is example code:

import waved;
import std.math;
import std.stdio;

const float fw = 500; // frequency of wave
const float fs = 44100; // sample frequence
const int nsamples = 60 * cast(int)fs; // 60s
                
void main()
{
        float[] samples = new float[nsamples];
        float dt = 1 / fs;
        float t0 = 0, t1 = 0; // time of each of the two waves
        const float fw_t0 = 1.0/fw;
        const float fw_t1 = 1.0/(fw + 1.0); // add a little binaural
        for(int i=0; i< nsamples; i++) {
                samples[i] = 0;

                bool hi0= false;
                t0 = fmod(t0, fw_t0);
                if(t0>=0.5*fw_t0) hi0 = true;
                t0 += dt;

                bool hi1 = false;
                t1 = fmod(t1, fw_t1);
                if(t1>=0.5*fw_t1) hi1 = true;
                t1 += dt;
                if(hi0 || hi1) samples[i] = 0.1;
        }
        writeln("sample array filled");
        Sound snd= Sound(cast(int)fs, 1, samples);
        encodeWAV(snd, "out.wav");
        writeln("Done");
}

The frequency in this case is 500Hz. There is a small offset frequency – 1 Hz works well – that modifies the on/off state.

A 60 sec sample output is available here (470k size).

The source code is available here.

Parting remarks

This is an efficient way of generating waves with interesting tonal qualities for use in note production.

Ref: db7.102

Posted in Uncategorized | Leave a comment

#libopencm3 examples for stm32f411

The examples may work on other STM32 microcontrollers, with modification.

Such examples include: a basic blink sketch, timers, exti, newlib integration with uart, spi, dma, i2c, pwm, systick, ssd1306, ds3231. So, quite a wealth of things to choose from. Check out my repo here.

Additionally, I’m creating a bunch of device drivers that I call “pot“. So far, I have drivers for the ds3231 real-time clock, the Adafruit 8×8 matrix based on the MAX7219, and the ever-useful SSD1306.

These drivers are based on the libopencm3 API. I’m creating an adapter layer for the Raspberry Pi Pico #RP2040, so you should find that all the afore-mentioned devices work with the Pico.

Have fun.

Posted in Uncategorized | Leave a comment

My #rp2040 dev board wish-list

Here’s what I want to see in a dev board:

  • Put the pins closer together (longitudinally, of course) so that the board can be inserted into a standard 40-pin IC socket. Forget castellations.
  • Number the pins on the topside of the board. Counting pins is no fun.
  • A built-in st-link (or equivalent) like on the Nucleo boards. This is my primary request. Boards feel so much more pleasant to use when you don’t all sorts of hardware hanging off the side.
  • A reset button (probably). Who wants to faff around holding down boot button and unplugging the USB cable? A reset button may not be necessary if the link works nicely, though.
  • Double male headers (a nice touch). The nice thing about Nucleo boards is that you can access the device from above and below. The boon of this is that you can mount most of your devices onto a permanent board, and incrementally experiment with additional hardware.
  • USB-C connector. Gotta love how I can just plug the thing in without fussing about orientation.

My list is all about ergonomics, something that makes a device pleasant to use rather than an exercise in frustration. I’m basically advocating for a copycat approach to the Nucleo-32 boards. My list may not be original, but who cares? My desire is to have a good product. Plagiarize, plagiarize, plagiarize. Let no-one’s work escape your eyes (Tom Lehrer, slighted modified).

The RP2040 is quite a nice chip, and doesn’t have some of the frustrations that I’ve had with STM32.

Posted in Uncategorized | Leave a comment

A nightmare function to kill you in your sleep in #golang

Clickbait title much?

I am not a golang programmer. I’m mostly C/C++.

I had played with golang many many years ago. I didn’t like it much at the time. I recently thought about parsing a binary file using golang, but quickly gave up when it seemed that there was no easy way to cast types. And yet …

I have recently been contemplating concurrency mechanisms for use with microcontrollers or event-based applications. I have a clock app written in C for the Raspberry Pi. I used threads at one stage, but settled on a superloop that updated tasks every few ticks.

A feature of the code is that there is global state. This is potentially tricky because there are right ways and wrong ways of adjusting state. As global state increases arithmetically, the risk of doing it wrong increases geometrically.

One thing the code does is activate a buzzer periodically. One buzz for half a second every five seconds whilst the timer is counting, and two buzzes every five seconds when the timer expires but is still running.

There is a function called buz_task() which is called every 4 milliseconds:

/* value of n:
 * -1 : update buzzer
 *  0 : stop buzzer
 *  1 : one beat every 5se
 */
void buz_task(int n)
{
	static uint32_t buz_start; // initialising unecessary as it is off anyway
	static int running = 0;


	if(n==-1) {
		uint32_t interval = (ticks - buz_start)%5000;
		buz_pattern(running, interval);
		return;
	}

	running = n;
	buz_start = ticks;
}

There is a global variable here: buz_start. It gives the millis count since the timer was started. It calls buz_pattern(), which is defined as follows:

void buz_pattern(int pattern, uint32_t interval)
{
	static int prev = 0;

	int on = 0;
	switch(pattern) {
		case 0:
			break;
		case 2:
			on = (1000 < interval) && (interval<1500);
			//fallthrough
		case 1:
			if(interval < 500) on = 1;
			break;
		case 3:
			on = (interval < 200) 
				|| (400 < interval && interval<600)
				|| (800 < interval && interval<1000);
	}

	if(on && (prev==0)) buz_on();
	if((on==0) && prev) buz_off();
	prev = on;

}

This is getting more complicated now, as it needs to know if it’s buzzing, double-buzzing, and the time since the timer started.

I guess it’s not too bad, but it starts to get tricky if you want to pile on more features. What I want is the idea of a process that can be started, killed and has idle wait. The buzzing algorithm can then be expressed in a more natural way, as a flow, rather than having to keep saving and reinstating state.

This got me to thinking if we could do better in language that supports concurrency.

I’m not yet trying to implement all of the buzzing code, but something simpler. The idea is to create a function that will delay for a certain time, but has a kill process. I call this function mare(). It can kill you whilst you are sleeping. Hence the title of this post. Here is its implementation:

func mare(c chan bool, n time.Duration)  (bool) {
        c1  := make(chan bool)
        go  func() {
                time.Sleep(n);
                c1 <- false
        }()

        select {
                case  <-c1: 
                        return false
                case v1, ok := <-c: 
                        if !ok { return true }
                        return v1
        }
        return false
}

The idea here is that a caller invokes it. It uses two channels: an external one, c, and an internal one, c1.

You see that it invokes a goroutine which just sleeps and sets the internal channel to false upon timeout.

Now the interesting thing here is the select statement. Channels usually block, but Go can respond to any channel that has data to read. Aha. Now the function can respond to either a normal timeout, or an abnormal abort.

I chose to use channels rather than just use the external one. A caller might decide to prematurely close the channel. In this case, Go will panic if the timeout writes to a closed channel. Not good.

The “select” statement can actually detect for a closed channel (via “ok”), and respond accordingly.

ALL OF THIS IS REALLY NEAT!

So, how would one use this? Well, I created a function called greeter(), which says “Hello” every second until its caller gets bored, upon which is does some cleanup. Here’s how it’s implemented:

func greeter(c chan bool, wg *sync.WaitGroup) {
        defer  func() {
                fmt.Println("Missing you already")
                wg.Done();
        }()

        for {
                fmt.Println("Hello")
                if mare(c, time.Second) {return; }
        }
}

We go around and around whilst mare() returns false, but quits when mare returns true. The cleanup function is called via the “defer” statement.

It’s a little more complicated than that, though. Go has something called a “WaitGroup”. greeter() can return, but it hasn’t necessarily done all of its cleanup. This is potentially bad, as the caller might do something that messes up state. The caller should wait until the cleanup is done. This is the purpose of a WaitGroup. You can see that the cleanup code in greeter() signals that it has finished by calling wg.Done().

So here’s how a caller to greeter() might look like:

func main() {
        wg := new(sync.WaitGroup)
        wg.Add(1)
        c := make(chan bool)
        go greeter(c, wg)
        time.Sleep(5 * time.Second)
        close(c)
        wg.Wait()
        //time.Sleep(2 * time.Second)
        fmt.Println("Over and out")
}

It calls the greeter() via a goroutine, then sleeps for 5 seconds. greeter(0 should print “Hello” 5 times. It then closes the channel to signal that it’s had enough, and then waits for the workgroup to finish. Without the wait. the message “Missing you already” might not be printed.

The folks who developed Go have obviously though a lot about concurrency.

Although closing the channel is the simplest way of doing things, it might not be the best. You might want to reuse the channel, for example.

I’m not sure that the waitgroup is necessary for this type of setup either. I’m thinking that one could eliminate it. Instead of closing the channel, the caller sends

c <- true

to signal a timeout. And instead of the defer statement calling wg.Done(), it calls the channel as above.

On the caller side, instead of doing wg.Wait(), it then does

<-c

i.e. it will block on the channel until the “defer” statement sends a message to the channel.

Food for thought. Here’s the complete code:

package main

import (
        "time"
        "fmt"
        "sync"
)


func mare(c chan bool, n time.Duration)  (bool) {
        c1  := make(chan bool)
        go  func() {
                time.Sleep(n);
                c1 <- false
        }()

        select {
                case  <-c1: 
                        return false
                case v1, ok := <-c: 
                        if !ok { return true }
                        return v1
        }
        return false
}

func greeter(c chan bool, wg *sync.WaitGroup) {
        defer  func() {
                fmt.Println("Missing you already")
                wg.Done();
        }()

        for {
                fmt.Println("Hello")
                if mare(c, time.Second) {return; }
                //time.Sleep(time.Second)
        }
}

func main() {
        wg := new(sync.WaitGroup)
        wg.Add(1)
        c := make(chan bool)
        go greeter(c, wg)
        time.Sleep(5 * time.Second)
        close(c)
        wg.Wait()
        //time.Sleep(2 * time.Second)
        fmt.Println("Over and out")
}

I had in mind that things I learned about Go on by Pi would be useful when I work with microcontrollers. There is a project called TinyGo, which is for just for such a purpose.

The caveats to this would be that it’s not ubiquitous like MicroPython, and not all features are necessarily implemented. It supports my STM32 Nucleo L432KC board, the bluepill, the Raspberry Pi Pico, but not the popular blackpill.

The Pico seems to have received some loving from the community. The docs suggests that it is fairly feature-complete, with the exception of the serial port on USB. That may be important to some. However, I often use a second Pico (actually a Tiny) as a debugger anyway, so you can get serial output via it.

Or should I explore Zig more, which also has concurrency features, and is likely to support a larger range of boards?

Or maybe I should just stick to C? Working through Go made me realise that perhaps a better approach would be that I only need 3 events for my buzzing function: start, wakeup, and kill. Maybe just wakeup and kill. It would mean creating some kind of wakeup scheduler, but I don’t think it would be too onerous a task.

At the very least, this little excursion into Golang has given me food for thought, and given me fresh insights as to how I might approach something in C. I can certainly say this: the goroutines are certainly a lot more understandable than the coroutines that recently made it into the C++ standards. Jeez guys, could you have made it any more complicated?

So, the thing I’m beginning to admire about golang is the simplicity of the syntax and the fact that it has a number of features aimed at concurrency that just mesh together nicely. In the past, I hadn’t been working on things that required concurrency, so I hadn’t perhaps figured out what the big deal was with golang.

One should aim for the simplest thing that could work, of course. Most of the utilities I made don’t require concurrency, so I didn’t use it. Which is as it should be.

It’s also got me thinking about issues such as State Machines. There seems to be a big divide between those who advocate for RTOSs (Real-Time Operating Systems) and State Machines. What Golang has got me thinking about is that it might be possible to have neither (for some cases). I’m thinking of a “State Machine Lite”, where there are still events and state, but in a much simplified form that adheres more to a sequential way of doing things rather than a full “Pearly King and Queen” approach that I had before.

Enjoy your day.

Posted in Uncategorized | Leave a comment