📝 Articles

Longer articles that talk about a specific topic.


MNT Reform Notes

A collection of notes on the MNT Reform which I received on June 26th 2022.

Shipping

  • The DHL form says the parcel contains Lithium-Ion batteries. Huh? The batteries seem to be LiFe-Po, though.

Assembly

  • The mainboard is not perfectly flush against the case, not a huge issue, I presume.
  • The bag of screws comes with a few extra screws and even tells you so. Very Thoughtful.
  • When connecting the OLED screen, a note that the connector actually can be open and closed would have been helpful.

First boot

  • After booting up for the first time, I quickly decided to apt upgrade 1, which led to the root partition running full and left the system in a somewhat broken state.
    I realized afterwards, that the root partition was not expanded to the full capacity of the sdcard.
    Ended up creating a new sdcard with the v3 image and running off that now.

NVME

  • Since working from only sd card is slow, I wanted to move my root partition to the nvme and and boot from sdcard. I could not find clear instructions on how to do this, there were a lot of questions unanswered.
    • How to boot to the rescue system?
    • How to flip the dip switch on the SoC?
    • Where are the reform-* scripts that are mentioned?
    • How to switch boot devices?
  • I managed to change my setup to boot from the eMMC and then load the OS from the nvme using the script by josch. This way I don’t need to have the sdcard plugged in and can use it for the recovery image.

Batteries

  • I read through the thread about isolating the battery clips which might lead to a short circuit when carelessly removing the batteries. I decided that I will with the foam solution since I don’t have a 3d printer nor head-shrink tubes at hand.
  • Bought some black foam and cut it into size so that it fits between the batteries. It sits relatively loose, better than nothing still.
  • One of the batteries started reporting 0.0V after forgetting to plug in the laptop and it shutting off while working on it. As suggested in the forum, I will try charging it with my NightCore charger to see if it can be revived.
  • Percentage has been ???% for a while now, after showing a correct value in the beginning.

Software

  • Brightness control through the hotkeys seems to be missing after I transferred the OS to the nvme. The solution seems to be to put the user in the video group (Same goes for volume controls and the audio group).
  • After adding myself to the video group, brightness controls are working fine again.
  • Lukas mentioned in the forums, that the operator handbook lists shortcuts for increasing screen brightness! It’s META+F1 and META+F2!
  • Looking into compiling wlsunset, have some missing dependencies
    • needed to install cmake, pkg-config, libwayland-dev, wayland-scanner++ (and link it to wayland-scanner)
    • I does not seem to run, need to try it at proper low light conditions.

Keyboard

  • I ordered the keycaps for the german QWERTZ layout but did not actually put them in when building the laptop, I blame my excited brain for this. When looking at the keylayout for it today, I started having doubts if I even want to switch.

    • The umlaut keys are not useful to me since i barely write german on the machine.
    • Also, curly and square brackets don’t show up! They might still be accessible, though.
    • The only inconvenience so far is the placement of y and z. I might look into keymapper for switching these two and leaving the rest as is.
  • I installed input-remapper to switch my y and z keys. Works really well, albeit only once I logged in.

  • Decided against switching any of the other keys for now. I’m getting used to the us layout of the reform and it seems even beneficial for my usecase (programming).

  • input-remapper keeps me from holding keys down, so right now I can’t delete a long line in the terminal by holding down backspace.

Trackball/Trackpad

  • I ordered Trackball and Trackpad with my kit and used the Trackball for the first few days. Switched to Trackpad today, because I kept on trying to tap the ball, like you do on the pad.
  • Switched back to the trackball. I like the haptics of the trackball a lot more and the pad did not support right clicking out of the box.

  1. despite having read a lot of people saying it tends to break, at least with the v2 image

I started going to the gym about 1 1/2 months ago and I have been really enjoying it so far.

When I started, I paid for an initial guided training, which was basically just an instructor showing me all the machines and giving me a basic training plan for my goal, which is general muscle-building and fitness.

I have been updating this plan with the weights I’m using 1. My instructor at the gym recommended to work with this plan for about 3 months and the switching it up, with a split-based training.

Regarding my current training, I am going three times a week and decided, without any reasons, to do it on Monday, Tuesday, and Thursday.

After watching a video on Supercompensation and creating your own training plan, I decided to change my gym days to Monday, Wednesday, Friday starting this week.


  1. Which makes me wish I had a history for notes on mirage so I can track my progress.

German Verb Game

German Word Game

Over the weekend I created a small site which builds on the observation that a lot of german words are actually made from a small set of verbs and prefixes. By mixing an matching these building blocks, we get a lot of words.

It is not really a game, but you can make it one.

  • Reload the page for a new word
  • Try to figure out if it’s a real word and what it means
  • When in doubt, click the link to reveal the meaning

You can find the site here: https://german.inhji.de

Have Fun!

Preloading in Elixir/Ecto

This is a pattern for preloading in Elixir that I have adopted for a few projects. I’m sharing it here for reference. The idea is to have one place to define your preloads instead of in every query.

@preloads [:listens]
defp with_preloads(query), do: preload(query, ^@preloads)
def preload_artist(artist), do: Repo.preload(artist, @preloads)

with_preloads can be used to enhance an query with preloads:

def list_artists do
 Artist
 |> with_preloads()
 |> Repo.all()
 end

Whereas preload_artist() is used to preload a single object, for example, after getting a single artist:

def get_artist!(id), do: Repo.get!(Artist, id) |> preload_artist()

More on Sewing Machines

Old Sewing machine

My mother had this sewing machine since I was born, I never recognized it as one. The machine itself is hidden in the body of the desk. Recently my mom told me about it and today I took a look at it, only to realize that it needs a key to open and take out the machine.


I also found that the reason for my Singer machine not working was a broken cable and talked about how I wanted to resolder it. I did that a few days ago using a bit of sticky solderflux to keep the cable in place while fiddle my iron into the body of the machine.

It worked out perfectly and the machine is running fine again. For practicing, I tore one of my old jeans and started sewing away! Fun!

A vintage sewing machine

A few days ago my friend got me a sewing machine. He rung me up in the evening and called me into his workshop where he pointed at a leather bag and just said, “I figured you might like this bag”. It was old and bulky and did not seem like anything a could use.

In a hunch, I opened it and found an old Singer sewing machine.

Singer Sewing Machine
The machine on the first night I got it

We had talked about sewing machines before and I mentioned that I wanted to use one to repair a few torn pants of mine.

Taking the machine plus bag home, I noticed that the machine was not working. I went back to my friend since I could not find anything wrong with the machine and we had a look at the pedal which seems to be one of the first things that need to be replaced with an old sewing machine. We figured the pedal would be the culprit, even though we could not see anything wrong with it. I decided to look for a replacement.

Singer Pedal 2
The old pedal that we took apart

A couple of days later I got a replacement pedal off ebay-kleinanzeigen, but the machine still would not work. I set it aside for a few weeks, when I got the itch to look into it again.

Talking with my landlord again, he asked me to check the motor with a multimeter to see if it receives any power at all. While attempting to do that and not electrochute myself, I noticed that was a cable from the power supply sitting loose.

When I pulled it, it broke off completely and I was pretty sure I found the source of my powerless machine.

The insides of the machine
The insides of the machine, on the bottom right there is a cable hanging as well as a solderpoint(?) where it used to be

What I want to do now is try to solder the cable back to its place. There is not much space for a hand holding the cable, the solder AND the iron, so I need to fix the cable in place first, or maybe use some of that honey flux I have lying around.

On Cycling

When I started my apprenticeship, I lived 2 cities away from my work place. With my limited budget, I could not afford going by bus and so I started cycling to work. I did it out of necessity and coming from a work day I remember cursing that uphill section just in from of my home.

After I finished my apprenticeship, I could afford to take the bus everyday and I happily did. For some reason, I never even considered a car to be an option for me, even though I have a drivers license.

My boss was a heavy proponent of cycling and he, his wife and their dog came to work by bike every day. Over lunch we had a lot of talks about how cycling is a good thing because it keeps your body fit (especially when you sit at a desk all day doing IT) and provides you with some balance.

Over the years this opinion found its way into my brain and I started cycling again, this time by choice. Luckily for me, I always stayed in cycling range of my work and so I kept ditching the bus for my transportation of choice.

I went from trying to find excuses for taking the bus (It’s cold outside, It’s raining, You’ll sweat, ..) to finding reasons to absolutely prefer the bike over bus, trains, cars in any possible situation:

  • Time: No more catching or waiting for buses. The liberation I felt when I realized this was immense. If you miss your bus by just one minute, tough luck, there won’t be another one until 30 minutes. If this bus is late by 5 minutes, you might not catch your connecting one, again, tough luck.

  • Space: While I can be hard to find dedicated parking spots for bikes, it is not that big of an issue. You can lock it to that lamppost over there, or on that fence. There are not many restrictions as to where you are allowed to park your bike 1.

  • Balance: One of the most important things for me, being a software developer, is a change of pace when coming home from a long day. While enjoy sitting in the bus and just zoning off sometimes, nothing beats a 30 minute ride home where you can reflect, let off steam or simply enjoy the scenery 2.

The bottom line is: I love cycling, it’s good for my mental and physical health and it’s also a lot of fun 😊


  1. At least in Germany, I’ve heard that you can pay a hefty fine for that in the Netherlands.

  2. My way home leads me through a lot of fields, a river lots of green.

Managing Elixir project versions with git_ops

When developing ELixir applications, I’d like to have an easy way to manage versions. A tool that makes this very easy is git_ops. It is an elixir/hex package which sets up a workflow of versioning your project and git commits using conventional commits.

Conventional commits uses a few easy.. well, conventions to make your commits parseable and actionable.

Here’s how I set up git_ops in my projects.

Plotting my listens since 2010

I have started playing around with my listens and trying to put them on a graph. My initial goal was to see trends of artists over the last years.

I started downloading my listen data from listenbrainz and grouping it by artist and then month:

def favorite_artists(listens, limit \\ 10) do
  listens
  |> Enum.group_by(fn listen -> listen.artist_name end)
  |> Enum.map(fn {artist, listens} ->
    {artist, Enum.count(listens),
     Enum.group_by(listens, fn listen ->
       listen.listened_at
       |> DateTime.from_unix!()
       |> Timex.set(day: 1, minute: 0, hour: 0, second: 0)

     end)}
  end)
  |> Enum.map(fn {artist, total, listens} ->
    %{
      artist: artist,
      total: total,
      listens:
        Enum.map(listens, fn {date, list} ->
          {date, Enum.count(list)}
        end)
        |> Enum.into(%{})
    }
  end)
  |> Enum.sort_by(fn map -> map.total end, :desc)
  |> Enum.take(limit)
  |> IO.inspect()
end

Grouping by month turned out to be pretty annoying and I ended up setting the day to 1 and time to 0 for each listen. Everying else is up to the charting library and I still have the option to convert it back to the unix timestamp if needed.

I used Contex Charts which is as pure elixir, server-side solution and I ended up with this graph, which leaves much to be desired but is fine as a first step:

Listens Part 2

I might switch to a js based charting library because this one is a bit limited.