SI117XDRV  0.1
si117xdrv.c
Go to the documentation of this file.
1 /***************************************************************************/
19 #include "si117xdrv.h"
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include "si117xdrv_config.h"
23 #include "si117x_functions.h"
24 
25 
26 
27 #define MEASCOUNT_LSB 20000 //20khz or 50us
28 #define MEASRATE_MIN 3
29 #define MEASRATE_MAX 0xffff
30 #define MEASCOUNT_MAX 0xff
31 
32 #define PPG_OFFSET 7
33 
34 /***************************************************************************/
38 typedef struct
40 {
42  void *user;
43  bool allocated;
45 
46 
47 //todo: generic DLE callback where the user can register for a given DLE byte
48 
50 typedef struct
51 {
53  void *user;
54  bool allocated;
56 
58 typedef struct
59 {
60  SI117XDRV_CallbackData_t preStartCallbacks[SI117XDRV_MAX_NUM_CALLBACKS];
61  SI117XDRV_CallbackData_t postStartCallbacks[SI117XDRV_MAX_NUM_CALLBACKS];
62  SI117XDRV_CallbackData_t preFifoFlushCallbacks[SI117XDRV_MAX_NUM_CALLBACKS];
63  SI117XDRV_CallbackData_t postFifoFlushCallbacks[SI117XDRV_MAX_NUM_CALLBACKS];
64  SI117XDRV_AccelCallbackData_t accelSyncRecvCallbacks[SI117XDRV_MAX_NUM_CALLBACKS]; //todo: does it makes sense to have a pre and post Stop Callback?
66 
67 
68 typedef struct {
69  uint8_t taskEnable;
70  uint16_t measrate;
71  uint16_t fifo_int_level;
72  uint8_t meas_cntl;
73  uint8_t synch_config;
74  uint8_t input_freq_sel;
75  uint8_t irq_enable;
77 
78 typedef struct {
79  uint8_t ecg_meascount;
80  uint8_t ecg_measconfig;
81  uint8_t ecg_adcconfig;
82  uint8_t ecg_feconfig;
83  uint8_t ecg_threshold;
84  uint8_t ecg_ld_meascount;
85  uint8_t ecg_ldconfig;
87 
88 typedef struct
89 {
90  uint8_t bioz_control1;
91  uint8_t bioz_control2;
92  uint8_t bioz_fe_gain1;
93  uint8_t bioz_fe_gain2;
94  uint8_t bioz_fe_mux;
96 
97 typedef struct
98 {
99  uint8_t ppg_led1_config;
100  uint8_t ppg_led2_config;
101  uint8_t ppg_led3_config;
102  uint8_t ppg_led4_config;
103  uint8_t ppg_mode;
104  uint8_t ppg_measconfig;
105  uint8_t ppg_adcconfig;
107 
108 typedef struct
109 {
110  uint8_t ppg_meascount;
111  uint8_t ppg4_threshold;
114 
115 
116 typedef struct
117 {
118  SI117XDRV_BIOZChannelRegisters_t biozConfig[2];
119  uint8_t bioz_meascount;
120  uint8_t bioz_dc_value;
122 
123 typedef struct
124 {
125  SI117XDRV_GlobalRegisters_t globalCfg;
130 
131 typedef struct
132 {
133  uint8_t partNumber;
134  uint8_t hrmOversamplingRatio; //HRM expects 25Hz
135  bool running;
136  uint8_t savedTasks;
137  uint8_t irqSave;
138  uint16_t savedMeasrate;
139  uint8_t savedPPG_meascount;
140  uint8_t savedECG_meascount;
142 
143 typedef struct
144 {
145  HANDLE deviceHandle;
146  SI117XDRV_DeviceRegisters_t deviceCfg;
147  SI117XDRV_DeviceStatus_t deviceStatus;
149 
150 /***************************************************************************/
154 static SI117XDRV_Device_t devices[ SI117XDRV_MAX_NUM_DEVICES ];
155 static SI117XDRV_Callbacks_t callbacks[ SI117XDRV_MAX_NUM_DEVICES ]; //todo: why dont we put callbacks, leadDetectionFlag, ect inside the device struct if they are associated with a device
156 static bool leadDetectionFlag [SI117XDRV_MAX_NUM_DEVICES];
157 static bool wristDetectionFlag [SI117XDRV_MAX_NUM_DEVICES];
158 static bool leadDetect[SI117XDRV_MAX_NUM_DEVICES];
159 
160 static int initFlag[SI117XDRV_MAX_NUM_DEVICES] = { 0 }; // all elements 0, cannot put this in device struct because it must be initilaized
161 
162 /***************************************************************************/
165 static void accelSyncCallbacks (SI117XDRV_DeviceSelect_t device, uint16_t ppg_count)
166 {
167  int i;
168  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
169  {
170  if (callbacks[device].accelSyncRecvCallbacks[i].allocated)
171  {
172  callbacks[device].accelSyncRecvCallbacks[i].callback(device,ppg_count,callbacks[device].accelSyncRecvCallbacks[i].user);
173  }
174  }
175 }
176 
177 static void preStartCallbacks (SI117XDRV_DeviceSelect_t device)
178 {
179  int i;
180  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
181  {
182  if (callbacks[device].preStartCallbacks[i].allocated)
183  {
184  callbacks[device].preStartCallbacks[i].callback(device,callbacks[device].preStartCallbacks[i].user);
185  }
186  }
187 }
188 
189 static void postStartCallbacks (SI117XDRV_DeviceSelect_t device)
190 {
191  int i;
192  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
193  {
194  if (callbacks[device].postStartCallbacks[i].allocated)
195  {
196  callbacks[device].postStartCallbacks[i].callback(device,callbacks[device].postStartCallbacks[i].user);
197  }
198  }
199 }
200 static void preFifoFlushCallbacks (SI117XDRV_DeviceSelect_t device)
201 {
202  int i;
203  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
204  {
205  if (callbacks[device].preFifoFlushCallbacks[i].allocated)
206  {
207  callbacks[device].preFifoFlushCallbacks[i].callback(device,callbacks[device].preFifoFlushCallbacks[i].user);
208  }
209  }
210 }
211 static void postFifoFlushCallbacks (SI117XDRV_DeviceSelect_t device)
212 {
213  int i;
214  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
215  {
216  if (callbacks[device].postFifoFlushCallbacks[i].allocated)
217  {
218  callbacks[device].postFifoFlushCallbacks[i].callback(device,callbacks[device].postFifoFlushCallbacks[i].user);
219  }
220  }
221 }
222 /***************************************************************************/
232 {
233  preFifoFlushCallbacks(device);
234  Si117xFlushFIFO(devices[device].deviceHandle);
235  postFifoFlushCallbacks(device);
236  return ECODE_SI117XDRV_OK;
237 }
238 
239 
240 /***************************************************************************/
250 {
251  int i;
252  uint8_t retval;
253  //devices[device].deviceHandle = NULL;
254  if (initFlag[device] != 1)
255  {
257  }
258  devices[device].deviceStatus.running = false;
259  devices[device].deviceStatus.savedTasks = 0;
260  devices[device].deviceStatus.hrmOversamplingRatio = 1;
261  devices[device].deviceStatus.partNumber = 0x70;
262  devices[device].deviceCfg.globalCfg.fifo_int_level = 0x100;
263  devices[device].deviceCfg.globalCfg.meas_cntl = 0x4;
264  devices[device].deviceCfg.globalCfg.measrate = 0x320;
265  devices[device].deviceCfg.globalCfg.synch_config = 0;
266  devices[device].deviceCfg.globalCfg.input_freq_sel = 0;
267  devices[device].deviceCfg.globalCfg.taskEnable = 0; //todo: 0
268  devices[device].deviceCfg.ppgCfg.ppg4_threshold = 0;
269  devices[device].deviceCfg.ppgCfg.ppg_meascount = 1;
270  devices[device].deviceCfg.globalCfg.irq_enable = 0;
271  for (i=0;i<4;i++)
272  {
273  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_mode = 0xf;
274  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_adcconfig = 0x30;
275  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led1_config = 0;
276  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led2_config = 0;
277  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led3_config = 0;
278  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led4_config = 0;
279  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_measconfig = 3;
280  }
281  devices[device].deviceCfg.ecgCfg.ecg_adcconfig = 0x8;
282  devices[device].deviceCfg.ecgCfg.ecg_feconfig = 0;
283  devices[device].deviceCfg.ecgCfg.ecg_ld_meascount = 0;
284  devices[device].deviceCfg.ecgCfg.ecg_ldconfig = 0;
285  devices[device].deviceCfg.ecgCfg.ecg_measconfig = 0;
286  devices[device].deviceCfg.ecgCfg.ecg_meascount = 0;
287  devices[device].deviceCfg.ecgCfg.ecg_threshold = 0;
288  devices[device].deviceCfg.biozCfg.bioz_dc_value = 0;
289  devices[device].deviceCfg.biozCfg.bioz_meascount = 0;
290  for (i=0;i<2;i++)
291  {
292  devices[device].deviceCfg.biozCfg.biozConfig[i].bioz_control1 = 0;
293  devices[device].deviceCfg.biozCfg.biozConfig[i].bioz_control2 = 0;
294  devices[device].deviceCfg.biozCfg.biozConfig[i].bioz_fe_gain1 = 0;
295  devices[device].deviceCfg.biozCfg.biozConfig[i].bioz_fe_gain2 = 0;
296  devices[device].deviceCfg.biozCfg.biozConfig[i].bioz_fe_mux = 0;
297  }
298  //reset part, send hw_key, read part id,
299  leadDetect[device] = false;
300  leadDetectionFlag[device]=false;
301  wristDetectionFlag[device]=false;
302  retval = Si117xReset(devices[device].deviceHandle);
303  retval += Si117xWriteToRegister(devices[device].deviceHandle, REG_HW_KEY, 0x00); // Set HW_KEY to 0
304  Si117xReadFromRegister (devices[device].deviceHandle, REG_HW_KEY); // Read back HW_KEY to check
305  devices[device].deviceStatus.partNumber = Si117xReadFromRegister (devices[device].deviceHandle, REG_PART_ID); // Read part id
306  //detect device
307  return ECODE_SI117XDRV_OK;
308 }
309 
310 
311 /***************************************************************************/
322 Si117x_Ecode_t SI117XDRV_GetPartInfo (SI117XDRV_DeviceSelect_t device, uint8_t *id, uint8_t *rev, uint8_t *mfr_id, uint8_t *pkg_led_cfg) //todo: create enums for these values
323 {
324  if (initFlag[device] != 1)
325  {
327  }
328  *id = devices[device].deviceStatus.partNumber;
329  *rev = Si117xReadFromRegister (devices[device].deviceHandle, REG_REV_ID);
330  *mfr_id = Si117xReadFromRegister (devices[device].deviceHandle, REG_MFR_ID) >> 5;
331  *pkg_led_cfg = Si117xReadFromRegister (devices[device].deviceHandle, REG_MFR_ID) & 0x1F;
332  return ECODE_SI117XDRV_OK;
333 }
334 
335 /***************************************************************************/
347 {
348  *fifo_int_level = devices[device].deviceCfg.globalCfg.fifo_int_level;
349  return ECODE_SI117XDRV_OK;
350 }
351 
352 /***************************************************************************/
364 {
365  if (initFlag[device] != 1)
366  {
368  }
369  if (devices[device].deviceStatus.running)
370  {
372  }
373  devices[device].deviceCfg.ecgCfg.ecg_adcconfig = ecgCfg->ecg_adcconfig;
374  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_ADCCONFIG,ecgCfg->ecg_adcconfig);
375  devices[device].deviceCfg.ecgCfg.ecg_measconfig = ecgCfg->ecg_measconfig;
376  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCONFIG,ecgCfg->ecg_measconfig);
377  devices[device].deviceCfg.ecgCfg.ecg_feconfig = ecgCfg->ecg_feconfig;
378  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_FECONFIG,ecgCfg->ecg_feconfig);
379  return ECODE_SI117XDRV_OK;
380 }
381 
382 /***************************************************************************/
394 {
395  if (initFlag[device] != 1)
396  {
398  }
399  if (devices[device].deviceStatus.running)
400  {
402  }
403  devices[device].deviceCfg.ecgCfg.ecg_threshold = ecgCfg->ecg_threshold;
404  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_THRESHOLD,ecgCfg->ecg_threshold);
405  devices[device].deviceCfg.ecgCfg.ecg_ldconfig = ecgCfg->ecg_ldconfig;
406  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_LDCONFIG,ecgCfg->ecg_ldconfig);
407  devices[device].deviceCfg.globalCfg.input_freq_sel = (ecgCfg->ecg_ld_freq_sel<<4) | (devices[device].deviceCfg.globalCfg.input_freq_sel&0xf);
408  Si117xParamSet(devices[device].deviceHandle,PARAM_INPUT_FREQ_SEL,devices[device].deviceCfg.globalCfg.input_freq_sel);
409  return ECODE_SI117XDRV_OK;
410 }
411 /***************************************************************************/
423 {
424  int i;
425  if (initFlag[device] != 1)
426  {
428  }
429  if (devices[device].deviceStatus.running)
430  {
432  }
433  devices[device].deviceCfg.ppgCfg.ppg4_threshold = ppgCfg->ppg4_threshold;
434  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG4_THRESHOLD,ppgCfg->ppg4_threshold);
435  for (i=0;i<4;i++)
436  {
437  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_adcconfig = ppgCfg->ppgCfg[i].ppg_adcconfig;
438  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_ADCCONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_adcconfig);
439  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_measconfig = ppgCfg->ppgCfg[i].ppg_measconfig;
440  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_MEASCONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_measconfig);
441  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_mode = ppgCfg->ppgCfg[i].ppg_mode;
442  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_MODE+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_mode);
443  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led1_config = ppgCfg->ppgCfg[i].ppg_led1_config;
444  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_LED1_CONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_led1_config);
445  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led2_config = ppgCfg->ppgCfg[i].ppg_led2_config;
446  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_LED2_CONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_led2_config);
447  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led3_config = ppgCfg->ppgCfg[i].ppg_led3_config;
448  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_LED3_CONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_led3_config);
449  devices[device].deviceCfg.ppgCfg.ppgCfg[i].ppg_led4_config = ppgCfg->ppgCfg[i].ppg_led4_config;
450  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG1_LED4_CONFIG+i*PPG_OFFSET,ppgCfg->ppgCfg[i].ppg_led4_config);
451  }
452  return ECODE_SI117XDRV_OK;
453 }
454 
455 /***************************************************************************/
466 Si117x_Ecode_t SI117XDRV_SetPPGTaskEnable (SI117XDRV_DeviceSelect_t device, uint8_t ppgTasks) //returns an error if device is currently running
467 {
468  int8_t retval;
469  if (initFlag[device] != 1)
470  {
472  }
473  if (devices[device].deviceStatus.running)
474  {
476  }
477  devices[device].deviceCfg.globalCfg.taskEnable = devices[device].deviceCfg.globalCfg.taskEnable&0xf0;
478  devices[device].deviceCfg.globalCfg.taskEnable |= ppgTasks&0xf;
479  retval = Si117xParamSet(devices[device].deviceHandle,PARAM_TASK_ENABLE,devices[device].deviceCfg.globalCfg.taskEnable);
480  return ECODE_SI117XDRV_OK;
481 }
482 
483 
484 /***************************************************************************/
496 {
497  int8_t retval;
498  if (initFlag[device] != 1)
499  {
501  }
502  if (devices[device].deviceStatus.running)
503  {
505  }
506  devices[device].deviceCfg.globalCfg.taskEnable = devices[device].deviceCfg.globalCfg.taskEnable&0x3F;
507  devices[device].deviceCfg.globalCfg.taskEnable |= ecgTasks&0xc0;
508  retval = Si117xParamSet(devices[device].deviceHandle,PARAM_TASK_ENABLE,devices[device].deviceCfg.globalCfg.taskEnable);
509  return ECODE_SI117XDRV_OK;
510 }
511 
512 /***************************************************************************/
524 {
525  int8_t retval;
526  if (initFlag[device] != 1)
527  {
529  }
530  devices[device].deviceCfg.globalCfg.irq_enable = devices[device].deviceCfg.globalCfg.irq_enable & ~(0x1);
531  if (enable)
532  {
533  devices[device].deviceCfg.globalCfg.irq_enable |= 0x1;
534  }
535  //retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, devices[device].deviceCfg.globalCfg.irq_enable);
536  return ECODE_SI117XDRV_OK;
537 }
538 
539 /***************************************************************************/
551 {
552  int8_t retval;
553  if (initFlag[device] != 1)
554  {
556  }
557  devices[device].deviceCfg.globalCfg.irq_enable = devices[device].deviceCfg.globalCfg.irq_enable & ~(0x2);
558  if (enable)
559  {
560  devices[device].deviceCfg.globalCfg.irq_enable |= 0x2;
561  }
562  //retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, devices[device].deviceCfg.globalCfg.irq_enable);
563  return ECODE_SI117XDRV_OK;
564 }
565 
566 /***************************************************************************/
578 {
579  int8_t retval;
580  if (initFlag[device] != 1)
581  {
583  }
584  devices[device].deviceCfg.globalCfg.irq_enable = devices[device].deviceCfg.globalCfg.irq_enable & ~(0x8);
585  if (enable)
586  {
587  devices[device].deviceCfg.globalCfg.irq_enable |= 0x8;
588  }
589  //retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, devices[device].deviceCfg.globalCfg.irq_enable);
590  return ECODE_SI117XDRV_OK;
591 }
592 
593 /***************************************************************************/
605 {
606  int8_t retval;
607  if (initFlag[device] != 1)
608  {
610  }
611  devices[device].deviceCfg.globalCfg.irq_enable = devices[device].deviceCfg.globalCfg.irq_enable & ~(0x4);
612  if (enable)
613  {
614  devices[device].deviceCfg.globalCfg.irq_enable |= 0x4;
615  }
616  //retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, devices[device].deviceCfg.globalCfg.irq_enable);
617  return ECODE_SI117XDRV_OK;
618 }
619 
620 
621 /***************************************************************************/
636 Si117x_Ecode_t SI117XDRV_StartLegacyPPG (SI117XDRV_DeviceSelect_t device, uint8_t ppg_meascount, uint16_t measrate) //used with HRM algorithm (required for DC sense)
637 {
638  uint8_t retval;
639  if (initFlag[device] != 1)
640  {
642  }
643  if (devices[device].deviceStatus.running)
644  {
646  }
647  //move anything other than ppg to pendingTasks
648  devices[device].deviceStatus.savedTasks = devices[device].deviceCfg.globalCfg.taskEnable;
649  devices[device].deviceStatus.irqSave = devices[device].deviceCfg.globalCfg.irq_enable;
650  devices[device].deviceStatus.savedMeasrate = devices[device].deviceCfg.globalCfg.measrate;
651  devices[device].deviceStatus.savedPPG_meascount = devices[device].deviceCfg.ppgCfg.ppg_meascount;
652  //devices[device].deviceStatus.savedECG_meascount = devices[device].deviceCfg.ecgCfg.ecg_meascount;
653  devices[device].deviceCfg.globalCfg.taskEnable = devices[device].deviceCfg.globalCfg.taskEnable & 0xf;
654  devices[device].deviceCfg.globalCfg.irq_enable = (SI117XDRV_IRQ_EN_FIFO+SI117XDRV_IRQ_EN_PPG1);
655  Si117xParamSet(devices[device].deviceHandle,PARAM_TASK_ENABLE,devices[device].deviceCfg.globalCfg.taskEnable);
656  //switch to new rate
657  //Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,0);
658  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,ppg_meascount);
659  Si117xParamSet(devices[device].deviceHandle, PARAM_MEASRATE_L, (measrate & 0xff));
660  Si117xParamSet(devices[device].deviceHandle, PARAM_MEASRATE_H, (measrate & 0xff00)>>8);
662  preStartCallbacks(device);
663 
664  retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, (SI117XDRV_IRQ_EN_FIFO+SI117XDRV_IRQ_EN_PPG1));
665  SI117XDRV_FifoFlush(device);
666  Si117xStart(devices[device].deviceHandle);
667  devices[device].deviceStatus.running = true;
668  postStartCallbacks(device);
669  return ECODE_SI117XDRV_OK;
670 
671 }
672 
673 /***************************************************************************/
683 {
684  //restore ppg meascounts, measrate, and irqenable etc to previous state...
685  uint8_t retval;
686  if (initFlag[device] != 1)
687  {
689  }
690  if (devices[device].deviceStatus.running == false)
691  {
693  }
694  SI117XDRV_Stop(device);
695  devices[device].deviceCfg.globalCfg.taskEnable = devices[device].deviceStatus.savedTasks;
696  devices[device].deviceCfg.globalCfg.irq_enable = devices[device].deviceStatus.irqSave;
697  devices[device].deviceCfg.globalCfg.measrate = devices[device].deviceStatus.savedMeasrate;
698  devices[device].deviceCfg.ppgCfg.ppg_meascount = devices[device].deviceStatus.savedPPG_meascount;
699  //devices[device].deviceCfg.ecgCfg.ecg_meascount = devices[device].deviceStatus.savedECG_meascount;
700  //Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,devices[device].deviceStatus.savedECG_meascount);
701  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,devices[device].deviceStatus.savedPPG_meascount);
702  Si117xParamSet(devices[device].deviceHandle, PARAM_MEASRATE_L, (devices[device].deviceStatus.savedMeasrate & 0xff));
703  Si117xParamSet(devices[device].deviceHandle, PARAM_MEASRATE_H, (devices[device].deviceStatus.savedMeasrate & 0xff00)>>8);
704  Si117xParamSet(devices[device].deviceHandle,PARAM_TASK_ENABLE,devices[device].deviceStatus.savedTasks);
705  retval = Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, 0);
706  devices[device].deviceStatus.running = false;
707  return ECODE_SI117XDRV_OK;
708 }
709 
710 /***************************************************************************/
720 {
721  if (initFlag[device] != 1)
722  {
724  }
725  if (devices[device].deviceStatus.running == false)
726  {
728  }
729  Si117xStop(devices[device].deviceHandle,0);
730 
731  Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE,0);
732  devices[device].deviceStatus.running = false;
733  return ECODE_SI117XDRV_OK;
734 }
735 
736 /***************************************************************************/
746 {
747  if (initFlag[device] != 1)
748  {
750  }
751  if (devices[device].deviceStatus.running)
752  {
754  }
755  preStartCallbacks(device);
757  Si117xWriteToRegister (devices[device].deviceHandle, REG_IRQ_ENABLE, devices[device].deviceCfg.globalCfg.irq_enable);
758  SI117XDRV_FifoFlush(device);
759  Si117xStart(devices[device].deviceHandle);
760  devices[device].deviceStatus.running = true;
761  postStartCallbacks(device);
762  return ECODE_SI117XDRV_OK;
763 }
764 
765 
766 static bool findMeasRate (uint16_t freqDivider, uint16_t *measrate, uint8_t *meascount, uint32_t accelSyncus)
767 {
768  int i,j;
769  bool foundVal=false;
770  //maximize measrate
771  *meascount = 1;
772  *measrate = freqDivider;
773  return true;
774 
775 }
776 
777 static uint16_t gcd2 (uint16_t n1, uint16_t n2)
778 {
779  uint16_t i, gcd=0;
780 
781  for(i=3; i <= n1 && i <= n2; ++i)
782  {
783  // Checks if i is factor of both integers
784  if(n1%i==0 && n2%i==0)
785  gcd = i;
786  }
787 
788  return gcd;
789 }
790 
791 static uint16_t gcd3 (uint16_t n1, uint16_t n2, uint16_t n3)
792 {
793  uint16_t i, gcd=0;
794 
795  for(i=3; i <= n1 && i <= n2 && i <= n3; ++i)
796  {
797  // Checks if i is factor of all integers
798  if(n1%i==0 && n2%i==0 && n3%i==0)
799  gcd = i;
800  }
801 
802  return gcd;
803 }
804 
805 static bool findTwoMeasCount (uint16_t freqDivider1, uint16_t freqDivider2, uint16_t *measrate, uint8_t *meascount1, uint8_t *meascount2, uint32_t accelSyncus)
806 {
807  int i,j,k;
808  bool foundVal=false;
809  //maximize measrate
810  if (freqDivider1 == freqDivider2)
811  {
812  *meascount1 = 1;
813  *meascount2 = 1;
814  *measrate = freqDivider1;
815  return true;
816  }
817  else
818  {
819  *measrate = gcd2(freqDivider1, freqDivider2);
820  }
821 
822  for (j=0;j<MEASCOUNT_MAX;j++)
823  {
824  for (k=0;k<MEASCOUNT_MAX;k++)
825  {
826  if ((((*measrate)*j) == freqDivider1) && (((*measrate)*k) == freqDivider2))
827  {
828  foundVal = true;
829  *meascount1 = j;
830  *meascount2 = k;
831  }
832  }
833  }
834 
835  return foundVal;
836 }
837 
838 static bool findThreeMeasCount (uint16_t freqDivider1, uint16_t freqDivider2, uint16_t freqDivider3, uint16_t *measrate, uint8_t *meascount1, uint8_t *meascount2, uint8_t *meascount3, uint32_t accelSyncus)
839 {
840  //this is certainly not efficient...to be rewritten
841  int i,j,k,m;
842  bool foundVal=false;
843  //maximize measrate
844  if (freqDivider1 == freqDivider2 == freqDivider3)
845  {
846  *meascount1 = 1;
847  *meascount2 = 1;
848  *meascount3 = 1;
849  *measrate = freqDivider1;
850  return true;
851  }
852  else
853  {
854  *measrate = gcd3(freqDivider1, freqDivider2,freqDivider3);
855  }
856  for (j=0;j<MEASCOUNT_MAX;j++)
857  {
858  for (k=0;k<MEASCOUNT_MAX;k++)
859  {
860  for (m=0;m<MEASCOUNT_MAX;m++)
861  {
862  if ((((*measrate)*j) == freqDivider1) && (((*measrate)*k) == freqDivider2)&& (((*measrate)*m) == freqDivider3))
863  {
864  foundVal = true;
865  *meascount1 = j;
866  *meascount2 = k;
867  *meascount3 = m;
868  }
869  }
870  }
871  }
872 
873  return foundVal;
874 }
875 
876 /***************************************************************************/
888 {
889  uint16_t measrate, fifo_int_level;
890  uint16_t freqDivider;
891  uint16_t freqDivider2;
892  uint16_t freqDivider3;
893  uint16_t bytesPerSample;
894  uint8_t ppg_meascount, ecg_meascount, bioz_meascount, ecgld_meascount;
895  //todo: handle accelSyncRateus in calculations
896  if (initFlag[device] != 1)
897  {
899  }
900  if (devices[device].deviceStatus.running)
901  {
903  }
904  devices[device].deviceCfg.globalCfg.synch_config = globalCfg->synch_mode | (globalCfg->ms_polar<<4);
905  Si117xParamSet(devices[device].deviceHandle,PARAM_SYNCH_CONFIG,devices[device].deviceCfg.globalCfg.synch_config);
906  devices[device].deviceCfg.globalCfg.meas_cntl = ((globalCfg->ppg_sw_avg&7)<<3) | (globalCfg->fifo_disable<<6) | (globalCfg->fifo_self_test<<7) | (globalCfg->ppgSampleSize) | (globalCfg->ecgSampleSize<<2) | (globalCfg->biozSampleSize<<1);
907  Si117xParamSet(devices[device].deviceHandle,PARAM_MEAS_CNTL,devices[device].deviceCfg.globalCfg.meas_cntl);
908  devices[device].deviceCfg.globalCfg.taskEnable = globalCfg->taskEnable;
909  Si117xParamSet(devices[device].deviceHandle,PARAM_TASK_ENABLE,devices[device].deviceCfg.globalCfg.taskEnable);
910  devices[device].deviceCfg.globalCfg.irq_enable = globalCfg->irq_enable;
911  //find measrate, meascounts
913  {
914  //make sure no other task enabled
916  {
918  }
919  //otherwise calculate bioz_meascount
920  freqDivider = globalCfg->biozSampleRateus/50;
921  if (findMeasRate(freqDivider,&measrate,&bioz_meascount, globalCfg->accelSyncRateus)!= true)
922  {
924  }
925  devices[device].deviceCfg.globalCfg.measrate = measrate;
926  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
927  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
928  devices[device].deviceCfg.biozCfg.bioz_meascount = bioz_meascount;
929  Si117xParamSet(devices[device].deviceHandle,PARAM_BIOZ_MEASCOUNT,bioz_meascount);
930  }
932  {
933  devices[device].deviceStatus.hrmOversamplingRatio = 40000 / globalCfg->ppgSampleRateus;
934  if (globalCfg->taskEnable & 0xC0)
935  {
936  //ECG and PPG tasks at same time
937  freqDivider3 = globalCfg->ppgSampleRateus/50;
938  if ((globalCfg->taskEnable & SI117XDRV_TASK_ECG_EN) && (globalCfg->taskEnable & SI117XDRV_TASK_ECG_LD_EN))
939  {
940  freqDivider = globalCfg->ecgSampleRateus/50;
941  freqDivider2 = (globalCfg->ecgldSampleRateus/4)/50; //ecg_ld has 4x divider
942  if (findThreeMeasCount (freqDivider, freqDivider2, freqDivider3, &measrate, &ecg_meascount, &ecgld_meascount,&ppg_meascount, globalCfg->accelSyncRateus)!= true)
943  {
945  }
946  devices[device].deviceCfg.globalCfg.measrate = measrate;
947  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
948  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
949  devices[device].deviceCfg.ecgCfg.ecg_meascount = ecg_meascount;
950  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,ecg_meascount);
951  devices[device].deviceCfg.ecgCfg.ecg_ld_meascount = ecgld_meascount;
952  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_LD_MEASCOUNT,ecgld_meascount);
953  devices[device].deviceCfg.ppgCfg.ppg_meascount = ppg_meascount;
954  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,ppg_meascount);
955  }
956  else if (globalCfg->taskEnable & SI117XDRV_TASK_ECG_EN)
957  {
958  freqDivider = globalCfg->ecgSampleRateus/50;
959  if (findTwoMeasCount(freqDivider,freqDivider3,&measrate,&ecg_meascount,&ppg_meascount, globalCfg->accelSyncRateus)!= true)
960  {
962  }
963  devices[device].deviceCfg.globalCfg.measrate = measrate;
964  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
965  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
966  devices[device].deviceCfg.ecgCfg.ecg_meascount = ecg_meascount;
967  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,ecg_meascount);
968  devices[device].deviceCfg.ppgCfg.ppg_meascount = ppg_meascount;
969  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,ppg_meascount);
970  }
971  else if (globalCfg->taskEnable & SI117XDRV_TASK_ECG_LD_EN)
972  {
973  freqDivider = (globalCfg->ecgldSampleRateus/4)/50; //ecg_ld has 4x divider
974  if (findTwoMeasCount(freqDivider,freqDivider3,&measrate,&ecgld_meascount,&ppg_meascount, globalCfg->accelSyncRateus)!= true)
975  {
977  }
978  devices[device].deviceCfg.globalCfg.measrate = measrate;
979  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
980  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
981  devices[device].deviceCfg.ecgCfg.ecg_ld_meascount = ecgld_meascount;
982  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_LD_MEASCOUNT,ecgld_meascount);
983  devices[device].deviceCfg.ppgCfg.ppg_meascount = ppg_meascount;
984  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,ppg_meascount);
985  }
986  }
987  else
988  {
989  //just PPG
990  freqDivider = globalCfg->ppgSampleRateus/50;
991  if (findMeasRate(freqDivider,&measrate,&ppg_meascount, globalCfg->accelSyncRateus)!= true)
992  {
994  }
995  devices[device].deviceCfg.globalCfg.measrate = measrate;
996  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
997  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
998  devices[device].deviceCfg.ppgCfg.ppg_meascount = ppg_meascount;
999  Si117xParamSet(devices[device].deviceHandle,PARAM_PPG_MEASCOUNT,ppg_meascount);
1000  }
1001  }
1002  else if (globalCfg->taskEnable & 0xc0)
1003  {
1004  //ECG tasks on their own
1005  if ((globalCfg->taskEnable & SI117XDRV_TASK_ECG_EN) && (globalCfg->taskEnable & SI117XDRV_TASK_ECG_LD_EN))
1006  {
1007  freqDivider = globalCfg->ecgSampleRateus/50;
1008  freqDivider2 = (globalCfg->ecgldSampleRateus/4)/50; //ecg_ld has 4x divider
1009  if (findTwoMeasCount (freqDivider, freqDivider2, &measrate, &ecg_meascount, &ecgld_meascount, globalCfg->accelSyncRateus)!= true)
1010  {
1012  }
1013  devices[device].deviceCfg.globalCfg.measrate = measrate;
1014  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
1015  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
1016  devices[device].deviceCfg.ecgCfg.ecg_meascount = ecg_meascount;
1017  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,ecg_meascount);
1018  devices[device].deviceCfg.ecgCfg.ecg_ld_meascount = ecgld_meascount;
1019  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_LD_MEASCOUNT,ecgld_meascount);
1020  }
1021  else if (globalCfg->taskEnable & SI117XDRV_TASK_ECG_EN)
1022  {
1023  freqDivider = globalCfg->ecgSampleRateus/50;
1024  if (findMeasRate(freqDivider,&measrate,&ecg_meascount, globalCfg->accelSyncRateus)!= true)
1025  {
1027  }
1028  devices[device].deviceCfg.globalCfg.measrate = measrate;
1029  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
1030  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
1031  devices[device].deviceCfg.ecgCfg.ecg_meascount = ecg_meascount;
1032  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_MEASCOUNT,ecg_meascount);
1033  }
1034  else if (globalCfg->taskEnable & SI117XDRV_TASK_ECG_LD_EN)
1035  {
1036  freqDivider = (globalCfg->ecgldSampleRateus/4)/50; //ecg_ld has 4x divider
1037  if (findMeasRate(freqDivider,&measrate,&ecgld_meascount, globalCfg->accelSyncRateus)!= true)
1038  {
1040  }
1041  devices[device].deviceCfg.globalCfg.measrate = measrate;
1042  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_H,measrate>>8);
1043  Si117xParamSet(devices[device].deviceHandle,PARAM_MEASRATE_L,measrate&0xff);
1044  devices[device].deviceCfg.ecgCfg.ecg_ld_meascount = ecgld_meascount;
1045  Si117xParamSet(devices[device].deviceHandle,PARAM_ECG_LD_MEASCOUNT,ecgld_meascount);
1046  }
1047  }
1048  //lastly, set fifo_int_level
1049  devices[device].deviceCfg.globalCfg.fifo_int_level = globalCfg->fifo_int_level;
1050  Si117xParamSet(devices[device].deviceHandle,PARAM_FIFO_INT_LEVEL_H,globalCfg->fifo_int_level>>8);
1051  Si117xParamSet(devices[device].deviceHandle,PARAM_FIFO_INT_LEVEL_L,globalCfg->fifo_int_level&0xff);
1052  return ECODE_SI117XDRV_OK;
1053 
1054 }
1055 
1056 /***************************************************************************/
1068 {
1069  int i;
1070  devices[device].deviceHandle = deviceHandle;
1071  for (i=0;i<SI117XDRV_MAX_NUM_CALLBACKS;i++)
1072  {
1073  callbacks[device].preStartCallbacks[ i ].allocated = false;
1074  callbacks[device].postStartCallbacks[ i ].allocated = false;
1075  callbacks[device].preFifoFlushCallbacks[ i ].allocated = false;
1076  callbacks[device].postFifoFlushCallbacks[ i ].allocated = false;
1077  }
1078  leadDetect[device] = false;
1079  leadDetectionFlag[device]=false;
1080  wristDetectionFlag[device]=false;
1081  initFlag[device] = 1;
1082  return ECODE_SI117XDRV_OK;
1083 
1084 }
1085 
1086 /***************************************************************************/
1100 {
1101  int i = 0;
1102 
1103  // Iterate through the table of the queues until the first available.
1104  while ( ( i < SI117XDRV_MAX_NUM_CALLBACKS ) && ( callbacks[device].accelSyncRecvCallbacks[ i ].allocated ) ) {
1105  i++;
1106  }
1107 
1108  // Check if we reached the end of the table.
1109  if ( i == SI117XDRV_MAX_NUM_CALLBACKS ) {
1111  } else {
1112  callbacks[device].accelSyncRecvCallbacks[ i ].allocated = true;
1113  callbacks[device].accelSyncRecvCallbacks[ i ].callback = callback;
1114  callbacks[device].accelSyncRecvCallbacks[ i ].user = user;
1115  }
1116 
1117  return ECODE_SI117XDRV_OK;
1118 }
1119 
1120 /***************************************************************************/
1134 {
1135  int i = 0;
1136 
1137  // Iterate through the table of the queues until the first available.
1138  while ( ( i < SI117XDRV_MAX_NUM_CALLBACKS ) && ( callbacks[device].preStartCallbacks[ i ].allocated ) ) {
1139  i++;
1140  }
1141 
1142  // Check if we reached the end of the table.
1143  if ( i == SI117XDRV_MAX_NUM_CALLBACKS ) {
1145  } else {
1146  callbacks[device].preStartCallbacks[ i ].allocated = true;
1147  callbacks[device].preStartCallbacks[ i ].callback = callback;
1148  callbacks[device].preStartCallbacks[ i ].user = user;
1149  }
1150 
1151  return ECODE_SI117XDRV_OK;
1152 }
1153 
1154 /***************************************************************************/
1168 {
1169  int i = 0;
1170 
1171  // Iterate through the table of the queues until the first available.
1172  while ( ( i < SI117XDRV_MAX_NUM_CALLBACKS ) && ( callbacks[device].postStartCallbacks[ i ].allocated ) ) {
1173  i++;
1174  }
1175 
1176  // Check if we reached the end of the table.
1177  if ( i == SI117XDRV_MAX_NUM_CALLBACKS ) {
1179  } else {
1180  callbacks[device].postStartCallbacks[ i ].allocated = true;
1181  callbacks[device].postStartCallbacks[ i ].callback = callback;
1182  callbacks[device].postStartCallbacks[ i ].user = user;
1183  }
1184 
1185  return ECODE_SI117XDRV_OK;
1186 }
1187 
1188 /***************************************************************************/
1202 {
1203  int i = 0;
1204 
1205  // Iterate through the table of the queues until the first available.
1206  while ( ( i < SI117XDRV_MAX_NUM_CALLBACKS ) && ( callbacks[device].preFifoFlushCallbacks[ i ].allocated ) ) {
1207  i++;
1208  }
1209 
1210  // Check if we reached the end of the table.
1211  if ( i == SI117XDRV_MAX_NUM_CALLBACKS ) {
1213  } else {
1214  callbacks[device].preFifoFlushCallbacks[ i ].allocated = true;
1215  callbacks[device].preFifoFlushCallbacks[ i ].callback = callback;
1216  callbacks[device].preFifoFlushCallbacks[ i ].user = user;
1217  }
1218  return ECODE_SI117XDRV_OK;
1219 }
1220 
1221 /***************************************************************************/
1235 {
1236  int i = 0;
1237 
1238  // Iterate through the table of the queues until the first available.
1239  while ( ( i < SI117XDRV_MAX_NUM_CALLBACKS ) && ( callbacks[device].postFifoFlushCallbacks[ i ].allocated ) ) {
1240  i++;
1241  }
1242 
1243  // Check if we reached the end of the table.
1244  if ( i == SI117XDRV_MAX_NUM_CALLBACKS ) {
1246  } else {
1247  callbacks[device].postFifoFlushCallbacks[ i ].allocated = true;
1248  callbacks[device].postFifoFlushCallbacks[ i ].callback = callback;
1249  callbacks[device].postFifoFlushCallbacks[ i ].user = user;
1250  }
1251  return ECODE_SI117XDRV_OK;
1252 }
1253 /***************************************************************************/
1257 /***************************************************************************/
1260 typedef struct {
1262  volatile uint16_t head;
1263  volatile uint16_t tail;
1264  volatile uint16_t used;
1265  uint16_t size;
1266  int8_t *fifo;
1268 
1270 typedef struct {
1271  SI117XDRV_FifoQueue_t queue;
1272  bool allocated;
1273  bool ppg;
1274  bool ppg16;
1275  bool ecg;
1276  bool ecgld;
1277  uint8_t sampleSize;
1279 
1280 static SI117XDRV_FifoQueueConfig_t queues[ SI117XDRV_MAX_DATA_QUEUES ];
1281 
1282 /***************************************************************************/
1286  int8_t *inputBuffer,
1287  uint16_t size);
1289  int8_t *buffer, uint16_t size);
1291 static uint16_t SI117XDRV_NumBytesInQueue (SI117XDRV_FifoQueue_t *queue);
1292 
1293 /***************************************************************************/
1307 {
1308  int i = 0;
1309  int retVal = 0;
1310  // Iterate through the table of the queues until the first available.
1311  while ( ( i < SI117XDRV_MAX_DATA_QUEUES ) && ( queues[ i ].allocated ) ) {
1312  i++;
1313  }
1314 
1315  // Check if we reached the end of the table.
1316  if ( i == SI117XDRV_MAX_DATA_QUEUES ) {
1318  } else {
1319  // Check if a NULL pointer was passed.
1320  if ( id != NULL ) {
1321  queues[ i ].allocated = true;
1322  queues[ i ].ppg = false;
1323  queues[ i ].ppg16 = true;
1324  queues[ i ].ecg = false;
1325  queues[ i ].ecgld = false;
1326  queues[ i ].queue.head = 0;
1327  queues[ i ].queue.tail = 0;
1328  queues[ i ].queue.used = 0;
1329  queues[ i ].queue.size = queueSizeInBytes;
1330  queues[ i ].queue.fifo = (int8_t*)queueBuffer;
1331  queues[ i ].sampleSize = SI117XDRV_PPG_SAMPLE_SIZE_BYTES;
1332  *id = i;
1333  retVal = ECODE_SI117XDRV_OK;
1334  if ((queueSizeInBytes % SI117XDRV_PPG_SAMPLE_SIZE_BYTES) != 0)
1335  {
1337  }
1338  } else {
1339  retVal = ECODE_SI117XDRV_PARAM_ERROR;
1340  }
1341  }
1342  return retVal;
1343 }
1344 /***************************************************************************/
1358 {
1359  int i = 0;
1360  int retVal = 0;
1361  // Iterate through the table of the queues until the first available.
1362  while ( ( i < SI117XDRV_MAX_DATA_QUEUES ) && ( queues[ i ].allocated ) ) {
1363  i++;
1364  }
1365 
1366  // Check if we reached the end of the table.
1367  if ( i == SI117XDRV_MAX_DATA_QUEUES ) {
1369  } else {
1370  // Check if a NULL pointer was passed.
1371  if ( id != NULL ) {
1372  queues[ i ].allocated = true;
1373  queues[ i ].ppg = true;
1374  queues[ i ].ppg16 = false;
1375  queues[ i ].ecg = false;
1376  queues[ i ].ecgld = false;
1377  queues[ i ].queue.head = 0;
1378  queues[ i ].queue.tail = 0;
1379  queues[ i ].queue.used = 0;
1380  queues[ i ].queue.size = queueSizeInBytes;
1381  queues[ i ].queue.fifo = (int8_t*)queueBuffer;
1382  queues[ i ].sampleSize = SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES;
1383  *id = i;
1384  retVal = ECODE_SI117XDRV_OK;
1385  if ((queueSizeInBytes % SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES) != 0)
1386  {
1388  }
1389  } else {
1390  retVal = ECODE_SI117XDRV_PARAM_ERROR;
1391  }
1392  }
1393  return retVal;
1394 }
1395 
1396 /***************************************************************************/
1410 {
1411  int i = 0;
1412  int retVal = 0;
1413  // Iterate through the table of the queues until the first available.
1414  while ( ( i < SI117XDRV_MAX_DATA_QUEUES ) && ( queues[ i ].allocated ) ) {
1415  i++;
1416  }
1417 
1418  // Check if we reached the end of the table.
1419  if ( i == SI117XDRV_MAX_DATA_QUEUES ) {
1421  } else {
1422  // Check if a NULL pointer was passed.
1423  if ( id != NULL ) {
1424  queues[ i ].allocated = true;
1425  queues[ i ].ppg = false;
1426  queues[ i ].ecg = true;
1427  queues[ i ].ppg16 = false;
1428  queues[ i ].ecgld = false;
1429  queues[ i ].queue.head = 0;
1430  queues[ i ].queue.tail = 0;
1431  queues[ i ].queue.used = 0;
1432  queues[ i ].queue.size = queueSizeInBytes;
1433  queues[ i ].queue.fifo = (int8_t*)queueBuffer;
1434  queues[ i ].sampleSize = SI117XDRV_ECG_SAMPLE_SIZE_BYTES;
1435  *id = i;
1436  retVal = ECODE_SI117XDRV_OK;
1437  if ((queueSizeInBytes % SI117XDRV_ECG_SAMPLE_SIZE_BYTES) != 0)
1438  {
1440  }
1441  } else {
1442  retVal = ECODE_SI117XDRV_PARAM_ERROR;
1443  }
1444  }
1445  return retVal;
1446 }
1447 
1448 /***************************************************************************/
1462 {
1463  int i = 0;
1464  int retVal = 0;
1465  // Iterate through the table of the queues until the first available.
1466  while ( ( i < SI117XDRV_MAX_DATA_QUEUES ) && ( queues[ i ].allocated ) ) {
1467  i++;
1468  }
1469 
1470  // Check if we reached the end of the table.
1471  if ( i == SI117XDRV_MAX_DATA_QUEUES ) {
1473  } else {
1474  // Check if a NULL pointer was passed.
1475  if ( id != NULL ) {
1476  queues[ i ].allocated = true;
1477  queues[ i ].ppg = false;
1478  queues[ i ].ecg = false;
1479  queues[ i ].ecgld = true;
1480  queues[ i ].ppg16 = false;
1481  queues[ i ].queue.head = 0;
1482  queues[ i ].queue.tail = 0;
1483  queues[ i ].queue.used = 0;
1484  queues[ i ].queue.size = queueSizeInBytes;
1485  queues[ i ].queue.fifo = (int8_t*)queueBuffer;
1486  queues[ i ].sampleSize = SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES;
1487  *id = i;
1488  retVal = ECODE_SI117XDRV_OK;
1489  if ((queueSizeInBytes % SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES) != 0)
1490  {
1492  }
1493  } else {
1494  retVal = ECODE_SI117XDRV_PARAM_ERROR;
1495  }
1496  }
1497  return retVal;
1498 }
1499 
1500 /***************************************************************************/
1510 {
1511  // Check if valid callback ID.
1512  if ( id >= SI117XDRV_MAX_DATA_QUEUES ) {
1514  }
1515 
1516  //CORE_ATOMIC_SECTION(
1517  queues[ id ].allocated = false;
1518  // )
1519 
1520  return ECODE_SI117XDRV_OK;
1521 }
1522 
1523 /***************************************************************************/
1527 {
1528  queue->head = 0;
1529  queue->tail = 0;
1530  queue->used = 0;
1531  return ECODE_SI117XDRV_OK;
1532 }
1533 
1534 /***************************************************************************/
1544 {
1545  return SI117XDRV_ClearRawQueue(&(queues[id].queue));
1546 }
1547 
1548 
1549 
1550 /***************************************************************************/
1554  int8_t *inputBuffer,
1555  uint16_t size)
1556 {
1557  int i;
1558  for(i=0; i<size; i++)
1559  {
1560  queue->fifo[queue->head] = inputBuffer[i];
1561  queue->head++;
1562  if(queue->head == queue->size)
1563  queue->head = 0;
1564  }
1565  queue->used += size;
1566  i = queue->tail;
1567  if (i == queue->head)
1568  {
1569  queue->tail += size; // if we have wrapped around then we must delete one sample
1570  queue->used -= size;
1571  if(queue->tail >= queue->size) //handle wrapping
1572  queue->tail = queue->tail - queue->size;
1573  return ECODE_SI117XDRV_QUEUE_FULL; //indicate to caller something bad happened
1574  }
1575  return ECODE_SI117XDRV_OK;
1576 }
1577 
1578 /***************************************************************************/
1582  int8_t *buffer, uint16_t size)
1583 {
1584  int i;
1585 
1586  if (queue->used < size) {
1587  buffer = NULL;
1588 
1590  }
1591  for(i=0; i<size; i++)
1592  {
1593  buffer[i] = queue->fifo[queue->tail];
1594  queue->tail++;
1595  if(queue->tail == queue->size)
1596  queue->tail = 0;
1597 
1598  }
1599  queue->used -= size;
1600 
1601  return ECODE_SI117XDRV_OK;
1602 }
1603 /***************************************************************************/
1607 {
1608  return queue->used;
1609 }
1610 
1611 /***************************************************************************/
1621 {
1622  uint16_t samples;
1623  if (id > SI117XDRV_MAX_DATA_QUEUES)
1624  return 0;
1625  samples = SI117XDRV_NumBytesInQueue(&(queues[id].queue))/(queues[id].sampleSize);
1626  return samples;
1627 }
1628 
1629 /***************************************************************************/
1633 {
1634  int8_t buffer[SI117XDRV_PPG_SAMPLE_SIZE_BYTES];
1635  int8_t *buf = buffer;
1636  int retVal = ECODE_SI117XDRV_OK;
1637  int i;
1638  int temp;
1639  for (i=0; i< SI117XDRV_MAX_DATA_QUEUES; i++)
1640  {
1641  if (queues[ i ].allocated && queues[ i ].ppg16)
1642  {
1643  buf = buffer;
1644  *(uint16_t*)(buf) = sample->sequence;
1645  buf+=2;
1646  *(uint16_t*)(buf) = sample->timestamp;
1647  buf+=2;
1648  *(uint8_t*)(buf) = sample->syncMessage;
1649  buf+=1;
1650  *(int16_t*)(buf) = sample->ppg1; //make sure sign is preserved??
1651  buf+=2;
1652  *(int16_t*)(buf) = sample->ppg2;
1653  buf+=2;
1654  *(int16_t*)(buf) = sample->ppg3;
1655  buf+=2;
1656  *(int16_t*)(buf) = sample->ppg4;
1657  buf+=2;
1658  temp = SI117XDRV_EnqueueRawData (&(queues[i].queue), buffer, queues[i].sampleSize);
1659  if (temp != ECODE_SI117XDRV_OK)
1660  retVal = temp;
1661  }
1662 
1663  }
1664  return retVal;
1665 }
1666 
1667 /***************************************************************************/
1671 {
1673  int8_t *buf = buffer;
1674  int retVal = ECODE_SI117XDRV_OK;
1675  int i;
1676  int temp;
1677  for (i=0; i< SI117XDRV_MAX_DATA_QUEUES; i++)
1678  {
1679  if (queues[ i ].allocated && queues[ i ].ppg)
1680  {
1681  buf = buffer;
1682  *(uint16_t*)(buf) = sample->sequence;
1683  buf+=2;
1684  *(uint16_t*)(buf) = sample->timestamp;
1685  buf+=2;
1686  *(uint8_t*)(buf) = sample->syncMessage;
1687  buf+=1;
1688  *(int32_t*)(buf) = sample->ppg1;
1689  buf+=4;
1690  *(int32_t*)(buf) = sample->ppg2;
1691  buf+=4;
1692  *(int32_t*)(buf) = sample->ppg3;
1693  buf+=4;
1694  *(int32_t*)(buf) = sample->ppg4;
1695  buf+=4;
1696  temp = SI117XDRV_EnqueueRawData (&(queues[i].queue), buffer, queues[i].sampleSize);
1697  if (temp != ECODE_SI117XDRV_OK)
1698  retVal = temp;
1699  }
1700 
1701  }
1702 
1703  return retVal;
1704 }
1705 
1706 
1707 
1708 /***************************************************************************/
1720 {
1722  int8_t *buf = buffer;
1723  int retVal = SI117XDRV_DequeueRawData (&(queues[id].queue), buf, queues[id].sampleSize);
1724  sample->sequence = *(uint16_t*)(buf);
1725  buf+=2;
1726  sample->timestamp = *(uint16_t*)(buf);
1727  buf+=2;
1728  sample->syncMessage = *(uint8_t*)(buf);
1729  buf+=1;
1730  sample->ppg1 = *(int32_t*)(buf);
1731  buf+=4;
1732  sample->ppg2 = *(int32_t*)(buf);
1733  buf+=4;
1734  sample->ppg3 = *(int32_t*)(buf);
1735  buf+=4;
1736  sample->ppg4 = *(int32_t*)(buf);
1737  buf+=4;
1738 
1739  return retVal;
1740 }
1741 
1742 /***************************************************************************/
1754 {
1755  int8_t buffer[SI117XDRV_PPG_SAMPLE_SIZE_BYTES];
1756  int8_t *buf = buffer;
1757  int retVal = SI117XDRV_DequeueRawData (&(queues[id].queue), buf, queues[id].sampleSize);
1758  sample->sequence = *(uint16_t*)(buf);
1759  buf+=2;
1760  sample->timestamp = *(uint16_t*)(buf);
1761  buf+=2;
1762  sample->syncMessage = *(uint8_t*)(buf);
1763  buf+=1;
1764  sample->ppg1 = *(int16_t*)(buf);
1765  buf+=2;
1766  sample->ppg2 = *(int16_t*)(buf);
1767  buf+=2;
1768  sample->ppg3 = *(int16_t*)(buf);
1769  buf+=2;
1770  sample->ppg4 = *(int16_t*)(buf);
1771  buf+=2;
1772 
1773  return retVal;
1774 }
1775 
1776 /***************************************************************************/
1780 {
1781  int8_t buffer[SI117XDRV_ECG_SAMPLE_SIZE_BYTES];
1782  int8_t *buf = buffer;
1783  int retVal = ECODE_SI117XDRV_OK;
1784  int i;
1785  int temp;
1786  for (i=0; i< SI117XDRV_MAX_DATA_QUEUES; i++)
1787  {
1788  if (queues[ i ].allocated && queues[i].ecg)
1789  {
1790  *(uint16_t*)(buf) = sample->sequence;
1791  buf+=2;
1792  *(uint16_t*)(buf) = sample->timestamp;
1793  buf+=2;
1794  *(uint8_t*)(buf) = sample->syncMessage;
1795  buf+=1;
1796  *(int32_t*)(buf) = sample->ecg;
1797  buf+=4;
1798  temp = SI117XDRV_EnqueueRawData (&(queues[i].queue), buffer, queues[i].sampleSize);
1799  if (temp != ECODE_SI117XDRV_OK)
1800  retVal = temp;
1801  }
1802 
1803  }
1804  return retVal;
1805 }
1806 
1807 /***************************************************************************/
1811 {
1812  int8_t buffer[SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES];
1813  int8_t *buf = buffer;
1814  int retVal = ECODE_SI117XDRV_OK;
1815  int i;
1816  int temp;
1817  for (i=0; i< SI117XDRV_MAX_DATA_QUEUES; i++)
1818  {
1819  if (queues[ i ].allocated && queues[i].ecgld)
1820  {
1821  *(uint16_t*)(buf) = sample->sequence;
1822  buf+=2;
1823  *(uint16_t*)(buf) = sample->timestamp;
1824  buf+=2;
1825  *(uint8_t*)(buf) = sample->syncMessage;
1826  buf+=1;
1827  *(uint8_t*)(buf) = sample->data[0];
1828  buf+=1;
1829  *(uint8_t*)(buf) = sample->data[1];
1830  buf+=1;
1831  *(uint8_t*)(buf) = sample->data[2];
1832  buf+=1;
1833  *(uint8_t*)(buf) = sample->data[3];
1834  buf+=1;
1835  temp = SI117XDRV_EnqueueRawData (&(queues[i].queue), buffer, queues[i].sampleSize);
1836  if (temp != ECODE_SI117XDRV_OK)
1837  retVal = temp;
1838  }
1839 
1840  }
1841  return retVal;
1842 }
1843 
1844 /***************************************************************************/
1856 {
1857  int8_t buffer[SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES];
1858  int8_t *buf = buffer;
1859  int retVal = SI117XDRV_DequeueRawData (&(queues[id].queue), buf, queues[id].sampleSize);
1860  sample->sequence = *(uint16_t*)(buf);
1861  buf+=2;
1862  sample->timestamp = *(uint16_t*)(buf);
1863  buf+=2;
1864  sample->syncMessage = *(uint8_t*)(buf);
1865  buf+=1;
1866  sample->data[0] = *(uint8_t*)(buf);
1867  buf+=1;
1868  sample->data[1] = *(uint8_t*)(buf);
1869  buf+=1;
1870  sample->data[2] = *(uint8_t*)(buf);
1871  buf+=1;
1872  sample->data[3] = *(uint8_t*)(buf);
1873  buf+=1;
1874  return retVal;
1875 }
1876 /***************************************************************************/
1888 {
1889  int8_t buffer[SI117XDRV_ECG_SAMPLE_SIZE_BYTES];
1890  int8_t *buf = buffer;
1891  int retVal = SI117XDRV_DequeueRawData (&(queues[id].queue), buf, queues[id].sampleSize);
1892  sample->sequence = *(uint16_t*)(buf);
1893  buf+=2;
1894  sample->timestamp = *(uint16_t*)(buf);
1895  buf+=2;
1896  sample->syncMessage = *(uint8_t*)(buf);
1897  buf+=1;
1898  sample->ecg = *(int32_t*)(buf);
1899  buf+=4;
1900 
1901 
1902  return retVal;
1903 }
1904 
1905 /***************************************************************************/
1909 {
1910 
1911  int retVal = ECODE_SI117XDRV_OK;
1912  //todo
1913  return retVal;
1914 }
1915 /***************************************************************************/
1919 {
1920  int retVal = ECODE_SI117XDRV_OK;
1921  //todo
1922  return retVal;
1923 }
1924 
1925 /***************************************************************************/
1937 {
1938  int16_t retval;
1939  uint8_t value;
1940  retval = Si117xParamRead(devices[device].deviceHandle, PARAM_ECG_LDCONFIG);
1941  if (leadDetectionFlag[device] && retval >= 0)
1942  {
1943  value = (uint8_t)retval;
1944  if(value & 0x80) // lead on detection
1945  {
1946  //lead on
1947  // Flip direction
1948  devices[device].deviceCfg.ecgCfg.ecg_ldconfig &= ~0x80;
1949  Si117xParamSet(devices[device].deviceHandle, PARAM_ECG_LDCONFIG, (value & 0x7F));
1950  leadDetect[device] = true;
1951  }else // lead off detection
1952  {
1953  // lead off
1954  // Flip direction
1955  devices[device].deviceCfg.ecgCfg.ecg_ldconfig |= 0x80;
1956  Si117xParamSet(devices[device].deviceHandle, PARAM_ECG_LDCONFIG, (value | 0x80));
1957  leadDetect[device] = false;
1958  }
1959  leadDetectionFlag[device] = false;
1960  }
1961  *leadDetectStatus = leadDetect[device];
1962  return ECODE_SI117XDRV_OK;
1963 }
1964 
1965 
1966 /***************************************************************************/
1978 {
1979  *wristDetectStatus = wristDetectionFlag[device];
1980  return ECODE_SI117XDRV_OK;
1981 }
1982 
1983 /***************************************************************************/
1995 {
1996  wristDetectionFlag[device] = false;
1997  return ECODE_SI117XDRV_OK;
1998 }
1999 
2000 /***************************************************************************/
2010 {
2011  leadDetectionFlag[device] = true;
2012  return ECODE_SI117XDRV_OK;
2013 }
2014 
2015 /***************************************************************************/
2025 {
2026  wristDetectionFlag[device] = true;
2027  return ECODE_SI117XDRV_OK;
2028 }
2029 
2030 /***************************************************************************/
2035 typedef enum si117xFifoState
2036 {
2037  SI117x_FIFO_STATE_PPG1_HI=0,
2038  SI117x_FIFO_STATE_PPG1_MID=1,
2039  SI117x_FIFO_STATE_PPG1_LO=2,
2040  SI117x_FIFO_STATE_PPG2_HI=3,
2041  SI117x_FIFO_STATE_PPG2_MID=4,
2042  SI117x_FIFO_STATE_PPG2_LO=5,
2043  SI117x_FIFO_STATE_PPG3_HI=6,
2044  SI117x_FIFO_STATE_PPG3_MID=7,
2045  SI117x_FIFO_STATE_PPG3_LO=8,
2046  SI117x_FIFO_STATE_PPG4_HI=9,
2047  SI117x_FIFO_STATE_PPG4_MID=10,
2048  SI117x_FIFO_STATE_PPG4_LO=11,
2049  SI117x_FIFO_STATE_BIOZ1_HI = 12,
2050  SI117x_FIFO_STATE_BIOZ1_MID = 13,
2051  SI117x_FIFO_STATE_BIOZ1_LO = 14,
2052  SI117x_FIFO_STATE_BIOZ2_HI = 15,
2053  SI117x_FIFO_STATE_BIOZ2_MID = 16,
2054  SI117x_FIFO_STATE_BIOZ2_LO = 17,
2055  SI117x_FIFO_STATE_ECG_HI=18,
2056  SI117x_FIFO_STATE_ECG_MID=19,
2057  SI117x_FIFO_STATE_ECG_LO=20,
2058  SI117x_FIFO_STATE_ECG_LD_BYTE1=21,
2059  SI117x_FIFO_STATE_ECG_LD_BYTE2=22,
2060  SI117x_FIFO_STATE_ECG_LD_BYTE3=23,
2061  SI117x_FIFO_STATE_ECG_LD_BYTE4=24,
2062  SI117x_FIFO_STATE_UNKNOWN = 0xff //a dle has not been received so the state is unknown
2064 
2066 {
2067  si117xFifoState_t fifoState;
2068  uint8_t isMsb; //Is the current state waiting for the MSB
2069  int32_t ppg_value[4];
2070  int32_t ecg_value;
2071  int32_t bioz_value[2];
2072  uint8_t ecg_ld_value[4];
2074 
2075 static si117xFifoStateMachine_t fifoStateMachines[SI117XDRV_MAX_NUM_DEVICES];
2076 
2077 #define SI117X_FIFO_DEFAULT_FIFO_STATE {SI117x_FIFO_STATE_UNKNOWN,1,0,0,0,0,0,0,0}
2078 
2079 /**************************************************************************/
2082 static bool Unprocessed_DLE=false;
2083 static bool Unprocessed_DLE_S=false;
2084 
2085 static uint8_t found_DLE_S=0, DLE_S_tag;
2086 
2087 typedef enum si117xFifoStateTaskComplete
2088 {
2089  SI117x_TASK_NOT_COMPLETE,
2090  SI117x_TASK_COMPLETE_PPG,
2091  SI117x_TASK_COMPLETE_BIOZ,
2092  SI117x_TASK_COMPLETE_ECG,
2093  SI117x_TASK_COMPLETE_ECG_LD
2094 }si117xFifoStateTaskComplete_t;
2095 
2096 
2097 
2098 
2099 
2100 static int16_t si117xFifoStateMachine_Next(SI117XDRV_DeviceSelect_t device, uint8_t isDle, uint8_t dleDataByte, si117xFifoStateTaskComplete_t *taskComplete);
2101 
2102 
2103 
2104 //dlc: We now have two different ways to perform accelerometer synchronization. The newer (and better) method does not use the accel synch markers in the FIFO. Need to make sure this architecture works with both methods
2105 static uint16_t ppg1_sample_count[SI117XDRV_MAX_NUM_DEVICES];
2106 static uint16_t ppg2_sample_count[SI117XDRV_MAX_NUM_DEVICES];
2107 static uint16_t ppg3_sample_count[SI117XDRV_MAX_NUM_DEVICES];
2108 static uint16_t ppg4_sample_count[SI117XDRV_MAX_NUM_DEVICES];
2109 
2110 
2111 
2112 static uint16_t ppg_count;
2113 
2114 static void resetSynchSampleCounters (SI117XDRV_DeviceSelect_t device)
2115 {
2116  ppg1_sample_count[device]=0;
2117  ppg2_sample_count[device]=0;
2118  ppg3_sample_count[device]=0;
2119  ppg4_sample_count[device]=0;
2120 }
2121 
2122 /***************************************************************************/
2132 {
2133  si117xFifoStateMachine_t *fifoStateMachine = &(fifoStateMachines[device]);
2134  fifoStateMachine->fifoState = SI117x_FIFO_STATE_UNKNOWN;
2135  fifoStateMachine->isMsb = 1;
2136  fifoStateMachine->ppg_value[0] = 0;
2137  fifoStateMachine->ppg_value[1] = 0;
2138  fifoStateMachine->ppg_value[2] = 0;
2139  fifoStateMachine->ppg_value[3] = 0;
2140  fifoStateMachine->bioz_value[0] = 0;
2141  fifoStateMachine->bioz_value[1] = 0;
2142  fifoStateMachine->ecg_value = 0;
2143  Unprocessed_DLE = false;
2144  resetSynchSampleCounters(device);
2145  return ECODE_SI117XDRV_OK;
2146 }
2147 
2148 /***************************************************************************/
2163 Si117x_Ecode_t SI117XDRV_ProcessPPGInterrupt (SI117XDRV_DeviceSelect_t device, uint8_t *fifoData, uint16_t timestamp, uint16_t irqSequence)
2164 {
2165  uint16_t ppg[4];
2166  Si117x_Ecode_t ret = 0;
2167  SI117XDRV_PPG24bSample_t sample;
2168  SI117XDRV_PPGSample_t sample16;
2169  int i;
2170  uint32_t j=0;
2171  for (i=0; i<4; i++)
2172  {
2173  if ( fifoData[j]==0x10 && fifoData[j+1]=='P' ) // discard PPG header
2174  j=j+2;
2175  if ( fifoData[j]==0x10 && fifoData[j+1]=='A' ) // discard SYNC header
2176  j=j+2;
2177  if (fifoData[j]== 0x10 && fifoData[j+1]== 0x10) // double DLE? Dump one
2178  j++;
2179  ppg[i] = 256 *fifoData[j] + fifoData[j+1]; // combine MSB with LSB. LSB does not have DLE shielding
2180  j = j+2;
2181  }
2182  sample.sequence = irqSequence;
2183  sample.syncMessage = 0;
2184  sample.timestamp = timestamp;
2185  sample.ppg1 = ppg[0];
2186  sample.ppg2 = ppg[1];
2187  sample.ppg3 = ppg[2];
2188  sample.ppg4 = ppg[3];
2189  ret = SI117XDRV_EnqueuePPG24bSampleData(&sample);
2190  sample16.timestamp = sample.timestamp;
2191  sample16.syncMessage = sample.syncMessage;
2192  sample16.sequence = sample.sequence;
2193  sample16.ppg1 = sample.ppg1;
2194  sample16.ppg2 = sample.ppg2;
2195  sample16.ppg3 = sample.ppg3;
2196  sample16.ppg4 = sample.ppg4;
2197  ret |= SI117XDRV_EnqueuePPG16bSampleData(&sample16);
2198  return ret;
2199 }
2200 
2201 void setFifoProcessingValues(int oversampling, uint8_t meas_cntl, uint8_t taskEnable, uint8_t ppg_measconfig0, uint8_t ppg_measconfig1, uint8_t ppg_measconfig2, uint8_t ppg_measconfig3 )
2202 //temporary function to get demo working
2203 {
2204  devices[0].deviceCfg.globalCfg.taskEnable = taskEnable;
2205  devices[0].deviceCfg.globalCfg.meas_cntl = meas_cntl;
2206  devices[0].deviceStatus.hrmOversamplingRatio = oversampling;
2207  devices[0].deviceCfg.ppgCfg.ppgCfg[0].ppg_measconfig = ppg_measconfig0;
2208  devices[0].deviceCfg.ppgCfg.ppgCfg[1].ppg_measconfig = ppg_measconfig1;
2209  devices[0].deviceCfg.ppgCfg.ppgCfg[2].ppg_measconfig = ppg_measconfig2;
2210  devices[0].deviceCfg.ppgCfg.ppgCfg[3].ppg_measconfig = ppg_measconfig3;
2211 }
2212 
2213 /***************************************************************************/
2230 Si117x_Ecode_t SI117XDRV_ProcessFifoData(SI117XDRV_DeviceSelect_t device, uint8_t *record, uint16_t fifo_length, uint16_t timestamp, uint16_t irqSequence)
2231 {
2232  int i;
2233  char data_byte = 0;
2234  uint8_t *record_ptr;
2236  si117xFifoStateTaskComplete_t task_complete;
2237  SI117XDRV_PPG24bSample_t sample;
2238  SI117XDRV_PPGSample_t sample16;
2239  SI117XDRV_ECGSample_t sampleECG;
2240  SI117XDRV_ECGLDSample_t sampleECGLD;
2241  si117xFifoStateMachine_t *fifoStateMachine = &(fifoStateMachines[device]);
2242  SI117XDRV_GlobalRegisters_t *configuration;
2243  SI117XDRV_PPGRegisters_t *ppgCfg;
2244  configuration = &(devices[device].deviceCfg.globalCfg);
2245  ppgCfg = &(devices[device].deviceCfg.ppgCfg);
2246  record_ptr = &(*record); // start of data read from FIFO
2247 
2248  for (i = 0; i < fifo_length; i += 1) // process until end of buffer
2249  {
2250  data_byte = record_ptr[i];
2251 
2252  if (Unprocessed_DLE==true) // If last record ended with a DLE, process it using first data bytes from this record .
2253  {
2254  Unprocessed_DLE = false; // Don't increment i
2255  if (data_byte != 0x10) // if the second byte is not a DLE then decode it as a command
2256  {
2257  if (data_byte=='S')
2258  { // <DLE>S found.
2259  found_DLE_S = 1; // insert S marker into next sample structure
2260  i++;
2261  DLE_S_tag = record_ptr[i]; // N, ID tag associated with <DLE>S
2262  continue;
2263  }
2264 
2265  si117xFifoStateMachine_Next(device, 1, data_byte, &task_complete);
2266  continue;
2267  }
2268  else
2269  goto Take_DLE_as_data;
2270  }
2271 
2272  if (Unprocessed_DLE_S == true)
2273  {
2274  Unprocessed_DLE_S = false;
2275  found_DLE_S = 1;
2276  DLE_S_tag = data_byte;
2277  continue;
2278  }
2279 
2280 
2281  if ((data_byte == 0x10) && fifoStateMachine->isMsb && (i <= fifo_length-2)) //if DLE & we are looking at MSB then check the next byte
2282  { // but will only work if there are at least two more data bytes left in this record. // "-5" includes the two ASCII DLE bytes + two more data bytes + 0x10 (real DLE) terminator.
2283 
2284  i += 1;
2285  data_byte = record_ptr[i];
2286 
2287  if (data_byte == 'S')
2288  {
2289  if (i == fifo_length-1) // <DLE>S, but we don't have N in this block since it is end of data block
2290  {
2291  Unprocessed_DLE_S = true;
2292  continue;
2293  }
2294 
2295  found_DLE_S = 1;
2296  i++;
2297  DLE_S_tag = record_ptr[i];
2298  continue;
2299  }
2300 
2301  if (data_byte != 0x10) //if the second byte is not a DLE then decode it as a command
2302  {
2303  si117xFifoStateMachine_Next(device, 1, data_byte, &task_complete);
2304  continue;
2305  }
2306  }
2307  else if ((data_byte == 0x10) && fifoStateMachine->isMsb) // (DLE) is at end of record. Cannot deal with it yet.
2308  {
2309  Unprocessed_DLE = true; // set flag to tell next record to deal with it
2310  return ret;
2311  }
2312 
2313 
2314 Take_DLE_as_data:
2315  switch (fifoStateMachine->fifoState)
2316  {
2317  case SI117x_FIFO_STATE_PPG1_HI:
2318  fifoStateMachine->ppg_value[0] = (data_byte << 16) & 0xFF0000;
2319  break;
2320  case SI117x_FIFO_STATE_PPG1_MID:
2321  fifoStateMachine->ppg_value[0] |= (data_byte << 8) & 0x00FF00;
2322  ppg1_sample_count[device]++;
2323  break;
2324  case SI117x_FIFO_STATE_PPG1_LO:
2325  fifoStateMachine->ppg_value[0] |= data_byte & 0x0000FF;
2326  break;
2327  case SI117x_FIFO_STATE_PPG2_HI:
2328  fifoStateMachine->ppg_value[1] = (data_byte << 16) & 0xFF0000;
2329  break;
2330  case SI117x_FIFO_STATE_PPG2_MID:
2331  fifoStateMachine->ppg_value[1] |= (data_byte << 8) & 0x00FF00;
2332  ppg2_sample_count[device]++;
2333  break;
2334  case SI117x_FIFO_STATE_PPG2_LO:
2335  fifoStateMachine->ppg_value[1] |= data_byte & 0x0000FF;
2336  break;
2337  case SI117x_FIFO_STATE_PPG3_HI:
2338  fifoStateMachine->ppg_value[2] = (data_byte << 16) & 0xFF0000;
2339  break;
2340  case SI117x_FIFO_STATE_PPG3_MID:
2341  fifoStateMachine->ppg_value[2] |= (data_byte << 8) & 0x00FF00;
2342  ppg3_sample_count[device]++;
2343  break;
2344  case SI117x_FIFO_STATE_PPG3_LO:
2345  fifoStateMachine->ppg_value[2] |= data_byte & 0x0000FF;
2346  break;
2347  case SI117x_FIFO_STATE_PPG4_HI:
2348  fifoStateMachine->ppg_value[3] = (data_byte << 16) & 0xFF0000;
2349  break;
2350  case SI117x_FIFO_STATE_PPG4_MID:
2351  fifoStateMachine->ppg_value[3] |= (data_byte << 8) & 0x00FF00;
2352  ppg4_sample_count[device]++;
2353  break;
2354  case SI117x_FIFO_STATE_PPG4_LO:
2355  fifoStateMachine->ppg_value[3] |= data_byte & 0x0000FF;
2356  break;
2357  case SI117x_FIFO_STATE_BIOZ1_HI:
2358  fifoStateMachine->bioz_value[0] = (data_byte << 16) & 0xFF0000;
2359  break;
2360  case SI117x_FIFO_STATE_BIOZ1_MID:
2361  fifoStateMachine->bioz_value[0] |= (data_byte << 8) & 0x00FF00;
2362  break;
2363  case SI117x_FIFO_STATE_BIOZ1_LO:
2364  fifoStateMachine->bioz_value[0] |= data_byte & 0x0000FF;
2365  break;
2366  case SI117x_FIFO_STATE_BIOZ2_HI:
2367  fifoStateMachine->bioz_value[1] = (data_byte << 16) & 0xFF0000;
2368  break;
2369  case SI117x_FIFO_STATE_BIOZ2_MID:
2370  fifoStateMachine->bioz_value[1] |= (data_byte << 8) & 0x00FF00;
2371  break;
2372  case SI117x_FIFO_STATE_BIOZ2_LO:
2373  fifoStateMachine->bioz_value[1] |= data_byte & 0x0000FF;
2374  break;
2375  case SI117x_FIFO_STATE_ECG_HI:
2376  fifoStateMachine->ecg_value = (data_byte << 16) & 0xFF0000;
2377  break;
2378  case SI117x_FIFO_STATE_ECG_MID:
2379  fifoStateMachine->ecg_value |= (data_byte << 8) & 0x00FF00;
2380  break;
2381  case SI117x_FIFO_STATE_ECG_LO:
2382  fifoStateMachine->ecg_value |= data_byte & 0x0000FF;
2383  break;
2384  case SI117x_FIFO_STATE_ECG_LD_BYTE1:
2385  fifoStateMachine->ecg_ld_value[0] = data_byte;
2386  break;
2387  case SI117x_FIFO_STATE_ECG_LD_BYTE2:
2388  fifoStateMachine->ecg_ld_value[1] = data_byte;
2389  break;
2390  case SI117x_FIFO_STATE_ECG_LD_BYTE3:
2391  fifoStateMachine->ecg_ld_value[2] = data_byte;
2392  break;
2393  case SI117x_FIFO_STATE_ECG_LD_BYTE4:
2394  fifoStateMachine->ecg_ld_value[3] = data_byte;
2395  break;
2396  case SI117x_FIFO_STATE_UNKNOWN:
2397  break;
2398  }
2399 
2400  si117xFifoStateMachine_Next(device, 0, 0, &task_complete);
2401 
2402  if (task_complete == SI117x_TASK_COMPLETE_ECG)
2403  {
2404 
2405  sampleECG.sequence = irqSequence;
2406  sampleECG.timestamp = timestamp;
2407  sampleECG.syncMessage = 0;
2408  sampleECG.ecg = fifoStateMachine->ecg_value;
2409  ret |= SI117XDRV_EnqueueECGSampleData(&sampleECG);
2410  fifoStateMachine->ecg_value =0;
2411  }
2412  if (task_complete == SI117x_TASK_COMPLETE_ECG_LD)
2413  {
2414 
2415  sampleECGLD.sequence = irqSequence;
2416  sampleECGLD.timestamp = timestamp;
2417  sampleECGLD.syncMessage = 0;
2418  sampleECGLD.data[0] = fifoStateMachine->ecg_ld_value[0];
2419  sampleECGLD.data[1] = fifoStateMachine->ecg_ld_value[1];
2420  sampleECGLD.data[2] = fifoStateMachine->ecg_ld_value[2];
2421  sampleECGLD.data[3] = fifoStateMachine->ecg_ld_value[3];
2422  ret |= SI117XDRV_EnqueueECGLDSampleData(&sampleECGLD);
2423  fifoStateMachine->ecg_ld_value[0] =0;
2424  fifoStateMachine->ecg_ld_value[1] =0;
2425  fifoStateMachine->ecg_ld_value[2] =0;
2426  fifoStateMachine->ecg_ld_value[3] =0;
2427  }
2428  if (task_complete == SI117x_TASK_COMPLETE_PPG)
2429  {
2430  int j;
2431  uint32_t mask;
2432 
2433  for (j = 0; j < 4; j++)
2434  {
2435  if ((ppgCfg->ppgCfg[j].ppg_measconfig & 0x10) != 0) // if raw ppg mode then the number is 2's complement and me must signe extend it
2436  {
2437  mask = (uint32_t)0x8000 << (8 * (configuration->meas_cntl & 0x01)); //create the 16 or 24-bit mask
2438  if (fifoStateMachine->ppg_value[j] & mask) //if sign bit is high then sign-extend
2439  fifoStateMachine->ppg_value[j] |= 0xFFFF0000 << (8 * (configuration->meas_cntl & 0x01));
2440  }
2441  }
2442 
2443  sample.timestamp = timestamp;
2444  sample.syncMessage = 0;
2445  sample.sequence = irqSequence;
2446  sample.ppg1 = fifoStateMachine->ppg_value[0];
2447  sample.ppg2 = fifoStateMachine->ppg_value[1];
2448  sample.ppg3 = fifoStateMachine->ppg_value[2];
2449  sample.ppg4 = fifoStateMachine->ppg_value[3];
2450  if (found_DLE_S==true)
2451  {
2452  sample.syncMessage = DLE_S_tag;
2453  found_DLE_S=false;
2454  }
2455 
2456  ret |= SI117XDRV_EnqueuePPG24bSampleData(&sample);
2457  sample16.timestamp = sample.timestamp;
2458  sample16.syncMessage = sample.syncMessage;
2459  sample16.sequence = sample.sequence;
2460  sample16.ppg1 = sample.ppg1;
2461  sample16.ppg2 = sample.ppg2;
2462  sample16.ppg3 = sample.ppg3;
2463  sample16.ppg4 = sample.ppg4;
2464  ret |= SI117XDRV_EnqueuePPG16bSampleData(&sample16);
2465  fifoStateMachine->ppg_value[0] = 0;
2466  fifoStateMachine->ppg_value[1] = 0;
2467  fifoStateMachine->ppg_value[2] = 0;
2468  fifoStateMachine->ppg_value[3] = 0;
2469 
2470  }
2471  }
2472  return ret;
2473 }
2474 
2475 
2476 
2477 /**************************************************************************/
2480 static int16_t si117xFifoStateMachine_Next(SI117XDRV_DeviceSelect_t device, uint8_t isDle, uint8_t dleDataByte, si117xFifoStateTaskComplete_t *taskComplete)
2481 {
2482  int16_t error = 0;
2483  si117xFifoStateMachine_t *fifoStateMachine = &(fifoStateMachines[device]);
2484  SI117XDRV_GlobalRegisters_t *configuration;
2485  configuration = &(devices[device].deviceCfg.globalCfg);
2486 #if 1
2487  *taskComplete = SI117x_TASK_NOT_COMPLETE;
2488  fifoStateMachine->isMsb = 1; //the code below will set this to 0 when it should
2489  uint16_t oversampling = devices[device].deviceStatus.hrmOversamplingRatio;
2490  if (isDle == 1)
2491  {
2492  switch (dleDataByte)
2493  {
2494  case 'P':
2495  if (configuration->taskEnable & 0x1)
2496  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG1_HI : SI117x_FIFO_STATE_PPG1_MID;
2497  else if (configuration->taskEnable & 0x2)
2498  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG2_HI : SI117x_FIFO_STATE_PPG2_MID;
2499  else if (configuration->taskEnable & 0x4)
2500  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG3_HI : SI117x_FIFO_STATE_PPG3_MID;
2501  else if (configuration->taskEnable & 0x8)
2502  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG4_HI : SI117x_FIFO_STATE_PPG4_MID;
2503  else
2504  fifoStateMachine->fifoState = SI117x_FIFO_STATE_UNKNOWN;
2505  break;
2506  case 'E':
2507  if (configuration->taskEnable & 0x40)
2508  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x4) ? SI117x_FIFO_STATE_ECG_HI : SI117x_FIFO_STATE_ECG_MID;
2509  else
2510  fifoStateMachine->fifoState = SI117x_FIFO_STATE_UNKNOWN;
2511  break;
2512  case 'B':
2513  if (configuration->taskEnable & 0x10)
2514  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ1_HI : SI117x_FIFO_STATE_BIOZ1_MID;
2515  else if (configuration->taskEnable & 0x20)
2516  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ2_HI : SI117x_FIFO_STATE_BIOZ2_MID;
2517  else
2518  fifoStateMachine->fifoState = SI117x_FIFO_STATE_UNKNOWN;
2519  break;
2520 
2521  case 'A':
2522 
2523  if (configuration->taskEnable & 0x01) {
2524  ppg_count = ppg1_sample_count[device];
2525  ppg1_sample_count[device] = 0; }
2526  else if (configuration->taskEnable & 0x02) {
2527  ppg_count = ppg2_sample_count[device];
2528  ppg2_sample_count[device] = 0; }
2529  else if (configuration->taskEnable & 0x04) {
2530  ppg_count = ppg3_sample_count[device];
2531  ppg3_sample_count[device] = 0; }
2532  else if (configuration->taskEnable & 0x08) {
2533  ppg_count = ppg4_sample_count[device];
2534  ppg4_sample_count[device] = 0; }
2535 
2536 
2537  // Only oversampling of 2, 4 and 8 are supported right now
2538  if (oversampling == 8)
2539  ppg_count = (ppg_count + 4) >> 3; // divide by configuration->oversampling with rounding
2540  if (oversampling == 4)
2541  ppg_count = (ppg_count + 2) >> 2; // divide by configuration->oversampling with rounding
2542  if (oversampling == 2)
2543  ppg_count = (ppg_count + 1) >> 1; // divide by configuration->oversampling with rounding
2544  accelSyncCallbacks(device, ppg_count);
2545  //AccelResample_SynchMessageReceived(ppg_count);
2546 
2547  break;
2548  case 'S':
2549  //user sync
2550  break;
2551  case 'F':
2552  //measurement overrun
2553  break;
2554  case 'L':
2555  fifoStateMachine->fifoState = SI117x_FIFO_STATE_ECG_LD_BYTE1;
2556  break;
2557  default:
2558  //fifoStateMachine->fifoState = SI117x_FIFO_STATE_UNKNOWN;
2559  break;
2560  }
2561  }
2562 
2563  else
2564  {
2565  switch (fifoStateMachine->fifoState)
2566  {
2567  case SI117x_FIFO_STATE_PPG1_HI: case SI117x_FIFO_STATE_PPG1_MID:
2568  case SI117x_FIFO_STATE_PPG2_HI: case SI117x_FIFO_STATE_PPG2_MID:
2569  case SI117x_FIFO_STATE_PPG3_HI: case SI117x_FIFO_STATE_PPG3_MID:
2570  case SI117x_FIFO_STATE_PPG4_HI: case SI117x_FIFO_STATE_PPG4_MID:
2571  case SI117x_FIFO_STATE_BIOZ1_HI: case SI117x_FIFO_STATE_BIOZ1_MID:
2572  case SI117x_FIFO_STATE_BIOZ2_HI: case SI117x_FIFO_STATE_BIOZ2_MID:
2573  case SI117x_FIFO_STATE_ECG_HI: case SI117x_FIFO_STATE_ECG_MID:
2574  case SI117x_FIFO_STATE_ECG_LD_BYTE1: case SI117x_FIFO_STATE_ECG_LD_BYTE2:
2575  case SI117x_FIFO_STATE_ECG_LD_BYTE3:
2576  fifoStateMachine->fifoState = (si117xFifoState_t)(fifoStateMachine->fifoState + 1);
2577  fifoStateMachine->isMsb = 0;
2578  break;
2579  case SI117x_FIFO_STATE_ECG_LD_BYTE4:
2580  fifoStateMachine->fifoState = SI117x_FIFO_STATE_ECG_LD_BYTE1;
2581  *taskComplete = SI117x_TASK_COMPLETE_ECG_LD;
2582  break;
2583  case SI117x_FIFO_STATE_PPG1_LO:
2584  if (configuration->taskEnable & 0x2)
2585  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG2_HI : SI117x_FIFO_STATE_PPG2_MID;
2586  else if (configuration->taskEnable & 0x4)
2587  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG3_HI : SI117x_FIFO_STATE_PPG3_MID;
2588  else if (configuration->taskEnable & 0x8)
2589  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG4_HI : SI117x_FIFO_STATE_PPG4_MID;
2590  else
2591  {
2592  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG1_HI : SI117x_FIFO_STATE_PPG1_MID;
2593  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2594  }
2595  break;
2596  case SI117x_FIFO_STATE_PPG2_LO:
2597  if (configuration->taskEnable & 0x4)
2598  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG3_HI : SI117x_FIFO_STATE_PPG3_MID;
2599  else if (configuration->taskEnable & 0x8)
2600  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG4_HI : SI117x_FIFO_STATE_PPG4_MID;
2601  else if (configuration->taskEnable & 0x1)
2602  {
2603  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG1_HI : SI117x_FIFO_STATE_PPG1_MID;
2604  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2605  }
2606  else
2607  {
2608  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG2_HI : SI117x_FIFO_STATE_PPG2_MID;
2609  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2610  }
2611  break;
2612  case SI117x_FIFO_STATE_PPG3_LO:
2613  if (configuration->taskEnable & 0x8)
2614  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG4_HI : SI117x_FIFO_STATE_PPG4_MID;
2615  else if (configuration->taskEnable & 0x1)
2616  {
2617  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG1_HI : SI117x_FIFO_STATE_PPG1_MID;
2618  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2619  }
2620  else if (configuration->taskEnable & 0x2)
2621  {
2622  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG2_HI : SI117x_FIFO_STATE_PPG2_MID;
2623  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2624  }
2625  else
2626  {
2627  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG3_HI : SI117x_FIFO_STATE_PPG3_MID;
2628  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2629  }
2630 
2631  break;
2632  case SI117x_FIFO_STATE_PPG4_LO:
2633  if (configuration->taskEnable & 0x1)
2634  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG1_HI : SI117x_FIFO_STATE_PPG1_MID;
2635  else if (configuration->taskEnable & 0x2)
2636  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG2_HI : SI117x_FIFO_STATE_PPG2_MID;
2637  else if (configuration->taskEnable & 0x4)
2638  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG3_HI : SI117x_FIFO_STATE_PPG3_MID;
2639  else
2640  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x1) ? SI117x_FIFO_STATE_PPG4_HI : SI117x_FIFO_STATE_PPG4_MID;
2641  *taskComplete = SI117x_TASK_COMPLETE_PPG;
2642  break;
2643  case SI117x_FIFO_STATE_BIOZ1_LO:
2644  if (configuration->taskEnable & 0x20)
2645  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ2_HI : SI117x_FIFO_STATE_BIOZ2_MID;
2646  else
2647  {
2648  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ1_HI : SI117x_FIFO_STATE_BIOZ1_MID;
2649  *taskComplete = SI117x_TASK_COMPLETE_BIOZ;
2650  }
2651  break;
2652  case SI117x_FIFO_STATE_BIOZ2_LO:
2653  if (configuration->taskEnable & 0x10)
2654  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ1_HI : SI117x_FIFO_STATE_BIOZ1_MID;
2655  else
2656  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x2) ? SI117x_FIFO_STATE_BIOZ2_HI : SI117x_FIFO_STATE_BIOZ2_MID;
2657  *taskComplete = SI117x_TASK_COMPLETE_BIOZ;
2658  break;
2659  case SI117x_FIFO_STATE_ECG_LO:
2660  fifoStateMachine->fifoState = (configuration->meas_cntl & 0x4) ? SI117x_FIFO_STATE_ECG_HI : SI117x_FIFO_STATE_ECG_MID;
2661  *taskComplete = SI117x_TASK_COMPLETE_ECG;
2662  break;
2663  case SI117x_FIFO_STATE_UNKNOWN:
2664  break;
2665  }
2666  }
2667 
2668  if (fifoStateMachine->fifoState == SI117x_FIFO_STATE_UNKNOWN)
2669  fifoStateMachine->isMsb = 0;
2670 #endif
2671  return error;
2672 }
2673 
2674 /* *INDENT-OFF* */
2675 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/
Si117x_Ecode_t SI117XDRV_FifoIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable fifo interrupt.
Definition: si117xdrv.c:523
int32_t ppg3
ppg3 sample data
Definition: si117xdrv.h:53
Si117x_Ecode_t SI117XDRV_SetECGTaskEnable(SI117XDRV_DeviceSelect_t device, uint8_t ecgTasks)
Configure ECG tasks.
Definition: si117xdrv.c:495
uint32_t SI117XDRV_DataQueueID_t
Queue ID.
Definition: si117xdrv.h:246
Si117x_Ecode_t SI117XDRV_GetFifoIntLevel(SI117XDRV_DeviceSelect_t device, uint16_t *fifo_int_level)
Returns the current fifo interrupt level the Si117x.
Definition: si117xdrv.c:346
uint32_t ecgldSampleRateus
desired ECG LD sample rate us
Definition: si117xdrv.h:142
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:61
void * user
User supplied data.
Definition: si117xdrv.c:53
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:49
static Si117x_Ecode_t SI117XDRV_EnqueueBIOZSampleData(SI117XDRV_BIOZSample_t *sample)
Enqueue Si117x bioz sample data.
Definition: si117xdrv.c:1908
uint32_t biozSampleRateus
desired bioz sample rate in us
Definition: si117xdrv.h:143
volatile uint16_t tail
Index of where to enqueue next byte.
Definition: si117xdrv.c:1263
SI117XDRV_SampleSize_t ecgSampleSize
ecg sample size setting
Definition: si117xdrv.h:152
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:84
Si117x_Ecode_t SI117XDRV_StartLegacyPPG(SI117XDRV_DeviceSelect_t device, uint8_t ppg_meascount, uint16_t measrate)
Start legacy PPG mode (ECG & BIOZ will be disabled before start) This function overwrites some config...
Definition: si117xdrv.c:636
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:62
Si117x_Ecode_t SI117XDRV_DequeuePPGSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_PPGSample_t *sample)
Remove a 16bit PPG sample from the queue.
Definition: si117xdrv.c:1753
General callback function datatype.
Definition: si117xdrv.c:39
static Si117x_Ecode_t SI117XDRV_EnqueueECGLDSampleData(SI117XDRV_ECGLDSample_t *sample)
Enqueue Si117x ECG LD sample data.
Definition: si117xdrv.c:1810
uint8_t data[4]
ecg ld sample data
Definition: si117xdrv.h:87
Si117x_Ecode_t SI117XDRV_Start(SI117XDRV_DeviceSelect_t device)
Start running measurements with the current configuration.
Definition: si117xdrv.c:745
#define SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES
PPG sample size in bytes.
Definition: si117xdrv.h:57
si117xFifoState
Definition: si117xdrv.c:2035
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:74
int16_t ppg1
ppg1 sample data
Definition: si117xdrv.h:64
#define SI117XDRV_ECG_SAMPLE_SIZE_BYTES
ECG sample size in bytes.
Definition: si117xdrv.h:80
Si117x_Ecode_t SI117XDRV_DequeueECGSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_ECGSample_t *sample)
Remove an ECG sample from the queue.
Definition: si117xdrv.c:1887
#define ECODE_SI117XDRV_ALL_CB_USED
All callbacks used.
Definition: si117xdrv.h:37
Si117x_Ecode_t SI117XDRV_ProcessPPGInterrupt(SI117XDRV_DeviceSelect_t device, uint8_t *fifoData, uint16_t timestamp, uint16_t irqSequence)
PPG1 interrupt handler.
Definition: si117xdrv.c:2163
Si117x_Ecode_t SI117XDRV_Stop(SI117XDRV_DeviceSelect_t device)
Stop running measurements in the Si117x.
Definition: si117xdrv.c:719
Si117x_Ecode_t SI117XDRV_PPG1IntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable PPG interrupt.
Definition: si117xdrv.c:550
#define SI117XDRV_TASK_BIOZ_DC_EN
BIOZ DC task enable bit.
Definition: si117xdrv.h:129
uint32_t SI117XDRV_DeviceSelect_t
Device ID.
Definition: si117xdrv.h:250
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:50
int32_t ppg2
ppg2 sample data
Definition: si117xdrv.h:52
SI117XDRV_MSPolar_t ms_polar
ms pin polarity
Definition: si117xdrv.h:150
uint16_t size
Size of FIFO.
Definition: si117xdrv.c:1265
bool allocated
Flag to indicate callback data is set //todo: do we really need this allocated member? Can&#39;t we just say if callback == NULL then not allocated?
Definition: si117xdrv.c:43
static uint16_t SI117XDRV_NumBytesInQueue(SI117XDRV_FifoQueue_t *queue)
Get number of bytes in queue.
Definition: si117xdrv.c:1606
Si117x global configuration.
Definition: si117xdrv.h:139
Si117x_Ecode_t SI117XDRV_DequeueECGLDSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_ECGLDSample_t *sample)
Remove an ECG LD sample from the queue.
Definition: si117xdrv.c:1855
SI117XDRV_SampleSize_t biozSampleSize
bioz sample size setting
Definition: si117xdrv.h:153
Si117x_Ecode_t SI117XDRV_InitECGLD(SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGLDCfg_t *ecgCfg)
Configure ECG LD parameters.
Definition: si117xdrv.c:393
Si117x_Ecode_t SI117XDRV_StopLegacyPPG(SI117XDRV_DeviceSelect_t device)
Stop legacy PPG mode (restores ECG & BIOZ tasks as previously set)
Definition: si117xdrv.c:682
Si117x_Ecode_t SI117XDRV_ClearWristDetection(SI117XDRV_DeviceSelect_t device)
wrist detection algorithm
Definition: si117xdrv.c:1994
Si117XDRV ECG configuration.
Definition: si117xdrv.h:179
PPG sample data typedef.
Definition: si117xdrv.h:47
Si117x_Ecode_t SI117XDRV_DequeueBIOZSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_BIOZSample_t *sample)
Dequeue Si117x bioz sample data.
Definition: si117xdrv.c:1918
static Si117x_Ecode_t SI117XDRV_EnqueuePPG16bSampleData(SI117XDRV_PPGSample_t *sample)
Enqueue Si117x 16 bit PPG sample data.
Definition: si117xdrv.c:1632
#define ECODE_SI117XDRV_PARAM_ERROR
Invalid parameter.
Definition: si117xdrv.h:33
Si117x_Ecode_t SI117XDRV_InitGlobal(SI117XDRV_DeviceSelect_t device, SI117XDRV_GlobalCfg_t *globalCfg)
Configure global Si117x settings.
Definition: si117xdrv.c:887
Si117x_Ecode_t SI117XDRV_LeadDetection(SI117XDRV_DeviceSelect_t device, bool *leadDetectStatus)
Lead detection algorithm.
Definition: si117xdrv.c:1936
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:75
static Si117x_Ecode_t SI117XDRV_ClearRawQueue(SI117XDRV_FifoQueue_t *queue)
Empty queue.
Definition: si117xdrv.c:1526
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:85
Si117x_Ecode_t SI117XDRV_InitECG(SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGCfg_t *ecgCfg)
Configure ECG parameters.
Definition: si117xdrv.c:363
SI117XDRV_SampleSize_t ppgSampleSize
ppg sample size setting
Definition: si117xdrv.h:151
static Si117x_Ecode_t SI117XDRV_EnqueueRawData(SI117XDRV_FifoQueue_t *queue, int8_t *inputBuffer, uint16_t size)
Enqueue Si117x raw data.
Definition: si117xdrv.c:1553
#define SI117XDRV_IRQ_EN_PPG1
Legacy PPG irq enable bit.
Definition: si117xdrv.h:134
int32_t ppg1
ppg1 sample data
Definition: si117xdrv.h:51
int16_t ppg2
ppg2 sample data
Definition: si117xdrv.h:65
Raw data FIFO queue typedef.
Definition: si117xdrv.c:1270
uint32_t ppgSampleRateus
desired PPG sample rate in us
Definition: si117xdrv.h:140
int8_t * fifo
Pointer to FIFO of queue data (allocated by user)
Definition: si117xdrv.c:1266
Si117x_Ecode_t SI117XDRV_RegisterPostFifoFlushCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
Register a post fifo flush callback.
Definition: si117xdrv.c:1234
uint8_t taskEnable
The global task enable register.
Definition: si117xdrv.c:69
Raw data FIFO queue typedef.
Definition: si117xdrv.c:1261
ECG sample data typedef.
Definition: si117xdrv.h:83
Si117x_Ecode_t SI117XDRV_InitializeSi117xFifoStateMachine(SI117XDRV_DeviceSelect_t device)
Initializes the FIFO processing state machine.
Definition: si117xdrv.c:2131
#define SI117XDRV_TASK_ECG_LD_EN
ECG LD task enable bit.
Definition: si117xdrv.h:131
Si117x_Ecode_t SI117XDRV_FifoFlush(SI117XDRV_DeviceSelect_t device)
Flushes the Si117x fifo.
Definition: si117xdrv.c:231
Si117x_Ecode_t SI117XDRV_RegisterAccelSyncCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_AccelCallback_t callback, void *user)
Register an accelerometer sync message callback.
Definition: si117xdrv.c:1099
bool fifo_self_test
enable fifo self test mode
Definition: si117xdrv.h:147
Si117x_Ecode_t SI117XDRV_InitPPG(SI117XDRV_DeviceSelect_t device, SI117XDRV_PPGCfg_t *ppgCfg)
Configure PPG parameters.
Definition: si117xdrv.c:422
uint16_t SI117XDRV_NumSamplesInQueue(SI117XDRV_DataQueueID_t id)
Get number of samples in the queue.
Definition: si117xdrv.c:1620
static bool Unprocessed_DLE
Definition: si117xdrv.c:2082
#define SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES
ECG LD sample size in bytes.
Definition: si117xdrv.h:90
int32_t ppg4
ppg4 sample data
Definition: si117xdrv.h:54
int32_t Si117x_Ecode_t
SI117XDRV error code.
Definition: si117xdrv.h:27
Si117x_Ecode_t SI117XDRV_RegisterPostStartCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
Register a post start callback.
Definition: si117xdrv.c:1167
Si117x_Ecode_t SI117XDRV_ProcessLDInterrupt(SI117XDRV_DeviceSelect_t device)
lead detection interrupt handler
Definition: si117xdrv.c:2009
Si117x_Ecode_t SI117XDRV_WristDetection(SI117XDRV_DeviceSelect_t device, bool *wristDetectStatus)
wrist detection algorithm
Definition: si117xdrv.c:1977
PPG 16bit sample data typedef. Use this data type to save memory.
Definition: si117xdrv.h:60
int16_t ppg4
ppg4 sample data
Definition: si117xdrv.h:67
#define SI117XDRV_TASK_PPG4_EN
PPG4 task enable bit.
Definition: si117xdrv.h:127
Si117x_Ecode_t SI117XDRV_AllocatePPGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_PPGSample_t *queueBuffer, int16_t queueSizeInBytes)
Allocate a fifo queue for 16 bit PPG data.
Definition: si117xdrv.c:1306
#define ECODE_SI117XDRV_ALL_QUEUES_USED
No more queues left.
Definition: si117xdrv.h:32
uint8_t irq_enable
irq enable setting
Definition: si117xdrv.h:155
static SI117XDRV_Device_t devices[SI117XDRV_MAX_NUM_DEVICES]
Definition: si117xdrv.c:154
enum si117xFifoState si117xFifoState_t
Si117x_Ecode_t SI117XDRV_AllocateECGLDDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_ECGLDSample_t *queueBuffer, int16_t queueSizeInBytes)
Allocate a fifo queue for ECG data.
Definition: si117xdrv.c:1461
Si117x_Ecode_t SI117XDRV_ProcessFifoData(SI117XDRV_DeviceSelect_t device, uint8_t *record, uint16_t fifo_length, uint16_t timestamp, uint16_t irqSequence)
FIFO interrupt handler.
Definition: si117xdrv.c:2230
SI117XDRV_SynchMode_t synch_mode
sync mode
Definition: si117xdrv.h:149
bool allocated
Flag to indicate callback data is set.
Definition: si117xdrv.c:54
Si117x_Ecode_t SI117XDRV_InitAPI(SI117XDRV_DeviceSelect_t device, HANDLE deviceHandle)
Initializes API memory and device handle.
Definition: si117xdrv.c:1067
Si117XDRV ECG LD configuration.
Definition: si117xdrv.h:186
Si117x_Ecode_t SI117XDRV_Allocate24bPPGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_PPG24bSample_t *queueBuffer, int16_t queueSizeInBytes)
Allocate a fifo queue for PPG data.
Definition: si117xdrv.c:1357
void * user
User supplied data.
Definition: si117xdrv.c:42
bool fifo_disable
disable fifo
Definition: si117xdrv.h:148
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:76
Data structure containing all callback info.
Definition: si117xdrv.c:58
int32_t ecg
ecg sample data
Definition: si117xdrv.h:77
volatile uint16_t head
Index of next byte to get.
Definition: si117xdrv.c:1262
Si117x_Ecode_t SI117XDRV_Dequeue24bPPGSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_PPG24bSample_t *sample)
Remove a PPG sample from the queue.
Definition: si117xdrv.c:1719
#define ECODE_SI117XDRV_QUEUE_EMPTY
Fifo queue empty.
Definition: si117xdrv.h:31
ECG sample data typedef.
Definition: si117xdrv.h:73
static void accelSyncCallbacks(SI117XDRV_DeviceSelect_t device, uint16_t ppg_count)
Call accel sync DLE received callback functions.
Definition: si117xdrv.c:165
Accel sync DLE callback function datatype.
Definition: si117xdrv.c:50
SI117XDRV_Callback_t callback
Callback function pointer.
Definition: si117xdrv.c:41
Si117x_Ecode_t SI117XDRV_RegisterPreFifoFlushCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
Register a pre fifo flush callback.
Definition: si117xdrv.c:1201
static Si117x_Ecode_t SI117XDRV_EnqueuePPG24bSampleData(SI117XDRV_PPG24bSample_t *sample)
Enqueue Si117x PPG sample data.
Definition: si117xdrv.c:1670
uint8_t taskEnable
task enable
Definition: si117xdrv.h:146
#define ECODE_SI117XDRV_QUEUE_SIZE_ERROR
Invalid queue size.
Definition: si117xdrv.h:34
#define ECODE_SI117XDRV_RUNNING
Si117x is already running.
Definition: si117xdrv.h:35
static int16_t si117xFifoStateMachine_Next(SI117XDRV_DeviceSelect_t device, uint8_t isDle, uint8_t dleDataByte, si117xFifoStateTaskComplete_t *taskComplete)
Definition: si117xdrv.c:2480
Driver for Si117x.
#define ECODE_SI117XDRV_QUEUE_FULL
Fifo queue full.
Definition: si117xdrv.h:30
#define SI117XDRV_TASK_ECG_EN
ECG task enable bit.
Definition: si117xdrv.h:130
static Si117x_Ecode_t SI117XDRV_EnqueueECGSampleData(SI117XDRV_ECGSample_t *sample)
Enqueue Si117x ECG sample data.
Definition: si117xdrv.c:1779
Si117x_Ecode_t SI117XDRV_LDIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable lead detection interrupt.
Definition: si117xdrv.c:577
Si117x_Ecode_t SI117XDRV_ClearQueue(SI117XDRV_DataQueueID_t id)
Empty a fifo queue.
Definition: si117xdrv.c:1543
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:63
volatile uint16_t used
Number of bytes queued.
Definition: si117xdrv.c:1264
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:86
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:48
int16_t ppg3
ppg3 sample data
Definition: si117xdrv.h:66
SI117XDRV_AccelCallback_t callback
Callback function pointer.
Definition: si117xdrv.c:52
Si117x_Ecode_t SI117XDRV_WDIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable wrist detection interrupt.
Definition: si117xdrv.c:604
static Si117x_Ecode_t SI117XDRV_DequeueRawData(SI117XDRV_FifoQueue_t *queue, int8_t *buffer, uint16_t size)
Dequeue si117x raw data.
Definition: si117xdrv.c:1581
Si117x_Ecode_t SI117XDRV_Reset(SI117XDRV_DeviceSelect_t device)
Resets the Si117x.
Definition: si117xdrv.c:249
#define SI117XDRV_IRQ_EN_FIFO
Fifo irq enable bit.
Definition: si117xdrv.h:133
Si117x_Ecode_t SI117XDRV_GetPartInfo(SI117XDRV_DeviceSelect_t device, uint8_t *id, uint8_t *rev, uint8_t *mfr_id, uint8_t *pkg_led_cfg)
Returns the part number read from the Si117x.
Definition: si117xdrv.c:322
#define SI117XDRV_TASK_PPG2_EN
PPG2 task enable bit.
Definition: si117xdrv.h:125
void(* SI117XDRV_AccelCallback_t)(SI117XDRV_DeviceSelect_t device, uint16_t ppgCount, void *user)
Typedef for accel sync DLE message received event.
Definition: si117xdrv.h:281
#define SI117XDRV_TASK_PPG1_EN
PPG1 task enable bit.
Definition: si117xdrv.h:124
Si117x_Ecode_t SI117XDRV_SetPPGTaskEnable(SI117XDRV_DeviceSelect_t device, uint8_t ppgTasks)
Configure PPG tasks.
Definition: si117xdrv.c:466
#define SI117XDRV_TASK_BIOZ1_AC_EN
BIOZ AC task enable bit.
Definition: si117xdrv.h:128
Si117x_Ecode_t SI117XDRV_FreeDataQueue(SI117XDRV_DataQueueID_t id)
De-allocate a fifo queue.
Definition: si117xdrv.c:1509
#define ECODE_SI117XDRV_UNINITIALIZED
All callbacks used.
Definition: si117xdrv.h:38
Si117x_Ecode_t SI117XDRV_AllocateECGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_ECGSample_t *queueBuffer, int16_t queueSizeInBytes)
Allocate a fifo queue for ECG data.
Definition: si117xdrv.c:1409
#define SI117XDRV_TASK_PPG3_EN
PPG3 task enable bit.
Definition: si117xdrv.h:126
uint32_t accelSyncRateus
accel synchronization period in us
Definition: si117xdrv.h:144
Si117x_Ecode_t SI117XDRV_ProcessWDInterrupt(SI117XDRV_DeviceSelect_t device)
wrist detection interrupt handler
Definition: si117xdrv.c:2024
uint32_t ecgSampleRateus
desired ECG sample rate in us
Definition: si117xdrv.h:141
void(* SI117XDRV_Callback_t)(SI117XDRV_DeviceSelect_t device, void *user)
Typedef for the user supplied callback function which is called when a specific event happens...
Definition: si117xdrv.h:262
bioz sample data typedef
Definition: si117xdrv.h:93
uint16_t fifo_int_level
fifo interrupt level
Definition: si117xdrv.h:145
#define ECODE_SI117XDRV_OK
Success return value. //dlc: It is my opinion that these should be SI117XDRV_ECODE_....
Definition: si117xdrv.h:29
#define SI117XDRV_PPG_SAMPLE_SIZE_BYTES
PPG 16 bit sample size in bytes.
Definition: si117xdrv.h:70
Si117x_Ecode_t SI117XDRV_RegisterPreStartCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
Register a pre start callback.
Definition: si117xdrv.c:1133
Si117XDRV PPG configuration.
Definition: si117xdrv.h:230
uint8_t ppg_sw_avg
ppg sw avg setting
Definition: si117xdrv.h:154
#define ECODE_SI117XDRV_NOT_RUNNING
Si117x is not running.
Definition: si117xdrv.h:36