Close

bixl, 1-bit pixel editor is born!

A project log for openSampler

a hardware sampler based on the raspberry pi running bare metal (so no Linux)

Nick VerlindenNick Verlinden 08/05/2020 at 08:270 Comments

If you read the previous logs, you might have gotten the message that I love 1-bit guis. I loved Atari TOS and the early version of MacOS. To create 1 bit graphics, you can draw lines or pixels using code like this for instance (this is not real code!):

Draw::Line(0,0,320,240);

 To draw fonts, there are several different solutions out there. Having followed David Welch's bare metal programming tutorials, I was using the psf font format, which is very simple. It contains a 32byte header with a few important parameters such as the width and height of the characters. You can create these fonts by hand if you want. Just create a C header filer with a byte array, and start entering bytes manually according to the spec.

Even though the format is quite simple, it's a very tedious job. I looked around, and there seemed to be no simple (free) app to create 1 bit pixel graphics. I also have a Samsung Note 9, and it seemed like a romantic idea to be able to use the included pen for drawing. I have to travel to work a lot this month, so I had some train time to waste. That's when I created bixl. It's a very simple pixel drawing program.

It's a web app that is available here: https://synthology.gitlab.io/bixl/

I had some experimentation code lying around for creating a pwa, so this web app is also a pwa that you can install directly from the browser onto your computer/phone/... 

You can start from scratch, or load an existing psf font. Only psf version 2 is supported at this time, but I'm not planning to add support for more file formats. If you want to add it yourself, dig in, it's open source! :-)

Fighting the lifelong enemy called perfection

Now is a great time to talk to you about the worst enemy I have to face all the time: perfection. If you don't want a lecture about that, just skip the rest of the log as there will be no new technical information.

When working on stuff like this, it's easy to lose yourself in details. I constantly think like: 'oh it would be nice to add x feature', or: 'people will probably need feature y'. This process keeps on going and if you give in to it, you will never deliver or it will take you a very long time to do so. And even then, it will never feel complete. there's always something more you can add.

A few years ago, I was dreaming of a distributed system where you could just include packages directly from github/lab/... in a web app. Think of it like npm, but without the need to locally download and keep these libraries. Your browser would just fetch them when needed. So I started experimenting and writing code. At one point I had a working system. It was fast, and it worked. Then the ocd kicked in and said: you need to rewrite this now, because people are going to see this mess you created. So I started to rewrite with the knowledge I gained by creating it. Javascript promises where the new thing, and everyone was using it, so I had to use them in my rewrite as well. Then, that version was almost finished, and I decided I wanted to add a feature because it seemed nice to have, or it just made sense (though not required!). But then I patched something and the code seemed messy again (though it really wasn't, but I thought it was), so I decided I would rewrite it from the ground up with this new knowledge. By the end, you could write plugins for loading from your own custom repository and all, quite fancy. It just took 3 years of train travel time, and a decent amount of spare time from my life to create it. A few months later, this project was almost obsolete by the javascript import api. I never started using it. So when I look back at it now, it just seemed like one big waste of time. Image you spent your life building your own car. But by the time you finish, cars are no longer being used and were replaced by drones. You created a nice car. For yourself. Great. Now you know how to build a car.

So it was then that I realised that I have to fight the ocd and perfectionism when it strikes. With bixl, I had the original idea to also integrate a reverse engineering tool for inspecting binary files for 1-bit graphics. There is a tool that I created a while ago, and recently cleaned up a bit for public use. it's available here: https://synthology.gitlab.io/ceebit/. My plan was to add that to bixl as well. While I still very much like the idea, I have to restrain myself Both products exist, and are working. There would be no other benefit except to have both tools in 1, and to satisfy my inner demon. Here is a screenshot of a wip version that had an extra top bar with a drawing tab, and an inspect tab.

If you look at the source code of bixl, you will see that every line of code is inside the index.html file. Ask any serious web developer and this would be frowned upon. The way I work is usually like this: I have an idea, I start messing around and suddenly I have something that works. Then I'm supposed to rewrite it the way it should be done, or to say it with proper terms: refactor. Nicely separate the ui code from the logic and stuff like that. instead, this time I decided to skip that step and leave it like this. In my mind this is a complete mess. But you know what? it works. It does what I want, it's reasonably featured, it works on desktop and smartphones, it looks nice and it can load and save psf files. Why on earth would I want to start refactoring it just to satisfy parts of my brain that like things clean. I'm giving this away for free. Not that this is a ground breaking piece of software, but I spent time on it. Hours of my life that I could have spent otherwise, and I'm giving them away to you for free. Are you really going to tell me I should have cleaned it up before 'donating' it to the community?

If you ever have the chance and access to look at some commercial closed-source code, you might be surprised at what you would find. When having a beer with a good friend that works for a company that delivers software for the military, this subject came up. He told me something that stuck around. His philosophy was that If it works and it's stable, it works. The time you usually spend to clean things up afterwards and make it 'just perfect' is not worthed. Because even if you reach perfection, something is going to mess that up anyway. A new feature, some system changes, ... Try to spent as little time as possible rewriting or refactoring.

Even now, when working on openSampler, it frequently comes to mind: should I just start over and do everything in C? Because if I would use C, then I can reuse a lot of code for other projects that only have C compilers. That would mean I have to rewrite or even reimplement certain features of Circle, and that would be an immense time hog. No. I need to fight the idea. Just stick to what you have created already. If the problem comes up that I want to reuse some code on a microcontroller, then I'll just have to cross that bridge when I come to it. Why start rewriting stuff when you don't even know you're going to use them. And why would I even think I could do a better job than what already exists in the Circle library? I probably don't, and most likely make a mess out of something beautiful!

Discussions