This page is work in progress…
First order IIR filter
In my book “Embedded Software for the IoT”, there is a chapter on Statistical Process Control. This introduces a simple-filter called EWMA – Exponentially Weighted Moving Average. It is the simplest possible low-pass IIR Filter:
y[n] = \alpha* x[n] + (1-\alpha)*y[n-1]
In other words, this filter has an output that corresponds to a fraction (less than 1) of the input plus 1 minus the same fraction times the previous output. If \alpha is close to one, the filter has a short impulse-response, and as \alpha goes towards 0 the impulse-response goes towards infinity.
Typically, filters are designed from their “3 dB cutoff frequency” – f_c . If we first introduce an intermediate variable – \beta – we can calculate the constant \alpha based on the cutoff frequency and the sampling frequency f_s .
\beta = cos(2\pi f_c/f_s)
\alpha = \beta-1+\sqrt{\beta^2-4\beta+3}
The above is easily done in Excel. You can see more on this filter here.
Alignment and Sign-Extension (C, Two’s Complement)
In my book Embedded Software for the IoT I discuss the so-called Q-notation for two’s complement numbers. To understand this, one first needs to understand the basics of signed integers in general. This section is about a specific practical problem that demonstrates some of these basics.
Problem: Copying a number into a wider representation – e.g. 16 bits into 32.
Often you get data from an input in another width than the CPU’s typical word-width. This could e.g. be 16 or 24 bits from an A/D-converter into a 32-bit std CPU memory cell.
You need to decide whether to align left – leaving unused bits at “the bottom” of the word – or align right. I prefer right-alignment because it will allow you to later do arithmetic that “overflows” into the extra bits at the left. In other words; you get to utilize the higher dynamic range.
However if you simply copy the 16 or 24 bits into a 32-bit word you may get problems. Lets look at a simpler problem with 8-bits into 16:
The decimal value 18, hexadecimal 0x12 in 8 bits – becomes 0x0012 in 16 bits. It’s the same – no problem.
However, -18 (minus 18), hexadecimal 0xee – becomes 0x00ee. This is 238 decimal!
We need to sign-extend. The leftmost bit – the sign – must be copied into all the new bits above (to the left). Thus 0xee becomes 0xffee. If you add 0x12 to this you get 0 – as you should.
Here’s a quick way to do this:
dst = (src << 8) >> 8); // Assuming signed data vars
When shifting a signed value left, C will add zeroes at the bottom (right). When shifting right it will do an arithmetic shift which preserves the sign-bit. The above operation first shifts data 8 bits up – letting zeroes in at the LSB (least Significant Bit). Then it shifts down again – now copying the old sign-bit into the new.
Strictly speaking, C does not guarantee what happens when you shift left into the sign-bit, but most compilers treat the left shift as a logical shift and the right shift as an arithmetic shift.
If you are careful, you may use casts to shift left in unsigned data and shift right in signed data.
If you are even more careful and not extremely worried about a few extra cycles, you can do the following – now using 24 bits in 32-bit word-size:
if (src | 0x00800000) dst = src | 0xff000000; else dst = src;
Or – the compact way:
dst = (src | 0x00800000) ? src | 0xff000000 : src;