AFBR-S50 API Reference Manual v1.5.6
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
Loading...
Searching...
No Matches
argus_map.h
Go to the documentation of this file.
1/*************************************************************************/
38#ifndef ARGUS_MAP_H
39#define ARGUS_MAP_H
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44/*!***************************************************************************
45 * @defgroup argus_map Pixel Channel Mapping
46 * @ingroup argus_api
47 *
48 * @brief Pixel Channel Mapping
49 *
50 * @details The ADC Channels of each pixel or auxiliary channel on the device
51 * are numbered in a way that is convenient on the chip architecture.
52 * The macros in this module are defined in order to map between the
53 * chip internal channel number (ch) to the two-dimensional
54 * x-y-indices or one-dimensional n-index representation.
55 *
56 * @addtogroup argus_map
57 * @{
58 *****************************************************************************/
59
60#include "utility/int_math.h"
61#include <stdbool.h>
62#include <assert.h>
63
64
65/*!***************************************************************************
66 * @brief The device pixel field size in x direction (long edge).
67 *****************************************************************************/
68#define ARGUS_PIXELS_X 8
69
70/*!***************************************************************************
71 * @brief The device pixel field size in y direction (short edge).
72 *****************************************************************************/
73#define ARGUS_PIXELS_Y 4
74
75/*!***************************************************************************
76 * @brief The total device pixel count.
77 *****************************************************************************/
78#define ARGUS_PIXELS ((ARGUS_PIXELS_X)*(ARGUS_PIXELS_Y))
79
80
81/*!*****************************************************************************
82 * @brief Macro to determine the pixel ADC channel number from the x-z-indices.
83 * @param x The x-index of the pixel.
84 * @param y The y-index of the pixel.
85 * @return The ADC channel number of the pixel.
86 ******************************************************************************/
87#define PIXEL_XY2CH(x, y) ((((y) << 3U) & 0x10U) | (((x) ^ 0x07U) << 1U) | ((y) & 0x01U))
88
89/*!*****************************************************************************
90 * @brief Macro to determine the pixel x-index from the ADC channel number.
91 * @param c The ADC channel number of the pixel.
92 * @return The x-index of the pixel.
93 ******************************************************************************/
94#define PIXEL_CH2X(c) ((((c) >> 1U) ^ 0x07U) & 0x07U)
95
96/*!*****************************************************************************
97 * @brief Macro to determine the pixel y-index from the ADC channel number.
98 * @param c The ADC channel number of the pixel.
99 * @return The y-index of the pixel.
100 ******************************************************************************/
101#define PIXEL_CH2Y(c) ((((c) >> 3U) & 0x02U) | ((c) & 0x01U))
102
103
104/*!*****************************************************************************
105 * @brief Macro to determine the n-index from the x-y-indices.
106 * @param x The x-index of the pixel.
107 * @param y The y-index of the pixel.
108 * @return The n-index of the pixel.
109 ******************************************************************************/
110#define PIXEL_XY2N(x, y) (((x) << 2U) | (y))
111
112/*!*****************************************************************************
113 * @brief Macro to determine the pixel x-index from the n-index.
114 * @param n The n-index of the pixel.
115 * @return The x-index number of the pixel.
116 ******************************************************************************/
117#define PIXEL_N2X(n) ((n) >> 2U)
118
119/*!*****************************************************************************
120 * @brief Macro to determine the pixel y-index from the n-index.
121 * @param n The n-index of the pixel.
122 * @return The y-index number of the pixel.
123 ******************************************************************************/
124#define PIXEL_N2Y(n) ((n) & 0x03U)
125
126
127/*!*****************************************************************************
128 * @brief Macro to determine the pixel n-index from the ADC channel number.
129 * @param n The n-index of the pixel.
130 * @return The ADC channel number of the pixel.
131 ******************************************************************************/
132#define PIXEL_N2CH(n) ((((n) << 3U) & 0x10U) | ((((n) >> 1U) ^ 0x0EU) & 0x0EU) | ((n) & 0x01U))
133
134/*!*****************************************************************************
135 * @brief Macro to determine the pixel
136 * @param c The ADC channel number of the pixel.
137 * @return The n-index of the pixel.
138 ******************************************************************************/
139#define PIXEL_CH2N(c) (((((c) << 1U) ^ 0x1CU) & 0x1CU) | (((c) >> 3U) & 0x02U) | ((c) & 0x01U))
140
141
142/*!*****************************************************************************
143 * @brief Macro to create a pixel mask given by the pixels n-index.
144 * @param n n-index of the pixel.
145 * @return The pixel mask with only n-index pixel set.
146 ******************************************************************************/
147#define PIXELN_MASK(n) (0x01U << (n))
148
149/*!*****************************************************************************
150 * @brief Macro to determine if a pixel given by the n-index is enabled in a pixel mask.
151 * @param msk 32-bit pixel mask
152 * @param n n-index of the pixel.
153 * @return True if the pixel (n) is enabled.
154 ******************************************************************************/
155#define PIXELN_ISENABLED(msk, n) (((msk) >> (n)) & 0x01U)
156
157/*!*****************************************************************************
158 * @brief Macro to enable a pixel given by the n-index in a pixel mask.
159 * @param msk 32-bit pixel mask
160 * @param n n-index of the pixel to enable.
161 ******************************************************************************/
162#define PIXELN_ENABLE(msk, n) ((msk) |= (PIXELN_MASK(n)))
163
164/*!*****************************************************************************
165 * @brief Macro disable a pixel given by the n-index in a pixel mask.
166 * @param msk 32-bit pixel mask
167 * @param n n-index of the pixel to disable.
168 ******************************************************************************/
169#define PIXELN_DISABLE(msk, n) ((msk) &= (~PIXELN_MASK(n)))
170
171
172/*!*****************************************************************************
173 * @brief Macro to create a pixel mask given by the pixels ADC channel number.
174 * @param c The ADC channel number of the pixel.
175 * @return The 32-bit pixel mask with only pixel ADC channel set.
176 ******************************************************************************/
177#define PIXELCH_MASK(c) (0x01U << (PIXEL_CH2N(c)))
178
179/*!*****************************************************************************
180 * @brief Macro to determine if an ADC pixel channel is enabled from a pixel mask.
181 * @param msk The 32-bit pixel mask
182 * @param c The ADC channel number of the pixel.
183 * @return True if the specified pixel ADC channel is enabled.
184 ******************************************************************************/
185#define PIXELCH_ISENABLED(msk, c) (PIXELN_ISENABLED(msk, PIXEL_CH2N(c)))
186
187/*!*****************************************************************************
188 * @brief Macro to enable an ADC pixel channel in a pixel mask.
189 * @param msk The 32-bit pixel mask
190 * @param c The pixel ADC channel number to enable.
191 ******************************************************************************/
192#define PIXELCH_ENABLE(msk, c) (PIXELN_ENABLE(msk, PIXEL_CH2N(c)))
193
194/*!*****************************************************************************
195 * @brief Macro to disable an ADC pixel channel in a pixel mask.
196 * @param msk The 32-bit pixel mask
197 * @param c The pixel ADC channel number to disable.
198 ******************************************************************************/
199#define PIXELCH_DISABLE(msk, c) (PIXELN_DISABLE(msk, PIXEL_CH2N(c)))
200
201
202/*!*****************************************************************************
203 * @brief Macro to create a pixel mask given by the pixel x-y-indices.
204 * @param x x-index of the pixel.
205 * @param y y-index of the pixel.
206 * @return The 32-bit pixel mask with only pixel ADC channel set.
207 ******************************************************************************/
208#define PIXELXY_MASK(x, y) (0x01U << (PIXEL_XY2N(x, y)))
209
210/*!*****************************************************************************
211 * @brief Macro to determine if a pixel given by the x-y-indices is enabled in a pixel mask.
212 * @param msk 32-bit pixel mask
213 * @param x x-index of the pixel.
214 * @param y y-index of the pixel.
215 * @return True if the pixel (x,y) is enabled.
216 ******************************************************************************/
217#define PIXELXY_ISENABLED(msk, x, y) (PIXELN_ISENABLED(msk, PIXEL_XY2N(x, y)))
218
219/*!*****************************************************************************
220 * @brief Macro to enable a pixel given by the x-y-indices in a pixel mask.
221 * @param msk 32-bit pixel mask
222 * @param x x-index of the pixel to enable.
223 * @param y y-index of the pixel to enable.
224 ******************************************************************************/
225#define PIXELXY_ENABLE(msk, x, y) (PIXELN_ENABLE(msk, PIXEL_XY2N(x, y)))
226
227/*!*****************************************************************************
228 * @brief Macro disable a pixel given by the x-y-indices in a pixel mask.
229 * @param msk 32-bit pixel mask
230 * @param x x-index of the pixel to disable.
231 * @param y y-index of the pixel to disable.
232 ******************************************************************************/
233#define PIXELXY_DISABLE(msk, x, y) (PIXELN_DISABLE(msk, PIXEL_XY2N(x, y)))
234
235
236/*!*****************************************************************************
237 * @brief Macro to determine if an ADC channel is enabled in a channel mask.
238 * @param msk 32-bit channel mask
239 * @param ch channel number of the ADC channel.
240 * @return True if the ADC channel is enabled.
241 ******************************************************************************/
242#define CHANNELN_ISENABLED(msk, ch) (((msk) >> ((ch) - 32U)) & 0x01U)
243
244/*!*****************************************************************************
245 * @brief Macro to determine if an ADC channel is enabled in a channel mask.
246 * @param msk 32-bit channel mask
247 * @param ch channel number of the ADC channel to enabled.
248 ******************************************************************************/
249#define CHANNELN_ENABLE(msk, ch) ((msk) |= (0x01U << ((ch) - 32U)))
250
251/*!*****************************************************************************
252 * @brief Macro to determine if an ADC channel is disabled in a channel mask.
253 * @param msk 32-bit channel mask
254 * @param ch channel number of the ADC channel to disable.
255 ******************************************************************************/
256#define CHANNELN_DISABLE(msk, ch) ((msk) &= (~(0x01U << ((ch) - 32U))))
257
258
259/*!*****************************************************************************
260 * @brief Macro to determine the number of enabled pixel/channels in a mask
261 * via a popcount algorithm.
262 * @param pxmsk 32-bit pixel mask
263 * @return The count of enabled pixel channels.
264 ******************************************************************************/
265#define PIXEL_COUNT(pxmsk) popcount(pxmsk)
266
267/*!*****************************************************************************
268 * @brief Macro to determine the number of enabled channels via a popcount
269 * algorithm.
270 * @param pxmsk 32-bit pixel mask
271 * @param chmsk 32-bit channel mask
272 * @return The count of enabled ADC channels.
273 ******************************************************************************/
274#define CHANNEL_COUNT(pxmsk, chmsk) (popcount(pxmsk) + popcount(chmsk))
275
276/*!*****************************************************************************
277 * @brief Converts a raw ADC channel mask to a x-y-sorted pixel mask.
278 * @param msk The raw ADC channel mask to be converted.
279 * @return The converted x-y-sorted pixel mask.
280 ******************************************************************************/
281static inline uint32_t ChannelToPixelMask(uint32_t msk)
282{
283 uint32_t res = 0;
284 for (uint_fast8_t n = 0; n < 32; n += 2)
285 {
286 res |= ((msk >> PIXEL_N2CH(n)) & 0x3U) << n; // sets 2 bits at once
287 }
288 return res;
289}
290
291/*!*****************************************************************************
292 * @brief Converts a x-y-sorted pixel mask to a raw ADC channel mask.
293 * @param msk The x-y-sorted pixel channel mask to be converted.
294 * @return The converted raw ADC channel mask.
295 ******************************************************************************/
296static inline uint32_t PixelToChannelMask(uint32_t msk)
297{
298 uint32_t res = 0;
299 for (uint_fast8_t ch = 0; ch < 32; ch += 2)
300 {
301 res |= ((msk >> PIXEL_CH2N(ch)) & 0x3U) << ch; // sets 2 bits at once
302 }
303 return res;
304}
305
306
307/*!*****************************************************************************
308 * @brief Shifts a pixel mask by a given offset.
309 *
310 * @details This moves the selected pixel pattern by a specified number of
311 * pixels in x and y direction.
312 * If the shift in y direction is odd (e.g +1), the pattern will be
313 * shifted by +0.5 or -0.5 in x direction due to the hexagonal shape
314 * of the pixel field. Thus, a center pixel (usually the Golden Pixel)
315 * is determined that is used to determine if the pattern is shifted
316 * by +0.5 or -0.5 pixels in x direction. The center pixel is then
317 * always shifted without changing the x index and the surrounding
318 * pixels are adopting its x index accordingly.
319 *
320 * Example: Consider the flower pattern, i.e. the Golden Pixel (e.g.
321 * 5/2) is selected and all is direct neighbors (i.e. 5/1, 6/1, 6/2,
322 * 6/3, 5/3, 4/2). If the pattern is shifted by -1 in y direction, the
323 * new Golden Pixel would be 5/1. Now all surrounding pixels are
324 * selected, namely 4/0, 4/1, 4/2, 5/0, 5/2, 6/1). This yields again
325 * the flower around the Golden Pixel.
326 *
327 * Thus, the pixels can not all be shifted by the same dx/dy values due
328 * to the hexagonal shape of the pixel field, e.g. the upper right
329 * neighbor of 5/2 is 5/1 but the upper right neighbor of 5/1 is NOT
330 * 5/0 but 4/0!
331 * This happens only if the shift in y direction is an odd number.
332 * The algorithm to determine new indices is as follows:
333 * - If the shift in y direction is even (e.g. +2, -2), no compensation
334 * of the hexagonal shape is needed; skip compensation, simply
335 * add/subtract indices.
336 * - If the center pixel y index is even, pixels that will have even y
337 * index after the shift will be additionally shifted by -1 in x
338 * direction.
339 * - If the center pixel y index is odd, pixel that will have odd y
340 * index after the shift will be additionally shifted by +1 in x
341 * direction.
342 *
343 * @see Please also refer to the function #Argus_GetCalibrationGoldenPixel
344 * to obtain the current Golden Pixel location.
345 *
346 * @param pixel_mask The x-y-sorted pixel mask to be shifted.
347 * @param dx The number of pixel to shift in x direction.
348 * @param dy The number of pixel to shift in y direction.
349 * @param center_y The center y index of the pattern that is shifted.
350 * @return The shifted pixel mask.
351 ******************************************************************************/
352static inline uint32_t ShiftSelectedPixels(const uint32_t pixel_mask,
353 const int8_t dx,
354 const int8_t dy,
355 const uint8_t center_y)
356{
357 if (dx == 0 && dy == 0) return pixel_mask;
358
359 uint32_t shifted_mask = 0;
360
361 for (int8_t x = 0; x < ARGUS_PIXELS_X; ++x)
362 {
363 for (int8_t y = 0; y < ARGUS_PIXELS_Y; ++y)
364 {
365 int8_t x_src = (int8_t)(x - dx);
366 int8_t y_src = (int8_t)(y - dy);
367
368 if (dy & 0x1)
369 {
370 /* Compensate for hexagonal pixel shape. */
371 if ((center_y & 0x1) && (y & 0x1))
372 {
373 x_src--;
374 }
375 if (!(center_y & 0x1) && !(y & 0x1))
376 {
377 x_src++;
378 }
379 }
380
381 if (x_src < 0 || x_src >= ARGUS_PIXELS_X) continue;
382 if (y_src < 0 || y_src >= ARGUS_PIXELS_Y) continue;
383
384 if (PIXELXY_ISENABLED(pixel_mask, x_src, y_src))
385 {
386 PIXELXY_ENABLE(shifted_mask, x, y);
387 }
388 }
389 }
390
391 return shifted_mask;
392}
393
394/*!*****************************************************************************
395 * @brief Fills a pixel mask to a specified number of pixels around a center pixel.
396 *
397 * @details The pixel mask is iteratively filled with the nearest pixel to a
398 * specified center pixel until a specified number of pixels is achieved.
399 * The distance between two pixel is determined via a quadratic metric,
400 * i.e. dx^2 + dy^2. Pixels towards the lower x indices are preferred.
401 *
402 * Note that the distance of only calculated approximately, e.g. the
403 * y distance of pixels is considered to be 2 instead of cos(60)*2.
404 *
405 * Nothing is done if the number of pixels already exceeds the specified
406 * /p pixel_count parameter.
407 *
408 * @see Please also refer to the function #Argus_GetCalibrationGoldenPixel
409 * to obtain the current Golden Pixel location.
410 *
411 * @param pixel_mask The x-y-sorted pixel mask to be filled with pixels.
412 * @param pixel_count The final number of pixels in the pixel mask.
413 * @param center_x The center pixel x-index.
414 * @param center_y The center pixel y-index.
415 * @return The filled pixel mask with at least /p pixel_count pixels selected.
416 ******************************************************************************/
417static inline uint32_t FillPixelMask(uint32_t pixel_mask,
418 const uint8_t pixel_count,
419 const uint8_t center_x,
420 const uint8_t center_y)
421{
422 assert(pixel_count <= ARGUS_PIXELS);
423 assert(center_x < ARGUS_PIXELS_X);
424 assert(center_y < ARGUS_PIXELS_Y);
425
426 if (pixel_count == ARGUS_PIXELS) return 0xFFFFFFFFU;
427
428 /* If the pattern was shifted towards boundaries, the pixel count may have
429 * decreased. In this case, the pixels closest to the reference pixel are
430 * selected. Pixel towards lower x index are prioritized. */
431 while (pixel_count > PIXEL_COUNT(pixel_mask))
432 {
433 int32_t min_dist = INT32_MAX;
434 int8_t min_x = -1;
435 int8_t min_y = -1;
436
437 /* Find nearest not selected pixel. */
438 for(int8_t x = 0; x < ARGUS_PIXELS_X; ++x)
439 {
440 for (int8_t y = 0; y < ARGUS_PIXELS_Y; ++y)
441 {
442 if (!PIXELXY_ISENABLED(pixel_mask, x, y))
443 {
444 int32_t distx = (x - center_x) << 1;
445 if (!(y & 0x1)) distx++;
446 if (!(center_y & 0x1)) distx--;
447
448 const int32_t disty = (y - center_y) << 1;
449 int32_t dist = distx * distx + disty * disty;
450
451 if (dist < min_dist)
452 {
453 min_dist = dist;
454 min_x = (int8_t)x;
455 min_y = (int8_t)y;
456 }
457 }
458 }
459 }
460
461 assert(min_x >= 0 && min_x < ARGUS_PIXELS_X);
462 assert(min_y >= 0 && min_y < ARGUS_PIXELS_Y);
463 assert(!PIXELXY_ISENABLED(pixel_mask, min_x, min_y));
464 PIXELXY_ENABLE(pixel_mask, min_x, min_y);
465 }
466
467 return pixel_mask;
468}
469
470/*!*****************************************************************************
471 * @brief Fills a pixel mask with the direct neighboring pixels around a pixel.
472 *
473 * @details The pixel mask is iteratively filled with the direct neighbors of the
474 * specified center pixel.
475 *
476 * Note that the function is able to handle corner and edge pixels and
477 * also to handle odd/even lines (which have different layouts)
478 *
479 * @param x The selected pixel x-index.
480 * @param y The selected pixel y-index.
481 * @return The filled pixel mask with all direct neighbors of the selected pixel.
482 ******************************************************************************/
483static inline uint32_t GetAdjacentPixelsMask(const uint_fast8_t x,
484 const uint_fast8_t y)
485{
486 assert(x < ARGUS_PIXELS_X);
487 assert(y < ARGUS_PIXELS_Y);
488
489 uint32_t mask = 0u;
490
491 bool isXEdgeLow = (x == 0);
492 bool isXEdgeHigh = (x == (ARGUS_PIXELS_X - 1));
493 bool isYEdgeLow = (y == 0);
494 bool isYEdgeHigh = (y == (ARGUS_PIXELS_Y - 1));
495
496 if (y % 2 == 0)
497 {
498 if (!isYEdgeLow) PIXELXY_ENABLE(mask, x, y - 1);
499 if ((!isXEdgeHigh) && (!isYEdgeLow)) PIXELXY_ENABLE(mask, x + 1, y - 1);
500 if (!isXEdgeHigh) PIXELXY_ENABLE(mask, x + 1, y);
501 if ((!isXEdgeHigh) && (!isYEdgeHigh)) PIXELXY_ENABLE(mask, x + 1, y + 1);
502 if (!isYEdgeHigh) PIXELXY_ENABLE(mask, x, y + 1);
503 if (!isXEdgeLow) PIXELXY_ENABLE(mask, x - 1, y);
504 }
505 else
506 {
507 if ((!isXEdgeLow) && (!isYEdgeLow)) PIXELXY_ENABLE(mask, x - 1, y - 1);
508 if (!isYEdgeLow) PIXELXY_ENABLE(mask, x, y - 1);
509 if (!isXEdgeHigh) PIXELXY_ENABLE(mask, x + 1, y);
510 if (!isYEdgeHigh) PIXELXY_ENABLE(mask, x, y + 1);
511 if ((!isXEdgeLow) && (!isYEdgeHigh)) PIXELXY_ENABLE(mask, x - 1, y + 1);
512 if (!isXEdgeLow) PIXELXY_ENABLE(mask, x - 1, y);
513 }
514
515 return mask;
516}
517
518
520#ifdef __cplusplus
521} // extern "C"
522#endif
523#endif /* ARGUS_MAP_H */
static uint32_t PixelToChannelMask(uint32_t msk)
Converts a x-y-sorted pixel mask to a raw ADC channel mask.
Definition argus_map.h:296
#define ARGUS_PIXELS_Y
The device pixel field size in y direction (short edge).
Definition argus_map.h:73
static uint32_t GetAdjacentPixelsMask(const uint_fast8_t x, const uint_fast8_t y)
Fills a pixel mask with the direct neighboring pixels around a pixel.
Definition argus_map.h:483
#define PIXEL_CH2N(c)
Macro to determine the pixel.
Definition argus_map.h:139
static uint32_t ShiftSelectedPixels(const uint32_t pixel_mask, const int8_t dx, const int8_t dy, const uint8_t center_y)
Shifts a pixel mask by a given offset.
Definition argus_map.h:352
static uint32_t FillPixelMask(uint32_t pixel_mask, const uint8_t pixel_count, const uint8_t center_x, const uint8_t center_y)
Fills a pixel mask to a specified number of pixels around a center pixel.
Definition argus_map.h:417
static uint32_t ChannelToPixelMask(uint32_t msk)
Converts a raw ADC channel mask to a x-y-sorted pixel mask.
Definition argus_map.h:281
#define ARGUS_PIXELS_X
The device pixel field size in x direction (long edge).
Definition argus_map.h:68
#define PIXELXY_ISENABLED(msk, x, y)
Macro to determine if a pixel given by the x-y-indices is enabled in a pixel mask.
Definition argus_map.h:217
#define PIXEL_N2CH(n)
Macro to determine the pixel n-index from the ADC channel number.
Definition argus_map.h:132
#define ARGUS_PIXELS
The total device pixel count.
Definition argus_map.h:78
#define PIXELXY_ENABLE(msk, x, y)
Macro to enable a pixel given by the x-y-indices in a pixel mask.
Definition argus_map.h:225
#define PIXEL_COUNT(pxmsk)
Macro to determine the number of enabled pixel/channels in a mask via a popcount algorithm.
Definition argus_map.h:265
This file is part of the AFBR-S50 API.