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 {
41 SI117XDRV_Callback_t callback;
42 void *user;
43 bool allocated;
44 }SI117XDRV_CallbackData_t;
45
46
47 //todo: generic DLE callback where the user can register for a given DLE byte
48
50 typedef struct
51 {
52 SI117XDRV_AccelCallback_t callback;
53 void *user;
54 bool allocated;
55 }SI117XDRV_AccelCallbackData_t;
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?
65 }SI117XDRV_Callbacks_t;
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;
76 } SI117XDRV_GlobalRegisters_t;
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;
86 } SI117XDRV_ECGRegisters_t;
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;
95 } SI117XDRV_BIOZChannelRegisters_t;
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;
106 } SI117XDRV_PPGChannelRegisters_t;
107
108 typedef struct
109 {
110 uint8_t ppg_meascount;
111 uint8_t ppg4_threshold;
112 SI117XDRV_PPGChannelRegisters_t ppgCfg[4];
113 } SI117XDRV_PPGRegisters_t;
114
115
116 typedef struct
117 {
118 SI117XDRV_BIOZChannelRegisters_t biozConfig[2];
119 uint8_t bioz_meascount;
120 uint8_t bioz_dc_value;
121 } SI117XDRV_BioZRegisters_t;
122
123 typedef struct
124 {
125 SI117XDRV_GlobalRegisters_t globalCfg;
126 SI117XDRV_ECGRegisters_t ecgCfg;
127 SI117XDRV_PPGRegisters_t ppgCfg;
128 SI117XDRV_BioZRegisters_t biozCfg;
129 } SI117XDRV_DeviceRegisters_t;
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;
141 } SI117XDRV_DeviceStatus_t;
142
143 typedef struct
144 {
145 HANDLE deviceHandle;
146 SI117XDRV_DeviceRegisters_t deviceCfg;
147 SI117XDRV_DeviceStatus_t deviceStatus;
148 } SI117XDRV_Device_t;
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 /***************************************************************************/
231 Si117x_Ecode_t SI117XDRV_FifoFlush (SI117XDRV_DeviceSelect_t device)
232 {
233 preFifoFlushCallbacks(device);
234 Si117xFlushFIFO(devices[device].deviceHandle);
235 postFifoFlushCallbacks(device);
236 return ECODE_SI117XDRV_OK;
237 }
238
239
240 /***************************************************************************/
249 Si117x_Ecode_t SI117XDRV_Reset (SI117XDRV_DeviceSelect_t device)
250 {
251 int i;
252 uint8_t retval;
253 //devices[device].deviceHandle = NULL;
254 if (initFlag[device] != 1)
255 {
256 return ECODE_SI117XDRV_UNINITIALIZED;
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 {
326 return ECODE_SI117XDRV_UNINITIALIZED;
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 /***************************************************************************/
346 Si117x_Ecode_t SI117XDRV_GetFifoIntLevel (SI117XDRV_DeviceSelect_t device, uint16_t *fifo_int_level)
347 {
348 *fifo_int_level = devices[device].deviceCfg.globalCfg.fifo_int_level;
349 return ECODE_SI117XDRV_OK;
350 }
351
352 /***************************************************************************/
363 Si117x_Ecode_t SI117XDRV_InitECG (SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGCfg_t *ecgCfg)
364 {
365 if (initFlag[device] != 1)
366 {
367 return ECODE_SI117XDRV_UNINITIALIZED;
368 }
369 if (devices[device].deviceStatus.running)
370 {
371 return ECODE_SI117XDRV_RUNNING;
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 /***************************************************************************/
393 Si117x_Ecode_t SI117XDRV_InitECGLD (SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGLDCfg_t *ecgCfg)
394 {
395 if (initFlag[device] != 1)
396 {
397 return ECODE_SI117XDRV_UNINITIALIZED;
398 }
399 if (devices[device].deviceStatus.running)
400 {
401 return ECODE_SI117XDRV_RUNNING;
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 /***************************************************************************/
422 Si117x_Ecode_t SI117XDRV_InitPPG (SI117XDRV_DeviceSelect_t device, SI117XDRV_PPGCfg_t *ppgCfg)
423 {
424 int i;
425 if (initFlag[device] != 1)
426 {
427 return ECODE_SI117XDRV_UNINITIALIZED;
428 }
429 if (devices[device].deviceStatus.running)
430 {
431 return ECODE_SI117XDRV_RUNNING;
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 {
471 return ECODE_SI117XDRV_UNINITIALIZED;
472 }
473 if (devices[device].deviceStatus.running)
474 {
475 return ECODE_SI117XDRV_RUNNING;
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 /***************************************************************************/
495 Si117x_Ecode_t SI117XDRV_SetECGTaskEnable (SI117XDRV_DeviceSelect_t device, uint8_t ecgTasks)
496 {
497 int8_t retval;
498 if (initFlag[device] != 1)
499 {
500 return ECODE_SI117XDRV_UNINITIALIZED;
501 }
502 if (devices[device].deviceStatus.running)
503 {
504 return ECODE_SI117XDRV_RUNNING;
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 /***************************************************************************/
523 Si117x_Ecode_t SI117XDRV_FifoIntConfig (SI117XDRV_DeviceSelect_t device, bool enable)
524 {
525 int8_t retval;
526 if (initFlag[device] != 1)
527 {
528 return ECODE_SI117XDRV_UNINITIALIZED;
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 /***************************************************************************/
550 Si117x_Ecode_t SI117XDRV_PPG1IntConfig (SI117XDRV_DeviceSelect_t device, bool enable)
551 {
552 int8_t retval;
553 if (initFlag[device] != 1)
554 {
555 return ECODE_SI117XDRV_UNINITIALIZED;
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 /***************************************************************************/
577 Si117x_Ecode_t SI117XDRV_LDIntConfig (SI117XDRV_DeviceSelect_t device, bool enable)
578 {
579 int8_t retval;
580 if (initFlag[device] != 1)
581 {
582 return ECODE_SI117XDRV_UNINITIALIZED;
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 /***************************************************************************/
604 Si117x_Ecode_t SI117XDRV_WDIntConfig (SI117XDRV_DeviceSelect_t device, bool enable)
605 {
606 int8_t retval;
607 if (initFlag[device] != 1)
608 {
609 return ECODE_SI117XDRV_UNINITIALIZED;
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 {
641 return ECODE_SI117XDRV_UNINITIALIZED;
642 }
643 if (devices[device].deviceStatus.running)
644 {
645 return ECODE_SI117XDRV_RUNNING;
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);
661 SI117XDRV_InitializeSi117xFifoStateMachine(device);
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 /***************************************************************************/
682 Si117x_Ecode_t SI117XDRV_StopLegacyPPG (SI117XDRV_DeviceSelect_t device)
683 {
684 //restore ppg meascounts, measrate, and irqenable etc to previous state...
685 uint8_t retval;
686 if (initFlag[device] != 1)
687 {
688 return ECODE_SI117XDRV_UNINITIALIZED;
689 }
690 if (devices[device].deviceStatus.running == false)
691 {
692 return ECODE_SI117XDRV_NOT_RUNNING;
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 /***************************************************************************/
719 Si117x_Ecode_t SI117XDRV_Stop (SI117XDRV_DeviceSelect_t device)
720 {
721 if (initFlag[device] != 1)
722 {
723 return ECODE_SI117XDRV_UNINITIALIZED;
724 }
725 if (devices[device].deviceStatus.running == false)
726 {
727 return ECODE_SI117XDRV_NOT_RUNNING;
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 /***************************************************************************/
745 Si117x_Ecode_t SI117XDRV_Start (SI117XDRV_DeviceSelect_t device)
746 {
747 if (initFlag[device] != 1)
748 {
749 return ECODE_SI117XDRV_UNINITIALIZED;
750 }
751 if (devices[device].deviceStatus.running)
752 {
753 return ECODE_SI117XDRV_RUNNING;
754 }
755 preStartCallbacks(device);
756 SI117XDRV_InitializeSi117xFifoStateMachine(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 /***************************************************************************/
887 Si117x_Ecode_t SI117XDRV_InitGlobal (SI117XDRV_DeviceSelect_t device, SI117XDRV_GlobalCfg_t *globalCfg)
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 {
898 return ECODE_SI117XDRV_UNINITIALIZED;
899 }
900 if (devices[device].deviceStatus.running)
901 {
902 return ECODE_SI117XDRV_RUNNING;
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
912 if (globalCfg->taskEnable & (SI117XDRV_TASK_BIOZ1_AC_EN|SI117XDRV_TASK_BIOZ_DC_EN))
913 {
914 //make sure no other task enabled
915 if (globalCfg->taskEnable & ~(SI117XDRV_TASK_BIOZ1_AC_EN|SI117XDRV_TASK_BIOZ_DC_EN))
916 {
917 return ECODE_SI117XDRV_PARAM_ERROR;
918 }
919 //otherwise calculate bioz_meascount
920 freqDivider = globalCfg->biozSampleRateus/50;
921 if (findMeasRate(freqDivider,&measrate,&bioz_meascount, globalCfg->accelSyncRateus)!= true)
922 {
923 return ECODE_SI117XDRV_PARAM_ERROR;
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 }
931 if (globalCfg->taskEnable & (SI117XDRV_TASK_PPG1_EN|SI117XDRV_TASK_PPG2_EN|SI117XDRV_TASK_PPG3_EN|SI117XDRV_TASK_PPG4_EN))
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 {
944 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
961 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
976 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
993 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
1011 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
1026 return ECODE_SI117XDRV_PARAM_ERROR;
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 {
1039 return ECODE_SI117XDRV_PARAM_ERROR;
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 /***************************************************************************/
1067 Si117x_Ecode_t SI117XDRV_InitAPI (SI117XDRV_DeviceSelect_t device, HANDLE deviceHandle)
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 /***************************************************************************/
1099 Si117x_Ecode_t SI117XDRV_RegisterAccelSyncCallback (SI117XDRV_DeviceSelect_t device, SI117XDRV_AccelCallback_t callback, void *user)
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 ) {
1110 return ECODE_SI117XDRV_ALL_CB_USED;
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 /***************************************************************************/
1133 Si117x_Ecode_t SI117XDRV_RegisterPreStartCallback (SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
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 ) {
1144 return ECODE_SI117XDRV_ALL_CB_USED;
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 /***************************************************************************/
1167 Si117x_Ecode_t SI117XDRV_RegisterPostStartCallback (SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
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 ) {
1178 return ECODE_SI117XDRV_ALL_CB_USED;
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 /***************************************************************************/
1201 Si117x_Ecode_t SI117XDRV_RegisterPreFifoFlushCallback (SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
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 ) {
1212 return ECODE_SI117XDRV_ALL_CB_USED;
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 /***************************************************************************/
1234 Si117x_Ecode_t SI117XDRV_RegisterPostFifoFlushCallback (SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
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 ) {
1245 return ECODE_SI117XDRV_ALL_CB_USED;
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;
1267 } SI117XDRV_FifoQueue_t;
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;
1278 } SI117XDRV_FifoQueueConfig_t;
1279
1280 static SI117XDRV_FifoQueueConfig_t queues[ SI117XDRV_MAX_DATA_QUEUES ];
1281
1282 /***************************************************************************/
1285 static Si117x_Ecode_t SI117XDRV_EnqueueRawData(SI117XDRV_FifoQueue_t *queue,
1286 int8_t *inputBuffer,
1287 uint16_t size);
1288 static Si117x_Ecode_t SI117XDRV_DequeueRawData(SI117XDRV_FifoQueue_t *queue,
1289 int8_t *buffer, uint16_t size);
1290 static Si117x_Ecode_t SI117XDRV_ClearRawQueue (SI117XDRV_FifoQueue_t *queue);
1291 static uint16_t SI117XDRV_NumBytesInQueue (SI117XDRV_FifoQueue_t *queue);
1292
1293 /***************************************************************************/
1306 Si117x_Ecode_t SI117XDRV_AllocatePPGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_PPGSample_t *queueBuffer, int16_t queueSizeInBytes)
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 ) {
1317 retVal = ECODE_SI117XDRV_ALL_QUEUES_USED;
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 {
1336 retVal = ECODE_SI117XDRV_QUEUE_SIZE_ERROR;
1337 }
1338 } else {
1339 retVal = ECODE_SI117XDRV_PARAM_ERROR;
1340 }
1341 }
1342 return retVal;
1343 }
1344 /***************************************************************************/
1357 Si117x_Ecode_t SI117XDRV_Allocate24bPPGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_PPG24bSample_t *queueBuffer, int16_t queueSizeInBytes)
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 ) {
1368 retVal = ECODE_SI117XDRV_ALL_QUEUES_USED;
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 {
1387 retVal = ECODE_SI117XDRV_QUEUE_SIZE_ERROR;
1388 }
1389 } else {
1390 retVal = ECODE_SI117XDRV_PARAM_ERROR;
1391 }
1392 }
1393 return retVal;
1394 }
1395
1396 /***************************************************************************/
1409 Si117x_Ecode_t SI117XDRV_AllocateECGDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_ECGSample_t *queueBuffer, int16_t queueSizeInBytes)
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 ) {
1420 retVal = ECODE_SI117XDRV_ALL_QUEUES_USED;
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 {
1439 retVal = ECODE_SI117XDRV_QUEUE_SIZE_ERROR;
1440 }
1441 } else {
1442 retVal = ECODE_SI117XDRV_PARAM_ERROR;
1443 }
1444 }
1445 return retVal;
1446 }
1447
1448 /***************************************************************************/
1461 Si117x_Ecode_t SI117XDRV_AllocateECGLDDataQueue(SI117XDRV_DataQueueID_t *id, SI117XDRV_ECGLDSample_t *queueBuffer, int16_t queueSizeInBytes)
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 ) {
1472 retVal = ECODE_SI117XDRV_ALL_QUEUES_USED;
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 {
1491 retVal = ECODE_SI117XDRV_QUEUE_SIZE_ERROR;
1492 }
1493 } else {
1494 retVal = ECODE_SI117XDRV_PARAM_ERROR;
1495 }
1496 }
1497 return retVal;
1498 }
1499
1500 /***************************************************************************/
1509 Si117x_Ecode_t SI117XDRV_FreeDataQueue(SI117XDRV_DataQueueID_t id)
1510 {
1511 // Check if valid callback ID.
1512 if ( id >= SI117XDRV_MAX_DATA_QUEUES ) {
1513 return ECODE_SI117XDRV_PARAM_ERROR;
1514 }
1515
1516 //CORE_ATOMIC_SECTION(
1517 queues[ id ].allocated = false;
1518 // )
1519
1520 return ECODE_SI117XDRV_OK;
1521 }
1522
1523 /***************************************************************************/
1526 static Si117x_Ecode_t SI117XDRV_ClearRawQueue (SI117XDRV_FifoQueue_t *queue)
1527 {
1528 queue->head = 0;
1529 queue->tail = 0;
1530 queue->used = 0;
1531 return ECODE_SI117XDRV_OK;
1532 }
1533
1534 /***************************************************************************/
1543 Si117x_Ecode_t SI117XDRV_ClearQueue (SI117XDRV_DataQueueID_t id)
1544 {
1545 return SI117XDRV_ClearRawQueue(&(queues[id].queue));
1546 }
1547
1548
1549
1550 /***************************************************************************/
1553 static Si117x_Ecode_t SI117XDRV_EnqueueRawData(SI117XDRV_FifoQueue_t *queue,
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 /***************************************************************************/
1581 static Si117x_Ecode_t SI117XDRV_DequeueRawData(SI117XDRV_FifoQueue_t *queue,
1582 int8_t *buffer, uint16_t size)
1583 {
1584 int i;
1585
1586 if (queue->used < size) {
1587 buffer = NULL;
1588
1589 return ECODE_SI117XDRV_QUEUE_EMPTY;
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 /***************************************************************************/
1606 static uint16_t SI117XDRV_NumBytesInQueue (SI117XDRV_FifoQueue_t *queue)
1607 {
1608 return queue->used;
1609 }
1610
1611 /***************************************************************************/
1620 uint16_t SI117XDRV_NumSamplesInQueue (SI117XDRV_DataQueueID_t id)
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 /***************************************************************************/
1632 static Si117x_Ecode_t SI117XDRV_EnqueuePPG16bSampleData(SI117XDRV_PPGSample_t *sample)
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 /***************************************************************************/
1670 static Si117x_Ecode_t SI117XDRV_EnqueuePPG24bSampleData(SI117XDRV_PPG24bSample_t *sample)
1671 {
1672 int8_t buffer[SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES];
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 /***************************************************************************/
1719 Si117x_Ecode_t SI117XDRV_Dequeue24bPPGSampleData (SI117XDRV_DataQueueID_t id, SI117XDRV_PPG24bSample_t *sample)
1720 {
1721 int8_t buffer[SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES];
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 /***************************************************************************/
1753 Si117x_Ecode_t SI117XDRV_DequeuePPGSampleData (SI117XDRV_DataQueueID_t id, SI117XDRV_PPGSample_t *sample)
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 /***************************************************************************/
1779 static Si117x_Ecode_t SI117XDRV_EnqueueECGSampleData(SI117XDRV_ECGSample_t *sample)
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 /***************************************************************************/
1810 static Si117x_Ecode_t SI117XDRV_EnqueueECGLDSampleData(SI117XDRV_ECGLDSample_t *sample)
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 /***************************************************************************/
1855 Si117x_Ecode_t SI117XDRV_DequeueECGLDSampleData (SI117XDRV_DataQueueID_t id, SI117XDRV_ECGLDSample_t *sample)
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 /***************************************************************************/
1887 Si117x_Ecode_t SI117XDRV_DequeueECGSampleData (SI117XDRV_DataQueueID_t id, SI117XDRV_ECGSample_t *sample)
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 /***************************************************************************/
1908 static Si117x_Ecode_t SI117XDRV_EnqueueBIOZSampleData(SI117XDRV_BIOZSample_t *sample)
1909 {
1910
1911 int retVal = ECODE_SI117XDRV_OK;
1912 //todo
1913 return retVal;
1914 }
1915 /***************************************************************************/
1918 Si117x_Ecode_t SI117XDRV_DequeueBIOZSampleData (SI117XDRV_DataQueueID_t id,SI117XDRV_BIOZSample_t *sample)
1919 {
1920 int retVal = ECODE_SI117XDRV_OK;
1921 //todo
1922 return retVal;
1923 }
1924
1925 /***************************************************************************/
1936 Si117x_Ecode_t SI117XDRV_LeadDetection (SI117XDRV_DeviceSelect_t device, bool *leadDetectStatus)
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 /***************************************************************************/
1977 Si117x_Ecode_t SI117XDRV_WristDetection (SI117XDRV_DeviceSelect_t device, bool *wristDetectStatus)
1978 {
1979 *wristDetectStatus = wristDetectionFlag[device];
1980 return ECODE_SI117XDRV_OK;
1981 }
1982
1983 /***************************************************************************/
1994 Si117x_Ecode_t SI117XDRV_ClearWristDetection (SI117XDRV_DeviceSelect_t device)
1995 {
1996 wristDetectionFlag[device] = false;
1997 return ECODE_SI117XDRV_OK;
1998 }
1999
2000 /***************************************************************************/
2009 Si117x_Ecode_t SI117XDRV_ProcessLDInterrupt (SI117XDRV_DeviceSelect_t device)
2010 {
2011 leadDetectionFlag[device] = true;
2012 return ECODE_SI117XDRV_OK;
2013 }
2014
2015 /***************************************************************************/
2024 Si117x_Ecode_t SI117XDRV_ProcessWDInterrupt (SI117XDRV_DeviceSelect_t device)
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
2063 }si117xFifoState_t;
2064
2065 typedef struct si117xFifoStateMachine
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];
2073 }si117xFifoStateMachine_t;
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 /***************************************************************************/
2131 Si117x_Ecode_t SI117XDRV_InitializeSi117xFifoStateMachine(SI117XDRV_DeviceSelect_t device)
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;
2235 Si117x_Ecode_t ret = ECODE_SI117XDRV_OK;
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 !**********************/
SI117XDRV_FifoIntConfig
Si117x_Ecode_t SI117XDRV_FifoIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable fifo interrupt.
Definition: si117xdrv.c:523
SI117XDRV_DeviceStatus_t
Definition: si117xdrv.c:131
SI117XDRV_PPG24bSample_t::ppg3
int32_t ppg3
ppg3 sample data
Definition: si117xdrv.h:53
SI117XDRV_SetECGTaskEnable
Si117x_Ecode_t SI117XDRV_SetECGTaskEnable(SI117XDRV_DeviceSelect_t device, uint8_t ecgTasks)
Configure ECG tasks.
Definition: si117xdrv.c:495
SI117XDRV_DataQueueID_t
uint32_t SI117XDRV_DataQueueID_t
Queue ID.
Definition: si117xdrv.h:246
SI117XDRV_GetFifoIntLevel
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
SI117XDRV_GlobalCfg_t::ecgldSampleRateus
uint32_t ecgldSampleRateus
desired ECG LD sample rate us
Definition: si117xdrv.h:142
SI117XDRV_PPGSample_t::sequence
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:61
SI117XDRV_AccelCallbackData_t::user
void * user
User supplied data.
Definition: si117xdrv.c:53
SI117XDRV_PPG24bSample_t::timestamp
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:49
SI117XDRV_EnqueueBIOZSampleData
static Si117x_Ecode_t SI117XDRV_EnqueueBIOZSampleData(SI117XDRV_BIOZSample_t *sample)
Enqueue Si117x bioz sample data.
Definition: si117xdrv.c:1908
SI117XDRV_GlobalCfg_t::biozSampleRateus
uint32_t biozSampleRateus
desired bioz sample rate in us
Definition: si117xdrv.h:143
SI117XDRV_FifoQueue_t::tail
volatile uint16_t tail
Index of where to enqueue next byte.
Definition: si117xdrv.c:1263
SI117XDRV_GlobalCfg_t::ecgSampleSize
SI117XDRV_SampleSize_t ecgSampleSize
ecg sample size setting
Definition: si117xdrv.h:152
SI117XDRV_ECGLDSample_t::sequence
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:84
SI117XDRV_StartLegacyPPG
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
SI117XDRV_PPGSample_t::timestamp
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:62
SI117XDRV_DequeuePPGSampleData
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
SI117XDRV_CallbackData_t
General callback function datatype.
Definition: si117xdrv.c:39
SI117XDRV_EnqueueECGLDSampleData
static Si117x_Ecode_t SI117XDRV_EnqueueECGLDSampleData(SI117XDRV_ECGLDSample_t *sample)
Enqueue Si117x ECG LD sample data.
Definition: si117xdrv.c:1810
SI117XDRV_ECGLDSample_t::data
uint8_t data[4]
ecg ld sample data
Definition: si117xdrv.h:87
SI117XDRV_Start
Si117x_Ecode_t SI117XDRV_Start(SI117XDRV_DeviceSelect_t device)
Start running measurements with the current configuration.
Definition: si117xdrv.c:745
SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES
#define SI117XDRV_PPG_24BIT_SAMPLE_SIZE_BYTES
PPG sample size in bytes.
Definition: si117xdrv.h:57
si117xFifoState
si117xFifoState
Definition: si117xdrv.c:2035
SI117XDRV_ECGSample_t::sequence
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:74
SI117XDRV_PPGSample_t::ppg1
int16_t ppg1
ppg1 sample data
Definition: si117xdrv.h:64
SI117XDRV_ECG_SAMPLE_SIZE_BYTES
#define SI117XDRV_ECG_SAMPLE_SIZE_BYTES
ECG sample size in bytes.
Definition: si117xdrv.h:80
SI117XDRV_DeviceRegisters_t
Definition: si117xdrv.c:123
SI117XDRV_DequeueECGSampleData
Si117x_Ecode_t SI117XDRV_DequeueECGSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_ECGSample_t *sample)
Remove an ECG sample from the queue.
Definition: si117xdrv.c:1887
ECODE_SI117XDRV_ALL_CB_USED
#define ECODE_SI117XDRV_ALL_CB_USED
All callbacks used.
Definition: si117xdrv.h:37
SI117XDRV_ProcessPPGInterrupt
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
SI117XDRV_Stop
Si117x_Ecode_t SI117XDRV_Stop(SI117XDRV_DeviceSelect_t device)
Stop running measurements in the Si117x.
Definition: si117xdrv.c:719
SI117XDRV_PPG1IntConfig
Si117x_Ecode_t SI117XDRV_PPG1IntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable PPG interrupt.
Definition: si117xdrv.c:550
SI117XDRV_TASK_BIOZ_DC_EN
#define SI117XDRV_TASK_BIOZ_DC_EN
BIOZ DC task enable bit.
Definition: si117xdrv.h:129
SI117XDRV_DeviceSelect_t
uint32_t SI117XDRV_DeviceSelect_t
Device ID.
Definition: si117xdrv.h:250
SI117XDRV_PPG24bSample_t::syncMessage
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:50
SI117XDRV_PPG24bSample_t::ppg2
int32_t ppg2
ppg2 sample data
Definition: si117xdrv.h:52
SI117XDRV_PPGRegisters_t
Definition: si117xdrv.c:108
SI117XDRV_GlobalCfg_t::ms_polar
SI117XDRV_MSPolar_t ms_polar
ms pin polarity
Definition: si117xdrv.h:150
SI117XDRV_FifoQueue_t::size
uint16_t size
Size of FIFO.
Definition: si117xdrv.c:1265
SI117XDRV_CallbackData_t::allocated
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
SI117XDRV_NumBytesInQueue
static uint16_t SI117XDRV_NumBytesInQueue(SI117XDRV_FifoQueue_t *queue)
Get number of bytes in queue.
Definition: si117xdrv.c:1606
SI117XDRV_GlobalCfg_t
Si117x global configuration.
Definition: si117xdrv.h:139
SI117XDRV_DequeueECGLDSampleData
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_GlobalCfg_t::biozSampleSize
SI117XDRV_SampleSize_t biozSampleSize
bioz sample size setting
Definition: si117xdrv.h:153
SI117XDRV_InitECGLD
Si117x_Ecode_t SI117XDRV_InitECGLD(SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGLDCfg_t *ecgCfg)
Configure ECG LD parameters.
Definition: si117xdrv.c:393
SI117XDRV_StopLegacyPPG
Si117x_Ecode_t SI117XDRV_StopLegacyPPG(SI117XDRV_DeviceSelect_t device)
Stop legacy PPG mode (restores ECG & BIOZ tasks as previously set)
Definition: si117xdrv.c:682
SI117XDRV_ClearWristDetection
Si117x_Ecode_t SI117XDRV_ClearWristDetection(SI117XDRV_DeviceSelect_t device)
wrist detection algorithm
Definition: si117xdrv.c:1994
SI117XDRV_ECGCfg_t
Si117XDRV ECG configuration.
Definition: si117xdrv.h:179
SI117XDRV_PPG24bSample_t
PPG sample data typedef.
Definition: si117xdrv.h:47
SI117XDRV_DequeueBIOZSampleData
Si117x_Ecode_t SI117XDRV_DequeueBIOZSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_BIOZSample_t *sample)
Dequeue Si117x bioz sample data.
Definition: si117xdrv.c:1918
SI117XDRV_EnqueuePPG16bSampleData
static Si117x_Ecode_t SI117XDRV_EnqueuePPG16bSampleData(SI117XDRV_PPGSample_t *sample)
Enqueue Si117x 16 bit PPG sample data.
Definition: si117xdrv.c:1632
ECODE_SI117XDRV_PARAM_ERROR
#define ECODE_SI117XDRV_PARAM_ERROR
Invalid parameter.
Definition: si117xdrv.h:33
SI117XDRV_InitGlobal
Si117x_Ecode_t SI117XDRV_InitGlobal(SI117XDRV_DeviceSelect_t device, SI117XDRV_GlobalCfg_t *globalCfg)
Configure global Si117x settings.
Definition: si117xdrv.c:887
SI117XDRV_LeadDetection
Si117x_Ecode_t SI117XDRV_LeadDetection(SI117XDRV_DeviceSelect_t device, bool *leadDetectStatus)
Lead detection algorithm.
Definition: si117xdrv.c:1936
SI117XDRV_ECGSample_t::timestamp
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:75
si117xFifoStateMachine
Definition: si117xdrv.c:2065
SI117XDRV_ClearRawQueue
static Si117x_Ecode_t SI117XDRV_ClearRawQueue(SI117XDRV_FifoQueue_t *queue)
Empty queue.
Definition: si117xdrv.c:1526
SI117XDRV_ECGLDSample_t::timestamp
uint16_t timestamp
irq timestamp
Definition: si117xdrv.h:85
SI117XDRV_InitECG
Si117x_Ecode_t SI117XDRV_InitECG(SI117XDRV_DeviceSelect_t device, SI117XDRV_ECGCfg_t *ecgCfg)
Configure ECG parameters.
Definition: si117xdrv.c:363
SI117XDRV_GlobalCfg_t::ppgSampleSize
SI117XDRV_SampleSize_t ppgSampleSize
ppg sample size setting
Definition: si117xdrv.h:151
SI117XDRV_EnqueueRawData
static Si117x_Ecode_t SI117XDRV_EnqueueRawData(SI117XDRV_FifoQueue_t *queue, int8_t *inputBuffer, uint16_t size)
Enqueue Si117x raw data.
Definition: si117xdrv.c:1553
SI117XDRV_IRQ_EN_PPG1
#define SI117XDRV_IRQ_EN_PPG1
Legacy PPG irq enable bit.
Definition: si117xdrv.h:134
SI117XDRV_PPG24bSample_t::ppg1
int32_t ppg1
ppg1 sample data
Definition: si117xdrv.h:51
SI117XDRV_PPGSample_t::ppg2
int16_t ppg2
ppg2 sample data
Definition: si117xdrv.h:65
SI117XDRV_FifoQueueConfig_t
Raw data FIFO queue typedef.
Definition: si117xdrv.c:1270
SI117XDRV_GlobalCfg_t::ppgSampleRateus
uint32_t ppgSampleRateus
desired PPG sample rate in us
Definition: si117xdrv.h:140
SI117XDRV_FifoQueue_t::fifo
int8_t * fifo
Pointer to FIFO of queue data (allocated by user)
Definition: si117xdrv.c:1266
SI117XDRV_RegisterPostFifoFlushCallback
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
SI117XDRV_GlobalRegisters_t::taskEnable
uint8_t taskEnable
The global task enable register.
Definition: si117xdrv.c:69
SI117XDRV_FifoQueue_t
Raw data FIFO queue typedef.
Definition: si117xdrv.c:1261
SI117XDRV_ECGLDSample_t
ECG sample data typedef.
Definition: si117xdrv.h:83
SI117XDRV_InitializeSi117xFifoStateMachine
Si117x_Ecode_t SI117XDRV_InitializeSi117xFifoStateMachine(SI117XDRV_DeviceSelect_t device)
Initializes the FIFO processing state machine.
Definition: si117xdrv.c:2131
SI117XDRV_TASK_ECG_LD_EN
#define SI117XDRV_TASK_ECG_LD_EN
ECG LD task enable bit.
Definition: si117xdrv.h:131
SI117XDRV_FifoFlush
Si117x_Ecode_t SI117XDRV_FifoFlush(SI117XDRV_DeviceSelect_t device)
Flushes the Si117x fifo.
Definition: si117xdrv.c:231
SI117XDRV_RegisterAccelSyncCallback
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
SI117XDRV_GlobalCfg_t::fifo_self_test
bool fifo_self_test
enable fifo self test mode
Definition: si117xdrv.h:147
SI117XDRV_Device_t
Definition: si117xdrv.c:143
SI117XDRV_InitPPG
Si117x_Ecode_t SI117XDRV_InitPPG(SI117XDRV_DeviceSelect_t device, SI117XDRV_PPGCfg_t *ppgCfg)
Configure PPG parameters.
Definition: si117xdrv.c:422
SI117XDRV_NumSamplesInQueue
uint16_t SI117XDRV_NumSamplesInQueue(SI117XDRV_DataQueueID_t id)
Get number of samples in the queue.
Definition: si117xdrv.c:1620
Unprocessed_DLE
static bool Unprocessed_DLE
Definition: si117xdrv.c:2082
SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES
#define SI117XDRV_ECG_LD_SAMPLE_SIZE_BYTES
ECG LD sample size in bytes.
Definition: si117xdrv.h:90
SI117XDRV_BioZRegisters_t
Definition: si117xdrv.c:116
SI117XDRV_PPG24bSample_t::ppg4
int32_t ppg4
ppg4 sample data
Definition: si117xdrv.h:54
Si117x_Ecode_t
int32_t Si117x_Ecode_t
SI117XDRV error code.
Definition: si117xdrv.h:27
SI117XDRV_RegisterPostStartCallback
Si117x_Ecode_t SI117XDRV_RegisterPostStartCallback(SI117XDRV_DeviceSelect_t device, SI117XDRV_Callback_t callback, void *user)
Register a post start callback.
Definition: si117xdrv.c:1167
SI117XDRV_ProcessLDInterrupt
Si117x_Ecode_t SI117XDRV_ProcessLDInterrupt(SI117XDRV_DeviceSelect_t device)
lead detection interrupt handler
Definition: si117xdrv.c:2009
SI117XDRV_WristDetection
Si117x_Ecode_t SI117XDRV_WristDetection(SI117XDRV_DeviceSelect_t device, bool *wristDetectStatus)
wrist detection algorithm
Definition: si117xdrv.c:1977
SI117XDRV_PPGSample_t
PPG 16bit sample data typedef. Use this data type to save memory.
Definition: si117xdrv.h:60
SI117XDRV_PPGSample_t::ppg4
int16_t ppg4
ppg4 sample data
Definition: si117xdrv.h:67
SI117XDRV_TASK_PPG4_EN
#define SI117XDRV_TASK_PPG4_EN
PPG4 task enable bit.
Definition: si117xdrv.h:127
SI117XDRV_AllocatePPGDataQueue
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
ECODE_SI117XDRV_ALL_QUEUES_USED
#define ECODE_SI117XDRV_ALL_QUEUES_USED
No more queues left.
Definition: si117xdrv.h:32
SI117XDRV_GlobalCfg_t::irq_enable
uint8_t irq_enable
irq enable setting
Definition: si117xdrv.h:155
devices
static SI117XDRV_Device_t devices[SI117XDRV_MAX_NUM_DEVICES]
Definition: si117xdrv.c:154
si117xFifoState_t
enum si117xFifoState si117xFifoState_t
SI117XDRV_AllocateECGLDDataQueue
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
SI117XDRV_ProcessFifoData
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_GlobalCfg_t::synch_mode
SI117XDRV_SynchMode_t synch_mode
sync mode
Definition: si117xdrv.h:149
SI117XDRV_AccelCallbackData_t::allocated
bool allocated
Flag to indicate callback data is set.
Definition: si117xdrv.c:54
SI117XDRV_InitAPI
Si117x_Ecode_t SI117XDRV_InitAPI(SI117XDRV_DeviceSelect_t device, HANDLE deviceHandle)
Initializes API memory and device handle.
Definition: si117xdrv.c:1067
SI117XDRV_ECGLDCfg_t
Si117XDRV ECG LD configuration.
Definition: si117xdrv.h:186
SI117XDRV_Allocate24bPPGDataQueue
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
SI117XDRV_CallbackData_t::user
void * user
User supplied data.
Definition: si117xdrv.c:42
SI117XDRV_GlobalCfg_t::fifo_disable
bool fifo_disable
disable fifo
Definition: si117xdrv.h:148
SI117XDRV_ECGSample_t::syncMessage
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:76
SI117XDRV_Callbacks_t
Data structure containing all callback info.
Definition: si117xdrv.c:58
SI117XDRV_ECGSample_t::ecg
int32_t ecg
ecg sample data
Definition: si117xdrv.h:77
SI117XDRV_FifoQueue_t::head
volatile uint16_t head
Index of next byte to get.
Definition: si117xdrv.c:1262
SI117XDRV_Dequeue24bPPGSampleData
Si117x_Ecode_t SI117XDRV_Dequeue24bPPGSampleData(SI117XDRV_DataQueueID_t id, SI117XDRV_PPG24bSample_t *sample)
Remove a PPG sample from the queue.
Definition: si117xdrv.c:1719
ECODE_SI117XDRV_QUEUE_EMPTY
#define ECODE_SI117XDRV_QUEUE_EMPTY
Fifo queue empty.
Definition: si117xdrv.h:31
SI117XDRV_ECGSample_t
ECG sample data typedef.
Definition: si117xdrv.h:73
accelSyncCallbacks
static void accelSyncCallbacks(SI117XDRV_DeviceSelect_t device, uint16_t ppg_count)
Call accel sync DLE received callback functions.
Definition: si117xdrv.c:165
SI117XDRV_AccelCallbackData_t
Accel sync DLE callback function datatype.
Definition: si117xdrv.c:50
SI117XDRV_CallbackData_t::callback
SI117XDRV_Callback_t callback
Callback function pointer.
Definition: si117xdrv.c:41
SI117XDRV_RegisterPreFifoFlushCallback
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
SI117XDRV_EnqueuePPG24bSampleData
static Si117x_Ecode_t SI117XDRV_EnqueuePPG24bSampleData(SI117XDRV_PPG24bSample_t *sample)
Enqueue Si117x PPG sample data.
Definition: si117xdrv.c:1670
SI117XDRV_GlobalCfg_t::taskEnable
uint8_t taskEnable
task enable
Definition: si117xdrv.h:146
SI117XDRV_PPGChannelRegisters_t
Definition: si117xdrv.c:97
ECODE_SI117XDRV_QUEUE_SIZE_ERROR
#define ECODE_SI117XDRV_QUEUE_SIZE_ERROR
Invalid queue size.
Definition: si117xdrv.h:34
ECODE_SI117XDRV_RUNNING
#define ECODE_SI117XDRV_RUNNING
Si117x is already running.
Definition: si117xdrv.h:35
si117xFifoStateMachine_Next
static int16_t si117xFifoStateMachine_Next(SI117XDRV_DeviceSelect_t device, uint8_t isDle, uint8_t dleDataByte, si117xFifoStateTaskComplete_t *taskComplete)
Definition: si117xdrv.c:2480
si117xdrv.h
Driver for Si117x.
ECODE_SI117XDRV_QUEUE_FULL
#define ECODE_SI117XDRV_QUEUE_FULL
Fifo queue full.
Definition: si117xdrv.h:30
SI117XDRV_TASK_ECG_EN
#define SI117XDRV_TASK_ECG_EN
ECG task enable bit.
Definition: si117xdrv.h:130
SI117XDRV_EnqueueECGSampleData
static Si117x_Ecode_t SI117XDRV_EnqueueECGSampleData(SI117XDRV_ECGSample_t *sample)
Enqueue Si117x ECG sample data.
Definition: si117xdrv.c:1779
SI117XDRV_LDIntConfig
Si117x_Ecode_t SI117XDRV_LDIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable lead detection interrupt.
Definition: si117xdrv.c:577
SI117XDRV_ClearQueue
Si117x_Ecode_t SI117XDRV_ClearQueue(SI117XDRV_DataQueueID_t id)
Empty a fifo queue.
Definition: si117xdrv.c:1543
SI117XDRV_PPGSample_t::syncMessage
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:63
SI117XDRV_FifoQueue_t::used
volatile uint16_t used
Number of bytes queued.
Definition: si117xdrv.c:1264
SI117XDRV_ECGLDSample_t::syncMessage
uint8_t syncMessage
sync message received
Definition: si117xdrv.h:86
SI117XDRV_PPG24bSample_t::sequence
uint16_t sequence
irq sequence number
Definition: si117xdrv.h:48
SI117XDRV_PPGSample_t::ppg3
int16_t ppg3
ppg3 sample data
Definition: si117xdrv.h:66
SI117XDRV_AccelCallbackData_t::callback
SI117XDRV_AccelCallback_t callback
Callback function pointer.
Definition: si117xdrv.c:52
SI117XDRV_WDIntConfig
Si117x_Ecode_t SI117XDRV_WDIntConfig(SI117XDRV_DeviceSelect_t device, bool enable)
Enable/disable wrist detection interrupt.
Definition: si117xdrv.c:604
SI117XDRV_DequeueRawData
static Si117x_Ecode_t SI117XDRV_DequeueRawData(SI117XDRV_FifoQueue_t *queue, int8_t *buffer, uint16_t size)
Dequeue si117x raw data.
Definition: si117xdrv.c:1581
SI117XDRV_GlobalRegisters_t
Definition: si117xdrv.c:68
SI117XDRV_Reset
Si117x_Ecode_t SI117XDRV_Reset(SI117XDRV_DeviceSelect_t device)
Resets the Si117x.
Definition: si117xdrv.c:249
SI117XDRV_IRQ_EN_FIFO
#define SI117XDRV_IRQ_EN_FIFO
Fifo irq enable bit.
Definition: si117xdrv.h:133
SI117XDRV_GetPartInfo
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
SI117XDRV_TASK_PPG2_EN
#define SI117XDRV_TASK_PPG2_EN
PPG2 task enable bit.
Definition: si117xdrv.h:125
SI117XDRV_AccelCallback_t
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
SI117XDRV_TASK_PPG1_EN
#define SI117XDRV_TASK_PPG1_EN
PPG1 task enable bit.
Definition: si117xdrv.h:124
SI117XDRV_SetPPGTaskEnable
Si117x_Ecode_t SI117XDRV_SetPPGTaskEnable(SI117XDRV_DeviceSelect_t device, uint8_t ppgTasks)
Configure PPG tasks.
Definition: si117xdrv.c:466
SI117XDRV_TASK_BIOZ1_AC_EN
#define SI117XDRV_TASK_BIOZ1_AC_EN
BIOZ AC task enable bit.
Definition: si117xdrv.h:128
SI117XDRV_BIOZChannelRegisters_t
Definition: si117xdrv.c:88
SI117XDRV_FreeDataQueue
Si117x_Ecode_t SI117XDRV_FreeDataQueue(SI117XDRV_DataQueueID_t id)
De-allocate a fifo queue.
Definition: si117xdrv.c:1509
ECODE_SI117XDRV_UNINITIALIZED
#define ECODE_SI117XDRV_UNINITIALIZED
All callbacks used.
Definition: si117xdrv.h:38
SI117XDRV_AllocateECGDataQueue
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
SI117XDRV_TASK_PPG3_EN
#define SI117XDRV_TASK_PPG3_EN
PPG3 task enable bit.
Definition: si117xdrv.h:126
SI117XDRV_GlobalCfg_t::accelSyncRateus
uint32_t accelSyncRateus
accel synchronization period in us
Definition: si117xdrv.h:144
SI117XDRV_ProcessWDInterrupt
Si117x_Ecode_t SI117XDRV_ProcessWDInterrupt(SI117XDRV_DeviceSelect_t device)
wrist detection interrupt handler
Definition: si117xdrv.c:2024
SI117XDRV_GlobalCfg_t::ecgSampleRateus
uint32_t ecgSampleRateus
desired ECG sample rate in us
Definition: si117xdrv.h:141
SI117XDRV_Callback_t
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
SI117XDRV_BIOZSample_t
bioz sample data typedef
Definition: si117xdrv.h:93
SI117XDRV_GlobalCfg_t::fifo_int_level
uint16_t fifo_int_level
fifo interrupt level
Definition: si117xdrv.h:145
ECODE_SI117XDRV_OK
#define ECODE_SI117XDRV_OK
Success return value. //dlc: It is my opinion that these should be SI117XDRV_ECODE_....
Definition: si117xdrv.h:29
SI117XDRV_ECGRegisters_t
Definition: si117xdrv.c:78
SI117XDRV_PPG_SAMPLE_SIZE_BYTES
#define SI117XDRV_PPG_SAMPLE_SIZE_BYTES
PPG 16 bit sample size in bytes.
Definition: si117xdrv.h:70
SI117XDRV_RegisterPreStartCallback
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_PPGCfg_t
Si117XDRV PPG configuration.
Definition: si117xdrv.h:230
SI117XDRV_GlobalCfg_t::ppg_sw_avg
uint8_t ppg_sw_avg
ppg sw avg setting
Definition: si117xdrv.h:154
ECODE_SI117XDRV_NOT_RUNNING
#define ECODE_SI117XDRV_NOT_RUNNING
Si117x is not running.
Definition: si117xdrv.h:36