| 1465 | } |
| 1466 | |
| 1467 | int get_oxygen_level (double *ppg_ir, double *ppg_red, int data_size, int sampling_rate, |
| 1468 | double callib_coef1, double callib_coef2, double callib_coef3, double *oxygen_level) |
| 1469 | { |
| 1470 | if ((ppg_red == NULL) || (ppg_ir == NULL) || (data_size < 40) || (sampling_rate < 1) || |
| 1471 | (oxygen_level == NULL)) |
| 1472 | { |
| 1473 | data_logger->error ("invalid inputs for get_oxygen_level, ir {}, red {}, size {}, sampling " |
| 1474 | "{}, output {}, min size is 40", |
| 1475 | (ppg_ir != NULL), (ppg_red != NULL), data_size, sampling_rate, (oxygen_level != NULL)); |
| 1476 | return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; |
| 1477 | } |
| 1478 | |
| 1479 | int res = (int)BrainFlowExitCodes::STATUS_OK; |
| 1480 | |
| 1481 | double *red_raw = new double[data_size]; |
| 1482 | double *ir_raw = new double[data_size]; |
| 1483 | int filter_shift = 25; // to get rif of filtereing artifact, dont use first elements |
| 1484 | int new_size = data_size - filter_shift; |
| 1485 | double *new_red_raw = red_raw + filter_shift; |
| 1486 | double *new_ir_raw = ir_raw + filter_shift; |
| 1487 | memcpy (red_raw, ppg_red, data_size * sizeof (double)); |
| 1488 | memcpy (ir_raw, ppg_ir, data_size * sizeof (double)); |
| 1489 | |
| 1490 | // need prefiltered mean of red and ir for dc |
| 1491 | double mean_red = mean (new_red_raw, new_size); |
| 1492 | double mean_ir = mean (new_ir_raw, new_size); |
| 1493 | |
| 1494 | // filtering(full size) |
| 1495 | res = detrend (red_raw, data_size, (int)DetrendOperations::CONSTANT); |
| 1496 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1497 | { |
| 1498 | res = detrend (ir_raw, data_size, (int)DetrendOperations::CONSTANT); |
| 1499 | } |
| 1500 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1501 | { |
| 1502 | res = perform_bandpass ( |
| 1503 | red_raw, data_size, sampling_rate, 0.7, 1.5, 4, (int)FilterTypes::BUTTERWORTH, 0.0); |
| 1504 | } |
| 1505 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1506 | { |
| 1507 | res = perform_bandpass ( |
| 1508 | ir_raw, data_size, sampling_rate, 0.7, 1.5, 4, (int)FilterTypes::BUTTERWORTH, 0.0); |
| 1509 | } |
| 1510 | |
| 1511 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1512 | { |
| 1513 | // calculate AC & DC components using mean & rms: |
| 1514 | double redac = rms (new_red_raw, new_size); |
| 1515 | double irac = rms (new_ir_raw, new_size); |
| 1516 | double reddc = mean_red; |
| 1517 | double irdc = mean_ir; |
| 1518 | |
| 1519 | // https://www.maximintegrated.com/en/design/technical-documents/app-notes/6/6845.html |
| 1520 | double r = (redac / reddc) / (irac / irdc); |
| 1521 | data_logger->trace ("r is: {}", r); |
| 1522 | double spo2 = callib_coef1 * r * r + callib_coef2 * r + callib_coef3; |
| 1523 | if (spo2 > 100.0) |
| 1524 | { |
no test coverage detected