Posts

Mind the cache (reference to "mind the gap" in the UK tube)

Memory read and write performance may be identical as far as the physical memory is concerned, but CPU manufacturers have designed unique hardware to manage the very different situations of reading from and writing to memory (from a program's perspective). When reading from memory, your program normally needs the data as fast as possible and often will halt the CPU execution until the result of the read is completed. The cache logic is designed to improve the overall speed of memory by optimizing access to the current data set (a subset of the total memory). Intel (and recently ARM) have designed smart cache logic which can predict read patterns and prefetch memory into the cache in anticipation of it being needed. When writing to memory, there normally isn't any hurry to complete the write, so the write buffer can collect a few write requests without stalling the CPU. The data will work its way through the write buffer and cache logic and only stall the CPU when a write o...

SIMD

Image
The dead horse that I like to keep beating - everyone should use SIMD (single-instruction-multiple data) in their software wherever possible. It's basically free performance, so why not use it? Every PC (x86 machine) sold in the last 10 years has it and so do mobile/embedded machines for at least the last 5 years. What is SIMD? It's a set of instructions which usually make use of extra-wide registers (typically 128-bits) and can do multiple operations in parallel. A regular CPU instruction can perform a single math operation (e.g. integer addition), while a SIMD instruction can do 2, 4, 8, or 16 separate additions in parallel in the same amount of time. It means your program can do its work many times faster. Many programmers are already aware of the existence of SIMD, but may assume that by enabling the "auto-vectorization" option of their C compiler, their program will magically contain beautifully crafted SIMD code. You can already guess from my last sentence ...

Optimizing JPEG entropy decoding

What Entropy coding is the term used for lossless data compression . It refers to increasing the entropy of data by taking advantage of the differing probabilities of symbols to create a more compact representation of them. The size of the code used to represent each symbol is inversely proportional to its probability. In other words, the more probable symbols will be replaced with shorter codes, and the less probable with longer codes thereby reducing the total size of the data. A simple example of entropy coding is Morse code. The letters of the alphabet are replaced by a series of dots and dashes where the probability of the letter (in English) determines the length of the code. The way Morse code is defined, there must be a space between each code in order to uniquely recognize it or it could be confused with a different code. For example, the letter E is a single dot. If two E's are sent without a space between them, they would be interpreted as an I. David Huffm...

Practical animation on I2C SSD1306 displays

Image
Intro I can hear the thought forming in your head already, "Why write another blog post about those ubiquitous little OLED displays, isn't this old news already?" It's a valid question, and there have been plenty of articles and libraries written for these displays over the last 6+ years. It's still new to me because I just started working with AVR MCUs and all of the common parts in the Arduino ecosystem not too long ago. I still see fun challenges with these parts because I encounter my favorite phrases while searching for projects - "It can't be done" or "That's as good as it gets". In this case, I came across a few new projects which would benefit from some animated graphics on a small, inexpensive display and MCU. The existing projects I found use uncompressed graphics and can only fit a few frames on an ATMega328. What Ideally, it would be great to be able to play animated GIF files right on an Arduino, but there are some insu...

Optimized Bresenham line drawing on the SSD1306

Image
What Jack Bresenham invented a low computation line drawing algorithm many years ago. The benefit of his algorithm is that it uses only integer variables and only addition and subtraction operations to calculate the pixel at each point along an arbitrary line. It's a very efficient method and has become the 'standard' way of drawing a line on computers. Why On a display device like the SSD1306 OLED, the image is changed by sending data (and commands) serially over the SPI or I2C bus. When the Bresenham algorithm is written for the SSD1306, the traditional way to implement it is to transmit each pixel (set the memory position and write the byte containing the pixel data) one at a time to the display. Essentially, to change a single bit of the display memory, at least 8 bytes need to be transmitted to the display. They are: 0x00 (0xb0 + y) - set y offset 0x00 (0x00 + (x & 0xf)) - set low 4 bits of x offset 0x00 (0x10 + (x >> 4)) - set high 4 bits of x offs...

Fast SSD1306 OLED drawing with I2C bit banging

Image
What The  SSD1306  OLED displays are very popular with hobbyists due to their low cost and easy interfacing. The majority of the ones sold expose a two wire interface (TWI) aka I2C. The default speed for I2C is 100Khz and the "fast" mode is 400Khz. These are the 2 standard speeds supported by most AVR Arduinos. An I2C clock rate of around 800Khz is also possible on AVR MCUs, but not supported directly by the Wire library. The I2C standard recently added some higher speeds (1Mhz and 3.4Mhz). The 3.4Mhz version uses a slightly different protocol. At 400Khz, using the I2C hardware and the Wire library, I was able to refresh the display around 23.5 frames per second (FPS) with my code. Why I have already written a SSD1306  library for both Linux and Arduino, but I wanted to drive the display from an ATtiny85 and learn about the I2C protocol in the process. The ATtiny85 doesn't have I2C hardware built in, so it needs to be emulated in software using GPIO pins. There ...