Eric's Place
Welcome to the DEEP WEB. No... wait... still the regular web.

Programming: Just the fun parts

I always like a challenge. Programming computers is fairly routine for the most part, but sometimes it can be challenging and overcoming the challenge always feels good, man. I thought I’d list some of the general categories where I’ve found interesting challenges in the delicate art of negotiating with a computer.

Algorithmic Adventures

This is the major challenge that people probably think of first when you say the word “programming”, so let’s list it first: Basically, it’s all those Google interview style questions like “how many distinct numbers on a phone could you hit if you were a knight (chess piece)” or those Kattis Challenges I wrote about a couple of times.

These types of problems generally involve totally contrived scenarios that you have to find a clever algorithm to hack your way out of. What’s neat is that they’re often totally “pure”, in that they’re mental exercises similar to a riddle or a puzzle where the language or implementation don’t really matter. Part of the fun is modeling the problem in your head in such a way that you can write a program to solve it, and then looking back at it and thinking “wow, it’s that easy, huh?”.

How Do I Get There From Here

This is probably the biggest one i’ve ran into in embedded systems: How do I get the thing to do the thing with the other thing? A good example was the Yogurt Alarm: I had a temperature sensor and a microcontroller, and I just needed to figure out how to make them talk to each other. Unlike the logical thinking wizardry you need for the previous category, this one seems to be all about reading comprehension and attention to detail. The resulting code is usually fairly straightforward, but it hides many hours of sending the right value to the right place at the right time, making sure the endianness is correct, and even that the hardware connections all line up. Since hardware often gives you little to no debugging feedback, these kinds of problems call for a lot of patience and trial-and-error.

Also, bonus points if there is little or no documentation and you have to reverse-engineer something or translate some obscure documentation from another language! In a way this is the antithesis to the previous category, since it’s almost all implementation-specific. That being said, it’s the exact same “wow, it’s that easy huh” when you finally realized your IRQs weren’t getting generated because you set the 1 in the “Interrupt Enable” register but not the global “Interrupt Enable” register. Foolish!

Marvelous Mathematics

Ever try programming a 3D renderer using OpenGL? Ever program an industrial robot to wield a plasma torch? If so, you might also be a victim of some impressively complex geometry. I feel like this category is a sort of relative to the first one: It also involves quite a bit of big-brain thinking, but involves more traditional math that we learned in school rather than logical algorithms like the kind you’d find in self-balancing binary trees. The amount of math involved in just generating the lighting for a 3D scene gave me a whole new respect for video games.

It can also meld well with the embedded systems world. Take for example the Megasquirt aftermarket fuel injection controller: It does hundreds of little Boyle’s law calculations per second to make sure your engine gets juuust the right amount of fuel for each (intake) stroke. Neat!

Architectural Astronomy

Big software projects have lots of little parts all talking to each other. This brings up the concept of “architecture”, similar to how you’d design a skyscraper, shopping mall, or in our case: A skyscraper that might need to be turned into a shopping mall. Unlike the previous fun challenges, this one is all about open-ended “big picture” style thinking, i.e: “What will our product be used for?” and “How can we make it reliable and scalable?”. There’s also a big downside to failure: Once you’re invested in an architecture it can be extremely costly to change it down the road.

What’s unique about this category is it often involves negotiating with people as much as it does computers. And since it involves people, there is often no one “right” answer - just what works well for you and your friends.

Gotta Go Fast

So you wrote your nice little algorithm to count how many goats can occupy n craters on the Moon, but the Lunar Goat Adjuster uses a puny 8-bit processor with a hardware-accelerated Goat Displacement Coprocoessor (GDC). Uh-oh.

This category is all the little implementation-specific things you have to do to get a program to run in parallel, on specific hardware, etc. all in the name of achieving acceptable performance. It’s similar to “How Do I Get There From Here”, but might involve a bit more creativity, especially since sometimes there are limitations you simply can’t get past and you need to start rethinking the problem itself (What about using sheep instead? They jump over the moon already!).

Debugging!

These are some of the challengiest challenges since they can span several domains, and are also the least glamorous because there’s rarely many accolades to be had for fixing some other guy’s (or your own, especially your own) thing. But hey, they can at least be challenging: Fixing someone else’s thing means understanding someone else’s thing, which is quite a feat unto itself since we all think a little differently. And then of course you have to figure out why the problem is happening based on often limited or inaccurate information.

My favorite so far was when I spent a week trying to figure out why a board wouldn’t boot - it turns out the manufacturer had forgotten to populate two 0402 (1mm x 500μm(!)) resistors. Whoopsie-daisy.

Aaaand I can’t think of any more. Good night!