Most natural observations are exponentational/logarithmic in nature.
I often do simple hardware using Microchip PIC processors (usually 12F or 16F families). Hardware doing some business in the home.
One such example is my Christmas-tree-lightning-controller. Basically it only turns my electric Christmas-tree-lights on when I want to see them on…
In order to do this, it needs to measure the out-door light. It uses an accumulation cell (of 8 samples) and a moving average register with 8 cells: Light or darkness is determined from 8 accumulated samples of “10-bits light” averaged through the latest 8×8 samples…
8×8 samples of 10-bits equals 6 bits of 10bits equals 16 bits…
So the output of the moving average register is at most 16 bits wide and should pose no problems on a modern microcontroller.
Unfortunately, the small PIC micros are not very good at “multi-byte” calculations why the 16-bit result is a bit awkward to deal with. And my simple experiments indicates that light-level comparisons should be measured on a “percentage change” basis and not as an absolute comparison.
If I could just do a simple 8-bit logarithm function of the 16-bit absolute result, I would be able to do simple percentage comparisons of different light level measurements by simple subtraction of 8-bit values. Even the simples PIC’s can do subtraction of 8-bit values without special engineered software subroutines 🙂
Being inspired by the µLaw compression schemes used in Telephony, I wrote this little routine, that basically calculates 16×log2(x), where x is some 16-bit value and the result is an 8-bit value. Simulating the calculations in software gives a maximum error of 1-bit on the result.
; NOTE: Variables wi, r0 and r1 are ; defined elsewhere in on-chip RAM ; ; log2: calcuate r0 = approx 16*log2(r1:r0). ; wi, r1 destroyed ; log2: movlw 16 movwf wi ; loop log2_loop: bcf STATUS,C rlf r0,f rlf r1,f ; C affected decfsz wi,f ; Z affected btfsc STATUS,C goto log2_done goto log2_loop ; done log2_done: movlw 0xf0 andwf r1,w iorwf wi,w movwf r0 swapf r0,f return |
The simpe logarithm shown above I’ve used lots of different places. If You want to know how or why it works, don’t hesistate to put a comment below.
Unfortunately, my Christmas-tree-lights-controller is not (yet) perfect, as sudden, heavy light seems to overflow the moving averager. In other words, when the terrorist children living next-door are having fun with fireworks, the lights on my outdoor Christmas tree blinks in its own secret manner 🙂
2 Responses to Simple logarithm implementation in PIC assembler