IRPyro API  (sKEMLIB1)
Collection of routines and data structures covering the functionality of the IRPyro sensor
IRPyro_API_single_device_layer.c
Go to the documentation of this file.
1 /**
2 ******************************************************************************
3 * @file IRPyro_API_single_device_layer.c
4 * @author _KEMET Ltd.
5 * @date March 2018
6 * @version Release 1.0.6
7 * @copyright (c) 2018 _KEMET, Ltd
8 * @brief IRPyro Application interface functions implementation
9 * @verbatim
10 ===============================================================================
11  ##### How to use this driver #####
12 ===============================================================================
13  [..]
14  (#) Declare an IRPyro_sensor_device_type in your code
15  (#) Fill the values for CS, INT and address
16  (#) Fill the values for number_of_active_channels and read_mode
17  (#) AFE, CCP and WUP can be left empty if desired, configuration macros
18  will fill them with default values
19  (#) Call IRPyro_open() to commit the values to the physical IRPyro
20  (#) IRPyro_read() retrieves the values sampled by the IRPyro sensor
21  (#) Modify the IRPyro settings using IRPyro_IOCTL()
22  (#) Close the device when finished using IRPyro_read()
23  [..]
24  @endverbatim
25 ******************************************************************************
26  @attention <h2><center>&copy; COPYRIGHT 2018 _KEMET, Ltd</center></h2>
27 
28  @verbatim
29  Copyright (c) 2018, _KEMET, Ltd
30  All rights reserved.
31 
32  THIS SOFTWARE IS PROVIDED BY _KEMET, Ltd ''AS IS'' AND ANY
33  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  DISCLAIMED. IN NO EVENT SHALL _KEMET, Ltd BE LIABLE FOR ANY
36  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  @endverbatim
43 ******************************************************************************
44  */
45 
46 /* Includes ------------------------------------------------------------------*/
47 #include "Version.h"
49 /** @defgroup IRPyro_API IRPyro application programming interface
50  * @brief Functions to configure and sample data from an IRPyro sensor
51  * @{
52  */
53 /** @defgroup IRPyro_single IRPyro Single Device Layer
54  * @brief Functions to configure and sample data from a single device
55  * @{
56  */
57 /** @defgroup API_G1_IRPyro IRPyro Constants
58  * @brief Hexadecimal constants for the IRPyro API
59  * @verbatim
60  * Values for the IRPyro commands, memory sizes, configuration values
61  * @endverbatim
62  * @note Do not modify the values since they are hardware dependent
63  * @{
64  */
65 
66 /** @defgroup API_G2_IRPyro IRPyro I2C Commands
67  * @brief I2C bytes to control IRPyro
68  * @verbatim
69  * One byte constants to configure and control the IRPyro sensor
70  * @endverbatim
71  * @note Do not modify the values since they are hardware dependent
72  * @{
73  */
74 
75 /* list of i2c commands available */
76 #define IRPyro_TEST 0x00
77 #define IRPyro_VERSION 0x02
78 #define IRPyro_FIFO_STATUS 0x04
79 #define IRPyro_FIFO_READ_FULL 0x06
80 #define IRPyro_FIFO_READ_ACTIVE 0x08
81 #define IRPyro_FIFO_CLEAR 0x0A
82 #define IRPyro_FIFO_RESET 0x0C
83 #define IRPyro_CCP_READ 0x0E
84 #define IRPyro_CCP_WRITE 0x10
85 #define IRPyro_AFE_READ 0x12
86 #define IRPyro_AFE_WRITE 0x14
87 #define IRPyro_WUP_READ 0x16
88 #define IRPyro_WUP_WRITE 0x18
89 #define IRPyro_ADDR_WRITE 0x1E
90 #define IRPyro_GO_TO_SLEEP 0x20
91 #define IRPyro_WAKE_UP 0x22
92 #define IRPyro_RESET_SOFT 0x24
93 #define IRPyro_RESET_FULL 0x26
94 
95 /** end of IRPyro I2C Commands
96  * @}
97  */
98 /** @defgroup API_G9_IRPyro IRPyro I2C Operation result codes
99  * @brief OK / ERR return codes for IRPyro I2C commands
100  * @note Do not modify the values since they are hardware dependent
101  * @{
102  */
103 #define IRPyro_TEST_OK 0x01
104 #define IRPyro_TEST_ERR 0x02
105 #define IRPyro_FIFO_CLEAR_OK 0X29
106 #define IRPyro_FIFO_CLEAR_ERR 0X2A
107 #define IRPyro_FIFO_RESET_OK 0X31
108 #define IRPyro_FIFO_RESET_ERR 0X32
109 #define IRPyro_GO_TO_SLEEP_OK 0X81
110 #define IRPyro_GO_TO_SLEEP_ERR 0X82
111 #define IRPyro_WAKE_UP_OK 0X89
112 #define IRPyro_WAKE_UP_ERR 0X8A
113 #define IRPyro_RESET_SOFT_OK 0X91
114 #define IRPyro_RESET_SOFT_ERR 0X92
115 #define IRPyro_RESET_FULL_OK 0X99
116 #define IRPyro_RESET_FULL_ERR 0X9A
117 
118 /** end of IRPyro I2C Operation result codes
119  * @}
120  */
121 
122 /** @defgroup API_G3_IRPyro IRPyro I2C Default Address
123  * @brief Default I2C address on power up
124  * @verbatim
125  * IRPyro assumes this value on CS enabled
126  *
127  * @endverbatim
128  * @note Do not modify this value since is hardware dependent
129  * @{
130  */
131 #define IRPyro_DEFAULT_I2C 0x65
132 /**
133  * @}
134  */
135 
136 /** @defgroup API_G4_IRPyro IRPyro registers allocation space
137  * @brief IRPyro registers sizes in bytes
138  * @verbatim
139  * IRPyro sizes used for I2C communications with the MCU
140  *
141  * @endverbatim
142  * @note Do not modify this values since they are hardware dependent
143  * @{
144  */
145 #define IRPyro_DATA_SIZE 17 // bytes in an IRPyro frame
146 #define IRPyro_AFE_SIZE 2 // bytes on the IRPyro AFE register
147 #define IRPyro_CCP_SIZE 5 // bytes on the IRPyro CCP register
148 #define IRPyro_WUP_SIZE 6 // bytes on the IRPyro WUP register
149 #define IRPyro_FIFO_STATUS_SIZE 1 // byte of the IRPyro STS register
150 #define IRPyro_BYTES_PER_CHANNEL 3 // 24 bits unsigned channel data MSB to LSB
151 #define IRPyro_BYTES_FRAME_COUNT 2 // 16 bit frame counter
152 #define IRPyro_FIFO_NO_FRAMES 14 // frames of IRPyro_DATA_SIZE
153 #define IRPyro_MAX_FRAME_COUNT 0xFFFF // maximum value on the frame counter
154 #define IRPyro_FIFO_WAKE_MASK 0X80 // masks the FIFO WAKE detection from the FIFO status
155 #define IRPyro_FIFO_INT_MASK 0X01 // masks the FIFO INT from the FIFO status
156 #define IRPyro_FIFO_COUNT_MASK 0X1E // masks the FIFO count from the FIFO status
157 #define IRPyro_FIFO_ERROR_MASK 0X60 // masks the FIFO ERROR from the FIFO status
158 #define IRPyro_FIFO_ERROR_OK 0X00 // FIFO status OK
159 #define IRPyro_FIFO_ERROR_WRITE_FULL 0X01 // write when FIFO is full (FIFO count = 14) or read when FIFO is empty (FIFO count = 0)
160 #define IRPyro_FIFO_ERROR_I2C_EARLY 0X02 // detect I2C read FIFO early termination (read less bytes than expected)
161 #define IRPyro_FIFO_ERROR_I2C_EXTRA 0X03 // detect I2C read FIFO extra (read more bytes than expected)
162 
163 #define IRPyro_FRAME_COUNT_TOP_BYTE 2 // top byte index location frame count
164 #define IRPyro_FRAME_COUNT_LOW_BYTE 1 // low byte index location frame count
165 #define IRPyro_SHIFT_TO_MSB 8 // bits to shift left the top byte of the frame count
166 #define IRPyro_SHIFT_ONE 1 // shift one bit
167 #define IRPyro_SHIFT_FOUR 4 // shift FOUR bitS
168 #define IRPyro_CHANNEL_DATA 0x7FFFFF // 23 bits unsigned channel data
169 #define IRPyro_CHANNEL_SAT 0X800000 // bit 24 saturation OFF(0)/ON(1)
170 #define IRPyro_FRAME_COUNT_LOCATION 5 // position on the user data buffer
171 /**
172  * @}
173  */
174 
175 /** API_G1_IRPyro IRPyro Constants
176  * @}
177  */
178 
179 /* Initialization Macros ---------------------------------------------------- */
180 /*
181  .AFE_register.S7_S0 = 0, // Sample rate 1 ms
182  .AFE_register.LP = LOW_POWER_DISABLE, // Low power disabled
183  .AFE_register.HP = HP_DISABLE, // High pass filter disabled
184  .AFE_register.C_LP = LOW_PASS_180, // Low pass filter selected to 180 Hz
185  .AFE_register.CLK_OUT = CLK_ENABLE, // Internal clock output ENABLED
186  .AFE_register.SYNC = MASTER, // Device set to master
187  .AFE_register.TEMP = TEMP_DISABLE, // Temperature detection off
188  .AFE_register.INT = INT_ENABLE, // Asserted LOW when data ready
189 
190 */
191 #define AFE_INIT_DEFAULT(X) AFE_reg_type X = { \
192  .S7_S0 = 0, \
193  .LP = LOW_POWER_DISABLE, \
194  .HP = HP_DISABLE, \
195  .C_LP = LOW_PASS_180, \
196  .CLK_OUT = CLK_ENABLE, \
197  .SYNC = MASTER, \
198  .TEMP = TEMP_DISABLE,\
199  .INT = INT_ENABLE \
200  }
201 /*
202  .status_bit = CH_ENABLE, // Channel enabled
203  .Feedback_transconductance = TCONDUCT_1_2T, // Gain to 1.2T
204  .High_pass_filter_setting = HIGH_PASS_1HZ, // High pass filter to 1Hz
205  .Feedback_cap = FEEDBACK_50_20, // Feedback cap to 50 fF
206 
207 */
208 
209 #define CCP_INIT_DEFAULT(X) CCP_reg_type X = { \
210  .status_bit = CH_ENABLE, \
211  .Feedback_transconductance = TCONDUCT_1_2T, \
212  .High_pass_filter_setting = HIGH_PASS_1HZ, \
213  .Feedback_cap = FEEDBACK_50_20 \
214  }
215 
216 /*
217  .UHT = 0xFF,
218  .ULT = 0xFF,
219  .LHT = 0x00,
220  .LLT = 0x00,
221  .WT_Threshold = 0x10,
222  .DP0_DP2 = REF_CH_0,
223  .CH0_CH2 = SEL_CH_2,
224  .ST = SLEEP_MODE_ONE_CH,
225 
226 */
227 #define WUP_INIT_DEFAULT(X) WUP_reg_type X ={ \
228  .UHT = 0xFF, \
229  .ULT = 0xFF, \
230  .LHT = 0x00, \
231  .LLT = 0x00, \
232  .WT_Threshold = 0x10, \
233  .DP0_DP2 = REF_CH_0, \
234  .CH0_CH2 = SEL_CH_2, \
235  .ST = SLEEP_MODE_ONE_CH \
236  }
237 
238 #define NORMAL_POWER_INIT_DEFAULT(X) power_settings_type X ={ \
239  .S7_S0 = 0x00, \
240  .C_LP = LOW_PASS_180, \
241  .CCP_High_pass[0].High_pass_filter_setting = HIGH_PASS_1HZ, \
242  .CCP_High_pass[1].High_pass_filter_setting = HIGH_PASS_1HZ, \
243  .CCP_High_pass[2].High_pass_filter_setting = HIGH_PASS_1HZ, \
244  .CCP_High_pass[3].High_pass_filter_setting = HIGH_PASS_1HZ, \
245  .CCP_High_pass[4].High_pass_filter_setting = HIGH_PASS_1HZ, \
246  .UHT = 0xFF, \
247  .ULT = 0xFF, \
248  .LHT = 0x00, \
249  .LLT = 0x00, \
250  .WT_Threshold = 0x10, \
251  }
252 
253 #define LOW_POWER_INIT_DEFAULT(X) power_settings_type X ={ \
254  .S7_S0 = 0x00, \
255  .C_LP = LOW_PASS_30, \
256  .CCP_High_pass[0].High_pass_filter_setting = HIGH_PASS_0_17HZ, \
257  .CCP_High_pass[1].High_pass_filter_setting = HIGH_PASS_0_17HZ, \
258  .CCP_High_pass[2].High_pass_filter_setting = HIGH_PASS_0_17HZ, \
259  .CCP_High_pass[3].High_pass_filter_setting = HIGH_PASS_0_17HZ, \
260  .CCP_High_pass[4].High_pass_filter_setting = HIGH_PASS_0_17HZ, \
261  .UHT = 0xFF, \
262  .ULT = 0xFF, \
263  .LHT = 0x00, \
264  .LLT = 0x00, \
265  .WT_Threshold = 0x10, \
266  }
267 
268 /* Private functions ---------------------------------------------------------*/
269 /* Initialization and Configuration functions *********************************/
270 static uint8_t AFE_init(IRPyro_sensor_device_type* this_device);
271 static uint8_t CCP_init(IRPyro_sensor_device_type* this_device);
272 static uint8_t WUP_init(IRPyro_sensor_device_type* this_device);
273 static uint8_t I2C_address_set(IRPyro_sensor_device_type* this_device);
274 
275 /* FIFO memory functions *****************************************************/
276 static uint8_t FIFO_data_active_get(IRPyro_sensor_device_type * this_device);
277 static uint8_t FIFO_ready_status_get(IRPyro_sensor_device_type* this_device);
278 static uint8_t FIFO_reset(IRPyro_sensor_device_type* this_device);
279 static uint8_t IRPyro_test(IRPyro_sensor_device_type* this_device);
280 
281 /* Support functions *****************************************************/
282 static uint8_t AFE_register_empty(AFE_reg_type first);
283 static uint8_t CCP_register_empty(CCP_reg_type first);
284 static uint8_t WUP_register_empty(WUP_reg_type first);
285 static uint8_t channel_value_decode(IRPyro_sensor_device_type* this_device);
286 
287 static void AFE_to_bytes(AFE_reg_type AFE_register, uint8_t * AFE_byte );
288 static void CCP_to_bytes(CCP_reg_type CCP_register, uint8_t * CCP_byte );
289 static void WUP_to_bytes(WUP_reg_type WUP_register, uint8_t * WUP_byte );
290 
291 static void bytes_to_AFE(uint8_t *AFE_bytes, AFE_reg_type *AFE_register);
292 static void bytes_to_CCP(uint8_t CCP_byte, CCP_reg_type *CCP_register);
293 static void bytes_to_WUP(uint8_t *WUP_bytes, WUP_reg_type *WUP_register);
294 
295 /* IO control functions*/
296 static uint8_t AFE_read(IRPyro_sensor_device_type *this_device, AFE_reg_type *AFE_data);
297 static uint8_t AFE_write(IRPyro_sensor_device_type *this_device);
298 static uint8_t CCP_read(IRPyro_sensor_device_type *this_device, CCP_reg_type *CCP_data);
299 static uint8_t CCP_write(IRPyro_sensor_device_type *this_device);
300 static uint8_t WUP_read(IRPyro_sensor_device_type *this_device, WUP_reg_type *WUP_data);
301 static uint8_t WUP_write(IRPyro_sensor_device_type *this_device);
302 
303 /* Power management functions *************************************************/
304 static uint8_t IRPyro_power_mode_sleep_set(IRPyro_sensor_device_type* this_device);
305 static uint8_t IRPyro_power_mode_wakeup_set(IRPyro_sensor_device_type* this_device);
306 
307 static uint8_t IRPyro_power_settings_init(IRPyro_sensor_device_type* this_device); // this needs to be run before power_mode_set
308 static uint8_t IRPyro_power_mode_low_set(IRPyro_sensor_device_type* this_device);
309 static uint8_t IRPyro_power_mode_normal_set(IRPyro_sensor_device_type* this_device);
310 static struct notice IRPyro_checksum(void);
311 /**
312  * @defgroup IRPyro_sensor_device_type_functions IRPyro sensor device functions
313  * @brief Public functions of IRPyro: Open, Read, IOCTL and Close
314  * @{
315  */
316 /**
317  * @brief Initializes the IRPyro device.
318  * @param this_device pointer to the IRPyro data structure
319  * @retval op_result 1 success / 0 error
320  */
322 {
323  uint8_t results_init_sequence[6]= {0};
324  uint8_t op_result = 0;
325 
326  results_init_sequence[0]= I2C_address_set(this_device);
327  results_init_sequence[1]= AFE_init(this_device);
328  results_init_sequence[2]= CCP_init(this_device);
329  results_init_sequence[3]= WUP_init(this_device);
330  results_init_sequence[4]= FIFO_reset(this_device);
331  results_init_sequence[5]= IRPyro_power_settings_init(this_device);
332  for(uint8_t idx=0; idx<5; ++idx)
333  {
334  op_result += results_init_sequence[idx];
335  }
336  op_result = (op_result == 5) ? 1 : 0; // 1 passed all / 0 fail
337  return op_result;
338 }
339 
340 /**
341  * @brief Stops streaming, deallocates memory and disable the IRPyro sensor
342  * @param this_device pointer to the IRPyro data structure
343  * @retval None
344  */
346 {
347  CS_pin_set(this_device->CS_Port,this_device->CS_Pin, 0);
348  return 1;
349 }
350 
351 /**
352  * @brief Reads a frame of data from the IRPyro
353  *
354  * Sensor data sampling into the FIFO (SECTION 12.6.1 )
355  * There are two methods of sampling the data available in the FIFO:
356  * Polling mode or Interrupt mode.
357  * - In interrupt mode the host can wait till the interrupt line goes
358  * low in order to read data from the FIFO. The interrupt remains
359  * low till the FIFO is cleared from data.
360  * - In polling mode the host has to read the FIFO status packet to
361  * determine if data is available in order to read it. The number of
362  * data packets available can also be determined from the status
363  * packet allowing multiple reads without having to keep reading the
364  * status packet.
365  * Interrupt mode is a single step operation, polling mode is a two step
366  * operation.
367  *
368  * IMPORTANT:
369  * FIFO data collected is stored in the first available position of the
370  * channel_value array.
371  *
372  * One channel active:
373  * channel 2 -> channel_value[0]
374  * Four channels active:
375  * channel 1 -> channel_value[0]
376  * channel 2 -> channel_value[1]
377  * channel 3 -> channel_value[2]
378  * channel 4 -> channel_value[3]
379  * For both cases:
380  * frame counter -> channel_value[5]
381  *
382  * @param this_device pointer to the IRPyro data structure
383  * @retval op_result 1 success / 0 error
384  */
386 {
387  uint8_t op_result = 0;
388  // determine type of reading operation
389  switch (this_device->read_mode)
390  {
391  case 0: // read by checking the INT pin status
392  this_device->FIFO_register.COUNT = INT_pin_read(this_device->INT_Port, this_device->INT_Pin );
393  break;
394  case 1: // read by polling
395  // query sensor FIFO status
396  op_result = FIFO_ready_status_get(this_device);
397  break;
398  case 2: // read by synchronized sampling: both modes available
399  if ((this_device->AFE_register.INT == INT_ENABLE) && (INT_pin_read(this_device->INT_Port, this_device->INT_Pin )))
400  {
401  this_device->FIFO_register.COUNT =1; // interrupt
402  }
403  else
404  {
405  op_result = FIFO_ready_status_get(this_device); // polling
406  }
407  break;
408  default:
409  break;
410  }
411  // read operation
412  if (this_device->FIFO_register.COUNT)
413  {
414  op_result = FIFO_data_active_get(this_device);
415  channel_value_decode(this_device);
416  }
417  return op_result;
418 }
419 /**
420  * @brief access to IRPyro registers
421  * @param this_device pointer to the IRPyro data structure
422  * @param cmd pointer to command data structure
423  * @param arg pointer to argument data structure
424  * @retval 1 success / 0 fail
425  */
427 {
428  uint8_t op_result = 0;
429 
430  switch (cmd->cmd)
431  {
432  case sampling_rate_set:
433  this_device->AFE_register.S7_S0 = arg.arg;
434  op_result = AFE_write(this_device);
435  break;
436  case sampling_rate_get:
437  op_result= AFE_read(this_device, &cmd->AFE_register);
438  cmd->cmd_return_code = cmd->AFE_register.S7_S0;
439  break;
440  case high_pass_set:
441  this_device->AFE_register.HP = 1;
442  this_device->CCP_register[arg.channel].High_pass_filter_setting = arg.arg;
443  op_result = (AFE_write(this_device) && CCP_write(this_device));
444  break;
445  case high_pass_get:
446  op_result = (AFE_read(this_device, &cmd->AFE_register) && CCP_read(this_device, cmd->CCP_register));
448  break;
449  case low_pass_set:
450  this_device->AFE_register.C_LP = arg.arg;
451  op_result = AFE_write(this_device);
452  break;
453  case low_pass_get:
454  op_result = AFE_read(this_device, &cmd->AFE_register);
455  cmd->cmd_return_code = this_device->AFE_register.C_LP;
456  break;
457  case gain_set:
458  this_device->CCP_register[arg.channel].Feedback_cap = arg.arg;
459  op_result= CCP_write(this_device);
460  break;
461  case gain_get:
462  op_result= CCP_read(this_device, cmd->CCP_register);
463  cmd->cmd_return_code = this_device->CCP_register[2].Feedback_cap;
464  break;
465  case power_off:
466  op_result= IRPyro_close(this_device);
467  break;
468  case power_normal:
469  op_result= IRPyro_power_mode_normal_set(this_device);
470  break;
471  case power_low:
472  op_result= IRPyro_power_mode_low_set(this_device);
473  break;
474  case power_sleep:
475  op_result= IRPyro_power_mode_sleep_set(this_device);
476  break;
477  case power_wakeup:
478  op_result= IRPyro_power_mode_wakeup_set(this_device);
479  break;
480  case register_set:
481  AFE_write(this_device);
482  CCP_write(this_device);
483  WUP_write(this_device);
484  op_result = 1;
485  break;
486  case register_get:
487  AFE_read(this_device, &cmd->AFE_register);
488  CCP_read(this_device, cmd->CCP_register);
489  WUP_read(this_device, &cmd->WUP_register);
490  op_result = 1;
491  break;
492  default:
493  break;
494  }
495  return op_result;
496 }
497 /** end of IRPyro_API
498  * @}
499  */
500 /** @defgroup API_F1_IRPyro Individual sensor initialization and Configuration functions
501  * @brief Default values defined in IRPyro_API_single_device_layer.c can be applied or user assigned
502  * @verbatim
503  ===============================================================================
504  ##### Initialization and Configuration functions #####
505  ===============================================================================
506  [..] This section provides a set of functions allowing to initialize the IRPyro sensor,
507  AFE, CCP and WUP registers, I2C address.
508  @endverbatim
509  * @{
510  */
511 /**
512  * @defgroup afe_functions AFE register functions
513  * @brief Allows to read/write the AFE register performing conversion between
514  * bytes and struct values
515  * @{
516  */
517 /**
518  * @brief Initializes the AFE register with this_device values
519  * @param this_device pointer to the IRPyro data structure
520  * @retval op_result 1 success / 0 error
521  */
522 static uint8_t AFE_init(IRPyro_sensor_device_type* this_device)
523 {
524  uint8_t op_result = 0;
525  AFE_INIT_DEFAULT(afe_defaults);
526 
527  if (AFE_register_empty(this_device->AFE_register))
528  {
529  this_device->AFE_register = afe_defaults;
530  }
531 
532  op_result = AFE_write(this_device);
533  return op_result;
534 }
535 /**
536  * @brief reads the AFE register on the IRPyro and loads into this_device
537  * @param this_device pointer to the IRPyro data structure
538  * @param AFE_data contents of the AFE register on the IRPyro sensor
539  * @retval op_result 1 success / 0 error
540  */
541 static uint8_t AFE_read(IRPyro_sensor_device_type *this_device, AFE_reg_type *AFE_data)
542 {
543  uint8_t op_result = 0;
544  uint8_t AFE_contents[IRPyro_AFE_SIZE] = {0};
545 
546  op_result = i2c_Read(this_device->address, IRPyro_AFE_READ, AFE_contents ,IRPyro_AFE_SIZE);
547  bytes_to_AFE(AFE_contents, AFE_data);
548 
549  return op_result;
550 }
551 /**
552  * @brief writes the AFE register contents of this_device into the IRPyro
553  * @param this_device pointer to the IRPyro data structure
554  * @retval op_result 1 success / 0 error
555  */
556 static uint8_t AFE_write(IRPyro_sensor_device_type *this_device)
557 {
558  uint8_t op_result = 0;
559  uint8_t AFE_byte[IRPyro_AFE_SIZE]= {0};
560 
561  AFE_to_bytes(this_device->AFE_register, AFE_byte);
562  op_result = i2c_Write(this_device->address, IRPyro_AFE_WRITE, AFE_byte ,IRPyro_AFE_SIZE);
563 
564  return op_result;
565 }
566 /**
567  * @brief encodes the AFE register contents of this_device into the IRPyro
568  */
569 static void AFE_to_bytes(AFE_reg_type AFE_register, uint8_t * AFE_byte )
570 {
571  uint8_t bit_value =0;
572 
573  AFE_byte[0] = AFE_register.S7_S0; // 0b11111111
574  bit_value |= (AFE_register.LP << 7 )& 0X80 ; // 0b10000000
575  bit_value |= (AFE_register.HP << 6 )& 0X40 ; // 0b01000000
576  bit_value |= (AFE_register.C_LP << 4 )& 0X30 ; // 0b00110000
577  bit_value |= (AFE_register.CLK_OUT << 3 )& 0X08 ; // 0b00001000
578  bit_value |= (AFE_register.SYNC << 2 )& 0X04 ; // 0b00000100
579  bit_value |= (AFE_register.TEMP << 1 )& 0X02 ; // 0b00000010
580  bit_value |= (AFE_register.INT << 0 )& 0X01 ; // 0b00000001
581  AFE_byte[1] = bit_value;
582 }
583 /**
584  * @brief decodes the AFE register of the IRPyro into this_device
585  */
586 static void bytes_to_AFE(uint8_t *AFE_bytes, AFE_reg_type *AFE_register)
587 {
588  AFE_register->S7_S0 = AFE_bytes[0]; // 0b11111111
589  AFE_register->LP = (AFE_bytes[1]& 0X80) >> 7; // 0b10000000
590  AFE_register->HP = (AFE_bytes[1]& 0X40) >> 6; // 0b01000000
591  AFE_register->C_LP = (AFE_bytes[1]& 0X30) >> 4; // 0b00110000
592  AFE_register->CLK_OUT = (AFE_bytes[1]& 0X08) >> 3; // 0b00001000
593  AFE_register->SYNC = (AFE_bytes[1]& 0X04) >> 2; // 0b00000100
594  AFE_register->TEMP = (AFE_bytes[1]& 0X02) >> 1; // 0b00000010
595  AFE_register->INT = (AFE_bytes[1]& 0X01) >> 0; // 0b00000001
596 }
597 /**@} end of AFE functions
598 */
599 /**
600  * @defgroup ccp_functions CCP register functions
601  * @brief All enabled channels in the device can be manipulated
602  * @{
603  */
604 /**
605  * @brief Initializes the CCP register with this_device values
606  * @param this_device pointer to the IRPyro data structure
607  * @retval op_result 1 success / 0 error
608  */
609 static uint8_t CCP_init(IRPyro_sensor_device_type* this_device)
610 {
611  uint8_t op_result = 0, initialization_failed =0;
612  uint8_t selected_channel = 0, ch_to_activate =0;
613 
614  CCP_INIT_DEFAULT(ccp_defaults);
615  CCP_reg_type CCP_data;
616  // active channels value is checked for 1 or 4 channels, if empty defaults to 1
617  switch (this_device->number_of_active_channels)
618  {
619  case 1:
620  ch_to_activate = 1;
621  selected_channel = 2;
622  break;
623  case 4:
624  ch_to_activate = 4;
625  selected_channel = 1;
626  break;
627  default:
628  // other than 1 or 4 the initialization fails.
629  initialization_failed =1;
630  break;
631  }
632  if (!initialization_failed)
633  {
634  this_device->number_of_active_channels = ch_to_activate;
635  // only active channels are initialized with default data if empty
636  while(ch_to_activate)
637  {
638  CCP_data = this_device->CCP_register[selected_channel];
639  if (CCP_register_empty(CCP_data))
640  {
641  this_device->CCP_register[selected_channel] = ccp_defaults;
642  }
643  ++selected_channel;
644  ch_to_activate--;
645  }
646  op_result = CCP_write(this_device);
647  }
648  return op_result;
649 }
650 /**
651  * @brief reads the CCP registers on the IRPyro and loads into this_device
652  * @param this_device pointer to the IRPyro data structure
653  * @param CCP_data contents of the CCP register on the IRPyro sensor
654  * @retval op_result 1 success / 0 error
655  */
656 static uint8_t CCP_read(IRPyro_sensor_device_type *this_device, CCP_reg_type *CCP_data)
657 {
658  uint8_t op_result = 0;
659  uint8_t CCP_contents[IRPyro_CCP_SIZE] = {0};
660 
661  op_result = i2c_Read(this_device->address, IRPyro_CCP_READ, CCP_contents ,IRPyro_CCP_SIZE);
662  for(uint8_t idx=0; idx < IRPyro_CCP_SIZE; ++idx)
663  {
664  bytes_to_CCP(CCP_contents[idx], &CCP_data[idx]);
665  }
666  return op_result;
667 }
668 /**
669  * @brief writes the CCP registers contents of this_device into the IRPyro
670  * @param this_device pointer to the IRPyro data structure
671  * @retval op_result 1 success / 0 error
672  */
673 static uint8_t CCP_write(IRPyro_sensor_device_type *this_device)
674 {
675  uint8_t op_result = 0;
676  uint8_t CCP_byte[IRPyro_CCP_SIZE] = {0};
677 
678  for(uint8_t idx=0; idx < IRPyro_CCP_SIZE; ++idx)
679  {
680  CCP_to_bytes(this_device->CCP_register[idx], &CCP_byte[idx]);
681  }
682  op_result = i2c_Write(this_device->address, IRPyro_CCP_WRITE, CCP_byte ,IRPyro_CCP_SIZE);
683 
684  return op_result;
685 }
686 /**
687  * @brief encodes the CCP register contents of this_device into IRPyro
688  */
689 static void CCP_to_bytes(CCP_reg_type CCP_register, uint8_t *CCP_byte )
690 {
691  uint8_t bit_value = 0;
692 
693  bit_value |= (CCP_register.Feedback_transconductance << 6)& 0XC0 ; // 0b11000000
694  bit_value |= (CCP_register.High_pass_filter_setting << 4)& 0X30 ; // 0b00110000
695  bit_value |= (CCP_register.Feedback_cap << 1)& 0X0E ; // 0b00001110
696  bit_value |= (CCP_register.status_bit << 0)& 0X01 ; // 0b00000001
697  *CCP_byte = bit_value;
698 }
699 /**
700  * @brief decodes the CCP register of the IRPyro into this_device
701  */
702 static void bytes_to_CCP(uint8_t CCP_byte, CCP_reg_type *CCP_register)
703 {
704  CCP_register->Feedback_transconductance = (CCP_byte & 0XC0 )>> 6 ; // 0b11000000
705  CCP_register->High_pass_filter_setting = (CCP_byte & 0X30 )>> 4 ; // 0b00110000
706  CCP_register->Feedback_cap = (CCP_byte & 0X0E )>> 1 ; // 0b00001110
707  CCP_register->status_bit = (CCP_byte & 0X01 )>> 0 ; // 0b00000001
708 }
709 /**@} end of CCP functions
710 */
711 /**
712  * @defgroup WUP_functions WUP register functions
713  * @brief Modifies the WUP register
714  * @{
715  */
716 /**
717  * @brief Initializes the WUP register with this_device values
718  * @param this_device pointer to the IRPyro data structure
719  * @retval op_result 1 success / 0 error
720  */
721 static uint8_t WUP_init(IRPyro_sensor_device_type* this_device)
722 {
723  uint8_t op_result = 0;
724  WUP_INIT_DEFAULT(wup_defaults);
725 
726  if (WUP_register_empty(this_device->WUP_register))
727  {
728  this_device->WUP_register = wup_defaults;
729  }
730 
731  op_result = WUP_write(this_device);
732  return op_result;
733 }
734 /**
735  * @brief reads the WUP register on the IRPyro and loads into this_device
736  * @param this_device pointer to the IRPyro data structure
737  * @param WUP_data pointer to the WUP data structure
738  * @retval op_result 1 success / 0 error
739  */
740 static uint8_t WUP_read(IRPyro_sensor_device_type *this_device, WUP_reg_type *WUP_data)
741 {
742  uint8_t op_result = 0;
743  uint8_t WUP_contents[IRPyro_WUP_SIZE] = {0};
744 
745  op_result = i2c_Read(this_device->address, IRPyro_WUP_READ, WUP_contents ,IRPyro_WUP_SIZE);
746  bytes_to_WUP(WUP_contents, WUP_data );
747 
748  return op_result;
749 }
750 /**
751  * @brief writes the WUP register contents of this_device into the IRPyro
752  * @param this_device pointer to the IRPyro data structure
753  * @retval op_result 1 success / 0 error
754  */
755 static uint8_t WUP_write(IRPyro_sensor_device_type *this_device)
756 {
757  uint8_t op_result = 0;
758  uint8_t WUP_byte[IRPyro_WUP_SIZE] = {0};
759 
760  WUP_to_bytes(this_device->WUP_register, WUP_byte);
761  op_result = i2c_Write(this_device->address, IRPyro_WUP_WRITE, WUP_byte ,IRPyro_WUP_SIZE);
762 
763  return op_result;
764 }
765 /**
766  * @brief encodes the WUP register contents of this_device into the IRPyro
767  */
768 static void WUP_to_bytes(WUP_reg_type WUP_register, uint8_t * WUP_byte)
769 {
770  uint8_t bit_value = 0;
771 
772  WUP_byte[0] = WUP_register.UHT;
773  WUP_byte[1] = WUP_register.ULT;
774  WUP_byte[2] = WUP_register.LHT;
775  WUP_byte[3] = WUP_register.LLT;
776  WUP_byte[4] = WUP_register.WT_Threshold;
777 
778  bit_value |= (WUP_register.ST << 6)& 0X40 ; // 0b01000000
779  bit_value |= (WUP_register.DP0_DP2 << 3)& 0X38 ; // 0b00111000
780  bit_value |= (WUP_register.CH0_CH2 << 0)& 0X07 ; // 0b00000111
781  WUP_byte[5] = bit_value;
782 }
783 /**
784  * @brief decodes the WUP register of the IRPyro into this_device
785  */
786 static void bytes_to_WUP(uint8_t *WUP_bytes, WUP_reg_type *WUP_register)
787 {
788  WUP_register->UHT = WUP_bytes[0];
789  WUP_register->ULT = WUP_bytes[1];
790  WUP_register->LHT = WUP_bytes[2];
791  WUP_register->LLT = WUP_bytes[3];
792  WUP_register->WT_Threshold = WUP_bytes[4];
793  WUP_register->ST =(WUP_bytes[5] & 0X40) >> 6; // 0b01000000
794  WUP_register->DP0_DP2 =(WUP_bytes[5] & 0X38) >> 3; // 0b00111000
795  WUP_register->CH0_CH2 =(WUP_bytes[5] & 0X07) >> 0; // 0b00000111
796 }
797 /**@} end of WUP functions
798 */
799 /**
800  * @brief Sends test code to the IRPyro sensor to confirm is there.
801  * @param this_device pointer to the IRPyro data structure
802  * @retval op_result 1 success / 0 error
803  */
804 static uint8_t IRPyro_test(IRPyro_sensor_device_type* this_device)
805 {
806  uint8_t op_result = 0;
807  uint8_t i2c_result = 0;
808 
809  i2c_result = i2c_Read(this_device->address, IRPyro_TEST, &op_result ,1);
810  if ((i2c_result == 1) && (op_result == IRPyro_TEST_OK))
811  {
812  op_result =1;
813  }
814  else
815  op_result = i2c_result;
816 
817  return op_result;
818 }
819 /**
820  * @brief Sends new I2C address to the IRPyro sensor
821  * Default i2c address is 0x65, if multiple devices are being used
822  * care needs to be taken when writing new i2c addresses by switching off
823  * other devices with the same address.
824  * @param this_device pointer to the IRPyro data structure
825  * @retval op_result 1 success / 0 error
826  */
827 static uint8_t I2C_address_set(IRPyro_sensor_device_type* this_device)
828 {
829  uint8_t op_result = 0;
830  uint8_t i2c_result = 0;
831  uint8_t attempt = 3;
832  do
833  {
834  if(this_device->CS_Port>0 && this_device->CS_Pin>0)
835  {
836  power_set(this_device->CS_Port, this_device->CS_Pin);
837  }
838  else
839  {
841  }
842  i2c_result= i2c_Read(IRPyro_DEFAULT_I2C, IRPyro_RESET_FULL, &op_result ,1);
843  if ((i2c_result == 1) && (op_result == IRPyro_RESET_FULL_OK))
844  {
845  op_result =1;
846  break;
847  }
848  else
849  op_result = i2c_result;
850 
851  }
852  while (--attempt);
853 
855 
856  if (op_result == 1)
857  {
858  uint8_t IRPyro_Address = this_device->address <<1;
859  i2c_result = i2c_Write(IRPyro_DEFAULT_I2C, IRPyro_ADDR_WRITE, &IRPyro_Address ,1);
860  if ((i2c_result == 1) && (op_result == IRPyro_RESET_FULL_OK))
861  {
862  op_result =1;
863  }
864  else
865  op_result = i2c_result;
866  }
867  return op_result;
868 }
869 /**
870  * @}
871  */
872 /** @defgroup API_F8_IRPyro FIFO memory functions
873  * @brief FIFO memory functions
874  *
875 @verbatim
876  ===============================================================================
877  ##### FIFO memory functions #####
878  ===============================================================================
879  [..] This section provides a set of functions allowing to get captured data
880  from the sensor RAM register
881 @endverbatim
882  * @{
883  */
884 /**
885  * @brief Read data packet (up to 17 bytes) for only active channel
886  * @param this_device pointer to the IRPyro data structure
887  * @retval op_result 1 success / 0 error
888  */
889 static uint8_t FIFO_data_active_get(IRPyro_sensor_device_type * this_device)
890 {
891  uint8_t bytes_to_read = IRPyro_BYTES_PER_CHANNEL * this_device->number_of_active_channels + IRPyro_BYTES_FRAME_COUNT;
892  uint8_t op_result = 0;
893  uint8_t i2c_result = 0;
894 
895  i2c_result = i2c_Read(this_device->address, IRPyro_FIFO_READ_ACTIVE, this_device->raw_data, bytes_to_read);
896  if (i2c_result == 1)
897  {
898  i2c_result = i2c_Read(this_device->address, IRPyro_FIFO_CLEAR, &op_result, 1);
899  if ((i2c_result == 1) && (op_result == IRPyro_FIFO_CLEAR_OK))
900  {
901  op_result = 1;
902  }
903  else
904  op_result = i2c_result;
905  }
906  else
907  op_result = i2c_result;
908 
909  return op_result;
910 }
911 /**
912  * @brief Ask the IRPyro if a frame of data is available
913  * used when a polling reading operation has started
914  * @param this_device pointer to the IRPyro data structure
915  * @retval op_result 1 success / 0 error
916  */
917 static uint8_t FIFO_ready_status_get(IRPyro_sensor_device_type* this_device)
918 {
919  uint8_t IRPyro_Sensor_FIFO_status = 0;
920  uint8_t op_result = 0;
921 
922  op_result = i2c_Read(this_device->address, IRPyro_FIFO_STATUS, &IRPyro_Sensor_FIFO_status, IRPyro_FIFO_STATUS_SIZE);
923  this_device->FIFO_register.WAKE = (IRPyro_Sensor_FIFO_status & IRPyro_FIFO_WAKE_MASK );
924  this_device->FIFO_register.STATUS_CODE = (IRPyro_Sensor_FIFO_status & IRPyro_FIFO_ERROR_MASK ) >> IRPyro_SHIFT_FOUR;
925  this_device->FIFO_register.COUNT = (IRPyro_Sensor_FIFO_status & IRPyro_FIFO_COUNT_MASK ) >> IRPyro_SHIFT_ONE;
926  this_device->FIFO_register.DATA_READY = (IRPyro_Sensor_FIFO_status & IRPyro_FIFO_INT_MASK );
927 
928  return op_result;
929 }
930 /**
931  * @brief Clear the entire FIFO (Rd/Wr pointer reset with the Empty)
932  * @param this_device pointer to the IRPyro data structure
933  * @retval op_result 1 success / 0 error
934  */
935 static uint8_t FIFO_reset(IRPyro_sensor_device_type* this_device)
936 {
937  uint8_t op_result = 0;
938  uint8_t i2c_result = 0;
939 
940  i2c_result = i2c_Read(this_device->address, IRPyro_FIFO_RESET, &op_result ,1);
941  if ((i2c_result == 1) && (op_result == IRPyro_FIFO_RESET_OK))
942  {
943  op_result =1;
944  }
945  else
946  op_result = i2c_result;
947  return op_result;
948 }
949 /** end of API_F8_IRPyro FIFO memory functions
950  * @}
951  */
952 
953 /** @defgroup API_F2_IRPyro Power management functions
954  * @brief Power management functions
955  *
956 @verbatim
957  ===============================================================================
958  ##### Power management functions #####
959  ===============================================================================
960  [..] This section provides a set of functions allowing to control the power
961  mode of the IRPyro sensor.
962 
963 @endverbatim
964  * @{
965  */
966 /**
967  * @brief The device will automatically enter either low power or normal power sleep mode
968  * depending in the power state the device is in when it is put to sleep.
969  * The WUP register contains the settings for either sleep mode.
970  * @param this_device pointer to the IRPyro data structure
971  * @retval 0 fail /1 success
972  */
973 static uint8_t IRPyro_power_mode_sleep_set(IRPyro_sensor_device_type* this_device)
974 {
975  uint8_t op_result = 0;
976  uint8_t i2c_result = 0;
977 
978  i2c_result = i2c_Read(this_device->address, IRPyro_GO_TO_SLEEP, &op_result ,1);
979  if ((i2c_result == 1) && (op_result == IRPyro_GO_TO_SLEEP_OK))
980  {
981  op_result =1;
982  }
983  else
984  op_result = i2c_result;
985 
986  return op_result;
987 }
988 
989 /**
990  * @brief The device will automatically enter either low power or normal power sleep mode
991  * depending in the power state the device is in when it is put to sleep.
992  * The WUP register contains the settings for either sleep mode.
993  * @param this_device pointer to the IRPyro data structure
994  * @retval 0 fail /1 success
995  */
996 static uint8_t IRPyro_power_mode_wakeup_set(IRPyro_sensor_device_type* this_device)
997 {
998  uint8_t op_result = 0;
999  uint8_t i2c_result = 0;
1000  i2c_result = i2c_Write(this_device->address, IRPyro_WAKE_UP, 0,0);
1001  if (i2c_result == 1)
1002  {
1003  op_result = IRPyro_test(this_device);
1004  }
1005  else
1006  op_result = i2c_result;
1007 
1008  return op_result; //(op_result == IRPyro_WAKE_UP_OK ? 1:0);
1009 }
1010 /**
1011  * @brief initializes with defaults the power settings of an IRPyro device
1012  */
1013 static uint8_t IRPyro_power_settings_init(IRPyro_sensor_device_type* this_device)
1014 {
1015  NORMAL_POWER_INIT_DEFAULT(normal_power_init);
1016  LOW_POWER_INIT_DEFAULT(low_power_init);
1017 
1018  this_device->normal_power = normal_power_init;
1019  this_device->low_power = low_power_init;
1020 
1021  return 1;
1022 }
1023 /**
1024  * @brief activates the low power mode settings stored on the IRPyro structure
1025  * @retval op_result 1 success / 0 error
1026  */
1027 static uint8_t IRPyro_power_mode_low_set(IRPyro_sensor_device_type* this_device)
1028 {
1029  uint8_t op_result = 0;
1030  this_device->AFE_register.LP = 1;
1031  this_device->AFE_register.S7_S0 = this_device->low_power.S7_S0;
1032  this_device->AFE_register.C_LP = this_device->low_power.C_LP;
1033 
1039 
1040  op_result = AFE_write(this_device) && CCP_write(this_device) ?1:0;
1041 
1042  return op_result;
1043 }
1044 /**
1045  * @brief activates the normal power mode settings stored on the IRPyro structure
1046  * @retval op_result 1 success / 0 error
1047  */
1048 static uint8_t IRPyro_power_mode_normal_set(IRPyro_sensor_device_type* this_device)
1049 {
1050  uint8_t op_result = 0;
1051  this_device->AFE_register.LP = 0;
1052  this_device->AFE_register.S7_S0 = this_device->normal_power.S7_S0;
1053  this_device->AFE_register.C_LP = this_device->normal_power.C_LP;
1054 
1060 
1061  op_result = AFE_write(this_device) && CCP_write(this_device) ?1:0;
1062 
1063  return op_result;
1064 }
1065 /** end of API_F2_IRPyro Power management functions
1066  * @}
1067  */
1068 
1069 /** @defgroup API_F10_IRPyro Support functions
1070  * @brief Data structures manipulation functions
1071  *
1072 @verbatim
1073  ===============================================================================
1074  ##### Support functions #####
1075  ===============================================================================
1076  [..] This section provides a set of auxiliary functions
1077 
1078 @endverbatim
1079  * @{
1080  */
1081 /**
1082  * @brief Decodes the channel values on a given frame
1083  * @param this_device pointer to IRPyro device
1084  * @retval ch_value pointer to IRPyro decoded channel data
1085  * @verbatim
1086  * Up to 17 Bytes containing the top frame available in the FIFO which has only
1087  * the active channel data as well as a frame counter (the example below shows
1088  * channel 0 and 4 active):
1089  *
1090  * FIFO_DPA Data
1091  * Byte 0 channel 0 bits 23-16
1092  * Byte 1 channel 0 bits 15-8
1093  * Byte 2 channel 0 bits 7-0
1094  * Byte 3 channel 4 bits 23-16
1095  * Byte 4 channel 4 bits 15-8
1096  * Byte 5 channel 4 bits 7-0
1097  * Byte 6 frame count MSB
1098  * Byte 7 frame count LSB
1099  *
1100  * Channel Data : 24 bits unsigned value
1101  * Frame count : 16 bits unsigned value
1102  * In this mode, the number of Bytes sent will depend on number of active channels e.g.
1103  * 2 channels (ch0 and ch4) active = 2 * (3 Bytes) + (2 Bytes frame counter) = 8 Bytes
1104  *
1105  * @endverbatim
1106  */
1107 static uint8_t channel_value_decode(IRPyro_sensor_device_type* this_device)
1108 {
1109  uint8_t bytes_to_read = 0;
1110  uint8_t ch_saturated = 0;
1111 
1112  // for number of active channels
1113  uint8_t channels_to_decode = 5;
1114  uint8_t channel_in_process = 0;
1115  uint8_t update_number_of_active_channels = 0;
1116  uint8_t channel_array[5] = {0};
1117  uint8_t channel_array_index = 0;
1118 
1119  do
1120  {
1121  if(this_device->CCP_register[channel_in_process].status_bit)
1122  {
1123  channel_array[channel_array_index] = channel_in_process;
1124  ++ update_number_of_active_channels;
1125  ++ channel_array_index;
1126  }
1127  -- channels_to_decode;
1128  ++ channel_in_process;
1129  }
1130  while (channels_to_decode);
1131 
1132  this_device->number_of_active_channels = update_number_of_active_channels;
1133  bytes_to_read = IRPyro_BYTES_PER_CHANNEL * this_device->number_of_active_channels + IRPyro_BYTES_FRAME_COUNT; // IRPyro_DATA_SIZE;
1134  for(uint8_t current_channel=0; current_channel<this_device->number_of_active_channels; ++current_channel)
1135  {
1136  // decode the value of the channel
1137  uint8_t ch_data_pos;
1138  uint8_t final_data_location;
1139  ch_data_pos = (current_channel*IRPyro_BYTES_PER_CHANNEL);
1140  final_data_location = channel_array[current_channel];
1141 
1142  this_device->channel_value[final_data_location] = (this_device->raw_data[ch_data_pos]<<16) + (this_device->raw_data[ch_data_pos+1]<<8) + this_device->raw_data[ch_data_pos+2];
1143  ch_saturated += (this_device->channel_value[final_data_location] & IRPyro_CHANNEL_SAT) >> (23 - current_channel);
1144  }
1145 
1146  this_device->channel_value[IRPyro_FRAME_COUNT_LOCATION] = (this_device->raw_data[bytes_to_read - IRPyro_FRAME_COUNT_TOP_BYTE] << IRPyro_SHIFT_TO_MSB) + this_device->raw_data[bytes_to_read- IRPyro_FRAME_COUNT_LOW_BYTE];
1147  this_device->channel_saturation_byte = ch_saturated;
1148  return 1;
1149 }
1150 /**
1151  * @brief Checks if the AFE register is empty
1152  * @param first AFE register
1153  * @retval result_empty 1 empty / 0 not empty
1154  */
1155 static uint8_t AFE_register_empty(AFE_reg_type first)
1156 {
1157  uint8_t i = 0, result_empty = 0;
1158  uint8_t *AFE_pointer_one = &(first.S7_S0);
1159  uint8_t AFE_size = sizeof(first);
1160 
1161  while (i<AFE_size)
1162  {
1163  result_empty +=AFE_pointer_one[i];
1164  ++i;
1165  }
1166  return (result_empty == 0 ?1:0);
1167 }
1168 /**
1169  * @brief Checks if the CCP register is empty
1170  * @param first CCP register
1171  * @retval result_empty 1 empty / 0 not empty
1172  */
1173 static uint8_t CCP_register_empty(CCP_reg_type first)
1174 {
1175  uint8_t i = 0, result_empty = 0;
1176  uint8_t *CCP_pointer_one = &(first.Feedback_cap);
1177  uint8_t CCP_size = sizeof(first);
1178 
1179  while (i<CCP_size)
1180  {
1181  result_empty +=CCP_pointer_one[i];
1182  ++i;
1183  }
1184  return (result_empty == 0 ?1:0);
1185 }
1186 /**
1187  * @brief Checks if the AFE register is empty
1188  * @param first First AFE
1189  * @retval result_empty 1 empty / 0 not empty
1190  */
1191 static uint8_t WUP_register_empty(WUP_reg_type first)
1192 {
1193  uint8_t i = 0, result_empty = 0;
1194  uint8_t *WUP_pointer_one = &(first.UHT);
1195  uint8_t WUP_size = sizeof(first);
1196 
1197  while (i<WUP_size)
1198  {
1199  result_empty +=WUP_pointer_one[i];
1200  ++i;
1201  }
1202  return (result_empty == 0 ?1:0);
1203 }
1204 /**
1205  * @brief Checksum string for the IRPyro API
1206  */
1207 struct notice
1209  char IRPyro_API_notice[35];
1210 };
1211 static struct notice IRPyro_checksum(void)
1212 {
1213  struct notice legend = {0x43 ,0x6f ,0x70 ,0x79 ,0x72 ,0x69 ,0x67 ,0x68 ,0x74 ,0x20 ,0x28 ,0x63 ,0x29 ,0x20 ,0x32 ,0x30 ,0x31 ,0x38 ,0x20 ,0x50 ,0x79 ,0x72 ,0x65 ,0x6f ,0x73 ,0x2c ,0x20 ,0x4c ,0x74 ,0x64 ,0x2e};
1214  return legend;
1215 }
1216 /** end of Support functions
1217  * @}
1218  */
1219 /** end of IRPyro Single Device Layer
1220  * @}
1221  */
1222 /** end of IRPyro_API
1223  * @}
1224  */
1225 
1226 /* ********** Copyright (c) 2018 _KEMET, Ltd. **********END OF FILE************/
#define IRPyro_FRAME_COUNT_LOCATION
#define IRPyro_FIFO_RESET_OK
#define IRPyro_FIFO_WAKE_MASK
uint8_t CS_Port
CS (Chip select) port.
static uint8_t WUP_register_empty(WUP_reg_type first)
Checks if the AFE register is empty.
uint8_t ST
Sleep_mode_type.
CCP_filter_type CCP_High_pass[IRPyro_CCP_NUMBER_OF_REGISTERS]
High pass filter configuration for each channel on the IRPyro device.
static uint8_t I2C_address_set(IRPyro_sensor_device_type *this_device)
Sends new I2C address to the IRPyro sensor Default i2c address is 0x65, if multiple devices are being...
#define IRPyro_WAKE_UP
power_settings_type normal_power
normal power configuration
static uint8_t AFE_read(IRPyro_sensor_device_type *this_device, AFE_reg_type *AFE_data)
reads the AFE register on the IRPyro and loads into this_device
WUP_reg_type WUP_register
WUP (Wake Up) configuration register.
uint8_t i2c_Write(uint8_t DeviceAddr, uint8_t Command, uint8_t *pBuffer, uint8_t len)
Sends data via I2C port.
uint8_t Feedback_transconductance
Charge amp. trans-conductance selection.
#define NORMAL_POWER_INIT_DEFAULT(X)
void power_set(uint8_t port, uint8_t pin)
Power sequence from the MCU to the IRPyro sensor.
#define WUP_INIT_DEFAULT(X)
#define IRPyro_DEFAULT_I2C
static uint8_t CCP_register_empty(CCP_reg_type first)
Checks if the CCP register is empty.
uint8_t C_LP
Low pass selection.
static uint8_t IRPyro_power_mode_wakeup_set(IRPyro_sensor_device_type *this_device)
The device will automatically enter either low power or normal power sleep mode depending in the powe...
#define IRPyro_ADDR_WRITE
Checksum string for the IRPyro API.
#define IRPyro_FIFO_CLEAR_OK
IRPyro device structure definition
uint32_t channel_value[IRPyro_CHANNEL_DATA_VALUES]
Active frame decoded channel data.
#define IRPyro_FIFO_COUNT_MASK
uint8_t IRPyro_open(IRPyro_sensor_device_type *this_device)
Initializes the IRPyro device.
static void WUP_to_bytes(WUP_reg_type WUP_register, uint8_t *WUP_byte)
encodes the WUP register contents of this_device into the IRPyro
uint8_t C_LP
Low pass filter selection.
uint8_t COUNT
Number of frames available.
IRPyro Channel Control Package register structure definition
#define IRPyro_FIFO_CLEAR
IRPyro data structures and prototype functions
CCP_reg_type CCP_register[IRPyro_CCP_NUMBER_OF_REGISTERS]
Channel configuration registers 0 - 4.
#define IRPyro_RESET_FULL
#define IRPyro_CCP_SIZE
uint8_t address
I2C address in 7 bit format.
uint8_t CLK_OUT
1 enable internal clock output on Clk pin, 0 disable internal clock output on the Clk pin (only apply...
static uint8_t AFE_init(IRPyro_sensor_device_type *this_device)
Initializes the AFE register with this_device values.
#define IRPyro_RESET_FULL_OK
static void bytes_to_WUP(uint8_t *WUP_bytes, WUP_reg_type *WUP_register)
decodes the WUP register of the IRPyro into this_device
static uint8_t CCP_read(IRPyro_sensor_device_type *this_device, CCP_reg_type *CCP_data)
reads the CCP registers on the IRPyro and loads into this_device
uint8_t number_of_active_channels
useful for read()
static uint8_t CCP_write(IRPyro_sensor_device_type *this_device)
writes the CCP registers contents of this_device into the IRPyro
static uint8_t CCP_init(IRPyro_sensor_device_type *this_device)
Initializes the CCP register with this_device values.
uint8_t UHT
Byte 0 to 3 (Upper and Lower thresholds) are the 8 MSB of channel ADC data (unsigned value)...
uint8_t IRPyro_ioctl(IRPyro_sensor_device_type *this_device, IRPyro_cmd_type *cmd, IRPyro_arg_type arg)
access to IRPyro registers
#define IRPyro_GO_TO_SLEEP_OK
FIFO_reg_type FIFO_register
FIFO status register.
uint8_t STATUS_CODE
response to read operation: 00 no error, 01 fifo full, 10 i2c master read less, 11 i2c master read mo...
uint8_t S7_S0
Sampling rate (8 bit) :Sampling Rate = 1000/(N+1).
static uint8_t WUP_write(IRPyro_sensor_device_type *this_device)
writes the WUP register contents of this_device into the IRPyro
#define LOW_POWER_INIT_DEFAULT(X)
uint8_t S7_S0
sample rate value
uint8_t CH0_CH2
Selected channel coding.
#define IRPyro_SHIFT_ONE
#define IRPyro_FIFO_STATUS
uint8_t High_pass_filter_setting
High pass selection.
void Micro_controller_delay_ms(uint32_t time_ms)
Example of delay function.
#define IRPyro_AFE_READ
static uint8_t AFE_register_empty(AFE_reg_type first)
Checks if the AFE register is empty.
static uint8_t WUP_init(IRPyro_sensor_device_type *this_device)
Initializes the WUP register with this_device values.
#define IRPyro_FIFO_STATUS_SIZE
uint8_t Feedback_cap
Feedback capacitor selection.
power_settings_type low_power
low power configuration
uint8_t TEMP
0 Normal channel data, 1 temperature data (apply to channel 0 only). When this bit is set...
#define INT_ENABLE
static void bytes_to_CCP(uint8_t CCP_byte, CCP_reg_type *CCP_register)
decodes the CCP register of the IRPyro into this_device
IRPyro Wake Up Package register structure definition
Product and component names and versions.
uint8_t status_bit
Status bit : Active (1) / Disable (0)
#define IRPyro_SHIFT_TO_MSB
static uint8_t WUP_read(IRPyro_sensor_device_type *this_device, WUP_reg_type *WUP_data)
reads the WUP register on the IRPyro and loads into this_device
static uint8_t FIFO_ready_status_get(IRPyro_sensor_device_type *this_device)
Ask the IRPyro if a frame of data is available used when a polling reading operation has started...
IRPyro Analog Front End (AFE) register structure definition
uint8_t i2c_Read(uint8_t DeviceAddr, uint8_t Command, uint8_t *pBuffer, uint16_t len)
Reads data via I2C port.
#define IRPyro_AFE_WRITE
#define IRPyro_FIFO_INT_MASK
#define IRPyro_TEST_OK
static uint8_t IRPyro_power_mode_low_set(IRPyro_sensor_device_type *this_device)
activates the low power mode settings stored on the IRPyro structure
void Micro_controller_delay_us(uint32_t time_us)
Example of delay function in micro seconds. Refer to section "12.8 Device Power Up and Reset" in the ...
uint8_t IRPyro_read(IRPyro_sensor_device_type *this_device)
Reads a frame of data from the IRPyro.
#define IRPyro_WUP_SIZE
uint8_t DATA_READY
Data ready.
uint8_t IRPyro_close(IRPyro_sensor_device_type *this_device)
Stops streaming, deallocates memory and disable the IRPyro sensor.
#define IRPyro_FIFO_RESET
uint8_t SYNC
Sync & Clk Pin option: 0 master, 1 slave.
#define IRPyro_BYTES_FRAME_COUNT
uint8_t read_mode
interrupt (0), polled (1) or synchronized sampling (2)
uint8_t channel
selected channel
#define IRPyro_CCP_READ
#define IRPyro_GO_TO_SLEEP
#define AFE_INIT_DEFAULT(X)
IRPyro command argument
#define CCP_INIT_DEFAULT(X)
#define IRPyro_FIFO_READ_ACTIVE
#define IRPyro_FIFO_ERROR_MASK
WUP_reg_type WUP_register
WUP (Wake Up) configuration register.
#define IRPyro_TEST
uint8_t DP0_DP2
Reference channel coding DP0-DP2: The Reference channel coding, and CH0-CH2: the selected channel cod...
static uint8_t IRPyro_test(IRPyro_sensor_device_type *this_device)
Sends test code to the IRPyro sensor to confirm is there.
#define IRPyro_CCP_WRITE
#define IRPyro_FRAME_COUNT_LOW_BYTE
#define IRPyro_AFE_SIZE
#define IRPyro_WUP_WRITE
static struct notice IRPyro_checksum(void)
static uint8_t IRPyro_power_mode_normal_set(IRPyro_sensor_device_type *this_device)
activates the normal power mode settings stored on the IRPyro structure
static void bytes_to_AFE(uint8_t *AFE_bytes, AFE_reg_type *AFE_register)
decodes the AFE register of the IRPyro into this_device
uint8_t WT_Threshold
Byte 4 is the number of samples required to trigger the wake up algorithm. ? UHT and ULT to detect po...
uint8_t channel_saturation_byte
Active frame saturation byte.
#define IRPyro_WUP_READ
uint8_t INT
Interrupt output: 1 Enable, 0 Disable (only apply at normal operation and not in Sleep mode)...
uint8_t INT_pin_read(uint8_t port, uint8_t pin)
Reads the status of the pin assigned to the INT line of IRPyro.
static uint8_t FIFO_reset(IRPyro_sensor_device_type *this_device)
Clear the entire FIFO (Rd/Wr pointer reset with the Empty)
uint8_t raw_data[IRPyro_DATA_SIZE]
static uint8_t channel_value_decode(IRPyro_sensor_device_type *this_device)
Decodes the channel values on a given frame.
static void AFE_to_bytes(AFE_reg_type AFE_register, uint8_t *AFE_byte)
encodes the AFE register contents of this_device into the IRPyro
void CS_pin_set(uint8_t port, uint8_t pin, uint8_t value)
ON/OFF control from the MCU to the IRPyro sensor.
uint8_t HP
Enable high pass filter: 1 Enable, 0 Disable. this is the enable trigger which needs to be set after ...
AFE_reg_type AFE_register
AFE (analog front end) configuration register.
static uint8_t FIFO_data_active_get(IRPyro_sensor_device_type *this_device)
Read data packet (up to 17 bytes) for only active channel.
static uint8_t AFE_write(IRPyro_sensor_device_type *this_device)
writes the AFE register contents of this_device into the IRPyro
uint8_t INT_Port
INT (Interrupt / Data Ready ) port.
uint8_t cmd_return_code
command result
#define IRPyro_BYTES_PER_CHANNEL
uint8_t High_pass_filter_setting
High pass selection.
uint8_t LP
Enable low power mode: 1 Enable, 0 Disable.
#define IRPyro_FRAME_COUNT_TOP_BYTE
static uint8_t IRPyro_power_settings_init(IRPyro_sensor_device_type *this_device)
initializes with defaults the power settings of an IRPyro device
#define IRPyro_CHANNEL_SAT
static void CCP_to_bytes(CCP_reg_type CCP_register, uint8_t *CCP_byte)
encodes the CCP register contents of this_device into IRPyro
CCP_reg_type CCP_register[IRPyro_CCP_NUMBER_OF_REGISTERS]
Channel configuration register.
IRPyro_command_type cmd
command
static uint8_t IRPyro_power_mode_sleep_set(IRPyro_sensor_device_type *this_device)
The device will automatically enter either low power or normal power sleep mode depending in the powe...
AFE_reg_type AFE_register
AFE (analog front end) configuration register.
#define IRPyro_SHIFT_FOUR