TSL256x I2C luminosity and IR sensor driver
[lpc82x] / lib / utils.c
1 /****************************************************************************
2  *  lib/utils.c
3  *
4  * Copyright 2014 Nathael Pajani <nathael.pajani@ed3l.fr>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *************************************************************************** */
21 #include "lib/stdint.h"
24 /***************************************************************************** */
25 /* Bit twidling hacks.
26  * http://graphics.stanford.edu/~seander/bithacks.html
27  */
29 /* Counting consecutive trailing or leading zero bits (or finding bit indices)
30  * The ARM Cortex M0 core does not have the __builtin_clz() and __builtin_ctz()
31  * instructions.
32  */
36 /* Count leading zeroes
37  * The following function is an efficient way to implement __builtin_clz(),
38  * or at least a good compromize between memory usage and speed.
39  */
40 uint8_t clz(uint32_t x)
41 {
42         static const uint8_t bval_clz[] = {0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4};
43         unsigned int r = 32;
44         if (x >= 0x10000) { /* Quicker than (x & 0xFFFF0000) on a 32bit arm arch */
45                 r -= 16;
46                 x >>= 16;
47         }
48         if (x & 0xFF00) {
49                 r -= 8;
50                 x >>= 8;
51         }
52         if (x & 0xF0) {
53                 r -= 4;
54                 x >>= 4;
55         }
56         return r - bval_clz[x];
57 }
59 /* Count traling zeroes
60  * The following function is an efficient way to implement __builtin_ctz(),
61  * or at least a good compromize between memory usage and speed.
62  */
63 uint8_t ctz(uint32_t x)
64 {
65         static const uint8_t bval_ctz[] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
66         unsigned int r = 0;
67         if (x & 0x1) {
68                 /* special case for odd value (assumed to happen half of the time) */
69                 return r;
70         }
71         if ((x & 0xFFFF) == 0) {
72                 r += 16;
73                 x >>= 16;
74         }
75         if ((x & 0xFF) == 0) {
76                 r += 8;
77                 x >>= 8;
78         }
79         if ((x & 0xF) == 0) {
80                 r += 4;
81                 x >>= 4;
82         }
83         return r + bval_ctz[(x & 0x0F)];
84 }
86 /* Count bits set
87  *
88  */
89 uint8_t bits_set(uint32_t x)
90 {
91         static const uint8_t bval_bsets[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
92         uint8_t r = 0; /* Accumulator for the total bits set in x */
93         
94         r = bval_bsets[x & 0xFF];
95         x >>= 8;
96         r += bval_bsets[x & 0xFF];
97         x >>= 8;
98         r += bval_bsets[x & 0xFF];
99         x >>= 8;
100         r += bval_bsets[x & 0xFF];
102         return r;