I used to have a small desk clock that I purchased for a trip. It was cheap but it had some really nice features that I quite liked. It had large digits that I could see from my bed each morning, and it was also able to measure and display the current room temperature, which I always thought was incredibly cool for a clock.
The problem is, that it required a lot of batteries to work; 4XAAA for the fancy LCD backlight and soothing RGB glowing action, and 2xLR66 (button cells) for keeping the thing ticking and actually displaying time and temperature on its LCD screen. It worked reasonably well, but it was running through the batteries way too fast, in my opinion.
I didn’t really care about the AAA batteries dying in a month, because I could always use rechargeable batteries there, but the small LR66 batteries were killing me. Replacing them each 5-6 months or less wasn’t really a pleasure, especially since it meant setting time, date and alarms all over again, every time.
So I adventured in the journey of building my own clock. My main objective was to keep the number of batteries low, while also having the nice features of my previous clock, like the big numbers and the temperature readings.
SPOILERS: This is what I ended up making. No, it’s not a bomb.
So in a previous post I’ve discussed how to communicate with a custom HID device using libhid and a Raspberry Pi running linux.
This post is a sort of sequel. I’ll talk about some of the issues and nuances I found when working on a more complex (but related) project; In this case a Composite USB Device that I had to implement on a PIC 18F4550 microcontroller.
I wanted to add a temperature sensor to a project I’m working on, and while I already had selected the perfect IC for the job, I decided to test a couple of other options I had, to see how they fare in comparison. I was originally going to compare only 3 sensors; the popular LM35, the not-so-popular LM335 and the kinda obscure TMP75, but as I started writing this post I remembered I got a Dallas DS18B20 as part of kit of sensors, so I added it to the mix to balance the digital-to-analog ratio of this comparison.
The original 3 sensors I was going to test.
If you have any experience with a soldering iron, or soldering electronic components in general, I’m sure it will come as no surprise for you that the “fumes” produced by the process are not exactly good for your health. They can be quite harmful in fact (** depends a bit on the chemical composition of the solder you use). Even if they weren’t, they are -at the very least– annoying as hell. They always find their way to your eyes and throat in the most unpleasant ways.
I discovered some time ago that a device specifically designed to cope with this issue existed, and it’s been in the market for a quite a long time. This unbelievable product of heaven-sent technology and engineering is unsurprisingly called Soldering Fume Extractor (I bet you didn’t see that coming) which is nothing but a pompous name for a small desktop fan with an active carbon filter.
It’s been with me for more than 10 years.
Back in the ’80s, Casio produced a line of calculators that was sold and advertised as “pocket personal computers”. This branding started with the PB-100 I believe, but the device concept started with a previous model, the FX-702P, produced in 1981.
While by today standards that claim seems a bit of an stretch, it held quite a bit of ground back then. These calculators featured a BASIC interpreter built-in, and internal memory to store user programs. They also featured a proprietary port/interface that allowed some Casio peripherals to be connected to the device, like a printer or a cassette drive. Personal computers back then were not much more than that.
The FX-850P model released in 1987 -and other calculators that followed- were a significantly step forward since their peripheral options (via the Casio FA-6 Casio interface) included standard Centronics parallel port and RS-232 serial connectivity, both ports widely used in computer hardware.
The FX-880P, released in 1990, was (I think) the last device in this line of Casio personal computers / calculators, and was basically a FX-850P with 32KB of RAM (instead of just 8KB).
When I was a kid I used to see this calculator in store catalogs and magazines and always wanted to have one. Many years later, when I was old enough to purchase my own stuff, I was finally able to get one (second hand) in pretty good condition, and I still use to this day.
If you follow me on Twitter, you might have seen this 1 year ago:
Although I think I never ever posted anything after that, I was definitely working on such a tool, focusing particularly on Gameboy Color development (and as you can see I got it working).
As part of a bigger project (that I’ll reveal later) I set on the journey of designing a simple “keyboard”. It needed to have enough keys to be usable as a general purpose input device (so it requires alphanumeric chars, common symbols, ENTER, ESC, etc) and preferably built around components I already had (like the bunch of 6x6mm push buttons that I don’t seem to be using fast enough).
Taking old devices and early computers as reference, I went with a 40 keys design (a 5×8 button matrix), arranged in a 10×4 distribution (internally 4 straight rows of 8 buttons, with the “fifth row” split into the 2 extra columns).
I spent some time doing a keyboard layout on Inkscape, trying to fit all the keys I wanted in a way that made sense:
Matrix Keyboard Layout
So I’m writing a program in C that needs to interact with a custom HID device I built. This program will be running on a Raspberry Pi. This isn’t a massively complicated task but it can be daunting when there’s not a single “barebone” example or tutorial out there on how to do this. So I decided to write this sort of guide in case it may come in handy for anyone (including myself, in a future).
Libhid is an open source library designed on top of libusb to deal with HID devices, so the first step is compiling libhid. I’d say this is relatively straight-forward except for the fact that “as-is”, the library fails to build in the Pi. Luckily the problem is a single line of code in one of the examples (yes, and that prevents the whole library from being compiled and installed).
Ok, so this is probably the last post I’ll make about my Brainfuck-on-Arduino project, basically because it has reached a point where I’ve already tried all the things I wanted to try and I’ve decided that there’s no point in taking it out of the breadboard and build a board for it. At least not for Brainfuck. And I’ll explain why.
The Performance Issue
I previously said that I was expecting the performance to “drop” a bit when reading directly from a SD card instead of the internal RAM, but I was hoping to mitigate that with a sector/block cache similar to the one I wrote for the SPI RAM.
And that’s completely reasonable and actually true. Where I made a mistake however, was in also assuming that doubling the SPI clock would result in a noticeable performance boost. That’s definitely false. Reading a whole 512bytes sector currently takes between 1 and 2 milliseconds at 4Mhz, and RAM access is done at the same speed, so being the RAM pages half the size of the SD sectors it probably takes half that much to get a whole RAM page.
Since we are caching so many bytes in advance, the number of page reads (both from RAM and SD) is not really that high, so even if we were to double the SPI bus speed we will only cut around 1ms from each access. Most programs I’ve tested don’t normally cross the RAM page boundaries nor require more than one SD sector to be stored, so the speedup won’t even be noticeable for most cases. It will be barely 1 or 2 ms, so if we run into performance issues, they are somewhere else. They are NOT in the SPI Bus speed.
DISCLAIMER: Over the course of this post I’ll be dealing with parsing, programming practices, code refactoring, SPI bus oddities, caching techniques,etc. It’s a mixed bag of things and it’s far from being serious analysis on the topic of optimization. Please don’t expect anything particularly smart in this post like branch prediction, overlapping cache windows, partial block reads, etc. This is just a chronicle of sorts, of the things I’ve done over the past few hours to improve the performance of my Brainfuck-on-Arduino interpreter, which was being painfully slow.
So in my previous post you hopefully got a glimpse of my current project: a Brainfuck interpreter running completely on Arduino. Something that I forgot to mention is that all the input/output (for testing purposes) currently happens through a serial connection. I’m using the “Serial Monitor” console that’s part of the Arduino IDE to “talk” with the board and run the code.
I’d also like to point out that I’m using an external 23K256 chip for the Brainfuck data space, This is basically a 32KB RAM IC that is accessed via SPI (Serial Peripheral Interface). This is relevant for some of the optimizations I’ll do next.