Posted on December 7, 2017. Tagged as: eZ430-Chronos

Here is a little writeup of the steps taken to implement an altitude module eZ430-Chronos within openchronos-ng-elf. The challenge is that the MSP430 controller is a 16bit RISC controller, which has no floating point and no builtin multiply/divide instructions. In addition, the code size is limited to 32K

The TI eZ430-Chronos contains a pressure sensor. To calculate the altitude from current pressure according to International Standard Atmosphere (ISA) we can derive the following equations:

A number of input values are constant:

Putting the constants into the ISA formula, we get:

As reference this uses *p*_{0}, the current pressure reduced to mean sea
level using the International Standard Atmosphere. In aviation that’s
called QNH and can be
looked up online for the closest airport.

Implementing the altitude function using pow() from libm, large chunks of libm get linked, resulting in a code size of about 16.8K. That is a lot, considering the controller in the eZ430-Chronos has only 32K of flash memory. So a better implementation is needed.

Next idea was to replace the exponentiation part of the formula with a binomial series, which doesn’t require to link libm anymore. That leaves only multiplications and additions after pre-computing the constants:

For low altitudes (p ~ QNH, x ~ 1) the series converges pretty quickly. As termination criterium for the series the step size seems to work ok. The resulting altitude module code size is reduced to about 8K.

The next optimization step was to use a lookup table with interpolation. This allows to avoid floating point math entirely. The function to replace with a lookup table looks like this:

The lookup table has been generated with a ruby script, that also determines the maximum error in a brute force way by feeding all possible input values into the lookup table and comparing with the exact altitude.

To get an error of max 5 ft with a QNH between 900 and 1100 and a pressure between 500 hPa and 1100 hPA a table size of 1342 bytes is sufficient. Since the lookup table generator places nodes directly onto the exact function values, we could optimize a bit by moving the points slightly off the exact value to minimize the error squares.

The resulting code including lookup table is reduced to about 3.6K. The code can be found on GitHub.

The following table compares code size of various alternatives with the firmware without altitude module compiled in (baseline).

```
---------------------------------------------------
Module rodata text sum relative
--------------- ------- ------ ------ ---------
baseline 356 13056 13412 0
lookup table 1738 15399 17137 3725
binomial series 716 20918 21634 8222
libm 722 29894 30616 17204
--------------- ------- ------ ------ ---------
```