firmware  v0.1.2
Chromation Spectrometer Dev-Kit
VisCmd.c
1 #include "VisCmd.h"
2 uint8_t frame[2*MAX_NUM_PIXELS];
3 /* ------------------ */
4 /* | ---Commands--- | */
5 /* ------------------ */
6 void NullCommand(void);
7 void GetSensorLED(void);
8 void SetSensorLED(void);
9 void GetSensorConfig(void);
10 void SetSensorConfig(void);
11 void GetExposure(void);
12 void SetExposure(void);
13 void CaptureFrame(void);
14 void AutoExposure(void);
15 void GetAutoExposeConfig(void);
16 void SetAutoExposeConfig(void);
17 void GetSensorHash(void);
18 
19 /* ---------------------------------------- */
20 /* | ---Command helpers (not commands)--- | */
21 /* ---------------------------------------- */
24 bool AutoExposeConfigIsValid(uint8_t, uint16_t, uint16_t, uint16_t);
25 
26 void LisReadout(uint16_t num_pixels);
27 void S13131Readout(void);
28 
29 uint16_t GetPeak(uint16_t const _start_pixel, uint16_t const _stop_pixel)
30 {
47  // start with a peak value of 0
48  uint16_t peak = 0;
49 
50  // do not look for peak if _stop_pixel < _start_pixel
51  if (_stop_pixel < _start_pixel) return peak;
52 
53  // convert pixel number to index into global frame buffer
60  uint16_t byte_index = (_start_pixel-1) * 2; // 2 bytes per pixel
61 
62  // point at _start_pixel in the global frame buffer
63  uint8_t * pframe = frame + byte_index;
64 
65  // check every pixel until _stop_pixel
66  for (uint16_t pixnum = _start_pixel; pixnum++ <= _stop_pixel;)
67  {
68  uint16_t pixval = (*(pframe++)) << 8;
69  pixval |= (*(pframe++));
70  if (pixval > peak) peak = pixval;
71  }
72  return peak;
73 }
74 
75 #ifdef USE_FAKES
76 #define LisExpose LisExpose_fake
77 #define LisReadout LisReadout_fake
78 #define S13131Expose S13131Expose_fake
79 #define S13131Readout S13131Readout_fake
80 #endif
81 uint16_t AutoExpose(void)
82 {
243  // red means AutoExpose started
244  BiColorLedRed(led_1);
245 
246  // report AutoExpose success/failure
247  bool success = false;
248 
249  // return final peak value for inspecting algorithm behavior
250  uint16_t peak=0;
251 
252  // determine number of pixels to readout
253 #ifdef LIS
254  uint16_t num_pixels;
255  if (binning == BINNING_OFF) num_pixels = MAX_NUM_PIXELS;
256  else num_pixels = MAX_NUM_PIXELS/2;
257 #endif
258 #ifdef S13131
259 // always 512 pixels, don't need a num_pixels variable
260 #endif
261  /* -------------------- */
262  /* | AutoExpose SETUP | */
263  /* -------------------- */
264 
265  // give up after iterations == max_tries
266  // SetAutoExposeConfig guarantees at least one try.
267  uint8_t iterations = 0;
268 
269  // calculate target range for peak values
270  uint16_t min_peak = _MinPeak(target, target_tolerance);
271  uint16_t max_peak = _MaxPeak(target, target_tolerance);
272 
273  /* ------------------- */
274  /* | AutoExpose LOOP | */
275  /* ------------------- */
276 
277  bool done = false;
278  while (!done)
279  {
280  /* -------------- */
281  /* | READ FRAME | */
282  /* -------------- */
283 
284 #ifdef LIS
285  // expose the LIS-770i pixels
286  LisExpose();
287 
288  // readout the LIS-770i pixels into global frame buffer
289  LisReadout(num_pixels);
290 #endif // LIS
291 #ifdef S13131
292  // expose the S13131-512 pixels
293  S13131Expose();
294 
295  // readout the S13131-512 pixels into global frame buffer
296  S13131Readout();
297 #endif
298 
299  // find peak in range start_pixel : stop_pixel
300  peak = GetPeak(start_pixel, stop_pixel);
301 
302  /* ------------------------ */
303  /* | ADJUST EXPOSURE TIME | */
304  /* ------------------------ */
305 
306  // one variable for all big calculation results
307  uint32_t big_result; // stores up to 4294967295
308 
309  // any signal?
310  if (peak < max_dark)
311  {
312  // stop if already at maximum exposure
313  // (compare with >= because max_exposure < UINT16_MAX)
314  if (exposure_ticks >= max_exposure) done = true;
315 
316  // otherwise, 10x exposure
317  else
318  {
319  big_result = 10 * exposure_ticks;
320 
321  // clamp exposure at its maximum value
322  if (big_result > max_exposure) big_result = max_exposure;
323  exposure_ticks = big_result;
324  }
325  }
326 
327  // peak ABOVE target range?
328  else if (peak > max_peak)
329  {
330  // TAKE BACK HALF
332 
333  // clamp exposure at its minimum value
335  }
336 
337  // peak BELOW target range?
338  else if (peak < min_peak)
339  {
340  // stop if already at maximum exposure
341  // (compare with >= because max_exposure < UINT16_MAX)
342  if (exposure_ticks >= max_exposure) done = true;
343 
344  // otherwise, scale exposure by gain
345  else
346  {
347  // -------------------------------------------------
348  // | AT LEAST ONE OPERAND MUST BE CAST AS uint32_t |
349  // | OTHERWISE THE OPERATION IS TREATED AS 16-bit |
350  // -------------------------------------------------
351  big_result = (uint32_t)target * exposure_ticks;
352  big_result = big_result / peak;
353 
354  // clamp exposure at its maximum value
355  if (big_result > max_exposure) big_result = max_exposure;
356  exposure_ticks = big_result;
357  }
358  }
359 
360  // peak is in the target range
361  else
362  {
363  done = true;
364  success = true;
365  // green means target hit
366  BiColorLedGreen(led_1);
367  }
368 
369  // give up if peak fails to hit target range after many tries
370  if (++iterations == max_tries) done = true;
371  }
372  // return success as MSB and iterations as LSB
373  uint16_t result = (uint16_t)(success << 8) | iterations;
374  return result;
375 }
376 #ifdef USE_FAKES
377 #undef LisExpose
378 #undef LisReadout
379 #undef S13131Expose
380 #undef S13131Readout
381 #endif
382 
383 
uint16_t max_exposure
max_exposure is 1.31 seconds (65535 20µs-cycles) This is the 16-bit limit, UINT16_MAX,...
Definition: AutoExpose.c:12
uint16_t start_pixel
AutoExpose() ignores pixels below start_pixel.
Definition: AutoExpose.c:6
uint8_t max_tries
maximum number of tries before AutoExpose() gives up
Definition: AutoExpose.c:5
uint16_t stop_pixel
AutoExpose() ignores pixels above stop_pixel.
Definition: AutoExpose.c:7
uint16_t target_tolerance
target ± target_tolerance is the target peak counts range for AutoExpose().
Definition: AutoExpose.c:9
uint16_t max_dark
max_dark is a conservative estimate on the largest dark offset
Definition: AutoExpose.c:10
uint16_t target
target peak counts for AutoExpose().
Definition: AutoExpose.c:8
uint16_t min_exposure
min_exposure is 100 microseconds (five 20µs-cycles) This is a safe lower limit to avoid dead frames.
Definition: AutoExpose.c:11
void BiColorLedGreen(bicolorled_num led)
Definition: BiColorLed.h:35
void BiColorLedRed(bicolorled_num led)
Definition: BiColorLed.h:42
uint8_t const bicolorled_num
Indicator LED numbers in the JSON file are not necessarily the same as the corresponding bit number i...
Definition: BiColorLed.h:10
uint16_t exposure_ticks
LIS-770i exposure time.
Definition: Lis.c:32
void LisExpose(void)
Definition: Lis.h:498
#define MAX_NUM_PIXELS
LIS-770i maximum number of pixels.
Definition: Lis.h:400
void S13131Expose(void)
Definition: S13131.h:191
void CaptureFrame(void)
Definition: UsbCmd.h:514
void GetSensorConfig(void)
Definition: UsbCmd.h:229
void GetSensorLED(void)
Definition: UsbCmd.h:124
void SetExposure(void)
Definition: UsbCmd.h:466
void SetSensorLED(void)
Definition: UsbCmd.h:175
uint8_t ReadLedState(void)
Definition: UsbCmd.h:30
void NullCommand(void)
Definition: UsbCmd.h:50
void SetSensorConfig(void)
Definition: UsbCmd.h:307
void GetExposure(void)
Definition: UsbCmd.h:422
uint8_t frame[]
One frame of pixel data is, at most, 1568 bytes.
Definition: VisCmd.c:2
uint16_t GetPeak(uint16_t const, uint16_t const)
Definition: VisCmd.c:29
bool LedNumIsValid(bicolorled_num led_num)
Definition: VisCmd.h:63
uint16_t AutoExpose(void)
Definition: VisCmd.c:81