![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Started a gui menuflow
Dependencies: LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI BSP_DISCO_F429ZI
Revision 3:b029a3f73a9e, committed 2020-06-11
- Comitter:
- ahaas92
- Date:
- Thu Jun 11 22:55:06 2020 +0000
- Parent:
- 2:5828e6917e75
- Commit message:
- Init of gui structure ;
Changed in this revision
--- a/Monitoring.c Tue Jun 09 22:57:20 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1375 +0,0 @@ -*********************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#define EXTERN extern -#include "SS.h" -#include "main.h" -#include "_ss_pwm.h" -#include "_SS_I2CX_Drivers.h" -#include "_SS_I2CX_SDP600.h" -#include "_SS_I2CX_X201641.h" -#include "Ventilation.h" -#include "MotorTempTable.h" -#include "_SS_FlowComputer.h" -#include "_SS_TSI_4040.h" -#include "_SS_Data_Logging.h" -#include "_SS_OnOffActioner.h" -#undef EXTERN - -#define INIT_VARIABLES -#define EXTERN -#include "Monitoring.h" -#undef EXTERN -#undef INIT_VARIABLES - - -// *********************** Register locations ********************************** -#define DMA_IFCR1 (*(volatile uint32_t *)0x40020004) -#define DMA_CCR1 (*(volatile uint32_t *)0x40020008) -#define DMA_CNTDR1 (*(volatile uint32_t *)0x4002000c) -#define DMA_CPAR1 (*(volatile uint32_t *)0x40020010) -#define DMA_CMAR1 (*(volatile uint32_t *)0x40020014) - -#define ADC1_SR (*(volatile uint32_t *)0x40012400) -#define ADC1_SQR1 (*(volatile uint32_t *)0x4001242C) -#define ADC1_SQR2 (*(volatile uint32_t *)0x40012430) -#define ADC1_SQR3 (*(volatile uint32_t *)0x40012434) -#define ADC1_LTR (*(volatile uint32_t *)0x40012428) -#define ADC1_HTR (*(volatile uint32_t *)0x40012424) -#define ADC1_CR1 (*(volatile uint32_t *)0x40012404) -#define ADC1_CR2 (*(volatile uint32_t *)0x40012408) - - -// ************************* ADC CONFIGURATION CHANNELS ************************ -#define FREE_MEAS_CHANNEL 0 -#define PPROX_MEAS_CHANNEL 1 -#define CURRENT_MEAS_CHANNEL 2 -#define ALIM_24V_MEAS_CHANNEL 6 -#define TEMP_PHASE_A 5 -#define TEMP_PHASE_B 4 -#define TEMP_PHASE_C 3 - -// ********************* 24V ALARM MANAGEMENT ********************************** -#ifndef C_M3_DEVICETEST_TARGET - -#endif - - - -// ************************ I2C SENSORS MANAGEMENT ***************************** -#ifndef C_M3_DEVICETEST_TARGET - #define READING_NO_SENSOR 0 - #define READING_FLOW_SENSORS 1 - //#define READING_PRESSURE_SENSORS 2 - #define STOP_READING_FLOW_SENSORS 3 - #define START_READING_FLOW_SENSORS 4 - #define NUMBER_I2C_REBOOT 3 - - #define FLOW_SENSOR_READING 0 - #define FLOW_SENSOR_OK 1 - #define FLOW_SENSOR_FAIL 2 - static u8 ucStatusSDP600=FLOW_SENSOR_READING; - static u8 ucStatusX201641=FLOW_SENSOR_READING; - - static volatile u8 ucReadingFlowSensor=START_READING_FLOW_SENSORS; // I2Cx sensor managment - static u8 ucCounterFlowErrorMeasurement=0; - static u16 uiTotalCounterFlowErrorMeasurement=0; - - #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) - #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW - #define SMOOTH_BLOWER_RAW_FLOW_COUNTER 50 - static u16 uiBlowerRAWFlowTemp[SMOOTH_BLOWER_RAW_FLOW_COUNTER]; - static u8 ucIndexBlowerRAWFlowSmooth=0; - - #define BLOWER_RAW_FLOW_SAMPLES_NUMBER 200 - static u32 ulSumBlowerFlowRAWMes=0; - static u16 uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; - #endif - - #define SMOOTH_BLOWER_FLOW_LARGE_COUNTER 75//100 // MUST BE HIGHER THAN SMOOTH_BLOWER_FLOW_SMALL_COUNTER - #define SMOOTH_BLOWER_FLOW_SMALL_COUNTER 15 // MUST BE LOWER THAN SMOOTH_BLOWER_FLOW_LARGE_COUNTER - static int16_t iTempBlowerFlowForSmallSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; - static int16_t iTempBlowerFlowForLargeSmooth[SMOOTH_BLOWER_FLOW_LARGE_COUNTER]; - static u8 ucIndexSmallBlowerFlowSmooth=0; - static u8 ucIndexLargeBlowerFlowSmooth=0; - - static int16_t idConductancedtSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; - #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) -#endif // C_M3_DEVICETEST_TARGET - - - -// ****************** PROXIMAL PRESSURE SENSOR MANAGEMENT ********************** -#ifndef C_M3_DEVICETEST_TARGET - #define SMOOTH_PPROX_PRESSURE_COUNTER 40 - static u8 ucIndexPproxPressureSmooth=0; - static u16 uiProximalPressureTemp[SMOOTH_PPROX_PRESSURE_COUNTER]; -#endif // C_M3_DEVICETEST_TARGET - - - -// ********************* MEASURES MANAGEMENT ********************************** -#ifndef C_M3_DEVICETEST_TARGET - // ---- Current measurement - static u32 ulSumCurrentADCMesFiltered=0; - static u32 ulCounterADC_FilteredBlowerCurrentMes=0; - - // ---- Temperature measurement - static u32 ulADCSumBlowerTemperature=0; - static u16 uiTemperatureSamplesCounter=0; - - #ifdef TEMPERATURE_TRENDS - #ifdef USE_FLOW_COMPUTER - #define FLOW_COMPUTER_CYCLE_DETECTION_TIMER 10 // 100ms - static u8 ucFlowComputerCycle=EXPIRATION_CYCLE; - static u16 uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; - #else - #define TIME_OUT_TEMPERATURE_MEASUREMENT 6000 // 60s - static u16 uiTimeOutTemperatureMeasurement=0; - #endif // #ifdef USE_FLOW_COMPUTER - static u32 ulADCSumTemperaturePhaseA=0; - static u16 uiADCTemperaturePhaseA; - static u32 ulADCSumTemperaturePhaseB=0; - static u16 uiADCTemperaturePhaseB; - static u32 ulADCSumTemperaturePhaseC=0; - static u16 uiADCTemperaturePhaseC; - #endif - - // ---- Blower Speed measurment - static u32 ulSumTachoTicks=0; - static u32 ulCounterAverageMotorSpeed=0; - - // --- Blower current Bessel filter - /*static u16 uiCurrentADCMesFilteredPrev2; - static u16 uiCurrentADCMesFilteredPrev1; - static u16 uiCurrentADCMesPrev2; - static u16 uiCurrentADCMesPrev1; - static u16 uiCurrentADCMesFiltered;*/ - - // --- Motor voltage - static u32 ulSumADC_MotorVoltage; - static u32 ulCounterADC_MotorVoltage; - - // --- Temporary measurements - static u16 uiPproxMax; - static u16 uiVtiTemp; - static u16 uiVteTemp; - static u16 uiTiMesTemp; - static u16 uiTeMesTemp; -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -#ifndef C_M3_DEVICETEST_TARGET - static u8 ucVentilationCycleCopy=INSPIRATION_CYCLE; - static int32_t lSumVti=0; - static int32_t lSumVte=0; - static u8 ucCounterAlarmVteMin=0; - static u8 ucCounterLPAlarm=0; -#endif // C_M3_DEVICETEST_TARGET - - -#define RCC_APB2RSTR (*(volatile uint32_t *)0x4002100c) - - -// ***************** Functions ********************************************** -int16_t ComputeFlowInLitersPerMin(u16 uFlowRAW, bool bPositiveFlow); -void ComputeBlowerPower(void); -u16 ComputeTemperature(u16 uiADCMotorTemp, u16 *puiTempLUT, u16 uiTemperatureGain); - - -/******************************************************************************* -* Function Name : ADC1_init -* Description : Init ADC1 -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ADC1_init(void) -{ - // First perform De_init - DMA_CCR1 &= (uint32_t)(~0x1); // channel 1 disable - DMA_CCR1 = 0; // Reset Channelx control register - DMA_CNTDR1 = 0; // Reset Channelx remaining bytes register - DMA_CPAR1 = 0; // Reset Channelx peripheral address register - DMA_CMAR1 = 0; // Reset Channelx memory address register - DMA_IFCR1 |= DMA_Channel1_IT_Mask; // Reset interrupt pending bits - // end de-init - - // Initialise DMA #1 - DMA_CPAR1 = (uint32_t)(ADC1_BASE + 0x4c); // base adress of ADC1 ADC_DR register - - DMA_CMAR1 = (unsigned long)(&uiADC_Value[0]); - DMA_CNTDR1 = NUMBER_ADC_CONVERSION; // numbers of data to be transfered - - DMA_CCR1 = (3<<12) + (1<<10) + (1<<8) + (1<<7) + (1<<5) /*+ (1<<1)*/; // very high priority, mem size 16 bits, periph size 16 bits, mem increase,/* circular enabled*/, /*transfer complete IT*/ - DMA_CCR1 |= 1; // channel 1 enable - - - - // De-init of the ADC 1 - RCC_APB2RSTR |= RCC_APB2Periph_ADC1; // enable - RCC_APB2RSTR &= ~RCC_APB2Periph_ADC1; // disable - // end De-init of the ADC 1 - - // Select channels of the regular group - #ifdef TEMPERATURE_TRENDS - ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; - ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + TEMP_PHASE_C; - ADC1_SQR3 = (TEMP_PHASE_B<<25) + (TEMP_PHASE_A<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; - #else - ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; - ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; - ADC1_SQR3 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; - #endif - - // 21 micros ADC conversion time - ADC1->SMPR2= (7<<27) + (7<<24) + (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; - ADC1->SMPR1= (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; - - ADC1_CR1 = (1<<8); // Scan mode enabled - ADC1_CR2 = (1<<8); // DMA mode enabled - - ADC1_CR2 |= 1; // start ADC1 - power-on - - // Delay at least 1uSec for ADC calibration/stabilisation. See ADC documentation - // Stabilization time > 1uS for ADC, between power-on and start of conversion - // Give it 10uSecs just to be sure. - Delay100NS(100); - - // Calibration of ADC1 - ADC1_CR2 |= (1<<3); // reset calibration registers - ADC1_CR2 |= (1<<2); // Enable calibration - while ((ADC1_CR2 & (1<<2)) == (1<<2)); // Wait end of calibration - - ADC1_CR2 |= 1; // start ADC1 - start conversions -} - - -/******************************************************************************* -* Function Name : CheckAlimMotorVoltage -* Description : Check the voltage range of the 24V power supply -* Input : None -* Output : None -* Return : OPSTATUS_OK or OPSTATUS_FAIL -*******************************************************************************/ -opstatus_t CheckAlimMotorVoltage(void) -{ - if (uiDCinADCMeas<271 || uiDCinADCMeas>2090) - return(OPSTATUS_FAIL); // <12V or >24V - return(OPSTATUS_OK); -} - - -/******************************************************************************* -* Function Name : Compute24VMeasure -* Description : Compute the 24V measure -* Input : None -* Output : None -* Return : OPSTATUS_OK or OPSTATUS_FAIL -*******************************************************************************/ -#ifndef C_M3_DEVICETEST_TARGET -void Compute24VMeasure(void) -{ - u32 ulTemp; - u16 uiADC_BlowerVoltage; - - if (bMemoStartVentilation==TRUE) - uiADC_BlowerVoltage=uiAverageADC_MotorVoltage; - else - uiADC_BlowerVoltage=uiDCinADCMeas; - - ulTemp=((u32)uiADC_BlowerVoltage*100)/1452; - ulTemp+=100; - uiTechnicalDataMes[MOTOR_VOLTAGE_TEC_MES]=(u16)ulTemp; - uiMotorVoltageMes=(u16)ulTemp; -} -#endif - -void GetFirstMotorVoltageReading(void) -{ - uiAverageADC_MotorVoltage=uiDCinADCMeas; -} -/******************************************************************************* -* Function Name : ComputeBlowerPower -* Description : Compute the power of the blower -* Input : None -* Output : None -* Return : OPSTATUS_OK or OPSTATUS_FAIL -*******************************************************************************/ -void ComputeBlowerPower(void) -{ - uiTechnicalDataMes[MOTOR_POWER_TEC_MES]=((u32)uiMotorVoltageMes*uiBlowerCurrentMes)/10; -} - -/******************************************************************************* -* Function Name : SpeedMeasurement -* Description : Return blower speed -* Input : Tacho counter -* Output : None -* Return : Blower speed in RPM -*******************************************************************************/ -u16 SpeedMeasurement(u16 uiTachoCounter) -{ - u16 uiSpeedTemp=65500; - - if (uiTachoCounter>915) - uiSpeedTemp=(u16)(60000000UL/uiTachoCounter); - - return(uiSpeedTemp); -} - - -/******************************************************************************* -* Function Name : ReadADCInputs -* Description : Read all ADC input (function calls every 1ms) -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ReadADCInputs(void) -{ - //u32 ulTerm1, ulTerm2, ulTerm3, ulTerm4, ulTerm5; - - // ADC Pprox measurement - uiProximalPressureADCMes=uiADC_Value[ADC_PPROX_MES]; - - // ADC DCin measurement - uiDCinADCMeas=uiADC_Value[ADC_DCIN_MES]; - - // ADC Blower current measurement - ComputeADCBlowerCurrent(FALSE); - - // ADC Free measurement - uiADCBlowerTemperatureMeas=uiADC_Value[ADC_FREE_MES]; - - #ifdef TEMPERATURE_TRENDS - uiADCTemperaturePhaseA=uiADC_Value[ADC_TEMP_PHASE_A]; - uiADCTemperaturePhaseB=uiADC_Value[ADC_TEMP_PHASE_B]; - uiADCTemperaturePhaseC=uiADC_Value[ADC_TEMP_PHASE_C]; - #endif - - // 2nd order Bessel Filter (Fcut-out=36Hz, sample rate=1KHz) - /*ulTerm1=(919UL*uiADCBlowerCurrent)>>6; - ulTerm2=(919UL*uiCurrentADCMesPrev1)>>5; - ulTerm3=(919UL*uiCurrentADCMesPrev2)>>6; - ulTerm4=(1427UL*uiCurrentADCMesFilteredPrev1)>>1; - ulTerm5=259UL*uiCurrentADCMesFilteredPrev2; - - uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>9; - uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; - uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; - uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; - uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ - - - // 2nd order Bessel Filter (Fcut-out=150Hz, sample rate=1KHz) - /*ulTerm1=(1929UL*uiADCBlowerCurrent)>>1; - ulTerm2=(1929UL*uiCurrentADCMesPrev1); - ulTerm3=(1929UL*uiCurrentADCMesPrev2)>>1; - ulTerm4=(1095UL*uiCurrentADCMesFilteredPrev1)>>1; - ulTerm5=(2479UL*uiCurrentADCMesFilteredPrev2)>>3; - - uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>12; - uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; - uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; - uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; - uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ - - // --- Start new conversions - ADC1->CR2 |= 1; -} - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : ComputeMeasurements -* Description : Compute different measures -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ComputeMeasurements(void) -{ - // ---------------------- Measure Current (A) ---------------------------- - uiBlowerCurrentMes=ComputeBlowerCurrentInAmper(uiADCBlowerCurrent); - - // -------------------- Compute motor voltage (V) ------------------------ - Compute24VMeasure(); - ComputeBlowerPower(); - - // ---------------------- Others measurements ---------------------------- - if (bMemoStartVentilation==TRUE) - { - // --- Motor speed (RPM) (every 10ms) - uiBlowerSpeedMes=SpeedMeasurement(uiTachoTimeTicks); - } -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -#ifndef C_M3_DEVICETEST_TARGET -#ifdef TEMPERATURE_TRENDS -/******************************************************************************* -* Function Name : ComputeAverageOnMeasurements -* Description : Average differents mesures : MUST BE CALLED EVERY 10ms -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ComputeAverageOnMeasurements(void) -{ - #ifdef USE_FLOW_COMPUTER - // ----------- USE THE FLOW COMPUTER TO DETECT CYCLE ---------------- - u16 uiDummy; - opstatus_t opstatus; - - // Read new flow from flow computer every 10ms - opstatus=SS_Xgetw(flc, &uiDummy); - if (opstatus==OPSTATUS_OK) - { - // Update flow/pressure displayed - uiBlowerFlow=iFlowFromFlowComputer*10; - uiPoutPressureMes=uiPressureFromFlowComputer; - - // Comm with flow computer OK !! - #ifdef DATA_LOGGING - if (bRecordTemperatureTrendsAllowed==FALSE) - { - bRecordTemperatureTrendsAllowed=TRUE; - uiTrendsSampleTime=RECORD_TRENDS_SAMPLE_TIME; - } - #endif // DATA_LOGGING - - // inspiration/expiration cycle detection - if (ucFlowComputerCycle==EXPIRATION_CYCLE) - { - // Inspiration detection - if (iFlowFromFlowComputer>50) // 5l/min - { - uiFlowComputerCycleModificationTimer--; - if (uiFlowComputerCycleModificationTimer==0) - { - ucFlowComputerCycle=INSPIRATION_CYCLE; - - // Compute temperature of the previous inspiratory cycle - if (uiTemperatureSamplesCounter!=0) - { - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); - uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; - uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; - uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; - } - ulADCSumBlowerTemperature=0; - ulADCSumTemperaturePhaseA=0; - ulADCSumTemperaturePhaseB=0; - ulADCSumTemperaturePhaseC=0; - uiTemperatureSamplesCounter=0; - } - } - else - uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; - } - else - { - // Record temperature as long as the flow is positive - if (iFlowFromFlowComputer>(-10)) // >-1l/min - { - ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; - ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; - ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; - ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; - uiTemperatureSamplesCounter++; - } - - // Expiration detection - if (iFlowFromFlowComputer<(-50)) // <-5l/min - { - uiFlowComputerCycleModificationTimer--; - if (uiFlowComputerCycleModificationTimer==0) - ucFlowComputerCycle=EXPIRATION_CYCLE; - } - else - uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; - } - } - else if (opstatus==OPSTATUS_FAIL) - { - // Comm Failure with flow computer => no data recorded - uiBlowerFlow=0; - uiPoutPressureMes=0; - - #ifdef DATA_LOGGING - bRecordTemperatureTrendsAllowed=FALSE; - #endif - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; - } - #else - // ----------- USE THE 24V MEASURE TO DETECT CYCLE ---------------- - if (uiDCinADCMeas>500) - { - // Inspiration - ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; - ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; - ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; - ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; - uiTemperatureSamplesCounter++; - uiTimeOutTemperatureMeasurement=TIME_OUT_TEMPERATURE_MEASUREMENT; - #ifdef DATA_LOGGING - bRecordTemperatureTrendsAllowed=TRUE; - #endif - } - else if (uiTimeOutTemperatureMeasurement!=0) - { - // Expiration - uiTimeOutTemperatureMeasurement--; - if (uiTemperatureSamplesCounter!=0) - { - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); - uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; - uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; - uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; - } - ulADCSumBlowerTemperature=0; - ulADCSumTemperaturePhaseA=0; - ulADCSumTemperaturePhaseB=0; - ulADCSumTemperaturePhaseC=0; - uiTemperatureSamplesCounter=0; - } - else - { - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; - - ulADCSumBlowerTemperature=0; - ulADCSumTemperaturePhaseA=0; - ulADCSumTemperaturePhaseB=0; - ulADCSumTemperaturePhaseC=0; - uiTemperatureSamplesCounter=0; - - #ifdef DATA_LOGGING - bRecordTemperatureTrendsAllowed=FALSE; - #endif - } - #endif // #ifdef USE_FLOW_COMPUTER -} -#endif // #ifdef TEMPERATURE_TRENDS -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -/******************************************************************************* -* Function Name : ComputeADCBlowerCurrent -* Description : Compute the average current during a PWM cycle (20micros) -* Input : bRecordCurrentOffset -* Output : None -* Return : None -*******************************************************************************/ -void ComputeADCBlowerCurrent(bool bRecordCurrentOffset) -{ - if (bRecordCurrentOffset==TRUE) - { - uiADCOffsetBlowerCurrent=uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; - } - else - { - uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; - } -} - - -/******************************************************************************* -* Function Name : ComputeBlowerCurrentInAmper -* Description : Return blower current value in cAmper (ex: 100=1.00A) -* Input : ADC value -* Output : None -* Return : Blower current in cAmper (ex: 100=1.00A) -*******************************************************************************/ -int16_t ComputeBlowerCurrentInAmper(u16 uiADCBlowerCurrentLocal) -{ - int32_t lTempValue; - - // Computation using MOT_CUR_MEAS2 - lTempValue=(int32_t)uiADCBlowerCurrentLocal-(int32_t)uiADCOffsetBlowerCurrent; - lTempValue*=1000; - lTempValue/=uiTechnicalDataSet[GAIN_BLOWER_CURRENT_TEC]; - return(lTempValue); -} - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : LaunchFlowReadingOnI2CBus -* Description : Open and Read the flow sensor(s) on the I2C bus -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void LaunchFlowReadingOnI2CBus(void) -{ - opstatus_t byOpStatus; - u16 uiSensorErr; - - if (fOpenI2C1SDP600Sensors==FALSE || fOpenI2C2SDP600Sensors==FALSE || - fOpenI2C1X201641Sensors==FALSE || fOpenI2C2X201641Sensors==FALSE) - { - byOpStatus=SS_Xopen(I2C_SDP600); - if (byOpStatus==OPSTATUS_FAIL) - uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; - - byOpStatus=SS_Xopen(I2C_X201641); - if (byOpStatus==OPSTATUS_FAIL) - uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; - - ucReadingFlowSensor=STOP_READING_FLOW_SENSORS; - } - else if (ucReadingFlowSensor==STOP_READING_FLOW_SENSORS) - { - ucReadingFlowSensor=START_READING_FLOW_SENSORS; - } - else if (ucReadingFlowSensor==READING_FLOW_SENSORS) - { - // Reading SDP600 Flow sensors - if (ucStatusSDP600==FLOW_SENSOR_READING) - { - byOpStatus=SS_Xgetw(I2C_SDP600, &uiSensorErr); - if (byOpStatus==OPSTATUS_OK) - ucStatusSDP600=FLOW_SENSOR_OK; - else if (byOpStatus==OPSTATUS_FAIL) - ucStatusSDP600=FLOW_SENSOR_FAIL; - } - - // Reading X201641 Flow sensors - if (ucStatusX201641==FLOW_SENSOR_READING) - { - byOpStatus=SS_Xgetw(I2C_X201641, &uiSensorErr); - if (byOpStatus==OPSTATUS_OK) - ucStatusX201641=FLOW_SENSOR_OK; - else if (byOpStatus==OPSTATUS_FAIL) - ucStatusX201641=FLOW_SENSOR_FAIL; - } - - // End of flow measurement? - if (ucStatusSDP600!=FLOW_SENSOR_READING && ucStatusX201641!=FLOW_SENSOR_READING) - { - if (ucStatusSDP600==FLOW_SENSOR_OK && ucStatusX201641==FLOW_SENSOR_OK) - { - ucCounterFlowErrorMeasurement=0; - #ifdef TIME_MEASUREMENT - GPIOB->BRR = GPIO_Pin_5; - #endif - } - else - { - // Error counters - uiTotalCounterFlowErrorMeasurement++; - ucCounterFlowErrorMeasurement++; - if (ucCounterFlowErrorMeasurement>=NUMBER_I2C_REBOOT) - { - //ulErrorCounter|=uiSensorErr; - uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; - } - } - - // Next Sensors to measure - ucReadingFlowSensor=READING_NO_SENSOR; - ucStatusSDP600=FLOW_SENSOR_READING; - ucStatusX201641=FLOW_SENSOR_READING; - } - } -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : ComputeFlowMeasurement -* Description : Conpute inspiratory and erxpiratory flow measurements -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ComputeFlowMeasurement(void) -{ - #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) - int32_t lValue; - u16 uiValue; - #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW - u32 ulValue; - #endif - #endif - - if (ucReadingFlowSensor==START_READING_FLOW_SENSORS) - { - ucReadingFlowSensor=READING_FLOW_SENSORS; - } - else if (ucReadingFlowSensor==READING_NO_SENSOR) - { - ucReadingFlowSensor=READING_FLOW_SENSORS; - - // **** Reading of the Inspiratory RAW Flow - #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) - #ifdef SDP600_USED_I2C1_BUS - SDP600_ReadADCFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &uiValue); - #endif - #ifdef X201641_USED_I2C1_BUS - X201641_ReadADCFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &uiValue); - #endif - if (uiValue==uiTechnicalDataSet[FLOWI_OFFSET_TEC]) - { - uiBlowerFlowRAWMes=0; - iBlowerFlowMes=0; - } - else if (uiValue>uiTechnicalDataSet[FLOWI_OFFSET_TEC]) - { - uiBlowerFlowRAWMes=uiValue-uiTechnicalDataSet[FLOWI_OFFSET_TEC]; - iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, FALSE); - } - else - { - uiBlowerFlowRAWMes=uiTechnicalDataSet[FLOWI_OFFSET_TEC]-uiValue; - iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, TRUE); - } - - // Smoothing RWA data signals - #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW - uiBlowerRAWFlowTemp[ucIndexBlowerRAWFlowSmooth]=uiBlowerFlowRAWMes; - ulValue=0; - for (uiValue=0; uiValue<SMOOTH_BLOWER_RAW_FLOW_COUNTER; uiValue++) - ulValue+=uiBlowerRAWFlowTemp[uiValue]; - uiBlowerFlowRAWSmoothingMes=ulValue/SMOOTH_BLOWER_RAW_FLOW_COUNTER; - ucIndexBlowerRAWFlowSmooth++; - if (ucIndexBlowerRAWFlowSmooth>=SMOOTH_BLOWER_RAW_FLOW_COUNTER) - ucIndexBlowerRAWFlowSmooth=0; - - // Average of the RAW data signal - ulSumBlowerFlowRAWMes+=uiBlowerFlowRAWSmoothingMes; - uiBlowerRAWFlowSamplesCounter--; - if (uiBlowerRAWFlowSamplesCounter==0) - { - uiAverageBlowerFlowRAWMes=ulSumBlowerFlowRAWMes/BLOWER_RAW_FLOW_SAMPLES_NUMBER; - ulSumBlowerFlowRAWMes=0; - uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; - } - #endif // DISPLAY_AVERAGE_BLOWER_RAW_FLOW - - - // **** Reading of the Inspiratory Flow in l/min - /*#ifdef SDP600_USED_I2C1_BUS - SDP600_CalculFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); - #endif - #ifdef X201641_USED_I2C1_BUS - X201641_CalculFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); - #endif*/ - iTempBlowerFlowForSmallSmooth[ucIndexSmallBlowerFlowSmooth]=iBlowerFlowMes; - iTempBlowerFlowForLargeSmooth[ucIndexLargeBlowerFlowSmooth]=iBlowerFlowMes; - - // Small Smoothing of the inspiratory flow signal - lValue=0; - for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_SMALL_COUNTER; uiValue++) - lValue+=iTempBlowerFlowForSmallSmooth[uiValue]; - iBlowerFlowSmoothingMes=lValue/(int16_t)SMOOTH_BLOWER_FLOW_SMALL_COUNTER; - ucIndexSmallBlowerFlowSmooth++; - if (ucIndexSmallBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_SMALL_COUNTER) - ucIndexSmallBlowerFlowSmooth=0; - - // Large Smoothing of the inspiratory flow signal - lValue=0; - for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_LARGE_COUNTER; uiValue++) - lValue+=iTempBlowerFlowForLargeSmooth[uiValue]; - iBlowerFlowSmoothingMesForTrigger=lValue/(int16_t)SMOOTH_BLOWER_FLOW_LARGE_COUNTER; - ucIndexLargeBlowerFlowSmooth++; - if (ucIndexLargeBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_LARGE_COUNTER) - ucIndexLargeBlowerFlowSmooth=0; - - // Flow for Optima Comm - uiBlowerFlow=iBlowerFlowMes; - uiBlowerFlowSmoothingMes=iBlowerFlowSmoothingMes; - uiBlowerFlowTriggerMes=iBlowerFlowSmoothingMesForTrigger; - #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) - } - -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - - -#ifndef C_M3_DEVICETEST_TARGET -double powApprox(double a, double x) -{ - union - { - double d; - int A[2]; - } Z = { a }; - Z.A[1] = (int)(x * (Z.A[1] - 1072632447) + 1072632447); - Z.A[0] = 0; - return Z.d; -} -/******************************************************************************* -* Function Name : ComputeConductance -* Description : Compute Conductance -* Input : Pressure, Flow -* Output : Conductance -* Return : None -*******************************************************************************/ -float prevConductance = 0.0f; -u8 bufferIndex = 0; -bool filled = FALSE; -int16_t littleSum = 0; - -void ComputeConductance(void) -{ - float pressure = iProximalPressureMes/10.0f; - float flow = iBlowerFlowSmoothingMes/100.0f/60.0f; - float density = 1.225f; - float viscosity = 0.00018f; - float calcConductance = 0.0f; - - if(pressure != 0) - { - calcConductance = (100000)*((powApprox((flow*0.001f),1.75)*powApprox(density,0.75)*powApprox(viscosity,0.25)/(pressure / 10.0f)* 98.0638f)); - calcConductance = calcConductance * 1000.0f; - if(calcConductance < 60000 && calcConductance > -60000) - { - uiConductanceCalc = (int16_t)calcConductance; - } - } -// int16_t tempValue = idConductancedtSmooth[bufferIndex]; -// idConductancedtSmooth[bufferIndex]= (int16_t)(calcConductance - prevConductance);//1000; -// littleSum += idConductancedtSmooth[bufferIndex]; -// bufferIndex++; -// if(bufferIndex > SMOOTH_BLOWER_FLOW_LARGE_COUNTER) -// { -// bufferIndex = 0; -// if(!filled) -// { -// filled = TRUE; -// } -// } -// -// if(filled) -// { -// littleSum -= tempValue; -// uidConductanceCalcdt = littleSum/SMOOTH_BLOWER_FLOW_LARGE_COUNTER; -// } - uidConductanceCalcdt = (int16_t)(calcConductance - prevConductance); - prevConductance = calcConductance; -} -/******************************************************************************* -* Function Name : ComputeProximalPressureMeasurements -* Description : Compute Proximal pressure measurements -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ComputeProximalPressureMeasurements(void) -{ - u32 ulValue; - u16 uiValue; - - iProximalPressureMes=((100L*((int16_t)uiProximalPressureADCMes-(int16_t)uiTechnicalDataSet[PPROX_OFFSET_TEC]))/(int16_t)uiTechnicalDataSet[PPROX_GAIN_TEC]); - if (iProximalPressureMes>0) - uiProximalPressureMes=(u16)iProximalPressureMes; - else - uiProximalPressureMes=0; - uiNegativeProximalPressureMes=iProximalPressureMes; - - // Smoothing proximal pressure - uiProximalPressureTemp[ucIndexPproxPressureSmooth]=uiProximalPressureMes; - ulValue=0; - for (uiValue=0; uiValue<SMOOTH_PPROX_PRESSURE_COUNTER; uiValue++) - ulValue+=uiProximalPressureTemp[uiValue]; - uiProximalPressureSmoothingMes=ulValue/SMOOTH_PPROX_PRESSURE_COUNTER; - - ucIndexPproxPressureSmooth++; - if (ucIndexPproxPressureSmooth>=SMOOTH_PPROX_PRESSURE_COUNTER) - ucIndexPproxPressureSmooth=0; -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : ComputeOffsetProximalPressureSensor -* Description : Compute offset of the proximal pressure sensor -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ComputeOffsetProximalPressureSensor(void) -{ - u32 ulOffsetSum=0; - u16 i; - - for (i=0; i<64; i++) - { - ulOffsetSum+=uiADC_Value[ADC_PPROX_MES]; - uiTempoSysTick=5; - while (uiTempoSysTick!=0){} - } - uiTechnicalDataSet[PPROX_OFFSET_TEC]=ulOffsetSum>>6; -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : VentilationMonitoringAndAlarms -* Description : Compute measurements and alarms during ventilation -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void VentilationMonitoringAndAlarms(void) -{ - u16 uiTotalTimeMes; - - if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) - { - if (ucVentilationCycle==INSPIRATION_CYCLE) - { - // ***************** INSPIRATION ****************** - if (ucVentilationCycleCopy==EXPIRATION_CYCLE) - { - // --- Beginning of inspiration - ucVentilationCycleCopy=INSPIRATION_CYCLE; - SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_ON); - - // Update Vte measurement - uiVentilationMeasures[VTE_MES]=uiVteTemp; - - // Update Te measurement - uiVentilationMeasures[TE_MES]=uiTeMesTemp; - - // Update Average ADC Motor Voltage - if (ulCounterADC_MotorVoltage!=0) - uiAverageADC_MotorVoltage=ulSumADC_MotorVoltage/ulCounterADC_MotorVoltage; - - // Update Current measurement - if (ulCounterADC_FilteredBlowerCurrentMes!=0) - uiBreathBlowerCurrentMes=ComputeBlowerCurrentInAmper(ulSumCurrentADCMesFiltered/ulCounterADC_FilteredBlowerCurrentMes); - ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; - - // Update average blower speed - if (ulCounterAverageMotorSpeed!=0) - uiAverageBlowerSpeedMes=SpeedMeasurement(ulSumTachoTicks/ulCounterAverageMotorSpeed); - ulSumTachoTicks=0; - ulCounterAverageMotorSpeed=0; - - // Update average motor temperature during inspiration - if (uiTemperatureSamplesCounter!=0) - { - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); - if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]>890) - uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_TEMPERATURE_ALARM_MASK; - else if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]<810) - uiFlagsAlarm[ALARM_FLAGS2]&=(~MOTOR_TEMPERATURE_ALARM_MASK); - } - ulADCSumBlowerTemperature=0; uiTemperatureSamplesCounter=0; - - // --- Pmax=0 - uiPproxMax=0; - - // --- Vti=0 - lSumVti=0; - uiRecordVtiMes=uiVentilationMeasures[VTI_MES]; - - // --- Dislay Breath rate - uiTotalTimeMes=uiVentilationMeasures[TI_MES]+uiVentilationMeasures[TE_MES]; - if (uiTotalTimeMes>0) - uiVentilationMeasures[BREATH_RATE_MES]=600000/uiTotalTimeMes; - - // --- Ti=0 - uiTiMesTemp=0; - - // --- Max flow - iBlowerFlowSmoothingMaxMes=0; - - // --- Alarm Vte Min - if (uiVentilationMeasures[VTE_MES]<uiVentilationSet[VTE_MIN_ALARM_SET] && enVentilationMode!=CPAP_MODE) - { - ucCounterAlarmVteMin++; - if (ucCounterAlarmVteMin>=5) - { - ucCounterAlarmVteMin=5; - uiFlagsAlarm[ALARM_FLAGS1]|=LOW_VTE_ALARM_MASK; - } - } - else - { - ucCounterAlarmVteMin=0; - uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_VTE_ALARM_MASK); - } - } - else //if (ucVentilationCycle==EXPIRATION_CYCLE) - { - // --- During inspiration - - // --- Motor Speed - ulSumTachoTicks+=uiTachoTimeTicks; - ulCounterAverageMotorSpeed++; - - // --- Blower Current - ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; - ulCounterADC_FilteredBlowerCurrentMes++; - - // --- Inc Pmax - if (uiProximalPressureMes>uiPproxMax) - uiPproxMax=uiProximalPressureMes; - - // --- Inc max flow - if (iBlowerFlowSmoothingMes>iBlowerFlowSmoothingMaxMes) - iBlowerFlowSmoothingMaxMes=iBlowerFlowSmoothingMes; - - // --- Inc Vti - if (iBlowerFlowMes>30) - lSumVti+=iBlowerFlowMes; - uiVtiTemp=(u32)lSumVti/6000; - - // --- Inc Ti - uiTiMesTemp++; - - // --- Motor temperature - ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; - uiTemperatureSamplesCounter++; - - // --- Alarm Pmax - if (uiProximalPressureMes>uiVentilationSet[HIGH_PRESSURE_ALARM_SET] && enVentilationMode!=CPAP_MODE) - { - uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_PRESSURE_ALARM_MASK; - fAlarmPmax=TRUE; - } - - // --- Alarm Vti Max - if ((uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==PS_MODE) || - (uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==APCV_MODE)) - { - uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_VTI_ALARM_MASK; - fAlarmVtiMax=TRUE; - } - } - } - else - { - // ***************** EXPIRATION ****************** - if (ucVentilationCycleCopy==INSPIRATION_CYCLE) - { - // --- Beginning of Expiration - ucVentilationCycleCopy=EXPIRATION_CYCLE; - SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_OFF); - - // Update Pprox max measurement - uiVentilationMeasures[PPROX_MAX_MES]=uiPproxMax; - - // Update Vti measurement - uiVentilationMeasures[VTI_MES]=uiVtiTemp; - - // Update Ti measurement - uiVentilationMeasures[TI_MES]=uiTiMesTemp; - - // --- Motor Speed - ulSumTachoTicks+=uiTachoTimeTicks; - ulCounterAverageMotorSpeed++; - - // --- Blower Current - ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; - ulCounterADC_FilteredBlowerCurrentMes++; - - // --- Vte=0 - lSumVte=0; - - // --- Te=0 - uiTeMesTemp=0; - - // --- Alarm Low Pressure - if ((uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PS_SET]-5) && enVentilationMode==PS_MODE) || - (uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PI_SET]-5) && enVentilationMode==APCV_MODE) || - (uiVentilationMeasures[PPROX_MAX_MES]<uiVentilationSet[LOW_PRESSURE_ALARM_SET] && enVentilationMode==AVC_MODE)) - { - ucCounterLPAlarm++; - if (ucCounterLPAlarm>=4) - { - ucCounterLPAlarm=4; - uiFlagsAlarm[ALARM_FLAGS1]|=LOW_PRESSURE_ALARM_MASK; - } - } - else - { - ucCounterLPAlarm=0; - uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_PRESSURE_ALARM_MASK); - } - - // --- Clear Alarm High pressure - if (fAlarmPmax==FALSE) - uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_PRESSURE_ALARM_MASK); - fAlarmPmax=FALSE; - - // --- Clear Alarm Vti Max - if (fAlarmVtiMax==FALSE) - uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_VTI_ALARM_MASK); - fAlarmVtiMax=FALSE; - } - else - { - // --- During Expiration - - // --- Motor Speed - ulSumTachoTicks+=uiTachoTimeTicks; - ulCounterAverageMotorSpeed++; - - // --- Blower Current - ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; - ulCounterADC_FilteredBlowerCurrentMes++; - - // --- Inc Vte - if (iBlowerFlowMes<(-30)) - lSumVte+=iBlowerFlowMes; - if (lSumVte<0) - uiVteTemp=(u32)(lSumVte/(-6000)); - else - uiVteTemp=0; - - // --- Inc Te - uiTeMesTemp++; - if (uiTeMesTemp>60000) uiTeMesTemp=60000; - - // --- Average motor voltage - if (uiTeMesTemp==100) - { - ulSumADC_MotorVoltage=0; - ulCounterADC_MotorVoltage=0; - } - else if (uiTeMesTemp>100) - { - ulSumADC_MotorVoltage+=uiDCinADCMeas; - ulCounterADC_MotorVoltage++; - } - } - } - } - else // if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) - { - #ifndef TEMPERATURE_TRENDS - uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(uiADCBlowerTemperatureMeas); - #endif - } -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : ClearVentilationAlarm -* Description : Clear all ventilation Alarms -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ClearAllVentilationAlarms(void) -{ - u8 i; - u8 ucAlarmFlag; - - for (i=0; i<SIZE_BLOWER_ALARM; i++) - { - ucAlarmFlag=stBlowerAlarmStatus[i].ucAlarmFlag; - if (stBlowerAlarmStatus[i].bVentilationAlarm==TRUE && (ucAlarmFlag==ALARM_FLAGS1 || ucAlarmFlag==ALARM_FLAGS2)) - uiFlagsAlarm[ucAlarmFlag]&=(~stBlowerAlarmStatus[i].uiAlarmMask); - } -} - - -/******************************************************************************* -* Function Name : ClearAlarm -* Description : Clear a specific alarm -* Input : Mask of the alarm -* Output : None -* Return : None -*******************************************************************************/ -void ClearAlarm(u8 ucAlarmFlag, u16 uiMask) -{ - uiFlagsAlarm[ucAlarmFlag]&=(~uiMask); -} - - -/******************************************************************************* -* Function Name : ClearAllMeasures -* Description : Clear all ventilation measures -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ClearAllMeasures(void) -{ - u8 i; - - // Reset measures except alarms - for (i=0; i<SIZE_LRM_GROUP; i++) - { - if (i!=ALARM_ID1_MES && i!=ALARM_ID2_MES)// && i!=ALARM_ID3_MES && i!=ALARM_ID4_MES) - uiVentilationMeasures[i]=0; - } - - // Reset others measures - uiBlowerSpeedMes=0; uiAverageBlowerSpeedMes=0; // Speed=0 RPM - ulSumTachoTicks=0; ulCounterAverageMotorSpeed=0; - uiBreathBlowerCurrentMes=0; // Blower current=0 A - ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; - bDisplayInspiratoryTrigger=FALSE; - #ifdef MOTOR_LIFE_TESTING - uiAverateMotorTempMes=0; - #endif // #ifdef MOTOR_LIFE_TESTING - - // Init temporary variables - ucVentilationCycleCopy=INSPIRATION_CYCLE; - uiPproxMax=0; - uiVtiTemp=0; - uiTiMesTemp=0; - ucCounterLPAlarm=0; - fAlarmPmax=FALSE; - fAlarmVtiMax=FALSE; - ucCounterAlarmVteMin=0; -} - - -/******************************************************************************* -* Function Name : ReadStopVentilationAlarmNumber -* Description : Read the alarm number which stops the ventilation -* Input : None -* Output : None -* Return : alarm number -*******************************************************************************/ -u8 ReadStopVentilationAlarmNumber(void) -{ - u16 uiMask; - u8 i; - u8 ucAlarmNumber=SIZE_BLOWER_ALARM; - - // Check Alarm which stops ventilation - if (uiFlagsAlarm[ALARM_FLAGS1]!=0 || - uiFlagsAlarm[ALARM_FLAGS2]!=0) - /*uiFlagsAlarm[ALARM_FLAGS3]!=0 || - uiFlagsAlarm[ALARM_FLAGS4]!=0)*/ - { - for (i=0; i<SIZE_BLOWER_ALARM; i++) - { - if (stBlowerAlarmStatus[i].bForceVentilToStop==TRUE) - { - uiMask=stBlowerAlarmStatus[i].uiAlarmMask; - if ((uiFlagsAlarm[stBlowerAlarmStatus[i].ucAlarmFlag]&uiMask)==uiMask) - { - ucAlarmNumber=i; - break; - } - } - } - } - return(ucAlarmNumber); -} - - -/******************************************************************************* -* Function Name : UpdateAlarmsMeasureID -* Description : Update the alarms ventilation measure variables -* Input : None -* Output : None -* Return : alarm number -*******************************************************************************/ -#ifdef USE_OPTIMACOMM -void UpdateAlarmsMeasureID(void) -{ - uiVentilationMeasures[ALARM_ID1_MES]=uiFlagsAlarm[ALARM_FLAGS1]; - uiVentilationMeasures[ALARM_ID2_MES]=uiFlagsAlarm[ALARM_FLAGS2]; -} -#endif // #ifdef USE_OPTIMACOMM -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -/******************************************************************************* -* Function Name : ComputeMotorTemperature -* Description : Return temperature (in degres C) -* Input : uiADCMotorTemp : ADC value -* Output : None -* Return : None -*******************************************************************************/ -u16 ComputeMotorTemperature(u16 uiADCMotorTemp) -{ - u16 uiTemp, uiTempDec; - u32 ulTemp; - - for (uiTemp=0; uiTemp<121; uiTemp++) - { - if (uiADCMotorTemp>=uiADCMotorTempTable[uiTemp]) - break; - } - - if (uiADCMotorTemp<uiADCMotorTempTable[120]) - return(1200); - else if (uiADCMotorTemp>=uiADCMotorTempTable[0]) - return(0); - else if (uiADCMotorTemp==uiADCMotorTempTable[uiTemp]) - ulTemp=uiTemp*10; - else - { - uiTempDec=((uiADCMotorTempTable[uiTemp-1]-uiADCMotorTemp)*10)/(uiADCMotorTempTable[uiTemp-1]-uiADCMotorTempTable[uiTemp]); - ulTemp=((uiTemp-1)*10)+uiTempDec; - } - - ulTemp*=1000; - ulTemp/=uiTechnicalDataSet[GAIN_BLOWER_TEMP_TEC]; - return((u16)ulTemp); -} - - -/******************************************************************************* -* Function Name : ComputeFlowInLitersPerMin -* Description : Compute the flow in l/min -* Input : uFlowRAW : flow digital value, bPositiveFlow= TRUE if positive flow -* Output : None -* Return : signed Flow in l/min -*******************************************************************************/ -int16_t ComputeFlowInLitersPerMin(u16 uiFlowRAW, bool bPositiveFlow) -{ - u16 uiIndex; - int16_t iFlow; - u32 a; - int32_t b; - int32_t y; - - for (uiIndex=0; uiIndex<stLUTFlowSensor.uiLUT_TableSize; uiIndex++) - { - if (uiFlowRAW==stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) - { - iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; - break; - } - else if (uiFlowRAW<stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) - { - if (uiIndex==0) - { - iFlow=(int16_t)(((u32)uiFlowRAW*stLUTFlowSensor.uiFlowValue[uiIndex])/stLUTFlowSensor.uiFlowSensorTicks[uiIndex]); - } - else - { - a=(100UL*(stLUTFlowSensor.uiFlowValue[uiIndex]-stLUTFlowSensor.uiFlowValue[uiIndex-1]))/(stLUTFlowSensor.uiFlowSensorTicks[uiIndex]-stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]); - b=((int32_t)stLUTFlowSensor.uiFlowValue[uiIndex-1]*100)-((int32_t)stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]*a); - y=((int32_t)a*(int32_t)uiFlowRAW)+b; - iFlow=(int16_t)(y/100); - } - break; - } - else - { - iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; - } - } - - if (bPositiveFlow==FALSE) - iFlow*=(-1); - - return(iFlow); -} - -/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ - - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Monitoring.txt Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,1375 @@ +/*********************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#define EXTERN extern +#include "SS.h" +#include "main.h" +#include "_ss_pwm.h" +#include "_SS_I2CX_Drivers.h" +#include "_SS_I2CX_SDP600.h" +#include "_SS_I2CX_X201641.h" +#include "Ventilation.h" +#include "MotorTempTable.h" +#include "_SS_FlowComputer.h" +#include "_SS_TSI_4040.h" +#include "_SS_Data_Logging.h" +#include "_SS_OnOffActioner.h" +#undef EXTERN + +#define INIT_VARIABLES +#define EXTERN +#include "Monitoring.h" +#undef EXTERN +#undef INIT_VARIABLES + + +// *********************** Register locations ********************************** +#define DMA_IFCR1 (*(volatile uint32_t *)0x40020004) +#define DMA_CCR1 (*(volatile uint32_t *)0x40020008) +#define DMA_CNTDR1 (*(volatile uint32_t *)0x4002000c) +#define DMA_CPAR1 (*(volatile uint32_t *)0x40020010) +#define DMA_CMAR1 (*(volatile uint32_t *)0x40020014) + +#define ADC1_SR (*(volatile uint32_t *)0x40012400) +#define ADC1_SQR1 (*(volatile uint32_t *)0x4001242C) +#define ADC1_SQR2 (*(volatile uint32_t *)0x40012430) +#define ADC1_SQR3 (*(volatile uint32_t *)0x40012434) +#define ADC1_LTR (*(volatile uint32_t *)0x40012428) +#define ADC1_HTR (*(volatile uint32_t *)0x40012424) +#define ADC1_CR1 (*(volatile uint32_t *)0x40012404) +#define ADC1_CR2 (*(volatile uint32_t *)0x40012408) + + +// ************************* ADC CONFIGURATION CHANNELS ************************ +#define FREE_MEAS_CHANNEL 0 +#define PPROX_MEAS_CHANNEL 1 +#define CURRENT_MEAS_CHANNEL 2 +#define ALIM_24V_MEAS_CHANNEL 6 +#define TEMP_PHASE_A 5 +#define TEMP_PHASE_B 4 +#define TEMP_PHASE_C 3 + +// ********************* 24V ALARM MANAGEMENT ********************************** +#ifndef C_M3_DEVICETEST_TARGET + +#endif + + + +// ************************ I2C SENSORS MANAGEMENT ***************************** +#ifndef C_M3_DEVICETEST_TARGET + #define READING_NO_SENSOR 0 + #define READING_FLOW_SENSORS 1 + //#define READING_PRESSURE_SENSORS 2 + #define STOP_READING_FLOW_SENSORS 3 + #define START_READING_FLOW_SENSORS 4 + #define NUMBER_I2C_REBOOT 3 + + #define FLOW_SENSOR_READING 0 + #define FLOW_SENSOR_OK 1 + #define FLOW_SENSOR_FAIL 2 + static u8 ucStatusSDP600=FLOW_SENSOR_READING; + static u8 ucStatusX201641=FLOW_SENSOR_READING; + + static volatile u8 ucReadingFlowSensor=START_READING_FLOW_SENSORS; // I2Cx sensor managment + static u8 ucCounterFlowErrorMeasurement=0; + static u16 uiTotalCounterFlowErrorMeasurement=0; + + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + #define SMOOTH_BLOWER_RAW_FLOW_COUNTER 50 + static u16 uiBlowerRAWFlowTemp[SMOOTH_BLOWER_RAW_FLOW_COUNTER]; + static u8 ucIndexBlowerRAWFlowSmooth=0; + + #define BLOWER_RAW_FLOW_SAMPLES_NUMBER 200 + static u32 ulSumBlowerFlowRAWMes=0; + static u16 uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; + #endif + + #define SMOOTH_BLOWER_FLOW_LARGE_COUNTER 75//100 // MUST BE HIGHER THAN SMOOTH_BLOWER_FLOW_SMALL_COUNTER + #define SMOOTH_BLOWER_FLOW_SMALL_COUNTER 15 // MUST BE LOWER THAN SMOOTH_BLOWER_FLOW_LARGE_COUNTER + static int16_t iTempBlowerFlowForSmallSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; + static int16_t iTempBlowerFlowForLargeSmooth[SMOOTH_BLOWER_FLOW_LARGE_COUNTER]; + static u8 ucIndexSmallBlowerFlowSmooth=0; + static u8 ucIndexLargeBlowerFlowSmooth=0; + + static int16_t idConductancedtSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; + #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) +#endif // C_M3_DEVICETEST_TARGET + + + +// ****************** PROXIMAL PRESSURE SENSOR MANAGEMENT ********************** +#ifndef C_M3_DEVICETEST_TARGET + #define SMOOTH_PPROX_PRESSURE_COUNTER 40 + static u8 ucIndexPproxPressureSmooth=0; + static u16 uiProximalPressureTemp[SMOOTH_PPROX_PRESSURE_COUNTER]; +#endif // C_M3_DEVICETEST_TARGET + + + +// ********************* MEASURES MANAGEMENT ********************************** +#ifndef C_M3_DEVICETEST_TARGET + // ---- Current measurement + static u32 ulSumCurrentADCMesFiltered=0; + static u32 ulCounterADC_FilteredBlowerCurrentMes=0; + + // ---- Temperature measurement + static u32 ulADCSumBlowerTemperature=0; + static u16 uiTemperatureSamplesCounter=0; + + #ifdef TEMPERATURE_TRENDS + #ifdef USE_FLOW_COMPUTER + #define FLOW_COMPUTER_CYCLE_DETECTION_TIMER 10 // 100ms + static u8 ucFlowComputerCycle=EXPIRATION_CYCLE; + static u16 uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + #else + #define TIME_OUT_TEMPERATURE_MEASUREMENT 6000 // 60s + static u16 uiTimeOutTemperatureMeasurement=0; + #endif // #ifdef USE_FLOW_COMPUTER + static u32 ulADCSumTemperaturePhaseA=0; + static u16 uiADCTemperaturePhaseA; + static u32 ulADCSumTemperaturePhaseB=0; + static u16 uiADCTemperaturePhaseB; + static u32 ulADCSumTemperaturePhaseC=0; + static u16 uiADCTemperaturePhaseC; + #endif + + // ---- Blower Speed measurment + static u32 ulSumTachoTicks=0; + static u32 ulCounterAverageMotorSpeed=0; + + // --- Blower current Bessel filter + /*static u16 uiCurrentADCMesFilteredPrev2; + static u16 uiCurrentADCMesFilteredPrev1; + static u16 uiCurrentADCMesPrev2; + static u16 uiCurrentADCMesPrev1; + static u16 uiCurrentADCMesFiltered;*/ + + // --- Motor voltage + static u32 ulSumADC_MotorVoltage; + static u32 ulCounterADC_MotorVoltage; + + // --- Temporary measurements + static u16 uiPproxMax; + static u16 uiVtiTemp; + static u16 uiVteTemp; + static u16 uiTiMesTemp; + static u16 uiTeMesTemp; +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET + static u8 ucVentilationCycleCopy=INSPIRATION_CYCLE; + static int32_t lSumVti=0; + static int32_t lSumVte=0; + static u8 ucCounterAlarmVteMin=0; + static u8 ucCounterLPAlarm=0; +#endif // C_M3_DEVICETEST_TARGET + + +#define RCC_APB2RSTR (*(volatile uint32_t *)0x4002100c) + + +// ***************** Functions ********************************************** +int16_t ComputeFlowInLitersPerMin(u16 uFlowRAW, bool bPositiveFlow); +void ComputeBlowerPower(void); +u16 ComputeTemperature(u16 uiADCMotorTemp, u16 *puiTempLUT, u16 uiTemperatureGain); + + +/******************************************************************************* +* Function Name : ADC1_init +* Description : Init ADC1 +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ADC1_init(void) +{ + // First perform De_init + DMA_CCR1 &= (uint32_t)(~0x1); // channel 1 disable + DMA_CCR1 = 0; // Reset Channelx control register + DMA_CNTDR1 = 0; // Reset Channelx remaining bytes register + DMA_CPAR1 = 0; // Reset Channelx peripheral address register + DMA_CMAR1 = 0; // Reset Channelx memory address register + DMA_IFCR1 |= DMA_Channel1_IT_Mask; // Reset interrupt pending bits + // end de-init + + // Initialise DMA #1 + DMA_CPAR1 = (uint32_t)(ADC1_BASE + 0x4c); // base adress of ADC1 ADC_DR register + + DMA_CMAR1 = (unsigned long)(&uiADC_Value[0]); + DMA_CNTDR1 = NUMBER_ADC_CONVERSION; // numbers of data to be transfered + + DMA_CCR1 = (3<<12) + (1<<10) + (1<<8) + (1<<7) + (1<<5) /*+ (1<<1)*/; // very high priority, mem size 16 bits, periph size 16 bits, mem increase,/* circular enabled*/, /*transfer complete IT*/ + DMA_CCR1 |= 1; // channel 1 enable + + + + // De-init of the ADC 1 + RCC_APB2RSTR |= RCC_APB2Periph_ADC1; // enable + RCC_APB2RSTR &= ~RCC_APB2Periph_ADC1; // disable + // end De-init of the ADC 1 + + // Select channels of the regular group + #ifdef TEMPERATURE_TRENDS + ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + TEMP_PHASE_C; + ADC1_SQR3 = (TEMP_PHASE_B<<25) + (TEMP_PHASE_A<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; + #else + ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR3 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; + #endif + + // 21 micros ADC conversion time + ADC1->SMPR2= (7<<27) + (7<<24) + (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; + ADC1->SMPR1= (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; + + ADC1_CR1 = (1<<8); // Scan mode enabled + ADC1_CR2 = (1<<8); // DMA mode enabled + + ADC1_CR2 |= 1; // start ADC1 - power-on + + // Delay at least 1uSec for ADC calibration/stabilisation. See ADC documentation + // Stabilization time > 1uS for ADC, between power-on and start of conversion + // Give it 10uSecs just to be sure. + Delay100NS(100); + + // Calibration of ADC1 + ADC1_CR2 |= (1<<3); // reset calibration registers + ADC1_CR2 |= (1<<2); // Enable calibration + while ((ADC1_CR2 & (1<<2)) == (1<<2)); // Wait end of calibration + + ADC1_CR2 |= 1; // start ADC1 - start conversions +} + + +/******************************************************************************* +* Function Name : CheckAlimMotorVoltage +* Description : Check the voltage range of the 24V power supply +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +opstatus_t CheckAlimMotorVoltage(void) +{ + if (uiDCinADCMeas<271 || uiDCinADCMeas>2090) + return(OPSTATUS_FAIL); // <12V or >24V + return(OPSTATUS_OK); +} + + +/******************************************************************************* +* Function Name : Compute24VMeasure +* Description : Compute the 24V measure +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +#ifndef C_M3_DEVICETEST_TARGET +void Compute24VMeasure(void) +{ + u32 ulTemp; + u16 uiADC_BlowerVoltage; + + if (bMemoStartVentilation==TRUE) + uiADC_BlowerVoltage=uiAverageADC_MotorVoltage; + else + uiADC_BlowerVoltage=uiDCinADCMeas; + + ulTemp=((u32)uiADC_BlowerVoltage*100)/1452; + ulTemp+=100; + uiTechnicalDataMes[MOTOR_VOLTAGE_TEC_MES]=(u16)ulTemp; + uiMotorVoltageMes=(u16)ulTemp; +} +#endif + +void GetFirstMotorVoltageReading(void) +{ + uiAverageADC_MotorVoltage=uiDCinADCMeas; +} +/******************************************************************************* +* Function Name : ComputeBlowerPower +* Description : Compute the power of the blower +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +void ComputeBlowerPower(void) +{ + uiTechnicalDataMes[MOTOR_POWER_TEC_MES]=((u32)uiMotorVoltageMes*uiBlowerCurrentMes)/10; +} + +/******************************************************************************* +* Function Name : SpeedMeasurement +* Description : Return blower speed +* Input : Tacho counter +* Output : None +* Return : Blower speed in RPM +*******************************************************************************/ +u16 SpeedMeasurement(u16 uiTachoCounter) +{ + u16 uiSpeedTemp=65500; + + if (uiTachoCounter>915) + uiSpeedTemp=(u16)(60000000UL/uiTachoCounter); + + return(uiSpeedTemp); +} + + +/******************************************************************************* +* Function Name : ReadADCInputs +* Description : Read all ADC input (function calls every 1ms) +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ReadADCInputs(void) +{ + //u32 ulTerm1, ulTerm2, ulTerm3, ulTerm4, ulTerm5; + + // ADC Pprox measurement + uiProximalPressureADCMes=uiADC_Value[ADC_PPROX_MES]; + + // ADC DCin measurement + uiDCinADCMeas=uiADC_Value[ADC_DCIN_MES]; + + // ADC Blower current measurement + ComputeADCBlowerCurrent(FALSE); + + // ADC Free measurement + uiADCBlowerTemperatureMeas=uiADC_Value[ADC_FREE_MES]; + + #ifdef TEMPERATURE_TRENDS + uiADCTemperaturePhaseA=uiADC_Value[ADC_TEMP_PHASE_A]; + uiADCTemperaturePhaseB=uiADC_Value[ADC_TEMP_PHASE_B]; + uiADCTemperaturePhaseC=uiADC_Value[ADC_TEMP_PHASE_C]; + #endif + + // 2nd order Bessel Filter (Fcut-out=36Hz, sample rate=1KHz) + /*ulTerm1=(919UL*uiADCBlowerCurrent)>>6; + ulTerm2=(919UL*uiCurrentADCMesPrev1)>>5; + ulTerm3=(919UL*uiCurrentADCMesPrev2)>>6; + ulTerm4=(1427UL*uiCurrentADCMesFilteredPrev1)>>1; + ulTerm5=259UL*uiCurrentADCMesFilteredPrev2; + + uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>9; + uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; + uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; + uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; + uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ + + + // 2nd order Bessel Filter (Fcut-out=150Hz, sample rate=1KHz) + /*ulTerm1=(1929UL*uiADCBlowerCurrent)>>1; + ulTerm2=(1929UL*uiCurrentADCMesPrev1); + ulTerm3=(1929UL*uiCurrentADCMesPrev2)>>1; + ulTerm4=(1095UL*uiCurrentADCMesFilteredPrev1)>>1; + ulTerm5=(2479UL*uiCurrentADCMesFilteredPrev2)>>3; + + uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>12; + uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; + uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; + uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; + uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ + + // --- Start new conversions + ADC1->CR2 |= 1; +} + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeMeasurements +* Description : Compute different measures +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeMeasurements(void) +{ + // ---------------------- Measure Current (A) ---------------------------- + uiBlowerCurrentMes=ComputeBlowerCurrentInAmper(uiADCBlowerCurrent); + + // -------------------- Compute motor voltage (V) ------------------------ + Compute24VMeasure(); + ComputeBlowerPower(); + + // ---------------------- Others measurements ---------------------------- + if (bMemoStartVentilation==TRUE) + { + // --- Motor speed (RPM) (every 10ms) + uiBlowerSpeedMes=SpeedMeasurement(uiTachoTimeTicks); + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +#ifdef TEMPERATURE_TRENDS +/******************************************************************************* +* Function Name : ComputeAverageOnMeasurements +* Description : Average differents mesures : MUST BE CALLED EVERY 10ms +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeAverageOnMeasurements(void) +{ + #ifdef USE_FLOW_COMPUTER + // ----------- USE THE FLOW COMPUTER TO DETECT CYCLE ---------------- + u16 uiDummy; + opstatus_t opstatus; + + // Read new flow from flow computer every 10ms + opstatus=SS_Xgetw(flc, &uiDummy); + if (opstatus==OPSTATUS_OK) + { + // Update flow/pressure displayed + uiBlowerFlow=iFlowFromFlowComputer*10; + uiPoutPressureMes=uiPressureFromFlowComputer; + + // Comm with flow computer OK !! + #ifdef DATA_LOGGING + if (bRecordTemperatureTrendsAllowed==FALSE) + { + bRecordTemperatureTrendsAllowed=TRUE; + uiTrendsSampleTime=RECORD_TRENDS_SAMPLE_TIME; + } + #endif // DATA_LOGGING + + // inspiration/expiration cycle detection + if (ucFlowComputerCycle==EXPIRATION_CYCLE) + { + // Inspiration detection + if (iFlowFromFlowComputer>50) // 5l/min + { + uiFlowComputerCycleModificationTimer--; + if (uiFlowComputerCycleModificationTimer==0) + { + ucFlowComputerCycle=INSPIRATION_CYCLE; + + // Compute temperature of the previous inspiratory cycle + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; + } + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + } + } + else + uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + } + else + { + // Record temperature as long as the flow is positive + if (iFlowFromFlowComputer>(-10)) // >-1l/min + { + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; + ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; + ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; + uiTemperatureSamplesCounter++; + } + + // Expiration detection + if (iFlowFromFlowComputer<(-50)) // <-5l/min + { + uiFlowComputerCycleModificationTimer--; + if (uiFlowComputerCycleModificationTimer==0) + ucFlowComputerCycle=EXPIRATION_CYCLE; + } + else + uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + } + } + else if (opstatus==OPSTATUS_FAIL) + { + // Comm Failure with flow computer => no data recorded + uiBlowerFlow=0; + uiPoutPressureMes=0; + + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=FALSE; + #endif + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; + } + #else + // ----------- USE THE 24V MEASURE TO DETECT CYCLE ---------------- + if (uiDCinADCMeas>500) + { + // Inspiration + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; + ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; + ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; + uiTemperatureSamplesCounter++; + uiTimeOutTemperatureMeasurement=TIME_OUT_TEMPERATURE_MEASUREMENT; + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=TRUE; + #endif + } + else if (uiTimeOutTemperatureMeasurement!=0) + { + // Expiration + uiTimeOutTemperatureMeasurement--; + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; + } + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + } + else + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; + + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=FALSE; + #endif + } + #endif // #ifdef USE_FLOW_COMPUTER +} +#endif // #ifdef TEMPERATURE_TRENDS +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +/******************************************************************************* +* Function Name : ComputeADCBlowerCurrent +* Description : Compute the average current during a PWM cycle (20micros) +* Input : bRecordCurrentOffset +* Output : None +* Return : None +*******************************************************************************/ +void ComputeADCBlowerCurrent(bool bRecordCurrentOffset) +{ + if (bRecordCurrentOffset==TRUE) + { + uiADCOffsetBlowerCurrent=uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; + } + else + { + uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; + } +} + + +/******************************************************************************* +* Function Name : ComputeBlowerCurrentInAmper +* Description : Return blower current value in cAmper (ex: 100=1.00A) +* Input : ADC value +* Output : None +* Return : Blower current in cAmper (ex: 100=1.00A) +*******************************************************************************/ +int16_t ComputeBlowerCurrentInAmper(u16 uiADCBlowerCurrentLocal) +{ + int32_t lTempValue; + + // Computation using MOT_CUR_MEAS2 + lTempValue=(int32_t)uiADCBlowerCurrentLocal-(int32_t)uiADCOffsetBlowerCurrent; + lTempValue*=1000; + lTempValue/=uiTechnicalDataSet[GAIN_BLOWER_CURRENT_TEC]; + return(lTempValue); +} + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : LaunchFlowReadingOnI2CBus +* Description : Open and Read the flow sensor(s) on the I2C bus +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void LaunchFlowReadingOnI2CBus(void) +{ + opstatus_t byOpStatus; + u16 uiSensorErr; + + if (fOpenI2C1SDP600Sensors==FALSE || fOpenI2C2SDP600Sensors==FALSE || + fOpenI2C1X201641Sensors==FALSE || fOpenI2C2X201641Sensors==FALSE) + { + byOpStatus=SS_Xopen(I2C_SDP600); + if (byOpStatus==OPSTATUS_FAIL) + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + + byOpStatus=SS_Xopen(I2C_X201641); + if (byOpStatus==OPSTATUS_FAIL) + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + + ucReadingFlowSensor=STOP_READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==STOP_READING_FLOW_SENSORS) + { + ucReadingFlowSensor=START_READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==READING_FLOW_SENSORS) + { + // Reading SDP600 Flow sensors + if (ucStatusSDP600==FLOW_SENSOR_READING) + { + byOpStatus=SS_Xgetw(I2C_SDP600, &uiSensorErr); + if (byOpStatus==OPSTATUS_OK) + ucStatusSDP600=FLOW_SENSOR_OK; + else if (byOpStatus==OPSTATUS_FAIL) + ucStatusSDP600=FLOW_SENSOR_FAIL; + } + + // Reading X201641 Flow sensors + if (ucStatusX201641==FLOW_SENSOR_READING) + { + byOpStatus=SS_Xgetw(I2C_X201641, &uiSensorErr); + if (byOpStatus==OPSTATUS_OK) + ucStatusX201641=FLOW_SENSOR_OK; + else if (byOpStatus==OPSTATUS_FAIL) + ucStatusX201641=FLOW_SENSOR_FAIL; + } + + // End of flow measurement? + if (ucStatusSDP600!=FLOW_SENSOR_READING && ucStatusX201641!=FLOW_SENSOR_READING) + { + if (ucStatusSDP600==FLOW_SENSOR_OK && ucStatusX201641==FLOW_SENSOR_OK) + { + ucCounterFlowErrorMeasurement=0; + #ifdef TIME_MEASUREMENT + GPIOB->BRR = GPIO_Pin_5; + #endif + } + else + { + // Error counters + uiTotalCounterFlowErrorMeasurement++; + ucCounterFlowErrorMeasurement++; + if (ucCounterFlowErrorMeasurement>=NUMBER_I2C_REBOOT) + { + //ulErrorCounter|=uiSensorErr; + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + } + } + + // Next Sensors to measure + ucReadingFlowSensor=READING_NO_SENSOR; + ucStatusSDP600=FLOW_SENSOR_READING; + ucStatusX201641=FLOW_SENSOR_READING; + } + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeFlowMeasurement +* Description : Conpute inspiratory and erxpiratory flow measurements +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeFlowMeasurement(void) +{ + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + int32_t lValue; + u16 uiValue; + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + u32 ulValue; + #endif + #endif + + if (ucReadingFlowSensor==START_READING_FLOW_SENSORS) + { + ucReadingFlowSensor=READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==READING_NO_SENSOR) + { + ucReadingFlowSensor=READING_FLOW_SENSORS; + + // **** Reading of the Inspiratory RAW Flow + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + #ifdef SDP600_USED_I2C1_BUS + SDP600_ReadADCFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &uiValue); + #endif + #ifdef X201641_USED_I2C1_BUS + X201641_ReadADCFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &uiValue); + #endif + if (uiValue==uiTechnicalDataSet[FLOWI_OFFSET_TEC]) + { + uiBlowerFlowRAWMes=0; + iBlowerFlowMes=0; + } + else if (uiValue>uiTechnicalDataSet[FLOWI_OFFSET_TEC]) + { + uiBlowerFlowRAWMes=uiValue-uiTechnicalDataSet[FLOWI_OFFSET_TEC]; + iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, FALSE); + } + else + { + uiBlowerFlowRAWMes=uiTechnicalDataSet[FLOWI_OFFSET_TEC]-uiValue; + iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, TRUE); + } + + // Smoothing RWA data signals + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + uiBlowerRAWFlowTemp[ucIndexBlowerRAWFlowSmooth]=uiBlowerFlowRAWMes; + ulValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_RAW_FLOW_COUNTER; uiValue++) + ulValue+=uiBlowerRAWFlowTemp[uiValue]; + uiBlowerFlowRAWSmoothingMes=ulValue/SMOOTH_BLOWER_RAW_FLOW_COUNTER; + ucIndexBlowerRAWFlowSmooth++; + if (ucIndexBlowerRAWFlowSmooth>=SMOOTH_BLOWER_RAW_FLOW_COUNTER) + ucIndexBlowerRAWFlowSmooth=0; + + // Average of the RAW data signal + ulSumBlowerFlowRAWMes+=uiBlowerFlowRAWSmoothingMes; + uiBlowerRAWFlowSamplesCounter--; + if (uiBlowerRAWFlowSamplesCounter==0) + { + uiAverageBlowerFlowRAWMes=ulSumBlowerFlowRAWMes/BLOWER_RAW_FLOW_SAMPLES_NUMBER; + ulSumBlowerFlowRAWMes=0; + uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; + } + #endif // DISPLAY_AVERAGE_BLOWER_RAW_FLOW + + + // **** Reading of the Inspiratory Flow in l/min + /*#ifdef SDP600_USED_I2C1_BUS + SDP600_CalculFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); + #endif + #ifdef X201641_USED_I2C1_BUS + X201641_CalculFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); + #endif*/ + iTempBlowerFlowForSmallSmooth[ucIndexSmallBlowerFlowSmooth]=iBlowerFlowMes; + iTempBlowerFlowForLargeSmooth[ucIndexLargeBlowerFlowSmooth]=iBlowerFlowMes; + + // Small Smoothing of the inspiratory flow signal + lValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_SMALL_COUNTER; uiValue++) + lValue+=iTempBlowerFlowForSmallSmooth[uiValue]; + iBlowerFlowSmoothingMes=lValue/(int16_t)SMOOTH_BLOWER_FLOW_SMALL_COUNTER; + ucIndexSmallBlowerFlowSmooth++; + if (ucIndexSmallBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_SMALL_COUNTER) + ucIndexSmallBlowerFlowSmooth=0; + + // Large Smoothing of the inspiratory flow signal + lValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_LARGE_COUNTER; uiValue++) + lValue+=iTempBlowerFlowForLargeSmooth[uiValue]; + iBlowerFlowSmoothingMesForTrigger=lValue/(int16_t)SMOOTH_BLOWER_FLOW_LARGE_COUNTER; + ucIndexLargeBlowerFlowSmooth++; + if (ucIndexLargeBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_LARGE_COUNTER) + ucIndexLargeBlowerFlowSmooth=0; + + // Flow for Optima Comm + uiBlowerFlow=iBlowerFlowMes; + uiBlowerFlowSmoothingMes=iBlowerFlowSmoothingMes; + uiBlowerFlowTriggerMes=iBlowerFlowSmoothingMesForTrigger; + #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) + } + +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +double powApprox(double a, double x) +{ + union + { + double d; + int A[2]; + } Z = { a }; + Z.A[1] = (int)(x * (Z.A[1] - 1072632447) + 1072632447); + Z.A[0] = 0; + return Z.d; +} +/******************************************************************************* +* Function Name : ComputeConductance +* Description : Compute Conductance +* Input : Pressure, Flow +* Output : Conductance +* Return : None +*******************************************************************************/ +float prevConductance = 0.0f; +u8 bufferIndex = 0; +bool filled = FALSE; +int16_t littleSum = 0; + +void ComputeConductance(void) +{ + float pressure = iProximalPressureMes/10.0f; + float flow = iBlowerFlowSmoothingMes/100.0f/60.0f; + float density = 1.225f; + float viscosity = 0.00018f; + float calcConductance = 0.0f; + + if(pressure != 0) + { + calcConductance = (100000)*((powApprox((flow*0.001f),1.75)*powApprox(density,0.75)*powApprox(viscosity,0.25)/(pressure / 10.0f)* 98.0638f)); + calcConductance = calcConductance * 1000.0f; + if(calcConductance < 60000 && calcConductance > -60000) + { + uiConductanceCalc = (int16_t)calcConductance; + } + } +// int16_t tempValue = idConductancedtSmooth[bufferIndex]; +// idConductancedtSmooth[bufferIndex]= (int16_t)(calcConductance - prevConductance);//1000; +// littleSum += idConductancedtSmooth[bufferIndex]; +// bufferIndex++; +// if(bufferIndex > SMOOTH_BLOWER_FLOW_LARGE_COUNTER) +// { +// bufferIndex = 0; +// if(!filled) +// { +// filled = TRUE; +// } +// } +// +// if(filled) +// { +// littleSum -= tempValue; +// uidConductanceCalcdt = littleSum/SMOOTH_BLOWER_FLOW_LARGE_COUNTER; +// } + uidConductanceCalcdt = (int16_t)(calcConductance - prevConductance); + prevConductance = calcConductance; +} +/******************************************************************************* +* Function Name : ComputeProximalPressureMeasurements +* Description : Compute Proximal pressure measurements +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeProximalPressureMeasurements(void) +{ + u32 ulValue; + u16 uiValue; + + iProximalPressureMes=((100L*((int16_t)uiProximalPressureADCMes-(int16_t)uiTechnicalDataSet[PPROX_OFFSET_TEC]))/(int16_t)uiTechnicalDataSet[PPROX_GAIN_TEC]); + if (iProximalPressureMes>0) + uiProximalPressureMes=(u16)iProximalPressureMes; + else + uiProximalPressureMes=0; + uiNegativeProximalPressureMes=iProximalPressureMes; + + // Smoothing proximal pressure + uiProximalPressureTemp[ucIndexPproxPressureSmooth]=uiProximalPressureMes; + ulValue=0; + for (uiValue=0; uiValue<SMOOTH_PPROX_PRESSURE_COUNTER; uiValue++) + ulValue+=uiProximalPressureTemp[uiValue]; + uiProximalPressureSmoothingMes=ulValue/SMOOTH_PPROX_PRESSURE_COUNTER; + + ucIndexPproxPressureSmooth++; + if (ucIndexPproxPressureSmooth>=SMOOTH_PPROX_PRESSURE_COUNTER) + ucIndexPproxPressureSmooth=0; +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeOffsetProximalPressureSensor +* Description : Compute offset of the proximal pressure sensor +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeOffsetProximalPressureSensor(void) +{ + u32 ulOffsetSum=0; + u16 i; + + for (i=0; i<64; i++) + { + ulOffsetSum+=uiADC_Value[ADC_PPROX_MES]; + uiTempoSysTick=5; + while (uiTempoSysTick!=0){} + } + uiTechnicalDataSet[PPROX_OFFSET_TEC]=ulOffsetSum>>6; +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : VentilationMonitoringAndAlarms +* Description : Compute measurements and alarms during ventilation +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void VentilationMonitoringAndAlarms(void) +{ + u16 uiTotalTimeMes; + + if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) + { + if (ucVentilationCycle==INSPIRATION_CYCLE) + { + // ***************** INSPIRATION ****************** + if (ucVentilationCycleCopy==EXPIRATION_CYCLE) + { + // --- Beginning of inspiration + ucVentilationCycleCopy=INSPIRATION_CYCLE; + SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_ON); + + // Update Vte measurement + uiVentilationMeasures[VTE_MES]=uiVteTemp; + + // Update Te measurement + uiVentilationMeasures[TE_MES]=uiTeMesTemp; + + // Update Average ADC Motor Voltage + if (ulCounterADC_MotorVoltage!=0) + uiAverageADC_MotorVoltage=ulSumADC_MotorVoltage/ulCounterADC_MotorVoltage; + + // Update Current measurement + if (ulCounterADC_FilteredBlowerCurrentMes!=0) + uiBreathBlowerCurrentMes=ComputeBlowerCurrentInAmper(ulSumCurrentADCMesFiltered/ulCounterADC_FilteredBlowerCurrentMes); + ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; + + // Update average blower speed + if (ulCounterAverageMotorSpeed!=0) + uiAverageBlowerSpeedMes=SpeedMeasurement(ulSumTachoTicks/ulCounterAverageMotorSpeed); + ulSumTachoTicks=0; + ulCounterAverageMotorSpeed=0; + + // Update average motor temperature during inspiration + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]>890) + uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_TEMPERATURE_ALARM_MASK; + else if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]<810) + uiFlagsAlarm[ALARM_FLAGS2]&=(~MOTOR_TEMPERATURE_ALARM_MASK); + } + ulADCSumBlowerTemperature=0; uiTemperatureSamplesCounter=0; + + // --- Pmax=0 + uiPproxMax=0; + + // --- Vti=0 + lSumVti=0; + uiRecordVtiMes=uiVentilationMeasures[VTI_MES]; + + // --- Dislay Breath rate + uiTotalTimeMes=uiVentilationMeasures[TI_MES]+uiVentilationMeasures[TE_MES]; + if (uiTotalTimeMes>0) + uiVentilationMeasures[BREATH_RATE_MES]=600000/uiTotalTimeMes; + + // --- Ti=0 + uiTiMesTemp=0; + + // --- Max flow + iBlowerFlowSmoothingMaxMes=0; + + // --- Alarm Vte Min + if (uiVentilationMeasures[VTE_MES]<uiVentilationSet[VTE_MIN_ALARM_SET] && enVentilationMode!=CPAP_MODE) + { + ucCounterAlarmVteMin++; + if (ucCounterAlarmVteMin>=5) + { + ucCounterAlarmVteMin=5; + uiFlagsAlarm[ALARM_FLAGS1]|=LOW_VTE_ALARM_MASK; + } + } + else + { + ucCounterAlarmVteMin=0; + uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_VTE_ALARM_MASK); + } + } + else //if (ucVentilationCycle==EXPIRATION_CYCLE) + { + // --- During inspiration + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Inc Pmax + if (uiProximalPressureMes>uiPproxMax) + uiPproxMax=uiProximalPressureMes; + + // --- Inc max flow + if (iBlowerFlowSmoothingMes>iBlowerFlowSmoothingMaxMes) + iBlowerFlowSmoothingMaxMes=iBlowerFlowSmoothingMes; + + // --- Inc Vti + if (iBlowerFlowMes>30) + lSumVti+=iBlowerFlowMes; + uiVtiTemp=(u32)lSumVti/6000; + + // --- Inc Ti + uiTiMesTemp++; + + // --- Motor temperature + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + uiTemperatureSamplesCounter++; + + // --- Alarm Pmax + if (uiProximalPressureMes>uiVentilationSet[HIGH_PRESSURE_ALARM_SET] && enVentilationMode!=CPAP_MODE) + { + uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_PRESSURE_ALARM_MASK; + fAlarmPmax=TRUE; + } + + // --- Alarm Vti Max + if ((uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==PS_MODE) || + (uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==APCV_MODE)) + { + uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_VTI_ALARM_MASK; + fAlarmVtiMax=TRUE; + } + } + } + else + { + // ***************** EXPIRATION ****************** + if (ucVentilationCycleCopy==INSPIRATION_CYCLE) + { + // --- Beginning of Expiration + ucVentilationCycleCopy=EXPIRATION_CYCLE; + SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_OFF); + + // Update Pprox max measurement + uiVentilationMeasures[PPROX_MAX_MES]=uiPproxMax; + + // Update Vti measurement + uiVentilationMeasures[VTI_MES]=uiVtiTemp; + + // Update Ti measurement + uiVentilationMeasures[TI_MES]=uiTiMesTemp; + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Vte=0 + lSumVte=0; + + // --- Te=0 + uiTeMesTemp=0; + + // --- Alarm Low Pressure + if ((uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PS_SET]-5) && enVentilationMode==PS_MODE) || + (uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PI_SET]-5) && enVentilationMode==APCV_MODE) || + (uiVentilationMeasures[PPROX_MAX_MES]<uiVentilationSet[LOW_PRESSURE_ALARM_SET] && enVentilationMode==AVC_MODE)) + { + ucCounterLPAlarm++; + if (ucCounterLPAlarm>=4) + { + ucCounterLPAlarm=4; + uiFlagsAlarm[ALARM_FLAGS1]|=LOW_PRESSURE_ALARM_MASK; + } + } + else + { + ucCounterLPAlarm=0; + uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_PRESSURE_ALARM_MASK); + } + + // --- Clear Alarm High pressure + if (fAlarmPmax==FALSE) + uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_PRESSURE_ALARM_MASK); + fAlarmPmax=FALSE; + + // --- Clear Alarm Vti Max + if (fAlarmVtiMax==FALSE) + uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_VTI_ALARM_MASK); + fAlarmVtiMax=FALSE; + } + else + { + // --- During Expiration + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Inc Vte + if (iBlowerFlowMes<(-30)) + lSumVte+=iBlowerFlowMes; + if (lSumVte<0) + uiVteTemp=(u32)(lSumVte/(-6000)); + else + uiVteTemp=0; + + // --- Inc Te + uiTeMesTemp++; + if (uiTeMesTemp>60000) uiTeMesTemp=60000; + + // --- Average motor voltage + if (uiTeMesTemp==100) + { + ulSumADC_MotorVoltage=0; + ulCounterADC_MotorVoltage=0; + } + else if (uiTeMesTemp>100) + { + ulSumADC_MotorVoltage+=uiDCinADCMeas; + ulCounterADC_MotorVoltage++; + } + } + } + } + else // if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) + { + #ifndef TEMPERATURE_TRENDS + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(uiADCBlowerTemperatureMeas); + #endif + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ClearVentilationAlarm +* Description : Clear all ventilation Alarms +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ClearAllVentilationAlarms(void) +{ + u8 i; + u8 ucAlarmFlag; + + for (i=0; i<SIZE_BLOWER_ALARM; i++) + { + ucAlarmFlag=stBlowerAlarmStatus[i].ucAlarmFlag; + if (stBlowerAlarmStatus[i].bVentilationAlarm==TRUE && (ucAlarmFlag==ALARM_FLAGS1 || ucAlarmFlag==ALARM_FLAGS2)) + uiFlagsAlarm[ucAlarmFlag]&=(~stBlowerAlarmStatus[i].uiAlarmMask); + } +} + + +/******************************************************************************* +* Function Name : ClearAlarm +* Description : Clear a specific alarm +* Input : Mask of the alarm +* Output : None +* Return : None +*******************************************************************************/ +void ClearAlarm(u8 ucAlarmFlag, u16 uiMask) +{ + uiFlagsAlarm[ucAlarmFlag]&=(~uiMask); +} + + +/******************************************************************************* +* Function Name : ClearAllMeasures +* Description : Clear all ventilation measures +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ClearAllMeasures(void) +{ + u8 i; + + // Reset measures except alarms + for (i=0; i<SIZE_LRM_GROUP; i++) + { + if (i!=ALARM_ID1_MES && i!=ALARM_ID2_MES)// && i!=ALARM_ID3_MES && i!=ALARM_ID4_MES) + uiVentilationMeasures[i]=0; + } + + // Reset others measures + uiBlowerSpeedMes=0; uiAverageBlowerSpeedMes=0; // Speed=0 RPM + ulSumTachoTicks=0; ulCounterAverageMotorSpeed=0; + uiBreathBlowerCurrentMes=0; // Blower current=0 A + ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; + bDisplayInspiratoryTrigger=FALSE; + #ifdef MOTOR_LIFE_TESTING + uiAverateMotorTempMes=0; + #endif // #ifdef MOTOR_LIFE_TESTING + + // Init temporary variables + ucVentilationCycleCopy=INSPIRATION_CYCLE; + uiPproxMax=0; + uiVtiTemp=0; + uiTiMesTemp=0; + ucCounterLPAlarm=0; + fAlarmPmax=FALSE; + fAlarmVtiMax=FALSE; + ucCounterAlarmVteMin=0; +} + + +/******************************************************************************* +* Function Name : ReadStopVentilationAlarmNumber +* Description : Read the alarm number which stops the ventilation +* Input : None +* Output : None +* Return : alarm number +*******************************************************************************/ +u8 ReadStopVentilationAlarmNumber(void) +{ + u16 uiMask; + u8 i; + u8 ucAlarmNumber=SIZE_BLOWER_ALARM; + + // Check Alarm which stops ventilation + if (uiFlagsAlarm[ALARM_FLAGS1]!=0 || + uiFlagsAlarm[ALARM_FLAGS2]!=0) + /*uiFlagsAlarm[ALARM_FLAGS3]!=0 || + uiFlagsAlarm[ALARM_FLAGS4]!=0)*/ + { + for (i=0; i<SIZE_BLOWER_ALARM; i++) + { + if (stBlowerAlarmStatus[i].bForceVentilToStop==TRUE) + { + uiMask=stBlowerAlarmStatus[i].uiAlarmMask; + if ((uiFlagsAlarm[stBlowerAlarmStatus[i].ucAlarmFlag]&uiMask)==uiMask) + { + ucAlarmNumber=i; + break; + } + } + } + } + return(ucAlarmNumber); +} + + +/******************************************************************************* +* Function Name : UpdateAlarmsMeasureID +* Description : Update the alarms ventilation measure variables +* Input : None +* Output : None +* Return : alarm number +*******************************************************************************/ +#ifdef USE_OPTIMACOMM +void UpdateAlarmsMeasureID(void) +{ + uiVentilationMeasures[ALARM_ID1_MES]=uiFlagsAlarm[ALARM_FLAGS1]; + uiVentilationMeasures[ALARM_ID2_MES]=uiFlagsAlarm[ALARM_FLAGS2]; +} +#endif // #ifdef USE_OPTIMACOMM +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +/******************************************************************************* +* Function Name : ComputeMotorTemperature +* Description : Return temperature (in degres C) +* Input : uiADCMotorTemp : ADC value +* Output : None +* Return : None +*******************************************************************************/ +u16 ComputeMotorTemperature(u16 uiADCMotorTemp) +{ + u16 uiTemp, uiTempDec; + u32 ulTemp; + + for (uiTemp=0; uiTemp<121; uiTemp++) + { + if (uiADCMotorTemp>=uiADCMotorTempTable[uiTemp]) + break; + } + + if (uiADCMotorTemp<uiADCMotorTempTable[120]) + return(1200); + else if (uiADCMotorTemp>=uiADCMotorTempTable[0]) + return(0); + else if (uiADCMotorTemp==uiADCMotorTempTable[uiTemp]) + ulTemp=uiTemp*10; + else + { + uiTempDec=((uiADCMotorTempTable[uiTemp-1]-uiADCMotorTemp)*10)/(uiADCMotorTempTable[uiTemp-1]-uiADCMotorTempTable[uiTemp]); + ulTemp=((uiTemp-1)*10)+uiTempDec; + } + + ulTemp*=1000; + ulTemp/=uiTechnicalDataSet[GAIN_BLOWER_TEMP_TEC]; + return((u16)ulTemp); +} + + +/******************************************************************************* +* Function Name : ComputeFlowInLitersPerMin +* Description : Compute the flow in l/min +* Input : uFlowRAW : flow digital value, bPositiveFlow= TRUE if positive flow +* Output : None +* Return : signed Flow in l/min +*******************************************************************************/ +int16_t ComputeFlowInLitersPerMin(u16 uiFlowRAW, bool bPositiveFlow) +{ + u16 uiIndex; + int16_t iFlow; + u32 a; + int32_t b; + int32_t y; + + for (uiIndex=0; uiIndex<stLUTFlowSensor.uiLUT_TableSize; uiIndex++) + { + if (uiFlowRAW==stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) + { + iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; + break; + } + else if (uiFlowRAW<stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) + { + if (uiIndex==0) + { + iFlow=(int16_t)(((u32)uiFlowRAW*stLUTFlowSensor.uiFlowValue[uiIndex])/stLUTFlowSensor.uiFlowSensorTicks[uiIndex]); + } + else + { + a=(100UL*(stLUTFlowSensor.uiFlowValue[uiIndex]-stLUTFlowSensor.uiFlowValue[uiIndex-1]))/(stLUTFlowSensor.uiFlowSensorTicks[uiIndex]-stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]); + b=((int32_t)stLUTFlowSensor.uiFlowValue[uiIndex-1]*100)-((int32_t)stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]*a); + y=((int32_t)a*(int32_t)uiFlowRAW)+b; + iFlow=(int16_t)(y/100); + } + break; + } + else + { + iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; + } + } + + if (bPositiveFlow==FALSE) + iFlow*=(-1); + + return(iFlow); +} + +/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ + + +
--- a/Safety.c Tue Jun 09 22:57:20 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ - -/* Includes ------------------------------------------------------------------*/ -#define EXTERN extern -#include "SS.h" -#include "_SS_OnOffActioner.h" -#include "main.h" -#undef EXTERN - -#define INIT_VARIABLES -#define EXTERN -#include "safety.h" -#undef EXTERN -#undef INIT_VARIABLES - - - -/******************************************************************************* -* Function Name : ControlHW -* Description : Control the STOP_BLOWER and WDI_CPLD pins -* Input : BLOWER_OFF__PAT_CPLD or BLOWER_ON__PAT_CPLD or BLOWER_OFF__STOP_PAT_CPLD -* Output : None -* Return : None -*******************************************************************************/ -void ControlHW(_enHWStatus enHWStatus) -{ - // Clock=0 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); - - /*if (enHWStatus==BLOWER_OFF__PAT_CPLD) - { - SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_OFF); // CTL_ACTUATORS=0 - SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=0 - - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); // Clock=0 - SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_ON); // CTL_CPLD=1 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=1 - }*/ - if (enHWStatus==BLOWER_ON__PAT_CPLD) - { - SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_ON); // CTL_ACTUATORS=1 - SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=1, WDI_CPLD=0 - - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); // Clock=0 - SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_ON); // CTL_CPLD=1 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=1, WDI_CPLD=1 - } - else //if (enHWStatus==BLOWER_OFF__STOP_PAT_CPLD) - { - SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_OFF); // CTL_ACTUATORS=0 - SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 - SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=0 - } -} - - - -/******************************************************************************* -* Function Name : TestStopBlowerInputPin -* Description : Test the state of the STOP_BLOWER input pin -* Input : None -* Output : None -* Return : OPSTATUS_OK if the pin="0" -*******************************************************************************/ -opstatus_t TestStopBlowerInputPin(void) -{ - if (GPIO_ReadInputDataBit(sPortConfig[STOP_BLOWER_PORT].Port, sPortConfig[STOP_BLOWER_PORT].Pin)==Bit_RESET) - return(OPSTATUS_OK); - return(OPSTATUS_FAIL); -} -/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ - - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Safety.txt Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,75 @@ + +/* Includes ------------------------------------------------------------------*/ +#define EXTERN extern +#include "SS.h" +#include "_SS_OnOffActioner.h" +#include "main.h" +#undef EXTERN + +#define INIT_VARIABLES +#define EXTERN +#include "safety.h" +#undef EXTERN +#undef INIT_VARIABLES + + + +/******************************************************************************* +* Function Name : ControlHW +* Description : Control the STOP_BLOWER and WDI_CPLD pins +* Input : BLOWER_OFF__PAT_CPLD or BLOWER_ON__PAT_CPLD or BLOWER_OFF__STOP_PAT_CPLD +* Output : None +* Return : None +*******************************************************************************/ +void ControlHW(_enHWStatus enHWStatus) +{ + // Clock=0 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); + + /*if (enHWStatus==BLOWER_OFF__PAT_CPLD) + { + SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_OFF); // CTL_ACTUATORS=0 + SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=0 + + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); // Clock=0 + SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_ON); // CTL_CPLD=1 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=1 + }*/ + if (enHWStatus==BLOWER_ON__PAT_CPLD) + { + SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_ON); // CTL_ACTUATORS=1 + SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=1, WDI_CPLD=0 + + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_OFF); // Clock=0 + SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_ON); // CTL_CPLD=1 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=1, WDI_CPLD=1 + } + else //if (enHWStatus==BLOWER_OFF__STOP_PAT_CPLD) + { + SS_Xputdw(act, CTL_ACTUATORS|FLAG_ACTIONER_OFF); // CTL_ACTUATORS=0 + SS_Xputdw(act, CTL_CPLD|FLAG_ACTIONER_OFF); // CTL_CPLD=0 + SS_Xputdw(act, CLK_ACTUATORS|FLAG_ACTIONER_ON); // Clock=1 => STOP_BLOWER=0, WDI_CPLD=0 + } +} + + + +/******************************************************************************* +* Function Name : TestStopBlowerInputPin +* Description : Test the state of the STOP_BLOWER input pin +* Input : None +* Output : None +* Return : OPSTATUS_OK if the pin="0" +*******************************************************************************/ +opstatus_t TestStopBlowerInputPin(void) +{ + if (GPIO_ReadInputDataBit(sPortConfig[STOP_BLOWER_PORT].Port, sPortConfig[STOP_BLOWER_PORT].Pin)==Bit_RESET) + return(OPSTATUS_OK); + return(OPSTATUS_FAIL); +} +/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Screens.cpp Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,143 @@ +#include "TS_DISCO_F429ZI.h" +#include "LCD_DISCO_F429ZI.h" +#include "Screens.h" +#include "main.h" + +bool refreshScreen = true; +// Pos 1 2 (row of button ) +void DrawBigButton(LCD_DISCO_F429ZI lcd, uint8_t position, char* array) +{ + BSP_LCD_SetFont(&Font20); + uint8_t text_array[30]; + sprintf((char*)text_array, array); + switch (position) + { + case 1: + lcd.DrawRect(BigButtonX, BigButton1Y, BigButtonWidth , BigButtonHeight ); + lcd.DisplayStringAt(0, LINE(4), (uint8_t *)&text_array, CENTER_MODE); + break; + case 2: + lcd.DrawRect(BigButtonX, BigButton2Y, BigButtonWidth , BigButtonHeight ); + lcd.DisplayStringAt(0, LINE(7), (uint8_t *)&text_array, CENTER_MODE); + break; + case 3: + lcd.DrawRect(BigButtonX,BigButton3Y,BigButtonWidth ,BigButtonHeight ); + lcd.DisplayStringAt(0, LINE(10), (uint8_t *)&text_array, CENTER_MODE); + break; + case 4: + lcd.DrawRect(BigButtonX,BigButton4Y,BigButtonWidth ,BigButtonHeight ); + lcd.DisplayStringAt(0, LINE(13), (uint8_t *)&text_array, CENTER_MODE); + default: + break; + } +} + +void CreatStartupScreen(LCD_DISCO_F429ZI lcd) +{ + lcd.Clear(LCD_COLOR_DARKGRAY); + uint8_t text_array[30]; + // Show Title Line - Select Mode + BSP_LCD_SetFont(&Font20); + sprintf((char*)text_array, "Select Mode"); + lcd.ClearStringLine(1); + lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text_array, CENTER_MODE); + // Show Two Buttons + // first CPAP Mode + DrawBigButton(lcd, 1, "CPAP"); + // On Press SHOW CPAP Screen + // second NIV + DrawBigButton(lcd, 2, "NIV"); + // On Press show NIV Screen +} +void CreateCPAPMainScreen(LCD_DISCO_F429ZI lcd) +{ + lcd.Clear(LCD_COLOR_DARKGRAY); + uint8_t text_array[30]; + // Show Title Line - Select Mode + BSP_LCD_SetFont(&Font20); + sprintf((char*)text_array, "CPAP"); + lcd.ClearStringLine(1); + lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text_array, CENTER_MODE); + // Show Two Buttons + // first CPAP Mode + DrawBigButton(lcd, 1, "START"); + // On Press SHOW CPAP Screen + // second NIV + DrawBigButton(lcd, 2, "SETTINGS"); + // On Press show NIV Screen + DrawBigButton(lcd, 3, "BACK"); +} +void CreateCPAPMainSettingsScreen(LCD_DISCO_F429ZI lcd) +{ + lcd.Clear(LCD_COLOR_DARKGRAY); + uint8_t text_array[30]; + // Show Title Line - Select Mode + BSP_LCD_SetFont(&Font20); + sprintf((char*)text_array, "CPAP Settings"); + lcd.ClearStringLine(1); + lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text_array, CENTER_MODE); + // Show Two Buttons + // first CPAP Mode + DrawBigButton(lcd, 1, "PEEP"); + DrawBigButton(lcd, 2, "TI"); + DrawBigButton(lcd, 3, "OTHER ->"); + DrawBigButton(lcd, 4, "BACK"); +} + + +void CreateNIVMainScreen(LCD_DISCO_F429ZI lcd) +{ + lcd.Clear(LCD_COLOR_DARKGRAY); + uint8_t text_array[30]; + // Show Title Line - Select Mode + BSP_LCD_SetFont(&Font20); + sprintf((char*)text_array, "NIV"); + lcd.ClearStringLine(1); + lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text_array, CENTER_MODE); + // Show Two Buttons + // first CPAP Mode + DrawBigButton(lcd, 1, "START"); + // On Press SHOW CPAP Screen + // second NIV + DrawBigButton(lcd, 2, "SETTINGS"); + // On Press show NIV Screen + DrawBigButton(lcd, 3, "BACK"); +} +void showScreen(ScreenState screen,LCD_DISCO_F429ZI lcd) +{ + if ( refreshScreen == false ) + return; + switch(screen) + { + case StartUp : + CreatStartupScreen(lcd); + refreshScreen = false; + break; + case CPAPMain : + CreateCPAPMainScreen(lcd); + refreshScreen = false; + break; + case NIVMain : + CreateNIVMainScreen(lcd); + refreshScreen = false; + break; + case CPAPRunning: + break; + case CPAPSettingsMain: + CreateCPAPMainSettingsScreen(lcd); + refreshScreen = false; + break; + case CPAPSettingsDetailView: + break; + case NIVRunning: + break; + case NIVSettingsMain: + break; + case NIVSettingsDetailView: + break; + + + + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Screens.h Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,39 @@ +#ifndef __SCREENS_H +#define __SCREENS_H +#ifdef TARGET_DISCO_F429ZI +#include "TS_DISCO_F429ZI.h" +#include "LCD_DISCO_F429ZI.h" + +#define BigButtonX 40 +#define BigButtonWidth 160 +#define BigButtonHeight 35 + +#define BigButton1Y 70 +#define BigButton2Y 130 +#define BigButton3Y 190 +#define BigButton4Y 250 + +typedef enum +{ + StartUp = 0, + CPAPMain = 1, + NIVMain = 2, + CPAPRunning = 3, + CPAPSettingsMain = 4, + CPAPSettingsDetailView = 5, + NIVRunning = 6, + NIVSettingsMain = 7, + NIVSettingsDetailView = 8 +} ScreenState; + +extern bool refreshScreen; + +void CreatStartupScreen(LCD_DISCO_F429ZI lcd); +void DrawBigButton(LCD_DISCO_F429ZI lcd, uint8_t position, char* array); +void showScreen(ScreenState screen,LCD_DISCO_F429ZI lcd); + +#else +#error "This class must be used with DISCO_F429ZI board only." +#endif // TARGET_DISCO_F429ZI + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Touch.cpp Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,176 @@ +#include "Touch.h" +#include "main.h" +#include "Screens.h" + +// in Bigbutton position same as draw big button position +// out 1 touch detected 0 no touch detected + +uint16_t x, y = 0; +uint16_t touch_x, touch_y = 0; +bool press_detected = false; + +TS_StateTypeDef TS_State; +TS_StateTypeDef Old_TS_State; + +void CheckTs() +{ + ts.GetState(&TS_State); + if (TS_State.TouchDetected) + { + x = TS_State.X; + y = TS_State.Y; + } + if ((Old_TS_State.TouchDetected) && (!TS_State.TouchDetected)) + { + touch_x = x; + touch_y = y; + press_detected = true; + } + Old_TS_State = TS_State; +} + + +bool CheckBigButtonTouch (uint8_t position) +{ + bool result = false; + if((touch_x >= BigButtonX) && (touch_x<=(BigButtonX + BigButtonWidth))) + { + switch(position) + { + case 1: + if((touch_y >= BigButton1Y)&&(touch_y <= (BigButton1Y+BigButtonHeight))) + { + result = true; + press_detected = false; + } + break; + case 2: + if((touch_y >= BigButton1Y)&&(touch_y <= (BigButton2Y+BigButtonHeight))) + { + result = true; + press_detected = false; + } + break; + case 3: + if((touch_y >= BigButton3Y)&&(touch_y <= (BigButton3Y+BigButtonHeight))) + { + result = true; + press_detected = false; + } + break; + case 4: + if((touch_y >= BigButton4Y)&&(touch_y <= (BigButton4Y+BigButtonHeight))) + { + result = true; + press_detected = false; + } + break; + + } + } + + return result; +} + +void CheckPress(ScreenState screen) +{ + if(press_detected) + { + switch(screen) + { + case StartUp: + //Mode Cpap + if(CheckBigButtonTouch(1)) + { + display_screen = CPAPMain; + refreshScreen = true; + break; + } + // Mode niv + if(CheckBigButtonTouch (2)) + { + display_screen = NIVMain; + refreshScreen = true; + break; + } + break; + case CPAPMain : + //Mode Cpap + if(CheckBigButtonTouch(1)) + { + display_screen = CPAPRunning; // Start CPAP + refreshScreen = true; + break; + } + // Mode niv + if(CheckBigButtonTouch (2)) // Settings CPAP + { + display_screen = CPAPSettingsMain; + refreshScreen = true; + break; + } + if(CheckBigButtonTouch (3)) + { + display_screen = StartUp; // Back to main screen + refreshScreen = true; + break; + } + break; + case NIVMain : + if(CheckBigButtonTouch(1)) + { + display_screen = NIVRunning; // Start NIV + refreshScreen = true; + break; + } + // Mode niv + if(CheckBigButtonTouch (2)) // Settings NIV + { + display_screen = NIVSettingsMain; + refreshScreen = true; + break; + } + if(CheckBigButtonTouch (3)) // Back + { + display_screen = StartUp; // Back to main screen + refreshScreen = true; + break; + } + break; + case CPAPRunning: + break; + case CPAPSettingsMain: + if(CheckBigButtonTouch(1)) + { + //display_screen = NIVRunning; // Start NIV + refreshScreen = true; + break; + } + // Mode niv + if(CheckBigButtonTouch (2)) // Settings NIV + { + //display_screen = NIVSettingsMain; + refreshScreen = true; + break; + } + if(CheckBigButtonTouch (4)) // Back + { + display_screen = CPAPMain; // Back to main screen + refreshScreen = true; + break; + } + break; + case CPAPSettingsDetailView: + break; + case NIVRunning: + break; + case NIVSettingsMain: + break; + case NIVSettingsDetailView: + break; + default: + break; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Touch.h Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,14 @@ +#ifndef __TOUCH_H +#define __TOUCH_H +#ifdef TARGET_DISCO_F429ZI +#include "TS_DISCO_F429ZI.h" +#include "LCD_DISCO_F429ZI.h" +#include "Screens.h" +void CheckTs(); +void CheckPress(ScreenState screen); + +#else +#error "This class must be used with DISCO_F429ZI board only." +#endif // TARGET_DISCO_F429ZI + +#endif
--- a/Ventilation.c Tue Jun 09 22:57:20 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3355 +0,0 @@ - -/* Includes ------------------------------------------------------------------*/ -#define EXTERN extern -#include <stdlib.h> -#include <string.h> -#include "SS.h" -#include "main.h" -#include "_SS_OnOffActioner.h" -#include "_SS_Pwm.h" -#include "Monitoring.h" -#include "Safety.h" -#include "_SS_Data_Logging.h" -#include "_SS_Record_Settings.h" -#include "_SS_I2CX_SDP600.h" -#include "_SS_I2CX_X201641.h" -#include "_SS_OptimaComm.h" -#undef EXTERN - -#define INIT_VARIABLES -#define EXTERN -#include "Ventilation.h" -#undef EXTERN -#undef INIT_VARIABLES - - -/* Internal constants --------------------------------------------------------*/ -// ******************* Min-max PI or PDF *************************************** -#define MAX_VOLTAGE_REF MAX_PI_OUTPUT // MAX_PI_OUTPUT = 1343 = 18.5micros = 93.3%, want 80% -#define MIN_VOLTAGE_REF MIN_PI_OUTPUT -#define INTEGRAL_MAX (2147483647) -#define INTEGRAL_MIN (-2147483648) - - -#ifndef C_M3_DEVICETEST_TARGET - /* Internal variables --------------------------------------------------------*/ - // ******************* MANAGED CONSTANT SPEED **************************** - static u16 uiBlowerSpeedSetting; - static int32_t lIntegral_Speed_I; - static bool bMaxPIOutputSpeedI; - static bool bMinPIOutputSpeedI; - - - // ************* MANAGED BAROMETRIC VENTILATION ************************* - static u16 uiIpapSettingTemp; - static u16 uiTeBaroSet; - static int32_t lIntegral_Pressure_I; - static bool bMaxPIOutputPressureI; - static bool bMinPIOutputPressureI; - static u16 uiTiD; - static u8 ucIndexTableSlope; - #define TEMPO_TRIGGER_EXPI 30 - static u8 ucTempoTriggerExpiAuto; - #define MIN_THRESHOLD_EXPI_TRIGGER_AUTO 25 - static u8 ucExpiTriggerTreshold; - static u8 fFirstCycleInspi; - - // ----------- Main blower management during expiration ------------------- - static u16 uiPWMatTheEndOfInspiration; - static bool fFirstCycleExpi; - static u16 uiEpapSettingTemp; - static int32_t lIntegral_Pressure_E; - static bool bMaxPIOutputPressureE; - static bool bMinPIOutputPressureE; - static u16 uiPWMatTheEndOfExpiration; - static u16 uiTeD; - static bool fBlockCloseLoop; - - static u16 uiTiTyp; - - // ************* MANAGED VOLUMETRIC VENTILATION ************************* - static u32 ulMaxIFlowSet; - static u32 ulMinIFlowSet; - static u32 ulDecFlowStep; - static u16 uiTeVoluSet; - static u16 uiProximalPressureAtTheEndOfInspiration; - static int32_t lIntegral_Flow_I; - static bool bMaxPIOutputFlowI; - static bool bMinPIOutputFlowI; - static int16_t iVtAdjust=0; - static u8 ucCounterHPAlarm=0; - - - // ******************* MANAGED_CPAP_VENTILATION ****************************** - #define EXPIRATORY_DISCONNECTION_TIME_OUT 500 // 500ms - #define CPAP_DISCONNECTION_TEST_PERIODICITY 4000 // 4s - static u16 uiDisconnectionTime; - static u16 uiDisconnectionTimeInCPAP; - static u16 uiMemoPWMDuringDisconnection; - //static u8 ucStandByMode; - - // ***************** MANAGED INSPIRATORY TRIGGER ***************************** - #define MAX_DELTA_FLOW 100 // 1 l/min - #define SIZE_DELTA_INSPIRATORY_FLOW_BUFFER 40 - #define NUMBER_TRIGGER_VALID 20 - #define NUMBER_MIN_FLOW_VALUE 30 - //static int16_t iBufferIFlowDelta[SIZE_DELTA_INSPIRATORY_FLOW_BUFFER]; - static u8 ucInspiTriggerScheduler; - static u8 ucMinFlowCounter; - static int16_t iInspiratoryFlowMin; - //static int16_t iOldInspiratoryFlowSmoothingMesForTrigger; - #define SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER 250 - static int16_t iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER]; - // static int16_t iBufferConductance[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER]; - static u8 ucCounterTriggerValid; - static int16_t iFlowBaseLineReference; - static bool bDetectionConstantFlow; - - - // *********************** MANAGED MONITORING FOR MLT ************************ - static u16 uiMLT_PressureSetPoint; - #ifdef MOTOR_LIFE_TESTING - #define MLT_AVERAGE_MONITORING 1000 - static u16 uiAverageMonitoringMLT; - static u32 ulMLT_SumSpeedMes; - static u32 ulMLT_SumCurrentMes; - static u32 ulMLT_SumTemperatureMes; - static u32 ulMLT_SumBlowerVoltage; - static u16 uiMLT_EnableAlarm; - #endif // #ifdef MOTOR_LIFE_TESTING - - - // ************************ MANAGED CALIBRATION ****************************** - typedef enum - { - INIT_FLOW_CALIB_TEST=0, - SET_GAS_TYPE, - SET_GAS_STANDARD, - START_FLOW_READING, - SEND_FLOW_COMMAND, - READ_FLOW_VALUE, - SEND_HIGH_FLOW_CALIB_REQUEST, - WAIT_FOR_HIGH_FLOW_CALIB_ACK, - PREPARE_FAILURE_COMMAND, - PREPARE_SUCCESS_COMMAND, - SEND_COMMAND_TO_PF300, - CHECK_COMMAND_FROM_PF300, - END_OF_CALIBRATION, - } type_enLowFlowCalibrationStep; - - typedef enum - { - INIT_PRESSURE_CALIB_TEST=0, - START_PRESSURE_READING, - SEND_PRESSURE_COMMAND, - READ_PRESSURE_VALUE, - PRESSURE_CALIB_FAILURE_COMMAND, - PRESSURE_CALIB_SUCCESS_COMMAND, - PRESSURE_CALIB_SEND_COMMAND_TO_PF300, - PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300, - PRESSURE_CALIB_END_OF_CALIBRATION, - } type_enPressureCalibrationStep; - - #define SIZE_BUFFER_FLOW_VALUE 15 - typedef struct - { - unsigned char ucIndex; - bool bFirstPartOfTheCRReceived; - char szValue[SIZE_BUFFER_FLOW_VALUE]; - } type_stFlow; - - // Flow and pressure calibration - #define TIME_OUT_RECEPTION_PACKET_FROM_PF300 2000 // 2s - #define SAMPLE_RATE_BETWEEN_TWO_FLOW 5000 // 5s - #define SIZE_RX_BUFFER_PF300 20 - static u16 uiCalibrationTimeOut; - static unsigned char ucIndexAnswerFromPF300; - static char szAnswerFromPF300[SIZE_RX_BUFFER_PF300]; - static char szExpectedAnswerFromPF300[SIZE_RX_BUFFER_PF300]; - static u8 ucNumberOfBytesToCheckFromPF300Answer; - - // Flow calibration - static type_enLowFlowCalibrationStep enLowFlowCalibrationStep; - static type_enLowFlowCalibrationStep enGoBackToStep; - static unsigned long ulSumFlowTicks; - static unsigned int uiFlowTicksSamplesCounter; - //static type_stLUTFlowSensor stTemporayLUTFlowSensor; - static bool bHighFlowCalibrationInProgress; - static unsigned int uiMotorDutyCyleForFlowCalib; - static unsigned int uiImHereMsgTimer; - - // Pressure calibration - #define SAMPLE_RATE_BETWEEN_TWO_PRESSURE 10000 // 30s - static type_enPressureCalibrationStep enPressureCalibrationStep; - static type_enPressureCalibrationStep enPressureCalibGoBackToStep; - static u32 ulSumPressureTicks; - static u16 uiPressureTicksSamplesCounter; - - // List of command to PF300 - static const char szPF300_CmdSwitchOffEcho[]={"%CM#5$0\r"}; // Command Echo from PF300 off - static const char szPF300_AnswerSwitchOffEcho[]={"%CM#5"}; // Answer echo off from PF300 (WO \r) - static const char szPF300_SetAirGasType[]={"%WS#1$0\r"}; // command Air - static const char szPF300_AnswerAirGasType[]={"%WS#1$0"}; // Answer Air - static const char szPF300_SetGasStandard[]={"%WS#3$1\r"}; // Command STPD - static const char szPF300_AnswerGasStandard[]={"%WS#3$1"}; // Answer STPD - static const char szPF300_ReadLowFlowCmd[]={"%RM#1\r"}; // Command read low flow - static const char szPF300_ReadLowFlowAnswer[]={"%RM#1$"}; // Answer read low flow - static const char szPF300_ReadHighFlowCmd[]={"%RM#0\r"}; // Command read high flow - static const char szPF300_ReadHighFlowAnswer[]={"%RM#0$"}; // Answer read high flow - static const char szPF300_ReadPdiffCmd[]={"%RM#3\r"}; // Command read pressure diff. - static const char szPF300_ReadPdiffAnswer[]={"%RM#3$"}; // Answewr read pressure diff. - - // List of Command to Handset - static const char szRequestHighFlowCalib[]={"@N"}; - static const char szEndOfCalibOK[]={"@S"}; - static const char szImHere[]={"@*"}; - - - // ---------------- Management FRAM for settings ----------------------------- - #ifdef RECORD_SETTINGS - #endif // RECORD_SETTINGS - - // -------------------- Manage Motor starting -------------------------------- - #ifndef TEMPERATURE_TRENDS - static u8 ucStartVentilationScheduler=0; - #endif - static enMaroubraModes enPreviousMode; - static u16 uiPreviousDeviceMode; -#endif // C_M3_DEVICETEST_TARGET - - -#ifndef C_M3_DEVICETEST_TARGET - #define SIZE_SLOPE2_TABLE 21 - const unsigned char ucSlope2Table[SIZE_SLOPE2_TABLE]= { - 0, 35, 50, 59, 65, 70, 74, 77, 80, 83, - 85, 87, 89, 91, 92, 94, 95, 96, 98, 99, - 100 }; - - // Table pente inspiratoire 2 - #define SIZE_SLOPE3_TABLE 41 - const unsigned char ucSlope3Table[SIZE_SLOPE3_TABLE]= { - 0, 20, 35, 44, 50, 55, 59, 62, 65, 68, 70, - 72, 74, 76, 77, 79, 80, 81, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, - 96, 96, 97, 98, 98, 99, 99, 100 }; - - // Table pente inspiratoire 3 - #define SIZE_SLOPE4_TABLE 61 - const unsigned char ucSlope4Table[SIZE_SLOPE4_TABLE]= { - 0, 11, 26, 35, 41, 46, 50, 53, 56, 59, 61, - 63, 65, 67, 68, 70, 71, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 83, 84, 85, 86, 86, - 87, 88, 88, 89 ,90, 90, 91, 91, 92, 92, 93, - 93, 94, 94, 95, 95, 96, 96, 96, 97, 97, 98, - 98, 99, 99, 99, 100, 100 }; - - - // Maximum allowed flow in expiration Flow=f(PEEP set) (example: flow-by max=29L/min @ 5hPa) - const u16 uiMaximumFlowInExpiration[41]={ - 0, 1300, 1830, 2250, 2600, 2900, 3180, 3430, 3670, 3900, - 4110, 4310, 4500, 4680, 4860, 5030, 5200, 5360, 5510, 5660, - 5810, 5950, 6090, 6230, 6360, 6500, 6620, 6750, 6870, 7000, - 7120, 7230, 7350, 7460, 7580, 7690, 7800, 7900, 8010, 8110, 8220 - }; -#endif // C_M3_DEVICETEST_TARGET - - -/* Internal functions --------------------------------------------------------*/ -#ifndef C_M3_DEVICETEST_TARGET - u16 ComputeTe(u16 uiF, u16 uiTi); - void ComputeInspiratoryFlowSetPointInAVC(u16 uiTypeOfPatient, u16 uiVtc, u16 uiTi, u16 uiFlowShape, u32 *ulMaxFlow, u32 *ulMinFlow, u32 *ulFlowStep); - unsigned char TestTriggerExpiratoire(unsigned char ucValeurSeuil, unsigned int uiPressureSetting); - bool TestInspiratoryTrigger(bool bSpont, u16 uiTe, u16 uiFlowThreshold); - int16_t UpdateInspiratoryFlowAverage(void); - int16_t UpdateInspiratoryConductanceAverage(void); - void ResetInspiratoryConductanceAverage(void); - bool TestInspiratorySlowTrigger(int16_t iTheFlowBaseLine, u16 uiFlowTreshold); - void ApplyDefaultValueToTemporaryVentilationSettings(void); - void ApplyDefaultValueToTechnicalSettings(void); - void ApplyAllDefaultValues(void); - bool ApplyNewVentilationMode(void); - void ApplyDefaultFlowLUT(void); - void CheckFlowLUTRange(void); - void ManageFlowCalibration(void); - void ManagePressureCalibration(void); - void ManageCstPressure(void); -#endif // C_M3_DEVICETEST_TARGET - - - -#ifndef C_M3_DEVICETEST_TARGET -/******************************************************************************* -* Function Name : InitSettings -* Description : Initialize parameters for ventilation -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void InitSettings(void) -{ - uiPreviousDeviceMode=0xFF; - enPreviousMode=NUMBER_OF_MODE; - - // --- Init Settings - uiTechnicalDataMes[SW_VERSION_TEC_MES]=MAROUBRA_BLOWER_SW_VERSION; - bComputeOffsetSensors=FALSE; - - #ifdef RECORD_SETTINGS - // Read and init FRAM - if (InitSettingsZoneAndTechnicalZoneInFRAM()==OPSTATUS_OK) - { - if (ReadSettingsZoneAndTechnicalZoneInFRAM()==OPSTATUS_FAIL) - { - uiFlagsAlarm[ALARM_FLAGS2]|=FRAM_FAILURE_ALARM_MASK; - ApplyAllDefaultValues(); - } - } - else - { - uiFlagsAlarm[ALARM_FLAGS2]|=FRAM_FAILURE_ALARM_MASK; - ApplyAllDefaultValues(); - } - #else - ApplyAllDefaultValues(); - #endif - - // Compute offsets sensors if necessary - if (bComputeOffsetSensors==TRUE) - { - // ------ Update Blower Flow sensor offset before ventilation ------- - #ifdef SDP600_USED_I2C1_BUS - SDP600_ComputeOffsetFlowSensorOnI2C1(SDP600_BLOWER_FLOW_SENSOR); - #endif // SDP600_USED_I2C1_BUS - - #ifdef X201641_USED_I2C1_BUS - X201641_ComputeOffsetFlowSensorOnI2C1(X201641_BLOWER_FLOW_SENSOR); - #endif // X201641_USED_I2C1_BUS - - // ----- Update Proximal Pressure sensor offset before ventilation ------- - ComputeOffsetProximalPressureSensor(); - } - - // Check Technical settings range - CheckTechnicalSettingsRange(); - - // Check Flow LUT - CheckFlowLUTRange(); - - // Check temporary ventilation setting range - if (CheckTemporaryVentilationSettingRange()==OPSTATUS_FAIL) - { - ApplyDefaultValueToTemporaryVentilationSettings(); - uiFlagsAlarm[ALARM_FLAGS2]|=VENTILATION_SETTINGS_RANGE_ALARM_MASK; - } - - // --- Update computed settings (Te,...) - UpdateSettings(); - - #ifdef MOTOR_LIFE_TESTING - uiTechnicalDataSet[DEVICE_MODE_TEC]=PRESSURE_CST_MODE; - uiTechnicalDataSet[START_STOP_VENTILATION]=1; - #endif -} - - -/******************************************************************************* -* Function Name : InitVentilation -* Description : Initialize variables for ventilation -* Function called : -* - when we start ventilation -* - when we change of ventilation mode -* - when we change of device mode -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void InitVentilation(void) -{ - ucVentilationCycle=EXPIRATION_CYCLE; - uiTiD=0; - uiTeD=0; - uiTiTyp = 1000; - bManualBreath=FALSE; - - if (enPreviousMode==NUMBER_OF_MODE) - { - // Start ventilation - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - uiDisconnectionTimeInCPAP=CPAP_DISCONNECTION_TEST_PERIODICITY; - uiMemoPWMDuringDisconnection=0; - fBlockCloseLoop=FALSE; - } - - ClearAllVentilationAlarms(); - ClearAllMeasures(); - - switch(uiTechnicalDataSet[DEVICE_MODE_TEC]) - { - default: - case VENTILATION_MODE: - { - if (enVentilationMode==APCV_MODE || enVentilationMode==PS_MODE) - { - if (enPreviousMode==APCV_MODE || enPreviousMode==PS_MODE) - { - // --- We are already in pressure mode - } - else - { - // --- Start a pressure mode - fFirstCycleInspi=TRUE; - uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; - - if (enPreviousMode!=AVC_MODE) - { - uiPWMatTheEndOfExpiration=MIN_VOLTAGE_REF; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE=FALSE; - bMinPIOutputPressureE=FALSE; - fFirstCycleExpi=TRUE; - } - } - } - else if (enVentilationMode==AVC_MODE) - { - iVtAdjust=0; - fFirstCycleInspi=TRUE; - uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; - - if (enPreviousMode!=APCV_MODE && enPreviousMode!=PS_MODE) - { - uiPWMatTheEndOfExpiration=MIN_VOLTAGE_REF; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE=FALSE; - bMinPIOutputPressureE=FALSE; - fFirstCycleExpi=TRUE; - } - } - else if (enVentilationMode==CPAP_MODE) - { - Ki_Pressure_I=1000; - uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; - lIntegral_Pressure_I=0; - bMaxPIOutputPressureI=FALSE; - bMinPIOutputPressureI=FALSE; - } - break; - } - case ONE_CST_PWM_MODE: - { - uiInspirationBlowerPWMTec=250; - break; - } - case TWO_CST_PWM_MODE: - { - uiInspirationBlowerPWMTec=350; - uiExpirationBlowerPWMTec=150; - break; - } - case CST_SPEED_MODE: - { - uiBlowerSpeedSet=15000; - uiBlowerSpeedSetting=5000; - break; - } - case FLOW_CAL_MODE: - { - enLowFlowCalibrationStep=INIT_FLOW_CALIB_TEST; - bHighFlowCalibrationInProgress=FALSE; - stTemporayLUTFlowSensor.uiLUT_TableSize=0; - uiCalibrationTimeOut=(TIME_OUT_BLOWER_HANDSET_COMM*20); // 2s - break; - } - case PRESSURE_CAL_MODE: - { - enPressureCalibrationStep=INIT_PRESSURE_CALIB_TEST; - uiCalibrationTimeOut=(TIME_OUT_BLOWER_HANDSET_COMM*20); // 2s - break; - } - case PRESSURE_CST_MODE: - { - uiMLT_PressureSetPoint=10; - lIntegral_Pressure_I=0; - bMaxPIOutputPressureI=FALSE; - bMinPIOutputPressureI=FALSE; - - #ifdef MOTOR_LIFE_TESTING - uiMLT_EnableAlarm=5000; // 5s before enabling alarm - uiAverageMonitoringMLT=MLT_AVERAGE_MONITORING; - ulMLT_SumSpeedMes=0; - ulMLT_SumCurrentMes=0; - ulMLT_SumTemperatureMes=0; - ulMLT_SumBlowerVoltage=0; - #endif // #ifdef MOTOR_LIFE_TESTING - break; - } - } - enPreviousMode=enVentilationMode; -} - - -/******************************************************************************* -* Function Name : StopAllActuators -* Description : Stop all actuators -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void StopAllActuators(void) -{ - // Stop main blower - SS_Xclose(mdrv); - - // Valve OFF - SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_OFF); -} - -/******************************************************************************* -* Function Name : CalculateHoseDrop -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -u16 CalculateHoseDrop(void) -{ - u16 hoseDrop = (u16)(10*(iBlowerFlowSmoothingMes/100.0f/60.0f * 0.5f)); - return hoseDrop; -} - -/******************************************************************************* -* Function Name : ManageCPAPVentilation -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageCPAPVentilation(void) -{ - - - - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - // **************************** Cycle detection ****************************** - // Test Synchronisation - /*if (iBlowerFlowSmoothingMesForTrigger<(-500) && ucVentilationCycle==INSPIRATION_CYCLE) - ucVentilationCycle=EXPIRATION_CYCLE; */ - int32_t peakP = 2;//(int32_t)uiVentilationSet[PS_CPAP_SET]; - // Cycle detection - if (ucVentilationCycle==INSPIRATION_CYCLE) - { - uiTiD++; - if(uiTiD < (0.1f * uiTiTyp)) - { - peakP =(int32_t)( uiVentilationSet[PS_CPAP_SET] * ((uiTiD* 1.0f)/(0.1f * uiTiTyp))); - } - else if(uiTiD < (1.0f * uiTiTyp)) - { - peakP = ((int32_t)uiVentilationSet[PS_CPAP_SET] - ((int32_t)(uiVentilationSet[PS_CPAP_SET] * (uiTiD * 1.0f)/(1.1f * uiTiTyp)))) + 20; - } - else - { - peakP = 2; - } - - if (uiTiD>5000 || (uiTiD>TiBaroSet_P_MIN && TestTriggerExpiratoire(20, uiVentilationSet[PS_CPAP_SET])==TRUE)) - { - ucVentilationCycle=EXPIRATION_CYCLE; - uiPWMatTheEndOfInspiration = uiInspirationBlowerPWMTec; - if(uiTiD < 2000) - { - uiTiTyp = uiTiD; - } - else - { - uiTiTyp = 2000; - } - - uiTeD=0; - } - } - else - { - uiTeD++; - if (uiTeD>TE_SET_MAX) uiTeD=TE_SET_MAX; - - if (TestInspiratoryTrigger(TRUE, uiTeD, 15)==TRUE) - { - ucVentilationCycle=INSPIRATION_CYCLE; - uiTiD=0; - } - } - - // Barometric Mode : error computation - ControlPressure((int32_t)(peakP + CalculateHoseDrop())); -} - -/******************************************************************************* -* Function Name : ControlPressure -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -int32_t previousError = 0; -int32_t lIntegralSum = 0; -void ControlPressure(int32_t setPressure)//pressure in cmH2O*10 -{ - int32_t lPropTerm; - int32_t lIntegralTerm; - int32_t lDerivativeTerm; - int32_t lOutputPressure; - - - int32_t lError = setPressure - uiProximalPressureMes; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; - lIntegralTerm += (int32_t)(uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I] * lError); - lDerivativeTerm = (int32_t)(uiTechnicalDataSet[KP_FLOW_I]*(lError - previousError/1000)); - previousError = lError; - - // Close loop in pressure - if ((lIntegralTerm + lIntegralSum) > INTEGRAL_MAX) - { - lIntegralSum = INTEGRAL_MAX; - } - else if ((lIntegralTerm - lIntegralSum)< INTEGRAL_MIN) - { - lIntegralSum = INTEGRAL_MIN; - } - else - { - lIntegralSum += lIntegralTerm; - } - - lOutputPressure = (lDerivativeTerm>>19) + (lIntegralSum>>16) + (lPropTerm>>13) ; - - lOutputPressure+=uiPWMatTheEndOfInspiration; - - - // Limit and Update blower PWM - if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiInspirationBlowerPWMTec = lOutputPressure; - } - - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - -} - - -/******************************************************************************* -* Function Name : DavidCControlPressure -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void DavidCControlPressure(int32_t setPressure)//pressure in cmH2O*10 -{ - int32_t lPropTerm; - int32_t lIntegralTerm; - int32_t lOutputPressure; - u16 uiFlowMaxInExpi; - int32_t lError = setPressure - uiProximalPressureMes; - - lIntegralTerm = (int32_t)Ki_Pressure_I * lError; - if (Ki_Pressure_I<uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I]) - { - Ki_Pressure_I++; - } - - // Close loop in pressure - if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm) <0) - lIntegral_Pressure_I = INTEGRAL_MAX; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm)>0) - lIntegral_Pressure_I = INTEGRAL_MIN; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) - lIntegral_Pressure_I += lIntegralTerm; - else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) - lIntegral_Pressure_I += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; - - lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); - - lOutputPressure+=uiPWMatTheEndOfInspiration; - - // Flow limiting - uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; - if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) - { - // Impossible to maintain the peep (patient disconnection) - if (uiDisconnectionTime==0) - { - if (fBlockCloseLoop==FALSE) - uiDisconnectionTimeInCPAP=CPAP_DISCONNECTION_TEST_PERIODICITY; - fBlockCloseLoop=TRUE; // Block the close loop - if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value - uiInspirationBlowerPWMTec=uiMemoPWMDuringDisconnection; - else - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - uiDisconnectionTime--; - } - else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) - { - // Good pressure : no disconnection - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - - if (fBlockCloseLoop==TRUE) - { - // The close loop was block before => unblock it - fBlockCloseLoop=FALSE; - lIntegral_Pressure_I=0; - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; - return; - } - else if (iBlowerFlowSmoothingMes>=0) - { - // Record current PWM - uiMemoPWMDuringDisconnection=uiInspirationBlowerPWMTec; - } - } - - // Unblock the close loop every 4s in case of none recorded PWM value - if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiDisconnectionTimeInCPAP==0) - { - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - fBlockCloseLoop=FALSE; - lIntegral_Pressure_I=0; - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; - return; - } - - // Update Time counters - if (uiDisconnectionTimeInCPAP!=0) - uiDisconnectionTimeInCPAP--; - - // Update blower PWM - if (fBlockCloseLoop==TRUE) - { - bMaxPIOutputPressureI = TRUE; - } - else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiInspirationBlowerPWMTec = lOutputPressure; - } - - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - -} - -/******************************************************************************* -* Function Name : ManageOneCstPWM -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageOneCstPWM(void) -{ - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - // Update Blower Speed - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); -} - - -/******************************************************************************* -* Function Name : Manage2CstPWM -* Description : Manage Ti, Te, DAC, Blower, PID -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void Manage2CstPWM(void) -{ - if (ucVentilationCycle==INSPIRATION_CYCLE) - { - // ------------- INSPIRATION ------------ - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - - // Inspiratoy time - uiTiD++; - if (uiTiD>=uiVentilationSet[TI_BARO_SET]) - { - ucVentilationCycle=EXPIRATION_CYCLE; - uiTiD=0; - } - } - else - { - // ------------- EXPIRATION ------------ - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); - - // Expiratoy time - uiTeD++; - if (uiTeD>=uiTeBaroSet) - { - ucVentilationCycle=INSPIRATION_CYCLE; - uiTeD=0; - } - } -} - - -/******************************************************************************* -* Function Name : ManageCstSpeed -* Description : Manage constant speed ventilation -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageCstSpeed(void) -{ - int32_t lError; - int32_t lPropTerm; - int32_t lIntegralTerm; - int32_t lOutputSpeed; - - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - // Update settings - if (uiBlowerSpeedSetting<uiBlowerSpeedSet) - uiBlowerSpeedSetting+=10; - else if (uiBlowerSpeedSetting>uiBlowerSpeedSet) - uiBlowerSpeedSetting-=10; - - uiTiD++; - if ((uiTiD%10)==0) - { - // Barometric Mode : error computation - lError=(int32_t)uiBlowerSpeedSetting-(int32_t)uiBlowerSpeedMes; - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_SPEED_I_TEC] * lError; - - // Close loop in pressure - if ((lIntegral_Speed_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputSpeedI==FALSE)) - { - if ((lIntegral_Speed_I + lIntegralTerm) <0) - lIntegral_Speed_I = INTEGRAL_MAX; - else - lIntegral_Speed_I += lIntegralTerm; - } - else if ((lIntegral_Speed_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputSpeedI==FALSE)) - { - if ((lIntegral_Speed_I + lIntegralTerm)>0) - lIntegral_Speed_I = INTEGRAL_MIN; - else - lIntegral_Speed_I += lIntegralTerm; - } - else if ((lIntegral_Speed_I<=0) && (lIntegralTerm>=0)) - lIntegral_Speed_I += lIntegralTerm; - else if ((lIntegral_Speed_I>=0) && (lIntegralTerm<=0)) - lIntegral_Speed_I += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_SPEED_I_TEC] * lError; - lOutputSpeed = (lIntegral_Speed_I>>16) + (lPropTerm>>13); - - if (lOutputSpeed>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputSpeedI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputSpeed<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputSpeedI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputSpeedI = FALSE; - bMinPIOutputSpeedI = FALSE; - uiInspirationBlowerPWMTec = lOutputSpeed; - } - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - } -} - -/******************************************************************************* -* Function Name : ManageFlowCalibration -* Description : Manage Low flow calibration -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageFlowCalibration(void) -{ - char cCharValue; - char szTempBuf[SIZE_RX_BUFFER_PF300]; - - /* - #ifdef USE_TSI_4040 - switch(enTSICommScheduler) - { - default: - case TSI_SET_TYPE_OF_GAS: - { - // Send Type of Gas command - ucTSICommand=TSI_SEND_GAS_TYPE_AIR_CMD; - if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) - { - enTSICommScheduler=TSI_CHECK_ANSWER; - enTSIGoBackToStep=TSI_SET_FLOW_UNIT; - } - break; - } - case TSI_SET_FLOW_UNIT: - { - // Send Type of Gas command - ucTSICommand=TSI_SEND_FLOW_UNIT_STANDARD_CMD; - if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) - { - enTSICommScheduler=TSI_CHECK_ANSWER; - enTSIGoBackToStep=TSI_SET_SAMPLE_TIME; - } - break; - } - case TSI_SET_SAMPLE_TIME: - { - // Send sample time - ucTSICommand=TSI_SEND_SAMPLE_TIME_10MS_CMD; - if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) - { - enTSICommScheduler=TSI_CHECK_ANSWER; - enTSIGoBackToStep=TSI_READ_FLOW; - } - break; - } - case TSI_READ_FLOW: - { - // Send sample time - ucTSICommand=TSI_SEND_READ_FLOW_CMD; - if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) - { - enTSICommScheduler=TSI_CHECK_ANSWER; - enTSIGoBackToStep=TSI_CYCLE_DETECTION; - } - break; - } - case TSI_CYCLE_DETECTION: - { - uiBlowerFlow=iFlowFromTSI; - break; - } - case TSI_CHECK_ANSWER: - { - opstatus=SS_Xgetw(tsi, &uiDummy); - if (opstatus==OPSTATUS_OK) - { - enTSICommScheduler=enTSIGoBackToStep; - } - else if (opstatus==OPSTATUS_FAIL) - { - enTSICommScheduler=TSI_SET_TYPE_OF_GAS; - } - break; - } - } - #endif // #ifdef USE_TSI_4040 - */ - - switch(enLowFlowCalibrationStep) - { - case INIT_FLOW_CALIB_TEST: - { - // Init comm with PF300 => wait 2s before sending first command to PF300 - // We need to wait for this delay in order to the handset to activate its transparent mode - if (uiCalibrationTimeOut==0) - { - bDisableMaroubraCommCommunication=TRUE; - - // Prepare command to PF300 - UpdateBufferToSend((char*)szPF300_CmdSwitchOffEcho); - enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; - strcpy(szExpectedAnswerFromPF300, szPF300_AnswerSwitchOffEcho); - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerSwitchOffEcho); - enGoBackToStep=SET_GAS_TYPE; - } - else - { - uiCalibrationTimeOut--; - } - break; - } - case SET_GAS_TYPE: - { - // Prepare command to PF300 - UpdateBufferToSend((char*)szPF300_SetAirGasType); - enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; - strcpy(szExpectedAnswerFromPF300, szPF300_AnswerAirGasType); - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerAirGasType); - enGoBackToStep=SET_GAS_STANDARD; - break; - } - case SET_GAS_STANDARD: - { - // Prepare command to PF300 - UpdateBufferToSend((char*)szPF300_SetGasStandard); - enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; - strcpy(szExpectedAnswerFromPF300, szPF300_AnswerGasStandard); - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerGasStandard); - enGoBackToStep=START_FLOW_READING; - break; - } - case START_FLOW_READING: - { - // Set Min blower speed - uiMotorDutyCyleForFlowCalib=MIN_PI_OUTPUT; - SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); - - // Init variable for flow sensor - uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_FLOW; - ulSumFlowTicks=0; - uiFlowTicksSamplesCounter=0; - - // Next step - enLowFlowCalibrationStep=SEND_FLOW_COMMAND; - break; - } - case SEND_FLOW_COMMAND: - { - if (uiCalibrationTimeOut!=0) - { - uiCalibrationTimeOut--; - - if (uiCalibrationTimeOut<(SAMPLE_RATE_BETWEEN_TWO_FLOW>>1)) - { - ulSumFlowTicks+=uiBlowerFlowRAWMes; - uiFlowTicksSamplesCounter++; - } - } - else - { - // Prepare next command (Read Low Flow) - enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; - if (bHighFlowCalibrationInProgress==FALSE) - { - UpdateBufferToSend((char*)szPF300_ReadLowFlowCmd); // %RM#1\r - strcpy(szExpectedAnswerFromPF300, szPF300_ReadLowFlowAnswer); // %RM#1$ - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadLowFlowAnswer); - } - else - { - UpdateBufferToSend((char*)szPF300_ReadHighFlowCmd); // %RM#0\r - strcpy(szExpectedAnswerFromPF300, szPF300_ReadHighFlowAnswer); // %RM#0$ - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadHighFlowAnswer); - } - enGoBackToStep=READ_FLOW_VALUE; - } - break; - } - case READ_FLOW_VALUE: - { - if (uiFlowTicksSamplesCounter!=0) - { - // Read PF300 flow (l/min) - strcpy(szTempBuf, &szAnswerFromPF300[ucNumberOfBytesToCheckFromPF300Answer]); - - // Store value of flow - if (stTemporayLUTFlowSensor.uiLUT_TableSize<LOW_FLOW_CALIB_NUMBER_OF_SAMPLES) - stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]=(unsigned int)atoi(szTempBuf); - else - stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]=(unsigned int)atoi(szTempBuf)*10; - - // Store ticks value - stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize]=ulSumFlowTicks/uiFlowTicksSamplesCounter; - uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_FLOW; - ulSumFlowTicks=0; - uiFlowTicksSamplesCounter=0; - - // Check if current flow <0.1l/min - if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<10) - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - break; - } - - // Check if the last low flow is higher than 20l/min or lower than 2l/min - if (stTemporayLUTFlowSensor.uiLUT_TableSize==(LOW_FLOW_CALIB_NUMBER_OF_SAMPLES-1)) - { - // Check if the last low flow is higher than 20l/min or lower than 2l/min - if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]>2000 || stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<200) - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - break; - } - } - - // Next flow sample - if (stTemporayLUTFlowSensor.uiLUT_TableSize==LOW_FLOW_CALIB_NUMBER_OF_SAMPLES && stTemporayLUTFlowSensor.uiFlowValue[LOW_FLOW_CALIB_NUMBER_OF_SAMPLES]<(stTemporayLUTFlowSensor.uiFlowValue[LOW_FLOW_CALIB_NUMBER_OF_SAMPLES-1]+500)) - { - // No enough flow margin between the last value of the low flow and the first value of the high flow - } - else if (stTemporayLUTFlowSensor.uiLUT_TableSize!=0 && stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<(stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize-1]+50)) - { - // No enough margin between two consecutives flow - } - else if (stTemporayLUTFlowSensor.uiLUT_TableSize!=0 && stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize]<=stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize-1]) - { - // Same or less ticks between two consecutives flow - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - break; - } - else - { - stTemporayLUTFlowSensor.uiLUT_TableSize++; - if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize-1]>=14000) - { - // End of calib => check the number of samples - if (stTemporayLUTFlowSensor.uiLUT_TableSize>(FLOW_CALIB_NUMBER_OF_SAMPLES>>1)) - { - enLowFlowCalibrationStep=PREPARE_SUCCESS_COMMAND; - - // Transfer the temporary LUT in the definitive LUT - stLUTFlowSensor=stTemporayLUTFlowSensor; - } - else - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - break; - } - else if (stTemporayLUTFlowSensor.uiLUT_TableSize>FLOW_CALIB_NUMBER_OF_SAMPLES) - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - break; - } - } - - // Prepare next flow reading - if (stTemporayLUTFlowSensor.uiLUT_TableSize<LOW_FLOW_CALIB_NUMBER_OF_SAMPLES) - { - // New motor speed - uiMotorDutyCyleForFlowCalib+=20; - enLowFlowCalibrationStep=SEND_FLOW_COMMAND; - } - else if (stTemporayLUTFlowSensor.uiLUT_TableSize==LOW_FLOW_CALIB_NUMBER_OF_SAMPLES && bHighFlowCalibrationInProgress==FALSE) - { - // Min speed for motor - uiMotorDutyCyleForFlowCalib=MIN_PI_OUTPUT; - SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); - enLowFlowCalibrationStep=SEND_HIGH_FLOW_CALIB_REQUEST; - break; - } - else - { - // New motor speed - uiMotorDutyCyleForFlowCalib+=10; - enLowFlowCalibrationStep=SEND_FLOW_COMMAND; - } - - // Update motor speed - if (uiMotorDutyCyleForFlowCalib<MAX_PI_OUTPUT) - { - SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); - } - else - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - break; - } - } - else // if (uiFlowTicksSamplesCounter!=0) - { - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - break; - } - case SEND_HIGH_FLOW_CALIB_REQUEST: - { - if (TransferCommandToHandset((char*)szRequestHighFlowCalib)==TRUE) - enLowFlowCalibrationStep=WAIT_FOR_HIGH_FLOW_CALIB_ACK; - break; - } - case WAIT_FOR_HIGH_FLOW_CALIB_ACK: - { - // Wait for acknownledge from handset - if (ReadByteReceive(&cCharValue)==TRUE) - { - if (cCharValue=='@') - { - // Continue flow calibration - bHighFlowCalibrationInProgress=TRUE; - enLowFlowCalibrationStep=SEND_FLOW_COMMAND; - } - else - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - break; - } - case PREPARE_FAILURE_COMMAND: - { - if (TransferCommandToHandset((char*)szEndOfCalibFailed)==TRUE) - enLowFlowCalibrationStep=END_OF_CALIBRATION; - break; - } - case PREPARE_SUCCESS_COMMAND: - { - if (TransferCommandToHandset((char*)szEndOfCalibOK)==TRUE) - enLowFlowCalibrationStep=END_OF_CALIBRATION; - break; - } - case SEND_COMMAND_TO_PF300: - { - // Send a byte every 1ms - if (TransferBufferToPF300()==TRUE) - { - // Buffer sent !! - if (ucNumberOfBytesToCheckFromPF300Answer!=0) - { - // Check answer from PF300 - ucIndexAnswerFromPF300=0; - uiCalibrationTimeOut=TIME_OUT_RECEPTION_PACKET_FROM_PF300; - enLowFlowCalibrationStep=CHECK_COMMAND_FROM_PF300; - } - else - enLowFlowCalibrationStep=enGoBackToStep; - } - break; - } - case CHECK_COMMAND_FROM_PF300: - { - if (uiCalibrationTimeOut==0) - { - // Time-out in reception !! - ucIndexAnswerFromPF300=0; - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - else if (ReadByteReceive(&cCharValue)==TRUE) - { - // Check last byte received - if (cCharValue=='\r') - { - // End of answer => check buffer content - ucIndexAnswerFromPF300=0; - strcpy(szTempBuf, szAnswerFromPF300); - szTempBuf[ucNumberOfBytesToCheckFromPF300Answer]=0; - if (strcmp(szTempBuf, szExpectedAnswerFromPF300)==0) - { - // Buffer OK !! - enLowFlowCalibrationStep=enGoBackToStep; - } - else - { - // Buffer wrong !! - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - } - else if (cCharValue=='?') - { - // PF300 is lost => end of calibration - ucIndexAnswerFromPF300=0; - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - else - { - // Store byte from PF300 into buffer - szAnswerFromPF300[ucIndexAnswerFromPF300++]=cCharValue; - if (ucIndexAnswerFromPF300>=SIZE_RX_BUFFER_PF300) - { - // Answer too long !! - ucIndexAnswerFromPF300=0; - enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; - } - else - { - // Add 0 at the end of the string - szAnswerFromPF300[ucIndexAnswerFromPF300]=0; - } - } - } - else - { - // No byte received !! - uiCalibrationTimeOut--; - } - break; - } - default: - case END_OF_CALIBRATION: - { - uiTechnicalDataSet[START_STOP_VENTILATION]=0; - bDisableMaroubraCommCommunication=FALSE; - break; - } - } // switch - - // Every 300ms, send '@*' to inform the handset that the blower works properly - if (uiImHereMsgTimer==0) - { - if (enLowFlowCalibrationStep!=SEND_COMMAND_TO_PF300) - { - uiImHereMsgTimer=300; - TransferCommandToHandset((char*)szImHere); - } - } - else - uiImHereMsgTimer--; -} - -/******************************************************************************* -* Function Name : ManagePressureCalibration -* Description : Manage pressure calibration -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManagePressureCalibration(void) -{ - char cCharValue; - char szTempBuf[SIZE_RX_BUFFER_PF300]; - u16 uiCalibPressureADCValue; - u16 uiCalibPressureValue; - u16 uiCalibPressureGain; - - switch(enPressureCalibrationStep) - { - case INIT_PRESSURE_CALIB_TEST: - { - // Init comm with PF300 => wait 2s before sending first command to PF300 - // We need to wait for this delay in order to the handset to activate its transparent mode - if (uiCalibrationTimeOut==0) - { - bDisableMaroubraCommCommunication=TRUE; - - // Prepare command to PF300 - UpdateBufferToSend((char*)szPF300_CmdSwitchOffEcho); - strcpy(szExpectedAnswerFromPF300, szPF300_AnswerSwitchOffEcho); - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerSwitchOffEcho); - enPressureCalibrationStep=PRESSURE_CALIB_SEND_COMMAND_TO_PF300; - enPressureCalibGoBackToStep=START_PRESSURE_READING; - } - else - { - uiCalibrationTimeOut--; - } - break; - } - case START_PRESSURE_READING: - { - // Set blower speed - SS_Xputdw(mdrv, 600); - - // Init variable for flow sensor - uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_PRESSURE; - ulSumPressureTicks=0; - uiPressureTicksSamplesCounter=0; - - enPressureCalibrationStep=SEND_PRESSURE_COMMAND; - break; - } - case SEND_PRESSURE_COMMAND: - { - if (uiCalibrationTimeOut!=0) - { - uiCalibrationTimeOut--; - - if (uiCalibrationTimeOut<2000) - { - ulSumPressureTicks+=uiProximalPressureADCMes; - uiPressureTicksSamplesCounter++; - } - } - else - { - // Prepare next command - UpdateBufferToSend((char*)szPF300_ReadPdiffCmd); - strcpy(szExpectedAnswerFromPF300, szPF300_ReadPdiffAnswer); - ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadPdiffAnswer); - enPressureCalibrationStep=PRESSURE_CALIB_SEND_COMMAND_TO_PF300; - enPressureCalibGoBackToStep=READ_PRESSURE_VALUE; - } - break; - } - case READ_PRESSURE_VALUE: - { - if (uiPressureTicksSamplesCounter!=0) - { - // Read PF300 pressure - strcpy(szTempBuf, &szAnswerFromPF300[ucNumberOfBytesToCheckFromPF300Answer]); - - // Store value of Pressure - uiCalibPressureValue=(unsigned int)atoi(szTempBuf); - - // Store ticks value - uiCalibPressureADCValue=ulSumPressureTicks/uiPressureTicksSamplesCounter; - uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_PRESSURE; - ulSumPressureTicks=0; - uiPressureTicksSamplesCounter=0; - - // Check if current pressure<10cmH20 - if (uiCalibPressureValue<1000) - { - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - break; - } - - // Compute pressure gain - uiCalibPressureGain=(10000UL*(uiCalibPressureADCValue-uiTechnicalDataSet[PPROX_OFFSET_TEC]))/uiCalibPressureValue; - uiCalibPressureGain+=5; - uiCalibPressureGain/=10; - - // Check pressure gain range - if (uiCalibPressureGain<Tec_GainPprox_MIN || uiCalibPressureGain>Tec_GainPprox_MAX) - { - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - else - { - enPressureCalibrationStep=PRESSURE_CALIB_SUCCESS_COMMAND; - - // Transfer the temporary LUT in the definitive LUT - uiTechnicalDataSet[PPROX_GAIN_TEC]=uiCalibPressureGain; - } - } - else // if (uiPressureTicksSamplesCounter!=0) - { - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - break; - } - case PRESSURE_CALIB_FAILURE_COMMAND: - { - if (TransferCommandToHandset((char*)szEndOfCalibFailed)==TRUE) - enPressureCalibrationStep=PRESSURE_CALIB_END_OF_CALIBRATION; - break; - } - case PRESSURE_CALIB_SUCCESS_COMMAND: - { - if (TransferCommandToHandset((char*)szEndOfCalibOK)==TRUE) - enPressureCalibrationStep=PRESSURE_CALIB_END_OF_CALIBRATION; - break; - } - case PRESSURE_CALIB_SEND_COMMAND_TO_PF300: - { - // Send a byte every 1ms - if (TransferBufferToPF300()==TRUE) - { - // Buffer sent !! - if (ucNumberOfBytesToCheckFromPF300Answer!=0) - { - // Check answer from PF300 - ucIndexAnswerFromPF300=0; - uiCalibrationTimeOut=TIME_OUT_RECEPTION_PACKET_FROM_PF300; - enPressureCalibrationStep=PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300; - } - else - enPressureCalibrationStep=enPressureCalibGoBackToStep; - } - break; - } - case PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300: - { - if (uiCalibrationTimeOut==0) - { - // Time-out in reception !! - ucIndexAnswerFromPF300=0; - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - else if (ReadByteReceive(&cCharValue)==TRUE) - { - // Check last byte received - if (cCharValue=='\r') - { - // End of answer => check buffer content - ucIndexAnswerFromPF300=0; - strcpy(szTempBuf, szAnswerFromPF300); - szTempBuf[ucNumberOfBytesToCheckFromPF300Answer]=0; - if (strcmp(szTempBuf, szExpectedAnswerFromPF300)==0) - { - // Buffer OK !! - enPressureCalibrationStep=enPressureCalibGoBackToStep; - } - else - { - // Buffer wrong !! - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - } - else if (cCharValue=='?') - { - // PF300 is lost => end of calibration - ucIndexAnswerFromPF300=0; - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - else - { - // Store byte from PF300 into buffer - szAnswerFromPF300[ucIndexAnswerFromPF300++]=cCharValue; - if (ucIndexAnswerFromPF300>=SIZE_RX_BUFFER_PF300) - { - // Answer too long !! - ucIndexAnswerFromPF300=0; - enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; - } - else - { - // Add 0 at the end of the string - szAnswerFromPF300[ucIndexAnswerFromPF300]=0; - } - } - } - else - { - // No byte received !! - uiCalibrationTimeOut--; - } - break; - } - default: - case PRESSURE_CALIB_END_OF_CALIBRATION: - { - uiTechnicalDataSet[START_STOP_VENTILATION]=0; - bDisableMaroubraCommCommunication=FALSE; - break; - } - } // switch - - // Every 300ms, send '@*' to inform the handset that the blower works properly - if (uiImHereMsgTimer==0) - { - if (enPressureCalibrationStep!=PRESSURE_CALIB_SEND_COMMAND_TO_PF300) - { - uiImHereMsgTimer=300; - TransferCommandToHandset((char*)szImHere); - } - } - else - uiImHereMsgTimer--; -} - - -/******************************************************************************* -* Function Name : ManageCstPressure -* Description : Manage constant pressure -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageCstPressure(void) -{ - int32_t lError; - int32_t lPropTerm; - int32_t lIntegralTerm; - int32_t lOutputPressure; - - - // Barometric Mode : error computation - lError=(int32_t)uiMLT_PressureSetPoint-(int32_t)uiProximalPressureMes; - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I] * lError; - if (uiMLT_PressureSetPoint<uiVentilationSet[PI_SET]) uiMLT_PressureSetPoint++; - - // Close loop in pressure - if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm) <0) - lIntegral_Pressure_I = INTEGRAL_MAX; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm)>0) - lIntegral_Pressure_I = INTEGRAL_MIN; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) - lIntegral_Pressure_I += lIntegralTerm; - else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) - lIntegral_Pressure_I += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; - lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); - - // Add constante value (PWM at the end of the previous inspiration) - //lOutputPressure+=300; - - if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiInspirationBlowerPWMTec = lOutputPressure; - } - - // Update Blower Speed - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - - // Monitoring and Alarm (every 1s) - #ifdef MOTOR_LIFE_TESTING - if (uiAverageMonitoringMLT==0) - { - uiAverageBlowerSpeedMes=ulMLT_SumSpeedMes/MLT_AVERAGE_MONITORING; - uiBreathBlowerCurrentMes=ulMLT_SumCurrentMes/MLT_AVERAGE_MONITORING; - uiAverateMotorTempMes=ulMLT_SumTemperatureMes/MLT_AVERAGE_MONITORING; - uiAverageMotorVoltage=ulMLT_SumBlowerVoltage/MLT_AVERAGE_MONITORING; - - ulMLT_SumSpeedMes=0; - ulMLT_SumCurrentMes=0; - ulMLT_SumTemperatureMes=0; - ulMLT_SumBlowerVoltage=0; - uiAverageMonitoringMLT=MLT_AVERAGE_MONITORING; - } - else - { - ulMLT_SumSpeedMes+=uiBlowerSpeedMes; - ulMLT_SumCurrentMes+=uiBlowerCurrentMes; - ulMLT_SumTemperatureMes+=uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]; - ulMLT_SumBlowerVoltage+=uiTechnicalDataMes[MOTOR_VOLTAGE_TEC_MES]; - uiAverageMonitoringMLT--; - } - - // Alarms management - if (uiMLT_EnableAlarm==0) - { - // High Speed alarm - if (uiAverageBlowerSpeedMes>uiTechnicalDataSet[MLT_HIGH_SPEED_TEC]) - uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_SPEED_ALARM_MASK; - - // Low Speed alarm - if (uiAverageBlowerSpeedMes<uiTechnicalDataSet[MLT_LOW_SPEED_TEC]) - uiFlagsAlarm[ALARM_FLAGS2]|=LOW_BLOWER_SPEED_ALARM_MASK; - - // High blower current alarm - if (uiBreathBlowerCurrentMes>uiTechnicalDataSet[MLT_HIGH_CURRENT_TEC]) - uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_CURRENT_ALARM_MASK; - - // High Blower temperature - if (uiAverateMotorTempMes>uiTechnicalDataSet[MLT_HIGH_TEMPERATURE_TEC]) - uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_TEMP_ALARM_MASK; - - // Low Blower temperature - if (uiAverateMotorTempMes<100) - uiFlagsAlarm[ALARM_FLAGS2]|=LOW_BLOWER_TEMP_ALARM_MASK; - - // High Blower Flow - if (iBlowerFlowSmoothingMesForTrigger>uiTechnicalDataSet[MLT_HIGH_FLOW_TEC] || iBlowerFlowSmoothingMesForTrigger<uiTechnicalDataSet[MLT_LOW_FLOW_TEC]) - uiFlagsAlarm[ALARM_FLAGS2]|=OOR_BLOWER_FLOW_ALARM_MASK; - } - else - uiMLT_EnableAlarm--; - #endif // MOTOR_LIFE_TESTING -} - - -/******************************************************************************* -* Function Name : ManagePACVVentilation -* Description : Manage Bilevel ventilation -* Input : bPSMode=true in PS mode, false in PI mode -* Output : None -* Return : None -*******************************************************************************/ -void ManagePACVVentilation(bool bPSMode) -{ -int32_t lError; -int32_t lPropTerm; -int32_t lIntegralTerm; -int32_t lOutputPressure; -u16 uiPressureSetPoint; -u16 uiTiMax; -u16 uiTiMin; -//u16 uiTeMax; -u16 uiFlowMaxInExpi; - -if (ucVentilationCycle==INSPIRATION_CYCLE) - { - // --------------------------------------------------------------------------- - // - INSPIRATION - - // -------------------------------------------------------------------------- - - // Ti et pressure set point management - if (bPSMode==TRUE) - { - uiPressureSetPoint=uiVentilationSet[PS_SET]; - uiTiMax=uiVentilationSet[TI_MAX_SET]; - } - else - { - uiPressureSetPoint=uiVentilationSet[PI_SET]; - uiTiMax=uiVentilationSet[TI_BARO_SET]; - } - - // Compute Timin - if (uiPatientType==PATIENT_ADULT) - uiTiMin=TiBaroSet_A_MIN; - else - uiTiMin=TiBaroSet_P_MIN; - - // Limit the pressure setting - if (uiVentilationSet[HIGH_PRESSURE_ALARM_SET]<uiPressureSetPoint) - uiPressureSetPoint=uiVentilationSet[HIGH_PRESSURE_ALARM_SET]; - - if (uiTiD==0) - { - // Management Expiratory Trigger - ucTempoTriggerExpiAuto=TEMPO_TRIGGER_EXPI; - ucExpiTriggerTreshold=MIN_THRESHOLD_EXPI_TRIGGER_AUTO; - - // Management Inspiratory slope - switch(uiVentilationSet[SLOPE_BARO_SET]) - { - default: - case 1: - { - // Slope of 5ms/hPa => 0.2hPa/ms - uiIpapSettingTemp=uiVentilationSet[PEEP_SET]+2; - break; - } - case 2: - { - ucIndexTableSlope=0; - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope2Table[ucIndexTableSlope++])/100; - break; - } - case 3: - { - ucIndexTableSlope=0; - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope3Table[ucIndexTableSlope++])/100; - break; - } - case 4: - { - ucIndexTableSlope=0; - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope4Table[ucIndexTableSlope++])/100; - break; - } - } - } - else - { - // Management Inspiratory slope - switch(uiVentilationSet[SLOPE_BARO_SET]) - { - default: - case 1: - { - // Slope of 5ms/hPa => 0.2hPa/ms - uiIpapSettingTemp+=2; - if (uiIpapSettingTemp>uiPressureSetPoint) - uiIpapSettingTemp=uiPressureSetPoint; - break; - } - case 2: - { - if (ucIndexTableSlope<SIZE_SLOPE2_TABLE && (uiTiD%10)==0) - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope2Table[ucIndexTableSlope++])/100; - break; - } - case 3: - { - if (ucIndexTableSlope<SIZE_SLOPE3_TABLE && (uiTiD%10)==0) - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope3Table[ucIndexTableSlope++])/100; - break; - } - case 4: - { - if (ucIndexTableSlope<SIZE_SLOPE4_TABLE && (uiTiD%10)==0) - uiIpapSettingTemp=(uiPressureSetPoint*ucSlope4Table[ucIndexTableSlope++])/100; - break; - } - } - } - - // Barometric Mode : error computation - lError=(int32_t)uiIpapSettingTemp-(int32_t)uiProximalPressureMes; - if (fFirstCycleInspi==FALSE) - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_I] * lError; - else - { - lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_I]>>2) * lError; - uiPWMatTheEndOfInspiration=uiExpirationBlowerPWMTec; - } - - // Close loop in pressure - if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm) <0) - lIntegral_Pressure_I = INTEGRAL_MAX; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) - { - if ((lIntegral_Pressure_I + lIntegralTerm)>0) - lIntegral_Pressure_I = INTEGRAL_MIN; - else - lIntegral_Pressure_I += lIntegralTerm; - } - else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) - lIntegral_Pressure_I += lIntegralTerm; - else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) - lIntegral_Pressure_I += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_I] * lError; - lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); - - // Add constante value (PWM at the end of the previous inspiration) - lOutputPressure+=uiPWMatTheEndOfInspiration; - - if (fAlarmPmax==TRUE || fAlarmVtiMax==TRUE) - { - bMaxPIOutputPressureI = TRUE; - } - else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureI = FALSE; - bMinPIOutputPressureI = FALSE; - uiInspirationBlowerPWMTec = lOutputPressure; - } - - // Update Blower Speed - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - - // ************************ CYCLE MANAGEMENT ********************************* - uiTiD++; - if ((uiTiD>=uiTiMax) || - (TestTriggerExpiratoire(uiVentilationSet[TRIG_E_SET], uiVentilationSet[PS_SET])==TRUE && uiTiD>uiVentilationSet[TI_MIN_SET] && bPSMode==TRUE) || - (fAlarmPmax==TRUE && uiTiD>uiTiMin) || - (fAlarmVtiMax==TRUE && uiTiD>uiTiMin)) - { - // Beginning of the expiration - if (fAlarmPmax==FALSE && fAlarmVtiMax==FALSE) - { - fFirstCycleInspi=FALSE; - uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; - } - else - { - fFirstCycleInspi=TRUE; - uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; - } - - ucVentilationCycle=EXPIRATION_CYCLE; - uiTiD=0; - - // Reset PI variables for next inspiration - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE=FALSE; - bMinPIOutputPressureE=FALSE; - - fFirstCycleExpi=FALSE; - } - } -else - { - // --------------------------------------------------------------------------- - // - EXPIRATION - - // --------------------------------------------------------------------------- - - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - // ******************** MAIN BLOWER MANAGEMENT ******************************* - if (uiVentilationSet[PEEP_SET]==0) - { - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); - } - else - { - if (uiTeD==0) - { - // First blower current setting - uiEpapSettingTemp=uiVentilationSet[PI_SET]-2; // Slope of 5ms/hPa => 0.2hPa/ms - } - else - { - // we increase the speed of the blower every 1ms - uiEpapSettingTemp-=2; // Slope of 5ms/hPa => 0.2hPa/ms - if (uiEpapSettingTemp<uiVentilationSet[PEEP_SET]) - uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; - } - - // Barometric Mode : error computation - if (fFirstCycleExpi==FALSE) - { - lError=(int32_t)uiEpapSettingTemp-(int32_t)uiProximalPressureMes; - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_E] * lError; - } - else - { - lError=(int32_t)uiVentilationSet[PEEP_SET]-(int32_t)uiProximalPressureMes; - lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_E]>>2) * lError; - } - - // Close loop in pressure - if ((lIntegral_Pressure_E>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureE==FALSE)) - { - if ((lIntegral_Pressure_E + lIntegralTerm) <0) - lIntegral_Pressure_E = INTEGRAL_MAX; - else - lIntegral_Pressure_E += lIntegralTerm; - } - else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureE==FALSE)) - { - if ((lIntegral_Pressure_E + lIntegralTerm)>0) - lIntegral_Pressure_E = INTEGRAL_MIN; - else - lIntegral_Pressure_E += lIntegralTerm; - } - else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm>=0)) - lIntegral_Pressure_E += lIntegralTerm; - else if ((lIntegral_Pressure_E>=0) && (lIntegralTerm<=0)) - lIntegral_Pressure_E += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_E] * lError; - lOutputPressure = (lIntegral_Pressure_E>>16) + (lPropTerm>>13); - - // Add constante value (PWM at the end of the previous expiration) - lOutputPressure+=uiPWMatTheEndOfExpiration; - - // Flow limiting - uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; - if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) - { - // Impossible to maintain the peep (patient disconnection) - if (uiDisconnectionTime==0) - { - fBlockCloseLoop=TRUE; // Block the close loop - if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value - uiExpirationBlowerPWMTec=uiMemoPWMDuringDisconnection; - else - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - uiDisconnectionTime--; - } - else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) - { - // Good pressure : no disconnection - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - if (fBlockCloseLoop==TRUE) - { - // The close loop was block before => unblock it - fBlockCloseLoop=FALSE; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - } - else if (iBlowerFlowSmoothingMes>=0) - { - // Record current PWM - uiMemoPWMDuringDisconnection=uiExpirationBlowerPWMTec; - } - } - - // Unblock the close loop every 4s in case of none recorded PWM value - if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiTeD==0) - { - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - fBlockCloseLoop=FALSE; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - } - - // Update blower PWM - if (fBlockCloseLoop==TRUE) - { - bMaxPIOutputPressureE = TRUE; - } - else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureE = TRUE; - uiExpirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureE = TRUE; - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - uiExpirationBlowerPWMTec = lOutputPressure; - } - SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); - } - - // Expiratory time - uiTeD++; - if (uiTeD>TE_SET_MAX) uiTeD=TE_SET_MAX; - if ((uiTeD>=uiTeBaroSet && bPSMode==FALSE) || TestInspiratoryTrigger(bPSMode, uiTeD, uiVentilationSet[TRIG_I_FLOW_SET])==TRUE) - { - ucVentilationCycle=INSPIRATION_CYCLE; - uiTeD=0; - - // Record PWM value at the end of the expiration - uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - - // Reset PI variables for next inspiration - lIntegral_Pressure_I=0; - bMaxPIOutputPressureI=FALSE; - bMinPIOutputPressureI=FALSE; - } - } -} - - - -/******************************************************************************* -* Function Name : ManageVolumetricVentilation -* Description : Manage Volumetric Ventilation -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ManageVolumetricVentilation(void) -{ -int32_t lError; -int32_t lPropTerm; -int32_t lIntegralTerm; -int32_t lOutputPressure; -int16_t iMaxVtAdjust; -u16 uiFlowMaxInExpi; -u16 uiTiMin; - -if (ucVentilationCycle==INSPIRATION_CYCLE) - { - // --------------------------------------------------------------------------- - // - INSPIRATION - - // --------------------------------------------------------------------------- - - // Compute Timin - if (uiPatientType==PATIENT_ADULT) - uiTiMin=TiVoluSet_A_MIN; - else - uiTiMin=TiVoluSet_P_MIN; - - // ************************** Main Blower MANAGEMENT ************************* - if (uiTiD==0) - { - // Compute Volume adjustment - if (fFirstCycleInspi==FALSE) - { - if ((uiFlagsAlarm[ALARM_FLAGS1]&HIGH_PRESSURE_ALARM_MASK)==0) - { - if (ucCounterHPAlarm==0) - { - iVtAdjust+=(((int16_t)uiVentilationSet[VT_SET]-(int16_t)uiRecordVtiMes>>1)); - if (iVtAdjust>0) - { - iMaxVtAdjust=(int16_t)(uiVentilationSet[VT_SET]>>1); // >0 - if (iVtAdjust>iMaxVtAdjust) - iVtAdjust=iMaxVtAdjust; - } - else if (iVtAdjust<0) - { - iMaxVtAdjust=(int16_t)(~(uiVentilationSet[VT_SET]>>1)+1); // <0 - if (iVtAdjust<iMaxVtAdjust) - iVtAdjust=iMaxVtAdjust; - } - } - else - ucCounterHPAlarm--; - } - else - ucCounterHPAlarm=1; - } - else - iVtAdjust=0; - - ComputeInspiratoryFlowSetPointInAVC(uiPatientType, (u16)((int16_t)uiVentilationSet[VT_SET]+iVtAdjust), uiVentilationSet[TI_VOLU_SET], uiVentilationSet[SHAPE_SET], &ulMaxIFlowSet, &ulMinIFlowSet, &ulDecFlowStep); - } - else - { - if (ulMaxIFlowSet>=ulDecFlowStep) - ulMaxIFlowSet-=ulDecFlowStep; - if (ulMaxIFlowSet<ulMinIFlowSet) - ulMaxIFlowSet=ulMinIFlowSet; - } - - // Volumetric Mode : error computation - //lError=(int32_t)(ulMaxIFlowSet/100)-iBlowerFlowMes; - lError=(int32_t)(ulMaxIFlowSet/100)-iBlowerFlowSmoothingMes; - if (fFirstCycleInspi==FALSE) - { - if (ulMaxIFlowSet<150000 && uiTiD>30000) - lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_FLOW_I]>>1) * lError; - else - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_FLOW_I] * lError; - } - else - lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_FLOW_I]>>2) * lError; - - // Close loop in pressure or flow (PI) - if ((lIntegral_Flow_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputFlowI==FALSE)) - { - if ((lIntegral_Flow_I + lIntegralTerm) <0) - lIntegral_Flow_I = INTEGRAL_MAX; - else - lIntegral_Flow_I += lIntegralTerm; - } - else if ((lIntegral_Flow_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputFlowI==FALSE)) - { - if ((lIntegral_Flow_I + lIntegralTerm)>0) - lIntegral_Flow_I = INTEGRAL_MIN; - else - lIntegral_Flow_I += lIntegralTerm; - } - else if ((lIntegral_Flow_I<=0) && (lIntegralTerm>=0)) - lIntegral_Flow_I += lIntegralTerm; - else if ((lIntegral_Flow_I>=0) && (lIntegralTerm<=0)) - lIntegral_Flow_I += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_FLOW_I] * lError; - lOutputPressure = (lIntegral_Flow_I>>16) + (lPropTerm>>13); - - // Add constante value (PWM at the end of the previous inspiration) - lOutputPressure+=uiPWMatTheEndOfExpiration; - - if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputFlowI = TRUE; - uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputFlowI = TRUE; - uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputFlowI = FALSE; - bMinPIOutputFlowI = FALSE; - uiInspirationBlowerPWMTec = lOutputPressure; - } - - // Update Blower Speed - SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); - - // ************************ CYCLE MANAGEMENT ********************************* - uiTiD++; - if ((uiTiD>=uiVentilationSet[TI_VOLU_SET]) || - (fAlarmPmax==TRUE && uiTiD>uiTiMin)) - { - // Beginning of the expiration - uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; - uiProximalPressureAtTheEndOfInspiration=uiProximalPressureMes; - - ucVentilationCycle=EXPIRATION_CYCLE; - uiTiD=0; - - // Reset PI variables for next inspiration - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE=FALSE; - bMinPIOutputPressureE=FALSE; - - fFirstCycleExpi=FALSE; - fFirstCycleInspi=FALSE; - } - } -else - { - // --------------------------------------------------------------------------- - // - EXPIRATION - - // --------------------------------------------------------------------------- - - // *************************** UPDATE SETTINGS ******************************* - if (ApplyNewVentilationMode()==TRUE) - return; - - // ******************** MAIN BLOWER MANAGEMENT ******************************* - if (uiVentilationSet[PEEP_SET]==0) - { - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); - } - else - { - if (uiTeD==0) - { - // First blower pressure setting - if (uiProximalPressureAtTheEndOfInspiration<uiVentilationSet[PEEP_SET]) - uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; - else if (uiProximalPressureAtTheEndOfInspiration>=2) - uiEpapSettingTemp=uiProximalPressureAtTheEndOfInspiration-2; // Slope of 5ms/hPa => 0.2hPa/ms - else - uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; - } - else - { - // we decrease the speed of the blower every 1ms - if (uiEpapSettingTemp>=2) - uiEpapSettingTemp-=2; // Slope of 5ms/hPa => 0.2hPa/ms - } - - // Pressure set point limitation - if (uiEpapSettingTemp<uiVentilationSet[PEEP_SET]) - uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; - - // Barometric Mode : error computation - if (fFirstCycleExpi==FALSE) - { - lError=(int32_t)uiEpapSettingTemp-(int32_t)uiProximalPressureMes; - lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_E] * lError; - } - else - { - lError=(int32_t)uiVentilationSetTemp[PEEP_SET]-(int32_t)uiProximalPressureMes; - lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_E]>>2) * lError; - } - - // Close loop in pressure - if ((lIntegral_Pressure_E>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureE==FALSE)) - { - if ((lIntegral_Pressure_E + lIntegralTerm) <0) - lIntegral_Pressure_E = INTEGRAL_MAX; - else - lIntegral_Pressure_E += lIntegralTerm; - } - else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureE==FALSE)) - { - if ((lIntegral_Pressure_E + lIntegralTerm)>0) - lIntegral_Pressure_E = INTEGRAL_MIN; - else - lIntegral_Pressure_E += lIntegralTerm; - } - else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm>=0)) - lIntegral_Pressure_E += lIntegralTerm; - else if ((lIntegral_Pressure_E>=0) && (lIntegralTerm<=0)) - lIntegral_Pressure_E += lIntegralTerm; - - lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_E] * lError; - lOutputPressure = (lIntegral_Pressure_E>>16) + (lPropTerm>>13); - - // Add constante value (PWM at the end of the previous expiration) - lOutputPressure+=uiPWMatTheEndOfExpiration; - - // Flow limiting - uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; - if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) - { - // Impossible to maintain the peep (patient disconnection) - if (uiDisconnectionTime==0) - { - fBlockCloseLoop=TRUE; // Block the close loop - if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value - uiExpirationBlowerPWMTec=uiMemoPWMDuringDisconnection; - else - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - uiDisconnectionTime--; - } - else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) - { - // Good pressure : no disconnection - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - if (fBlockCloseLoop==TRUE) - { - // The close loop was block before => unblock it - fBlockCloseLoop=FALSE; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - } - else if (iBlowerFlowSmoothingMes>=0) - { - // Record current PWM - uiMemoPWMDuringDisconnection=uiExpirationBlowerPWMTec; - } - } - - // Unblock the close loop every 4s in case of none recorded PWM value - if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiTeD==0) - { - uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; - fBlockCloseLoop=FALSE; - lIntegral_Pressure_E=0; - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - } - - // Update blower PWM - if (fBlockCloseLoop==TRUE) - { - bMaxPIOutputPressureE = TRUE; - } - else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) - { - bMaxPIOutputPressureE = TRUE; - uiExpirationBlowerPWMTec=MAX_VOLTAGE_REF; - } - else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) - { - bMinPIOutputPressureE = TRUE; - uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; - } - else - { - bMaxPIOutputPressureE = FALSE; - bMinPIOutputPressureE = FALSE; - uiExpirationBlowerPWMTec = lOutputPressure; - } - // Update Blower Speed - SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); - } - - // Expiratory time - uiTeD++; - if (uiTeD>=uiTeVoluSet || TestInspiratoryTrigger(FALSE, uiTeD, uiVentilationSet[TRIG_I_FLOW_SET])==TRUE) - { - ucVentilationCycle=INSPIRATION_CYCLE; - uiTeD=0; - - // Record PWM value at the end of the expiration - if (fBlockCloseLoop==FALSE) - uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; - else - uiPWMatTheEndOfExpiration=0; - fBlockCloseLoop=FALSE; - - // Reset PI variables for next inspiration - lIntegral_Flow_I=0; - bMaxPIOutputFlowI=FALSE; - bMinPIOutputFlowI=FALSE; - } - } -} - - - -/******************************************************************************* -* Function Name : LaunchTherapyEngine -* Description : Select and launch the therapy engine -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void LaunchTherapyEngine(void) -{ - if (bMemoStartVentilation==TRUE) - { - // ---- Check new configuration - if (uiTechnicalDataSet[DEVICE_MODE_TEC]!=uiPreviousDeviceMode) - { - UpdateSettings(); - enPreviousMode=NUMBER_OF_MODE; // Force full init of the variables - InitVentilation(); - uiPreviousDeviceMode=uiTechnicalDataSet[DEVICE_MODE_TEC]; - } - - - switch(uiTechnicalDataSet[DEVICE_MODE_TEC]) - { - default: - case VENTILATION_MODE: - { - if (enVentilationMode==PS_MODE) - ManagePACVVentilation(TRUE); - else if (enVentilationMode==APCV_MODE) - ManagePACVVentilation(FALSE); - else if (enVentilationMode==AVC_MODE) - ManageVolumetricVentilation(); - else if (enVentilationMode==CPAP_MODE) - ManageCPAPVentilation(); - break; - } - case ONE_CST_PWM_MODE: - { - ManageOneCstPWM(); - break; - } - case TWO_CST_PWM_MODE: - { - Manage2CstPWM(); - break; - } - case CST_SPEED_MODE: - { - ManageCstSpeed(); - break; - } - case FLOW_CAL_MODE: - { - ManageFlowCalibration(); - break; - } - case PRESSURE_CAL_MODE: - { - ManagePressureCalibration(); - break; - } - case PRESSURE_CST_MODE: - { - ManageCstPressure(); - break; - } - } - } -} - - -/******************************************************************************* -* Function Name : StartStopVentilation -* Description : Detect a start/stop ventilation request -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void StartStopVentilation(void) -{ - #ifndef TEMPERATURE_TRENDS - opstatus_t byOpStatus; - #endif - - // Check if an alarm must stop the ventilation - ucStopVentilationAlarmNumber=ReadStopVentilationAlarmNumber(); - - #ifndef TEMPERATURE_TRENDS - if (uiTechnicalDataSet[START_STOP_VENTILATION]==1 && ucStopVentilationAlarmNumber==SIZE_BLOWER_ALARM) - { - // *************** VENTILATION is ON ************** - if (bMemoStartVentilation==FALSE) - { - switch(ucStartVentilationScheduler) - { - default: - case 0: - { - // Active the HW safety system - ControlHW(BLOWER_ON__PAT_CPLD); - ucStartVentilationScheduler++; - break; - } - case 1: - { - // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 - ControlHW(BLOWER_ON__PAT_CPLD); - - // Read Offset of the Blower current - ComputeADCBlowerCurrent(TRUE); - - ucStartVentilationScheduler++; - break; - } - case 2: - { - // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 - ControlHW(BLOWER_ON__PAT_CPLD); - - // Open motor driver - byOpStatus=SS_Xopen(mdrv); - if (byOpStatus==OPSTATUS_FAIL) - { - uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_FAILURE_ALARM_MASK; - ucStartVentilationScheduler=0; - } - else if (byOpStatus==OPSTATUS_OK) - { - // Force init settings and variables - uiPreviousDeviceMode=0xFF; - - uiTempo1min=TEMPO_1MIN; - #ifdef DATA_LOGGING - uiTrendsSampleTime=RECORD_TRENDS_SAMPLE_TIME; - #endif // DATA_LOGGING - - // Check if ventilation mode is activated - if (uiTechnicalDataSet[DEVICE_MODE_TEC]!=VENTILATION_MODE) - uiFlagsAlarm[ALARM_FLAGS2]|=DEVICE_MODE_ALARM_MASK; - - bMemoStartVentilation=TRUE; - ucStartVentilationScheduler=0; - } - break; - } - } - } - // --- Check Safety system for Motor transistors ---- - else if (IsMotorOK()==FALSE) - { - ControlHW(BLOWER_OFF__STOP_PAT_CPLD); - uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_FAILURE_ALARM_MASK; - } - // --- Test safety system thanks to the "STOP_BLOWER" Input pin - else if (TestStopBlowerInputPin()==OPSTATUS_OK) - { - ControlHW(BLOWER_ON__PAT_CPLD); - uiFlagsAlarm[ALARM_FLAGS2]&=(~HW_SAFETY_ALARM_MASK); - } - else - { - uiFlagsAlarm[ALARM_FLAGS2]|=HW_SAFETY_ALARM_MASK; - } - } - else - #endif // #ifndef TEMPERATURE_TRENDS - { - // *************** VENTILATION is OFF ************** - uiFlagsAlarm[ALARM_FLAGS2]&=(~DEVICE_MODE_ALARM_MASK); - - if (ucStopVentilationAlarmNumber!=SIZE_BLOWER_ALARM) - { - // Stop patting CPLD (WDI_CPLD=0), STOP_BLOWER=0 - ControlHW(BLOWER_OFF__STOP_PAT_CPLD); - } - else - { - // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 - ControlHW(BLOWER_ON__PAT_CPLD); - - // ---- Test STOP_ACTUATOR Input pin Status - if (TestStopBlowerInputPin()==OPSTATUS_FAIL) - uiFlagsAlarm[ALARM_FLAGS2]|=HW_SAFETY_ALARM_MASK; - else - uiFlagsAlarm[ALARM_FLAGS2]&=(~HW_SAFETY_ALARM_MASK); - } - - if (bMemoStartVentilation==TRUE) - { - StopAllActuators(); - ClearAllVentilationAlarms(); - ClearAllMeasures(); - } - - uiTechnicalDataSet[START_STOP_VENTILATION]=0; - bMemoStartVentilation=FALSE; - #ifndef TEMPERATURE_TRENDS - ucStartVentilationScheduler=0; - #endif - bDisableMaroubraCommCommunication=FALSE; - } -} -#endif // #ifndef C_M3_DEVICETEST_TARGET - - -/******************************************************************************* -* Function Name : ComputeTe -* Description : Compute expiratory time -* Input : uiF = Breath frequency (bpm) - uiTi = Inspiratory time (ms) -* Output : Expiratory time (ms) -* Return : None -*******************************************************************************/ -#ifndef C_M3_DEVICETEST_TARGET -u16 ComputeTe(u16 uiF, u16 uiTi) -{ - u16 uiTtot; - u16 uiTeTemp=TE_SET_MIN; - - if (uiF!=0) - { - // Compute Ttotal - uiTtot=60000/uiF; - if (uiTtot>uiTi) - { - uiTeTemp=uiTtot-uiTi; - if (uiTeTemp<TE_SET_MIN) - uiTeTemp=TE_SET_MIN; - } - } - else - { - // F=0 => Te=2xTi - uiTeTemp=uiTi<<1; - } - return(uiTeTemp); -} - - -/******************************************************************************* -* Function Name : UpdateSettings -* Description : Update the settings zone with the temporary settings zone -* Input : None -* Output : None -* Return : TRUE if the ventilation mode has changed -*******************************************************************************/ -bool UpdateSettings(void) -{ - u8 ucIndex; - - // Take into account a modification of the PEEP - if (uiVentilationSet[PEEP_SET]!=uiVentilationSetTemp[PEEP_SET] || uiVentilationSet[PS_CPAP_SET]!=uiVentilationSetTemp[PS_CPAP_SET]) - uiMemoPWMDuringDisconnection=0; - - // Transfert data from the setting temporary zone to the settings zone - for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) - uiVentilationSet[ucIndex]=uiVentilationSetTemp[ucIndex]; - - // Update barometric expiratory time - uiTeBaroSet=ComputeTe(uiVentilationSet[BREATH_RATE_BARO_SET], uiVentilationSet[TI_BARO_SET]); - - // Update volumetric expiratory time - uiTeVoluSet=ComputeTe(uiVentilationSet[BREATH_RATE_VOLU_SET], uiVentilationSet[TI_VOLU_SET]); - - // Update Tube configuration type - enTubeConfigType=enTubeConfigTypeTemp; - - // Update Patient type - uiPatientType=uiPatientTypeTemp; - - // Update Ventilation mode - if (enVentilationMode!=enVentilationModeTemp) - { - enVentilationMode=enVentilationModeTemp; - InitVentilation(); - return(TRUE); - } - return(FALSE); -} - - -/******************************************************************************* -* Function Name : ApplyNewVentilationMode -* Description : Update settings and init variables if the ventilation mode has changed -* Input : None -* Output : None -* Return : TRUE if new ventilation mode is applied -*******************************************************************************/ -bool ApplyNewVentilationMode(void) -{ - if (fUpdateTheSettings==TRUE) - { - fUpdateTheSettings=FALSE; - if (UpdateSettings()==TRUE) - { - InitVentilation(); - return(TRUE); - } - } - return(FALSE); -} - - -/******************************************************************************* -* Function Name : ComputeInspiratoryFlowSetPointInAVC -* Description : Compute: - - the inspiratory flow max set point - - the inspiratory flow min set point - - the flow step between the flow max and the flow min during Ti -* Input : uiTypeOfPatient = Adult or Pedia - uiVtc = set point in volume (ml) - uiTi = Ti set point (ms) - uiFlowShape = Flow shape (0 to 4) -* Output : uiMaxFlow = the inspiratory flow max set point (cl/min => 100=1l/min) - uiMinFlow = the inspiratory flow min set point (cl/min => 100=1l/min) - uiFlowStep = the flow step between the flow max and the flow min during Ti (cl/min => 100=1l/min) -* Return : None -*******************************************************************************/ -void ComputeInspiratoryFlowSetPointInAVC(u16 uiTypeOfPatient, u16 uiVtc, u16 uiTi, u16 uiFlowShape, u32 *ulMaxFlow, u32 *ulMinFlow, u32 *ulFlowStep) -{ - u32 ulFlowMax; - u32 ulFlowMin; - u32 ulMaxMaxFlow; - u32 ulMinMinFlow; - u16 uiTiMin; - u32 ulFlowStepTemp; - - // Define min/max flow - if (uiTypeOfPatient==PATIENT_ADULT) - { - ulMinMinFlow=InspiratoryFlowSet_A_MIN; - ulMaxMaxFlow=InspiratoryFlowSet_A_MAX; - uiTiMin=TiVoluSet_A_MIN; - } - else - { - ulMinMinFlow=InspiratoryFlowSet_P_MIN; - ulMaxMaxFlow=InspiratoryFlowSet_P_MAX; - uiTiMin=TiVoluSet_P_MIN; - } - - // Check Ti - if (uiTi==0) - uiTi=uiTiMin; - - // Compute flow max - switch(uiFlowShape) - { - default: - case 0: - { - ulFlowMax=((u32)uiVtc*6000)/uiTi; - break; - } - case 1: - { - ulFlowMax=((u32)uiVtc*7500)/uiTi; - break; - } - case 2: - { - ulFlowMax=((u32)uiVtc*9000)/uiTi; - break; - } - case 3: - { - ulFlowMax=((u32)uiVtc*10500)/uiTi; - break; - } - case 4: - { - ulFlowMax=((u32)uiVtc*12000)/uiTi; - break; - } - } - - // Limitation of the max flow - if (ulFlowMax>ulMaxMaxFlow) - ulFlowMax=ulMaxMaxFlow; - - // Limitation of the min flow - if (ulFlowMax<ulMinMinFlow) - ulFlowMax=ulMinMinFlow; - - // Factor 100 on flow max (and flow min and flow step) - ulFlowMax*=100; - - // Compute flow min and flow step - switch(uiFlowShape) - { - default: - case 0: - { - ulFlowMin=ulFlowMax; - break; - } - case 1: - { - ulFlowMin=(ulFlowMax*3)>>2; - break; - } - case 2: - { - ulFlowMin=ulFlowMax>>1; - break; - } - case 3: - { - ulFlowMin=ulFlowMax>>2; - break; - } - case 4: - { - ulFlowMin=0; - break; - } - } - - // Max flow - *ulMaxFlow=ulFlowMax; - - // Min flow - *ulMinFlow=ulFlowMin; - - // Flow Step - ulFlowStepTemp=(ulFlowMax-ulFlowMin)/uiTi; - //if (uiFlowStepTemp==0 && uiFlowShape!=0) uiFlowStepTemp=1; - *ulFlowStep=ulFlowStepTemp; -} - - - -/******************************************************************************* -* Function Name : TestTriggerExpiratoire -* Description : Manage the expiratory trigger -* Input : ucValeurSeuil = threshold (% of the flow max) to reach in order to cycle -* Output : None -* Return : TRUE if cycling active -*******************************************************************************/ -unsigned char TestTriggerExpiratoire(unsigned char ucValeurSeuil, unsigned int uiPressureSetting) -{ - unsigned char ucSeuil=ucValeurSeuil; - unsigned int uiCalculTemp; - int16_t iConductanceBaseLine=UpdateInspiratoryConductanceAverage(); - // Management automatic expiratory trigger - ucTempoTriggerExpiAuto--; - if (ucTempoTriggerExpiAuto==0) - { - ucTempoTriggerExpiAuto=TEMPO_TRIGGER_EXPI; - ucExpiTriggerTreshold++; - } - - // Test si flow<0?? - if (iBlowerFlowSmoothingMes<0) - { - return(TRUE); - } - // Test if deacring flow?? - else if (iBlowerFlowSmoothingMes<iBlowerFlowSmoothingMaxMes) - { - // Test if Trigger Expi=AUTO ?? - if ((ucValeurSeuil==ExpiTriggerSet_A_MAX && uiPatientType==PATIENT_ADULT) || - (ucValeurSeuil==ExpiTriggerSet_P_MAX && uiPatientType==PATIENT_PEDIA)) - ucSeuil=ucExpiTriggerTreshold; - - u16 conducThresh = 2000; - - if(enTubeConfigType == 1 ) - conducThresh = 750; - else if(enTubeConfigType == 2) - conducThresh = 1500; - - // Test if cycling or not - uiCalculTemp=((unsigned long)iBlowerFlowSmoothingMaxMes*ucSeuil)/100; - if (uiCalculTemp>iBlowerFlowSmoothingMes) - return(TRUE); - else if (uiProximalPressureMes>(uiPressureSetting+20)) - return(TRUE); - else if (uiConductanceCalc < (iConductanceBaseLine - conducThresh)) - { - ResetInspiratoryConductanceAverage(); - return(TRUE); - } - } - return(FALSE); -} - - -/******************************************************************************* -* Function Name : TestInspiratoryTrigger -* Description : Manage the inspiratory trigger -* Input : bSpont = TRUE if spontaneous mode -* uiTe = expiration time (ms) -* uiFlowTreshold = flow threshold (dl/min) -* Output : None -* Return : TRUE if cycling active -*******************************************************************************/ -bool TestInspiratoryTrigger(bool bSpont, u16 uiTe, u16 uiFlowTreshold) -{ - //int16_t iInspiratoryFlowDeltaAverage; - //int16_t iDeltaOfTheDelta1, iDeltaOfTheDelta2, iDeltaOfTheDelta3, iDeltaOfTheDelta4; - bool bTrigger=FALSE; - //int16_t iVirtualFlow; - int16_t iConductanceBaseLine; - - // Manual breath management - if (uiTe>TE_SET_MIN) - { - if (bManualBreath==TRUE) - { - bManualBreath=FALSE; - bDisplayInspiratoryTrigger=TRUE; - return(TRUE); - } - } - - // Trigger management - if ((bSpont==TRUE) || - (bSpont==FALSE && uiFlowTreshold<InspiTriggerFlowSet_A_MAX && uiPatientType==PATIENT_ADULT) || - (bSpont==FALSE && uiFlowTreshold<InspiTriggerFlowSet_P_MAX && uiPatientType==PATIENT_PEDIA)) - { - // Init scheduler - if (uiTe==1) - { - ucInspiTriggerScheduler=0; - iInspiratoryFlowMin=0; - ucMinFlowCounter=NUMBER_MIN_FLOW_VALUE; - ucCounterTriggerValid=NUMBER_TRIGGER_VALID; - bDetectionConstantFlow=FALSE; - } - - iConductanceBaseLine=UpdateInspiratoryConductanceAverage(); - // Manage detection phase - switch(ucInspiTriggerScheduler) - { - default: - case 0: - { - // Update the buffer on the Inspiratory flow average - - // Detect min flow - if (iBlowerFlowSmoothingMesForTrigger<iInspiratoryFlowMin) - { - iInspiratoryFlowMin=iBlowerFlowSmoothingMesForTrigger; - ucMinFlowCounter=NUMBER_MIN_FLOW_VALUE; - } - else - { - ucMinFlowCounter--; - if (ucMinFlowCounter==0) - ucInspiTriggerScheduler=1; - } - break; - } - case 1: - { - //ucTriggerNumber=0; - - if (uiTe>TE_SET_MIN) - { -// // Fast trigger management -// if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]<=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-25]) -// { -// iVirtualFlow=(iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-25]<<1)-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]; -// if (iBlowerFlowSmoothingMesForTrigger>=(iVirtualFlow+(int16_t)(uiFlowTreshold*7))) -// { -// //ucTriggerNumber=1; -// //if (fBlockCloseLoop==FALSE) -// bTrigger=TRUE; -// } -// } -// if (bTrigger==FALSE && iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-100]<=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]) -// { -// iVirtualFlow=(iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]<<1)-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-100]; -// if (iBlowerFlowSmoothingMesForTrigger>=(iVirtualFlow+(int16_t)(uiFlowTreshold*15))) -// { -// //ucTriggerNumber=2; -// //if (fBlockCloseLoop==FALSE) -// bTrigger=TRUE; -// } -// } -// -// // Slow trigger management -// if (TestInspiratorySlowTrigger(iFlowBaseLine, uiFlowTreshold*10)==TRUE) -// { -// //ucTriggerNumber=3; -// bTrigger=TRUE; -// } - //Conductance Trigger - if(uiConductanceCalc >= (iConductanceBaseLine + 2000)) - { - bTrigger = TRUE; - } - - // Trigger occurs?? - if (bTrigger==TRUE) - { - ucCounterTriggerValid--; - if (ucCounterTriggerValid==0) - { - bDisplayInspiratoryTrigger=TRUE; - ResetInspiratoryConductanceAverage(); - return(TRUE); - } - } - else - ucCounterTriggerValid=NUMBER_TRIGGER_VALID; - } - break; - } - } - } - return(FALSE); -} - -/******************************************************************************* -* Function Name : UpdateInspiratoryConductanceAverage -* Description : Fill the buffer with the expiratory conductance and compute the average -* Input : None -* Output : None -* Return : Inspiratory flow average -*******************************************************************************/ -u16 conducIndex = 0; -int32_t lSumConductance = 0; -bool bufFilled = FALSE; - -int16_t UpdateInspiratoryConductanceAverage(void) -{ - int16_t oldValue = iBufferIFlow[conducIndex]; - iBufferIFlow[conducIndex] = uiConductanceCalc; - lSumConductance += uiConductanceCalc; - conducIndex++; - - if(conducIndex > SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER) - { - conducIndex = 0; - bufFilled = TRUE; - } - - if(bufFilled) - { - lSumConductance -= oldValue; - return (lSumConductance/SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER); - } - else - { - return (lSumConductance/conducIndex); - } -} - -/******************************************************************************* -* Function Name : ResetInspiratoryConductanceAverage -* Description : Fill the buffer with the expiratory conductance and compute the average -* Input : None -* Output : None -* Return : Inspiratory flow average -*******************************************************************************/ - -void ResetInspiratoryConductanceAverage(void) -{ - conducIndex = 0; - lSumConductance = 0; - bufFilled = FALSE; -} - -/******************************************************************************* -* Function Name : UpdateInspiratoryFlowAverage -* Description : Fill the buffer with the inspiratory flow and compute the average -* Input : None -* Output : None -* Return : Inspiratory flow average -*******************************************************************************/ -int16_t UpdateInspiratoryFlowAverage(void) -{ - u16 uiIndex; - int32_t lSumIFlow=0; - - // Roll the buffer - for(uiIndex=1; uiIndex<SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER; uiIndex++) - { - iBufferIFlow[uiIndex-1]=iBufferIFlow[uiIndex]; // Upate the Inspiratory Flow buffer - lSumIFlow+=iBufferIFlow[uiIndex-1]; // Sum the Inspiratory Flow - } - - // Add new flow value - iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]=iBlowerFlowSmoothingMesForTrigger; // Upate the Inspiratory Flow buffer - lSumIFlow+=iBlowerFlowSmoothingMesForTrigger; // Sum the Inspiratory Flow - - return(lSumIFlow/SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER); -} - - -/******************************************************************************* -* Function Name : TestInspiratorySlowTrigger -* Description : Compute flow base line and test trigger -* Input : FlowTreshold = flow threshold (cl/min) -* Output : None -* Return : TRUE if trigger occurs -*******************************************************************************/ -bool TestInspiratorySlowTrigger(int16_t iTheFlowBaseLine, u16 uiFlowTreshold) -{ - int16_t iFlowDelta1, iFlowDelta2, iFlowDelta3; - - if (bDetectionConstantFlow==FALSE) - { - // Detection constant flow - if (iBufferIFlow[0]<iTheFlowBaseLine) - iFlowDelta1=iTheFlowBaseLine-iBufferIFlow[0]; - else - iFlowDelta1=iBufferIFlow[0]-iTheFlowBaseLine; - - if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]<iTheFlowBaseLine) - iFlowDelta2=iTheFlowBaseLine-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]; - else - iFlowDelta2=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]-iTheFlowBaseLine; - - if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]<iTheFlowBaseLine) - iFlowDelta3=iTheFlowBaseLine-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]; - else - iFlowDelta3=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]-iTheFlowBaseLine; - - if (iFlowDelta1<60 && iFlowDelta2<60 && iFlowDelta3<60) - { - iFlowBaseLineReference=iTheFlowBaseLine; - bDetectionConstantFlow=TRUE; - } - } - else - { - // Detect trigger - if (iBlowerFlowSmoothingMesForTrigger>=(iFlowBaseLineReference+(int16_t)uiFlowTreshold)) - { - return(TRUE); - } - } - return(FALSE); -} - - -/******************************************************************************* -* Function Name : ApplyDefaultValueToTemporaryVentilationSettings -* Description : Init temporary ventilation settings with default values -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ApplyDefaultValueToTemporaryVentilationSettings(void) -{ - u8 ucIndex; - - enVentilationModeTemp=VentilationMode_DEF; - uiPatientTypeTemp=PatientType_DEF; - enTubeConfigTypeTemp=(enMaroubraTubeConfigurationList)ReturnDefaultTubeConfiguration(VentilationMode_DEF); - - // Init all temporary settings - if (uiPatientType==PATIENT_ADULT) - { - for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) - uiVentilationSetTemp[ucIndex]=sLRSGroup[ucIndex].uiDefault_Adult; - } - else - { - for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) - uiVentilationSetTemp[ucIndex]=sLRSGroup[ucIndex].uiDefault_Pedia; - } -} - - -/******************************************************************************* -* Function Name : CheckTemporaryVentilationSettingRange -* Description : Check all the temporary settings range -* Input : None -* Output : None -* Return : FALSE if one the settings is out of range -*******************************************************************************/ -opstatus_t CheckTemporaryVentilationSettingRange(void) -{ - u8 ucIndex; - - if ((uiPatientTypeTemp==PATIENT_PEDIA || uiPatientTypeTemp==PATIENT_ADULT) && enVentilationModeTemp<NUMBER_OF_MODE && enTubeConfigTypeTemp<NUMBER_OF_TUBE_CONFIGURATION) - { - for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) - { - // Check data range - if (uiPatientTypeTemp==PATIENT_PEDIA) - { - if (uiVentilationSetTemp[ucIndex]<sLRSGroup[ucIndex].uiMin_Pedia) - return(OPSTATUS_FAIL); - else if (uiVentilationSetTemp[ucIndex]>sLRSGroup[ucIndex].uiMax_Pedia) - return(OPSTATUS_FAIL); - } - else - { - if (uiVentilationSetTemp[ucIndex]<sLRSGroup[ucIndex].uiMin_Adult) - return(OPSTATUS_FAIL); - else if (uiVentilationSetTemp[ucIndex]>sLRSGroup[ucIndex].uiMax_Adult) - return(OPSTATUS_FAIL); - } - } - return(OPSTATUS_OK); - } - return(OPSTATUS_FAIL); -} - - - -/******************************************************************************* -* Function Name : ApplyDefaultValueToTechnicalSettings -* Description : Init technical settings with default values -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ApplyDefaultValueToTechnicalSettings(void) -{ - u8 ucIndex; - - // Init all temporary settings - for (ucIndex=0; ucIndex<SIZE_LRTS_GROUP; ucIndex++) - uiTechnicalDataSet[ucIndex]=sLRTSGroup[ucIndex].uiDefault; -} - - -/******************************************************************************* -* Function Name : CheckTechnicalSettingsRange -* Description : Check all the technical settings range -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void CheckTechnicalSettingsRange(void) -{ - u8 ucIndex; - bool fError=FALSE; - - for (ucIndex=0; ucIndex<SIZE_LRTS_GROUP; ucIndex++) - { - if (uiTechnicalDataSet[ucIndex]<sLRTSGroup[ucIndex].uiMin || uiTechnicalDataSet[ucIndex]>sLRTSGroup[ucIndex].uiMax) - { - uiTechnicalDataSet[ucIndex]=sLRTSGroup[ucIndex].uiDefault; - fError=TRUE; - //break; - } - } - - if (fError==TRUE) - uiFlagsAlarm[ALARM_FLAGS2]|=TECHNICAL_SETTINGS_RANGE_ALARM_MASK; - else - uiFlagsAlarm[ALARM_FLAGS2]&=(~TECHNICAL_SETTINGS_RANGE_ALARM_MASK); -} - - -/******************************************************************************* -* Function Name : CheckFlowLUTRange -* Description : Check the flow LUT -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void CheckFlowLUTRange(void) -{ - u16 uiIndex; - bool fError=FALSE; - - if (stLUTFlowSensor.uiLUT_TableSize<(FLOW_CALIB_NUMBER_OF_SAMPLES>>1) || stLUTFlowSensor.uiLUT_TableSize>FLOW_CALIB_NUMBER_OF_SAMPLES) - { - ApplyDefaultFlowLUT(); - fError=TRUE; - } - else - { - for (uiIndex=1; uiIndex<stLUTFlowSensor.uiLUT_TableSize; uiIndex++) - { - if (stLUTFlowSensor.uiFlowValue[uiIndex]<=stLUTFlowSensor.uiFlowValue[uiIndex-1] || - stLUTFlowSensor.uiFlowSensorTicks[uiIndex]<=stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]) - { - ApplyDefaultFlowLUT(); - fError=TRUE; - break; - } - } - } - - if (fError==TRUE) - uiFlagsAlarm[ALARM_FLAGS2]|=NO_FLOW_LUT_ALARM_MASK; - else - uiFlagsAlarm[ALARM_FLAGS2]&=(~NO_FLOW_LUT_ALARM_MASK); -} - - -/******************************************************************************* -* Function Name : ApplyDefaultFlowLUT -* Description : Apply default value for the flow LUT -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ApplyDefaultFlowLUT(void) -{ - u16 uiIndex; - - stLUTFlowSensor.uiLUT_TableSize=stDefaultLUTFlowSensor.uiLUT_TableSize; - for (uiIndex=0; uiIndex<FLOW_CALIB_NUMBER_OF_SAMPLES; uiIndex++) - { - stLUTFlowSensor.uiFlowValue[uiIndex]=stDefaultLUTFlowSensor.uiFlowValue[uiIndex]; - stLUTFlowSensor.uiFlowSensorTicks[uiIndex]=stDefaultLUTFlowSensor.uiFlowSensorTicks[uiIndex]; - } -} - - -/******************************************************************************* -* Function Name : ReturnDefaultTubeConfiguration -* Description : The default tubing configuration according to the current ventilation mode -* Input : a ventilation mode -* Output : None -* Return : The tube configuration -*******************************************************************************/ -u16 ReturnDefaultTubeConfiguration(u16 uiMode) -{ - u8 ucIndex; - - for (ucIndex=0; ucIndex<NUMBER_OF_TUBE_CONFIGURATION; ucIndex++) - { - if (ucTubeConfigurationTable[ucIndex][uiMode]==TUBE_DEFAULT) - { - return(ucIndex); - } - } - return(0); -} - - -/******************************************************************************* -* Function Name : ApplyAllDefaultValues -* Description : Apply all default values in the technical and settings zones -* : BE CARFUL this function call "ControlHW" function -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void ApplyAllDefaultValues(void) -{ - // Init ventilation settings - ApplyDefaultValueToTemporaryVentilationSettings(); - - // Init technical settings - ApplyDefaultValueToTechnicalSettings(); - - // Init flow LUT - ApplyDefaultFlowLUT(); - - // Default value for the device/patient time counter - ulDeviceTimeCounter=0; - ulPatientTimeCounter=0; - - // Default value for the blower revolution counter - ulBlowerRevolutionCounter=0; - - bComputeOffsetSensors=TRUE; -} -#endif // C_M3_DEVICETEST_TARGET - -/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ - - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ventilation.txt Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,3355 @@ + +/* Includes ------------------------------------------------------------------*/ +#define EXTERN extern +#include <stdlib.h> +#include <string.h> +#include "SS.h" +#include "main.h" +#include "_SS_OnOffActioner.h" +#include "_SS_Pwm.h" +#include "Monitoring.h" +#include "Safety.h" +#include "_SS_Data_Logging.h" +#include "_SS_Record_Settings.h" +#include "_SS_I2CX_SDP600.h" +#include "_SS_I2CX_X201641.h" +#include "_SS_OptimaComm.h" +#undef EXTERN + +#define INIT_VARIABLES +#define EXTERN +#include "Ventilation.h" +#undef EXTERN +#undef INIT_VARIABLES + + +/* Internal constants --------------------------------------------------------*/ +// ******************* Min-max PI or PDF *************************************** +#define MAX_VOLTAGE_REF MAX_PI_OUTPUT // MAX_PI_OUTPUT = 1343 = 18.5micros = 93.3%, want 80% +#define MIN_VOLTAGE_REF MIN_PI_OUTPUT +#define INTEGRAL_MAX (2147483647) +#define INTEGRAL_MIN (-2147483648) + + +#ifndef C_M3_DEVICETEST_TARGET + /* Internal variables --------------------------------------------------------*/ + // ******************* MANAGED CONSTANT SPEED **************************** + static u16 uiBlowerSpeedSetting; + static int32_t lIntegral_Speed_I; + static bool bMaxPIOutputSpeedI; + static bool bMinPIOutputSpeedI; + + + // ************* MANAGED BAROMETRIC VENTILATION ************************* + static u16 uiIpapSettingTemp; + static u16 uiTeBaroSet; + static int32_t lIntegral_Pressure_I; + static bool bMaxPIOutputPressureI; + static bool bMinPIOutputPressureI; + static u16 uiTiD; + static u8 ucIndexTableSlope; + #define TEMPO_TRIGGER_EXPI 30 + static u8 ucTempoTriggerExpiAuto; + #define MIN_THRESHOLD_EXPI_TRIGGER_AUTO 25 + static u8 ucExpiTriggerTreshold; + static u8 fFirstCycleInspi; + + // ----------- Main blower management during expiration ------------------- + static u16 uiPWMatTheEndOfInspiration; + static bool fFirstCycleExpi; + static u16 uiEpapSettingTemp; + static int32_t lIntegral_Pressure_E; + static bool bMaxPIOutputPressureE; + static bool bMinPIOutputPressureE; + static u16 uiPWMatTheEndOfExpiration; + static u16 uiTeD; + static bool fBlockCloseLoop; + + static u16 uiTiTyp; + + // ************* MANAGED VOLUMETRIC VENTILATION ************************* + static u32 ulMaxIFlowSet; + static u32 ulMinIFlowSet; + static u32 ulDecFlowStep; + static u16 uiTeVoluSet; + static u16 uiProximalPressureAtTheEndOfInspiration; + static int32_t lIntegral_Flow_I; + static bool bMaxPIOutputFlowI; + static bool bMinPIOutputFlowI; + static int16_t iVtAdjust=0; + static u8 ucCounterHPAlarm=0; + + + // ******************* MANAGED_CPAP_VENTILATION ****************************** + #define EXPIRATORY_DISCONNECTION_TIME_OUT 500 // 500ms + #define CPAP_DISCONNECTION_TEST_PERIODICITY 4000 // 4s + static u16 uiDisconnectionTime; + static u16 uiDisconnectionTimeInCPAP; + static u16 uiMemoPWMDuringDisconnection; + //static u8 ucStandByMode; + + // ***************** MANAGED INSPIRATORY TRIGGER ***************************** + #define MAX_DELTA_FLOW 100 // 1 l/min + #define SIZE_DELTA_INSPIRATORY_FLOW_BUFFER 40 + #define NUMBER_TRIGGER_VALID 20 + #define NUMBER_MIN_FLOW_VALUE 30 + //static int16_t iBufferIFlowDelta[SIZE_DELTA_INSPIRATORY_FLOW_BUFFER]; + static u8 ucInspiTriggerScheduler; + static u8 ucMinFlowCounter; + static int16_t iInspiratoryFlowMin; + //static int16_t iOldInspiratoryFlowSmoothingMesForTrigger; + #define SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER 250 + static int16_t iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER]; + // static int16_t iBufferConductance[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER]; + static u8 ucCounterTriggerValid; + static int16_t iFlowBaseLineReference; + static bool bDetectionConstantFlow; + + + // *********************** MANAGED MONITORING FOR MLT ************************ + static u16 uiMLT_PressureSetPoint; + #ifdef MOTOR_LIFE_TESTING + #define MLT_AVERAGE_MONITORING 1000 + static u16 uiAverageMonitoringMLT; + static u32 ulMLT_SumSpeedMes; + static u32 ulMLT_SumCurrentMes; + static u32 ulMLT_SumTemperatureMes; + static u32 ulMLT_SumBlowerVoltage; + static u16 uiMLT_EnableAlarm; + #endif // #ifdef MOTOR_LIFE_TESTING + + + // ************************ MANAGED CALIBRATION ****************************** + typedef enum + { + INIT_FLOW_CALIB_TEST=0, + SET_GAS_TYPE, + SET_GAS_STANDARD, + START_FLOW_READING, + SEND_FLOW_COMMAND, + READ_FLOW_VALUE, + SEND_HIGH_FLOW_CALIB_REQUEST, + WAIT_FOR_HIGH_FLOW_CALIB_ACK, + PREPARE_FAILURE_COMMAND, + PREPARE_SUCCESS_COMMAND, + SEND_COMMAND_TO_PF300, + CHECK_COMMAND_FROM_PF300, + END_OF_CALIBRATION, + } type_enLowFlowCalibrationStep; + + typedef enum + { + INIT_PRESSURE_CALIB_TEST=0, + START_PRESSURE_READING, + SEND_PRESSURE_COMMAND, + READ_PRESSURE_VALUE, + PRESSURE_CALIB_FAILURE_COMMAND, + PRESSURE_CALIB_SUCCESS_COMMAND, + PRESSURE_CALIB_SEND_COMMAND_TO_PF300, + PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300, + PRESSURE_CALIB_END_OF_CALIBRATION, + } type_enPressureCalibrationStep; + + #define SIZE_BUFFER_FLOW_VALUE 15 + typedef struct + { + unsigned char ucIndex; + bool bFirstPartOfTheCRReceived; + char szValue[SIZE_BUFFER_FLOW_VALUE]; + } type_stFlow; + + // Flow and pressure calibration + #define TIME_OUT_RECEPTION_PACKET_FROM_PF300 2000 // 2s + #define SAMPLE_RATE_BETWEEN_TWO_FLOW 5000 // 5s + #define SIZE_RX_BUFFER_PF300 20 + static u16 uiCalibrationTimeOut; + static unsigned char ucIndexAnswerFromPF300; + static char szAnswerFromPF300[SIZE_RX_BUFFER_PF300]; + static char szExpectedAnswerFromPF300[SIZE_RX_BUFFER_PF300]; + static u8 ucNumberOfBytesToCheckFromPF300Answer; + + // Flow calibration + static type_enLowFlowCalibrationStep enLowFlowCalibrationStep; + static type_enLowFlowCalibrationStep enGoBackToStep; + static unsigned long ulSumFlowTicks; + static unsigned int uiFlowTicksSamplesCounter; + //static type_stLUTFlowSensor stTemporayLUTFlowSensor; + static bool bHighFlowCalibrationInProgress; + static unsigned int uiMotorDutyCyleForFlowCalib; + static unsigned int uiImHereMsgTimer; + + // Pressure calibration + #define SAMPLE_RATE_BETWEEN_TWO_PRESSURE 10000 // 30s + static type_enPressureCalibrationStep enPressureCalibrationStep; + static type_enPressureCalibrationStep enPressureCalibGoBackToStep; + static u32 ulSumPressureTicks; + static u16 uiPressureTicksSamplesCounter; + + // List of command to PF300 + static const char szPF300_CmdSwitchOffEcho[]={"%CM#5$0\r"}; // Command Echo from PF300 off + static const char szPF300_AnswerSwitchOffEcho[]={"%CM#5"}; // Answer echo off from PF300 (WO \r) + static const char szPF300_SetAirGasType[]={"%WS#1$0\r"}; // command Air + static const char szPF300_AnswerAirGasType[]={"%WS#1$0"}; // Answer Air + static const char szPF300_SetGasStandard[]={"%WS#3$1\r"}; // Command STPD + static const char szPF300_AnswerGasStandard[]={"%WS#3$1"}; // Answer STPD + static const char szPF300_ReadLowFlowCmd[]={"%RM#1\r"}; // Command read low flow + static const char szPF300_ReadLowFlowAnswer[]={"%RM#1$"}; // Answer read low flow + static const char szPF300_ReadHighFlowCmd[]={"%RM#0\r"}; // Command read high flow + static const char szPF300_ReadHighFlowAnswer[]={"%RM#0$"}; // Answer read high flow + static const char szPF300_ReadPdiffCmd[]={"%RM#3\r"}; // Command read pressure diff. + static const char szPF300_ReadPdiffAnswer[]={"%RM#3$"}; // Answewr read pressure diff. + + // List of Command to Handset + static const char szRequestHighFlowCalib[]={"@N"}; + static const char szEndOfCalibOK[]={"@S"}; + static const char szImHere[]={"@*"}; + + + // ---------------- Management FRAM for settings ----------------------------- + #ifdef RECORD_SETTINGS + #endif // RECORD_SETTINGS + + // -------------------- Manage Motor starting -------------------------------- + #ifndef TEMPERATURE_TRENDS + static u8 ucStartVentilationScheduler=0; + #endif + static enMaroubraModes enPreviousMode; + static u16 uiPreviousDeviceMode; +#endif // C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET + #define SIZE_SLOPE2_TABLE 21 + const unsigned char ucSlope2Table[SIZE_SLOPE2_TABLE]= { + 0, 35, 50, 59, 65, 70, 74, 77, 80, 83, + 85, 87, 89, 91, 92, 94, 95, 96, 98, 99, + 100 }; + + // Table pente inspiratoire 2 + #define SIZE_SLOPE3_TABLE 41 + const unsigned char ucSlope3Table[SIZE_SLOPE3_TABLE]= { + 0, 20, 35, 44, 50, 55, 59, 62, 65, 68, 70, + 72, 74, 76, 77, 79, 80, 81, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, + 96, 96, 97, 98, 98, 99, 99, 100 }; + + // Table pente inspiratoire 3 + #define SIZE_SLOPE4_TABLE 61 + const unsigned char ucSlope4Table[SIZE_SLOPE4_TABLE]= { + 0, 11, 26, 35, 41, 46, 50, 53, 56, 59, 61, + 63, 65, 67, 68, 70, 71, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 83, 84, 85, 86, 86, + 87, 88, 88, 89 ,90, 90, 91, 91, 92, 92, 93, + 93, 94, 94, 95, 95, 96, 96, 96, 97, 97, 98, + 98, 99, 99, 99, 100, 100 }; + + + // Maximum allowed flow in expiration Flow=f(PEEP set) (example: flow-by max=29L/min @ 5hPa) + const u16 uiMaximumFlowInExpiration[41]={ + 0, 1300, 1830, 2250, 2600, 2900, 3180, 3430, 3670, 3900, + 4110, 4310, 4500, 4680, 4860, 5030, 5200, 5360, 5510, 5660, + 5810, 5950, 6090, 6230, 6360, 6500, 6620, 6750, 6870, 7000, + 7120, 7230, 7350, 7460, 7580, 7690, 7800, 7900, 8010, 8110, 8220 + }; +#endif // C_M3_DEVICETEST_TARGET + + +/* Internal functions --------------------------------------------------------*/ +#ifndef C_M3_DEVICETEST_TARGET + u16 ComputeTe(u16 uiF, u16 uiTi); + void ComputeInspiratoryFlowSetPointInAVC(u16 uiTypeOfPatient, u16 uiVtc, u16 uiTi, u16 uiFlowShape, u32 *ulMaxFlow, u32 *ulMinFlow, u32 *ulFlowStep); + unsigned char TestTriggerExpiratoire(unsigned char ucValeurSeuil, unsigned int uiPressureSetting); + bool TestInspiratoryTrigger(bool bSpont, u16 uiTe, u16 uiFlowThreshold); + int16_t UpdateInspiratoryFlowAverage(void); + int16_t UpdateInspiratoryConductanceAverage(void); + void ResetInspiratoryConductanceAverage(void); + bool TestInspiratorySlowTrigger(int16_t iTheFlowBaseLine, u16 uiFlowTreshold); + void ApplyDefaultValueToTemporaryVentilationSettings(void); + void ApplyDefaultValueToTechnicalSettings(void); + void ApplyAllDefaultValues(void); + bool ApplyNewVentilationMode(void); + void ApplyDefaultFlowLUT(void); + void CheckFlowLUTRange(void); + void ManageFlowCalibration(void); + void ManagePressureCalibration(void); + void ManageCstPressure(void); +#endif // C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : InitSettings +* Description : Initialize parameters for ventilation +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void InitSettings(void) +{ + uiPreviousDeviceMode=0xFF; + enPreviousMode=NUMBER_OF_MODE; + + // --- Init Settings + uiTechnicalDataMes[SW_VERSION_TEC_MES]=MAROUBRA_BLOWER_SW_VERSION; + bComputeOffsetSensors=FALSE; + + #ifdef RECORD_SETTINGS + // Read and init FRAM + if (InitSettingsZoneAndTechnicalZoneInFRAM()==OPSTATUS_OK) + { + if (ReadSettingsZoneAndTechnicalZoneInFRAM()==OPSTATUS_FAIL) + { + uiFlagsAlarm[ALARM_FLAGS2]|=FRAM_FAILURE_ALARM_MASK; + ApplyAllDefaultValues(); + } + } + else + { + uiFlagsAlarm[ALARM_FLAGS2]|=FRAM_FAILURE_ALARM_MASK; + ApplyAllDefaultValues(); + } + #else + ApplyAllDefaultValues(); + #endif + + // Compute offsets sensors if necessary + if (bComputeOffsetSensors==TRUE) + { + // ------ Update Blower Flow sensor offset before ventilation ------- + #ifdef SDP600_USED_I2C1_BUS + SDP600_ComputeOffsetFlowSensorOnI2C1(SDP600_BLOWER_FLOW_SENSOR); + #endif // SDP600_USED_I2C1_BUS + + #ifdef X201641_USED_I2C1_BUS + X201641_ComputeOffsetFlowSensorOnI2C1(X201641_BLOWER_FLOW_SENSOR); + #endif // X201641_USED_I2C1_BUS + + // ----- Update Proximal Pressure sensor offset before ventilation ------- + ComputeOffsetProximalPressureSensor(); + } + + // Check Technical settings range + CheckTechnicalSettingsRange(); + + // Check Flow LUT + CheckFlowLUTRange(); + + // Check temporary ventilation setting range + if (CheckTemporaryVentilationSettingRange()==OPSTATUS_FAIL) + { + ApplyDefaultValueToTemporaryVentilationSettings(); + uiFlagsAlarm[ALARM_FLAGS2]|=VENTILATION_SETTINGS_RANGE_ALARM_MASK; + } + + // --- Update computed settings (Te,...) + UpdateSettings(); + + #ifdef MOTOR_LIFE_TESTING + uiTechnicalDataSet[DEVICE_MODE_TEC]=PRESSURE_CST_MODE; + uiTechnicalDataSet[START_STOP_VENTILATION]=1; + #endif +} + + +/******************************************************************************* +* Function Name : InitVentilation +* Description : Initialize variables for ventilation +* Function called : +* - when we start ventilation +* - when we change of ventilation mode +* - when we change of device mode +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void InitVentilation(void) +{ + ucVentilationCycle=EXPIRATION_CYCLE; + uiTiD=0; + uiTeD=0; + uiTiTyp = 1000; + bManualBreath=FALSE; + + if (enPreviousMode==NUMBER_OF_MODE) + { + // Start ventilation + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + uiDisconnectionTimeInCPAP=CPAP_DISCONNECTION_TEST_PERIODICITY; + uiMemoPWMDuringDisconnection=0; + fBlockCloseLoop=FALSE; + } + + ClearAllVentilationAlarms(); + ClearAllMeasures(); + + switch(uiTechnicalDataSet[DEVICE_MODE_TEC]) + { + default: + case VENTILATION_MODE: + { + if (enVentilationMode==APCV_MODE || enVentilationMode==PS_MODE) + { + if (enPreviousMode==APCV_MODE || enPreviousMode==PS_MODE) + { + // --- We are already in pressure mode + } + else + { + // --- Start a pressure mode + fFirstCycleInspi=TRUE; + uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; + + if (enPreviousMode!=AVC_MODE) + { + uiPWMatTheEndOfExpiration=MIN_VOLTAGE_REF; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE=FALSE; + bMinPIOutputPressureE=FALSE; + fFirstCycleExpi=TRUE; + } + } + } + else if (enVentilationMode==AVC_MODE) + { + iVtAdjust=0; + fFirstCycleInspi=TRUE; + uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; + + if (enPreviousMode!=APCV_MODE && enPreviousMode!=PS_MODE) + { + uiPWMatTheEndOfExpiration=MIN_VOLTAGE_REF; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE=FALSE; + bMinPIOutputPressureE=FALSE; + fFirstCycleExpi=TRUE; + } + } + else if (enVentilationMode==CPAP_MODE) + { + Ki_Pressure_I=1000; + uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; + lIntegral_Pressure_I=0; + bMaxPIOutputPressureI=FALSE; + bMinPIOutputPressureI=FALSE; + } + break; + } + case ONE_CST_PWM_MODE: + { + uiInspirationBlowerPWMTec=250; + break; + } + case TWO_CST_PWM_MODE: + { + uiInspirationBlowerPWMTec=350; + uiExpirationBlowerPWMTec=150; + break; + } + case CST_SPEED_MODE: + { + uiBlowerSpeedSet=15000; + uiBlowerSpeedSetting=5000; + break; + } + case FLOW_CAL_MODE: + { + enLowFlowCalibrationStep=INIT_FLOW_CALIB_TEST; + bHighFlowCalibrationInProgress=FALSE; + stTemporayLUTFlowSensor.uiLUT_TableSize=0; + uiCalibrationTimeOut=(TIME_OUT_BLOWER_HANDSET_COMM*20); // 2s + break; + } + case PRESSURE_CAL_MODE: + { + enPressureCalibrationStep=INIT_PRESSURE_CALIB_TEST; + uiCalibrationTimeOut=(TIME_OUT_BLOWER_HANDSET_COMM*20); // 2s + break; + } + case PRESSURE_CST_MODE: + { + uiMLT_PressureSetPoint=10; + lIntegral_Pressure_I=0; + bMaxPIOutputPressureI=FALSE; + bMinPIOutputPressureI=FALSE; + + #ifdef MOTOR_LIFE_TESTING + uiMLT_EnableAlarm=5000; // 5s before enabling alarm + uiAverageMonitoringMLT=MLT_AVERAGE_MONITORING; + ulMLT_SumSpeedMes=0; + ulMLT_SumCurrentMes=0; + ulMLT_SumTemperatureMes=0; + ulMLT_SumBlowerVoltage=0; + #endif // #ifdef MOTOR_LIFE_TESTING + break; + } + } + enPreviousMode=enVentilationMode; +} + + +/******************************************************************************* +* Function Name : StopAllActuators +* Description : Stop all actuators +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void StopAllActuators(void) +{ + // Stop main blower + SS_Xclose(mdrv); + + // Valve OFF + SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_OFF); +} + +/******************************************************************************* +* Function Name : CalculateHoseDrop +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +u16 CalculateHoseDrop(void) +{ + u16 hoseDrop = (u16)(10*(iBlowerFlowSmoothingMes/100.0f/60.0f * 0.5f)); + return hoseDrop; +} + +/******************************************************************************* +* Function Name : ManageCPAPVentilation +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageCPAPVentilation(void) +{ + + + + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + // **************************** Cycle detection ****************************** + // Test Synchronisation + /*if (iBlowerFlowSmoothingMesForTrigger<(-500) && ucVentilationCycle==INSPIRATION_CYCLE) + ucVentilationCycle=EXPIRATION_CYCLE; */ + int32_t peakP = 2;//(int32_t)uiVentilationSet[PS_CPAP_SET]; + // Cycle detection + if (ucVentilationCycle==INSPIRATION_CYCLE) + { + uiTiD++; + if(uiTiD < (0.1f * uiTiTyp)) + { + peakP =(int32_t)( uiVentilationSet[PS_CPAP_SET] * ((uiTiD* 1.0f)/(0.1f * uiTiTyp))); + } + else if(uiTiD < (1.0f * uiTiTyp)) + { + peakP = ((int32_t)uiVentilationSet[PS_CPAP_SET] - ((int32_t)(uiVentilationSet[PS_CPAP_SET] * (uiTiD * 1.0f)/(1.1f * uiTiTyp)))) + 20; + } + else + { + peakP = 2; + } + + if (uiTiD>5000 || (uiTiD>TiBaroSet_P_MIN && TestTriggerExpiratoire(20, uiVentilationSet[PS_CPAP_SET])==TRUE)) + { + ucVentilationCycle=EXPIRATION_CYCLE; + uiPWMatTheEndOfInspiration = uiInspirationBlowerPWMTec; + if(uiTiD < 2000) + { + uiTiTyp = uiTiD; + } + else + { + uiTiTyp = 2000; + } + + uiTeD=0; + } + } + else + { + uiTeD++; + if (uiTeD>TE_SET_MAX) uiTeD=TE_SET_MAX; + + if (TestInspiratoryTrigger(TRUE, uiTeD, 15)==TRUE) + { + ucVentilationCycle=INSPIRATION_CYCLE; + uiTiD=0; + } + } + + // Barometric Mode : error computation + ControlPressure((int32_t)(peakP + CalculateHoseDrop())); +} + +/******************************************************************************* +* Function Name : ControlPressure +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +int32_t previousError = 0; +int32_t lIntegralSum = 0; +void ControlPressure(int32_t setPressure)//pressure in cmH2O*10 +{ + int32_t lPropTerm; + int32_t lIntegralTerm; + int32_t lDerivativeTerm; + int32_t lOutputPressure; + + + int32_t lError = setPressure - uiProximalPressureMes; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; + lIntegralTerm += (int32_t)(uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I] * lError); + lDerivativeTerm = (int32_t)(uiTechnicalDataSet[KP_FLOW_I]*(lError - previousError/1000)); + previousError = lError; + + // Close loop in pressure + if ((lIntegralTerm + lIntegralSum) > INTEGRAL_MAX) + { + lIntegralSum = INTEGRAL_MAX; + } + else if ((lIntegralTerm - lIntegralSum)< INTEGRAL_MIN) + { + lIntegralSum = INTEGRAL_MIN; + } + else + { + lIntegralSum += lIntegralTerm; + } + + lOutputPressure = (lDerivativeTerm>>19) + (lIntegralSum>>16) + (lPropTerm>>13) ; + + lOutputPressure+=uiPWMatTheEndOfInspiration; + + + // Limit and Update blower PWM + if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiInspirationBlowerPWMTec = lOutputPressure; + } + + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + +} + + +/******************************************************************************* +* Function Name : DavidCControlPressure +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void DavidCControlPressure(int32_t setPressure)//pressure in cmH2O*10 +{ + int32_t lPropTerm; + int32_t lIntegralTerm; + int32_t lOutputPressure; + u16 uiFlowMaxInExpi; + int32_t lError = setPressure - uiProximalPressureMes; + + lIntegralTerm = (int32_t)Ki_Pressure_I * lError; + if (Ki_Pressure_I<uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I]) + { + Ki_Pressure_I++; + } + + // Close loop in pressure + if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm) <0) + lIntegral_Pressure_I = INTEGRAL_MAX; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm)>0) + lIntegral_Pressure_I = INTEGRAL_MIN; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) + lIntegral_Pressure_I += lIntegralTerm; + else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) + lIntegral_Pressure_I += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; + + lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); + + lOutputPressure+=uiPWMatTheEndOfInspiration; + + // Flow limiting + uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; + if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) + { + // Impossible to maintain the peep (patient disconnection) + if (uiDisconnectionTime==0) + { + if (fBlockCloseLoop==FALSE) + uiDisconnectionTimeInCPAP=CPAP_DISCONNECTION_TEST_PERIODICITY; + fBlockCloseLoop=TRUE; // Block the close loop + if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value + uiInspirationBlowerPWMTec=uiMemoPWMDuringDisconnection; + else + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + uiDisconnectionTime--; + } + else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) + { + // Good pressure : no disconnection + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + + if (fBlockCloseLoop==TRUE) + { + // The close loop was block before => unblock it + fBlockCloseLoop=FALSE; + lIntegral_Pressure_I=0; + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; + return; + } + else if (iBlowerFlowSmoothingMes>=0) + { + // Record current PWM + uiMemoPWMDuringDisconnection=uiInspirationBlowerPWMTec; + } + } + + // Unblock the close loop every 4s in case of none recorded PWM value + if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiDisconnectionTimeInCPAP==0) + { + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + fBlockCloseLoop=FALSE; + lIntegral_Pressure_I=0; + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; + return; + } + + // Update Time counters + if (uiDisconnectionTimeInCPAP!=0) + uiDisconnectionTimeInCPAP--; + + // Update blower PWM + if (fBlockCloseLoop==TRUE) + { + bMaxPIOutputPressureI = TRUE; + } + else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiInspirationBlowerPWMTec = lOutputPressure; + } + + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + +} + +/******************************************************************************* +* Function Name : ManageOneCstPWM +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageOneCstPWM(void) +{ + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + // Update Blower Speed + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); +} + + +/******************************************************************************* +* Function Name : Manage2CstPWM +* Description : Manage Ti, Te, DAC, Blower, PID +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void Manage2CstPWM(void) +{ + if (ucVentilationCycle==INSPIRATION_CYCLE) + { + // ------------- INSPIRATION ------------ + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + + // Inspiratoy time + uiTiD++; + if (uiTiD>=uiVentilationSet[TI_BARO_SET]) + { + ucVentilationCycle=EXPIRATION_CYCLE; + uiTiD=0; + } + } + else + { + // ------------- EXPIRATION ------------ + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); + + // Expiratoy time + uiTeD++; + if (uiTeD>=uiTeBaroSet) + { + ucVentilationCycle=INSPIRATION_CYCLE; + uiTeD=0; + } + } +} + + +/******************************************************************************* +* Function Name : ManageCstSpeed +* Description : Manage constant speed ventilation +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageCstSpeed(void) +{ + int32_t lError; + int32_t lPropTerm; + int32_t lIntegralTerm; + int32_t lOutputSpeed; + + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + // Update settings + if (uiBlowerSpeedSetting<uiBlowerSpeedSet) + uiBlowerSpeedSetting+=10; + else if (uiBlowerSpeedSetting>uiBlowerSpeedSet) + uiBlowerSpeedSetting-=10; + + uiTiD++; + if ((uiTiD%10)==0) + { + // Barometric Mode : error computation + lError=(int32_t)uiBlowerSpeedSetting-(int32_t)uiBlowerSpeedMes; + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_SPEED_I_TEC] * lError; + + // Close loop in pressure + if ((lIntegral_Speed_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputSpeedI==FALSE)) + { + if ((lIntegral_Speed_I + lIntegralTerm) <0) + lIntegral_Speed_I = INTEGRAL_MAX; + else + lIntegral_Speed_I += lIntegralTerm; + } + else if ((lIntegral_Speed_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputSpeedI==FALSE)) + { + if ((lIntegral_Speed_I + lIntegralTerm)>0) + lIntegral_Speed_I = INTEGRAL_MIN; + else + lIntegral_Speed_I += lIntegralTerm; + } + else if ((lIntegral_Speed_I<=0) && (lIntegralTerm>=0)) + lIntegral_Speed_I += lIntegralTerm; + else if ((lIntegral_Speed_I>=0) && (lIntegralTerm<=0)) + lIntegral_Speed_I += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_SPEED_I_TEC] * lError; + lOutputSpeed = (lIntegral_Speed_I>>16) + (lPropTerm>>13); + + if (lOutputSpeed>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputSpeedI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputSpeed<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputSpeedI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputSpeedI = FALSE; + bMinPIOutputSpeedI = FALSE; + uiInspirationBlowerPWMTec = lOutputSpeed; + } + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + } +} + +/******************************************************************************* +* Function Name : ManageFlowCalibration +* Description : Manage Low flow calibration +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageFlowCalibration(void) +{ + char cCharValue; + char szTempBuf[SIZE_RX_BUFFER_PF300]; + + /* + #ifdef USE_TSI_4040 + switch(enTSICommScheduler) + { + default: + case TSI_SET_TYPE_OF_GAS: + { + // Send Type of Gas command + ucTSICommand=TSI_SEND_GAS_TYPE_AIR_CMD; + if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) + { + enTSICommScheduler=TSI_CHECK_ANSWER; + enTSIGoBackToStep=TSI_SET_FLOW_UNIT; + } + break; + } + case TSI_SET_FLOW_UNIT: + { + // Send Type of Gas command + ucTSICommand=TSI_SEND_FLOW_UNIT_STANDARD_CMD; + if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) + { + enTSICommScheduler=TSI_CHECK_ANSWER; + enTSIGoBackToStep=TSI_SET_SAMPLE_TIME; + } + break; + } + case TSI_SET_SAMPLE_TIME: + { + // Send sample time + ucTSICommand=TSI_SEND_SAMPLE_TIME_10MS_CMD; + if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) + { + enTSICommScheduler=TSI_CHECK_ANSWER; + enTSIGoBackToStep=TSI_READ_FLOW; + } + break; + } + case TSI_READ_FLOW: + { + // Send sample time + ucTSICommand=TSI_SEND_READ_FLOW_CMD; + if (SS_Xputdw(tsi, &ucTSICommand)==TRUE) + { + enTSICommScheduler=TSI_CHECK_ANSWER; + enTSIGoBackToStep=TSI_CYCLE_DETECTION; + } + break; + } + case TSI_CYCLE_DETECTION: + { + uiBlowerFlow=iFlowFromTSI; + break; + } + case TSI_CHECK_ANSWER: + { + opstatus=SS_Xgetw(tsi, &uiDummy); + if (opstatus==OPSTATUS_OK) + { + enTSICommScheduler=enTSIGoBackToStep; + } + else if (opstatus==OPSTATUS_FAIL) + { + enTSICommScheduler=TSI_SET_TYPE_OF_GAS; + } + break; + } + } + #endif // #ifdef USE_TSI_4040 + */ + + switch(enLowFlowCalibrationStep) + { + case INIT_FLOW_CALIB_TEST: + { + // Init comm with PF300 => wait 2s before sending first command to PF300 + // We need to wait for this delay in order to the handset to activate its transparent mode + if (uiCalibrationTimeOut==0) + { + bDisableMaroubraCommCommunication=TRUE; + + // Prepare command to PF300 + UpdateBufferToSend((char*)szPF300_CmdSwitchOffEcho); + enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; + strcpy(szExpectedAnswerFromPF300, szPF300_AnswerSwitchOffEcho); + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerSwitchOffEcho); + enGoBackToStep=SET_GAS_TYPE; + } + else + { + uiCalibrationTimeOut--; + } + break; + } + case SET_GAS_TYPE: + { + // Prepare command to PF300 + UpdateBufferToSend((char*)szPF300_SetAirGasType); + enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; + strcpy(szExpectedAnswerFromPF300, szPF300_AnswerAirGasType); + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerAirGasType); + enGoBackToStep=SET_GAS_STANDARD; + break; + } + case SET_GAS_STANDARD: + { + // Prepare command to PF300 + UpdateBufferToSend((char*)szPF300_SetGasStandard); + enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; + strcpy(szExpectedAnswerFromPF300, szPF300_AnswerGasStandard); + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerGasStandard); + enGoBackToStep=START_FLOW_READING; + break; + } + case START_FLOW_READING: + { + // Set Min blower speed + uiMotorDutyCyleForFlowCalib=MIN_PI_OUTPUT; + SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); + + // Init variable for flow sensor + uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_FLOW; + ulSumFlowTicks=0; + uiFlowTicksSamplesCounter=0; + + // Next step + enLowFlowCalibrationStep=SEND_FLOW_COMMAND; + break; + } + case SEND_FLOW_COMMAND: + { + if (uiCalibrationTimeOut!=0) + { + uiCalibrationTimeOut--; + + if (uiCalibrationTimeOut<(SAMPLE_RATE_BETWEEN_TWO_FLOW>>1)) + { + ulSumFlowTicks+=uiBlowerFlowRAWMes; + uiFlowTicksSamplesCounter++; + } + } + else + { + // Prepare next command (Read Low Flow) + enLowFlowCalibrationStep=SEND_COMMAND_TO_PF300; + if (bHighFlowCalibrationInProgress==FALSE) + { + UpdateBufferToSend((char*)szPF300_ReadLowFlowCmd); // %RM#1\r + strcpy(szExpectedAnswerFromPF300, szPF300_ReadLowFlowAnswer); // %RM#1$ + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadLowFlowAnswer); + } + else + { + UpdateBufferToSend((char*)szPF300_ReadHighFlowCmd); // %RM#0\r + strcpy(szExpectedAnswerFromPF300, szPF300_ReadHighFlowAnswer); // %RM#0$ + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadHighFlowAnswer); + } + enGoBackToStep=READ_FLOW_VALUE; + } + break; + } + case READ_FLOW_VALUE: + { + if (uiFlowTicksSamplesCounter!=0) + { + // Read PF300 flow (l/min) + strcpy(szTempBuf, &szAnswerFromPF300[ucNumberOfBytesToCheckFromPF300Answer]); + + // Store value of flow + if (stTemporayLUTFlowSensor.uiLUT_TableSize<LOW_FLOW_CALIB_NUMBER_OF_SAMPLES) + stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]=(unsigned int)atoi(szTempBuf); + else + stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]=(unsigned int)atoi(szTempBuf)*10; + + // Store ticks value + stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize]=ulSumFlowTicks/uiFlowTicksSamplesCounter; + uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_FLOW; + ulSumFlowTicks=0; + uiFlowTicksSamplesCounter=0; + + // Check if current flow <0.1l/min + if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<10) + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + break; + } + + // Check if the last low flow is higher than 20l/min or lower than 2l/min + if (stTemporayLUTFlowSensor.uiLUT_TableSize==(LOW_FLOW_CALIB_NUMBER_OF_SAMPLES-1)) + { + // Check if the last low flow is higher than 20l/min or lower than 2l/min + if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]>2000 || stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<200) + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + break; + } + } + + // Next flow sample + if (stTemporayLUTFlowSensor.uiLUT_TableSize==LOW_FLOW_CALIB_NUMBER_OF_SAMPLES && stTemporayLUTFlowSensor.uiFlowValue[LOW_FLOW_CALIB_NUMBER_OF_SAMPLES]<(stTemporayLUTFlowSensor.uiFlowValue[LOW_FLOW_CALIB_NUMBER_OF_SAMPLES-1]+500)) + { + // No enough flow margin between the last value of the low flow and the first value of the high flow + } + else if (stTemporayLUTFlowSensor.uiLUT_TableSize!=0 && stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize]<(stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize-1]+50)) + { + // No enough margin between two consecutives flow + } + else if (stTemporayLUTFlowSensor.uiLUT_TableSize!=0 && stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize]<=stTemporayLUTFlowSensor.uiFlowSensorTicks[stTemporayLUTFlowSensor.uiLUT_TableSize-1]) + { + // Same or less ticks between two consecutives flow + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + break; + } + else + { + stTemporayLUTFlowSensor.uiLUT_TableSize++; + if (stTemporayLUTFlowSensor.uiFlowValue[stTemporayLUTFlowSensor.uiLUT_TableSize-1]>=14000) + { + // End of calib => check the number of samples + if (stTemporayLUTFlowSensor.uiLUT_TableSize>(FLOW_CALIB_NUMBER_OF_SAMPLES>>1)) + { + enLowFlowCalibrationStep=PREPARE_SUCCESS_COMMAND; + + // Transfer the temporary LUT in the definitive LUT + stLUTFlowSensor=stTemporayLUTFlowSensor; + } + else + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + break; + } + else if (stTemporayLUTFlowSensor.uiLUT_TableSize>FLOW_CALIB_NUMBER_OF_SAMPLES) + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + break; + } + } + + // Prepare next flow reading + if (stTemporayLUTFlowSensor.uiLUT_TableSize<LOW_FLOW_CALIB_NUMBER_OF_SAMPLES) + { + // New motor speed + uiMotorDutyCyleForFlowCalib+=20; + enLowFlowCalibrationStep=SEND_FLOW_COMMAND; + } + else if (stTemporayLUTFlowSensor.uiLUT_TableSize==LOW_FLOW_CALIB_NUMBER_OF_SAMPLES && bHighFlowCalibrationInProgress==FALSE) + { + // Min speed for motor + uiMotorDutyCyleForFlowCalib=MIN_PI_OUTPUT; + SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); + enLowFlowCalibrationStep=SEND_HIGH_FLOW_CALIB_REQUEST; + break; + } + else + { + // New motor speed + uiMotorDutyCyleForFlowCalib+=10; + enLowFlowCalibrationStep=SEND_FLOW_COMMAND; + } + + // Update motor speed + if (uiMotorDutyCyleForFlowCalib<MAX_PI_OUTPUT) + { + SS_Xputdw(mdrv, uiMotorDutyCyleForFlowCalib); + } + else + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + break; + } + } + else // if (uiFlowTicksSamplesCounter!=0) + { + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + break; + } + case SEND_HIGH_FLOW_CALIB_REQUEST: + { + if (TransferCommandToHandset((char*)szRequestHighFlowCalib)==TRUE) + enLowFlowCalibrationStep=WAIT_FOR_HIGH_FLOW_CALIB_ACK; + break; + } + case WAIT_FOR_HIGH_FLOW_CALIB_ACK: + { + // Wait for acknownledge from handset + if (ReadByteReceive(&cCharValue)==TRUE) + { + if (cCharValue=='@') + { + // Continue flow calibration + bHighFlowCalibrationInProgress=TRUE; + enLowFlowCalibrationStep=SEND_FLOW_COMMAND; + } + else + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + break; + } + case PREPARE_FAILURE_COMMAND: + { + if (TransferCommandToHandset((char*)szEndOfCalibFailed)==TRUE) + enLowFlowCalibrationStep=END_OF_CALIBRATION; + break; + } + case PREPARE_SUCCESS_COMMAND: + { + if (TransferCommandToHandset((char*)szEndOfCalibOK)==TRUE) + enLowFlowCalibrationStep=END_OF_CALIBRATION; + break; + } + case SEND_COMMAND_TO_PF300: + { + // Send a byte every 1ms + if (TransferBufferToPF300()==TRUE) + { + // Buffer sent !! + if (ucNumberOfBytesToCheckFromPF300Answer!=0) + { + // Check answer from PF300 + ucIndexAnswerFromPF300=0; + uiCalibrationTimeOut=TIME_OUT_RECEPTION_PACKET_FROM_PF300; + enLowFlowCalibrationStep=CHECK_COMMAND_FROM_PF300; + } + else + enLowFlowCalibrationStep=enGoBackToStep; + } + break; + } + case CHECK_COMMAND_FROM_PF300: + { + if (uiCalibrationTimeOut==0) + { + // Time-out in reception !! + ucIndexAnswerFromPF300=0; + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + else if (ReadByteReceive(&cCharValue)==TRUE) + { + // Check last byte received + if (cCharValue=='\r') + { + // End of answer => check buffer content + ucIndexAnswerFromPF300=0; + strcpy(szTempBuf, szAnswerFromPF300); + szTempBuf[ucNumberOfBytesToCheckFromPF300Answer]=0; + if (strcmp(szTempBuf, szExpectedAnswerFromPF300)==0) + { + // Buffer OK !! + enLowFlowCalibrationStep=enGoBackToStep; + } + else + { + // Buffer wrong !! + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + } + else if (cCharValue=='?') + { + // PF300 is lost => end of calibration + ucIndexAnswerFromPF300=0; + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + else + { + // Store byte from PF300 into buffer + szAnswerFromPF300[ucIndexAnswerFromPF300++]=cCharValue; + if (ucIndexAnswerFromPF300>=SIZE_RX_BUFFER_PF300) + { + // Answer too long !! + ucIndexAnswerFromPF300=0; + enLowFlowCalibrationStep=PREPARE_FAILURE_COMMAND; + } + else + { + // Add 0 at the end of the string + szAnswerFromPF300[ucIndexAnswerFromPF300]=0; + } + } + } + else + { + // No byte received !! + uiCalibrationTimeOut--; + } + break; + } + default: + case END_OF_CALIBRATION: + { + uiTechnicalDataSet[START_STOP_VENTILATION]=0; + bDisableMaroubraCommCommunication=FALSE; + break; + } + } // switch + + // Every 300ms, send '@*' to inform the handset that the blower works properly + if (uiImHereMsgTimer==0) + { + if (enLowFlowCalibrationStep!=SEND_COMMAND_TO_PF300) + { + uiImHereMsgTimer=300; + TransferCommandToHandset((char*)szImHere); + } + } + else + uiImHereMsgTimer--; +} + +/******************************************************************************* +* Function Name : ManagePressureCalibration +* Description : Manage pressure calibration +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManagePressureCalibration(void) +{ + char cCharValue; + char szTempBuf[SIZE_RX_BUFFER_PF300]; + u16 uiCalibPressureADCValue; + u16 uiCalibPressureValue; + u16 uiCalibPressureGain; + + switch(enPressureCalibrationStep) + { + case INIT_PRESSURE_CALIB_TEST: + { + // Init comm with PF300 => wait 2s before sending first command to PF300 + // We need to wait for this delay in order to the handset to activate its transparent mode + if (uiCalibrationTimeOut==0) + { + bDisableMaroubraCommCommunication=TRUE; + + // Prepare command to PF300 + UpdateBufferToSend((char*)szPF300_CmdSwitchOffEcho); + strcpy(szExpectedAnswerFromPF300, szPF300_AnswerSwitchOffEcho); + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_AnswerSwitchOffEcho); + enPressureCalibrationStep=PRESSURE_CALIB_SEND_COMMAND_TO_PF300; + enPressureCalibGoBackToStep=START_PRESSURE_READING; + } + else + { + uiCalibrationTimeOut--; + } + break; + } + case START_PRESSURE_READING: + { + // Set blower speed + SS_Xputdw(mdrv, 600); + + // Init variable for flow sensor + uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_PRESSURE; + ulSumPressureTicks=0; + uiPressureTicksSamplesCounter=0; + + enPressureCalibrationStep=SEND_PRESSURE_COMMAND; + break; + } + case SEND_PRESSURE_COMMAND: + { + if (uiCalibrationTimeOut!=0) + { + uiCalibrationTimeOut--; + + if (uiCalibrationTimeOut<2000) + { + ulSumPressureTicks+=uiProximalPressureADCMes; + uiPressureTicksSamplesCounter++; + } + } + else + { + // Prepare next command + UpdateBufferToSend((char*)szPF300_ReadPdiffCmd); + strcpy(szExpectedAnswerFromPF300, szPF300_ReadPdiffAnswer); + ucNumberOfBytesToCheckFromPF300Answer=strlen(szPF300_ReadPdiffAnswer); + enPressureCalibrationStep=PRESSURE_CALIB_SEND_COMMAND_TO_PF300; + enPressureCalibGoBackToStep=READ_PRESSURE_VALUE; + } + break; + } + case READ_PRESSURE_VALUE: + { + if (uiPressureTicksSamplesCounter!=0) + { + // Read PF300 pressure + strcpy(szTempBuf, &szAnswerFromPF300[ucNumberOfBytesToCheckFromPF300Answer]); + + // Store value of Pressure + uiCalibPressureValue=(unsigned int)atoi(szTempBuf); + + // Store ticks value + uiCalibPressureADCValue=ulSumPressureTicks/uiPressureTicksSamplesCounter; + uiCalibrationTimeOut=SAMPLE_RATE_BETWEEN_TWO_PRESSURE; + ulSumPressureTicks=0; + uiPressureTicksSamplesCounter=0; + + // Check if current pressure<10cmH20 + if (uiCalibPressureValue<1000) + { + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + break; + } + + // Compute pressure gain + uiCalibPressureGain=(10000UL*(uiCalibPressureADCValue-uiTechnicalDataSet[PPROX_OFFSET_TEC]))/uiCalibPressureValue; + uiCalibPressureGain+=5; + uiCalibPressureGain/=10; + + // Check pressure gain range + if (uiCalibPressureGain<Tec_GainPprox_MIN || uiCalibPressureGain>Tec_GainPprox_MAX) + { + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + else + { + enPressureCalibrationStep=PRESSURE_CALIB_SUCCESS_COMMAND; + + // Transfer the temporary LUT in the definitive LUT + uiTechnicalDataSet[PPROX_GAIN_TEC]=uiCalibPressureGain; + } + } + else // if (uiPressureTicksSamplesCounter!=0) + { + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + break; + } + case PRESSURE_CALIB_FAILURE_COMMAND: + { + if (TransferCommandToHandset((char*)szEndOfCalibFailed)==TRUE) + enPressureCalibrationStep=PRESSURE_CALIB_END_OF_CALIBRATION; + break; + } + case PRESSURE_CALIB_SUCCESS_COMMAND: + { + if (TransferCommandToHandset((char*)szEndOfCalibOK)==TRUE) + enPressureCalibrationStep=PRESSURE_CALIB_END_OF_CALIBRATION; + break; + } + case PRESSURE_CALIB_SEND_COMMAND_TO_PF300: + { + // Send a byte every 1ms + if (TransferBufferToPF300()==TRUE) + { + // Buffer sent !! + if (ucNumberOfBytesToCheckFromPF300Answer!=0) + { + // Check answer from PF300 + ucIndexAnswerFromPF300=0; + uiCalibrationTimeOut=TIME_OUT_RECEPTION_PACKET_FROM_PF300; + enPressureCalibrationStep=PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300; + } + else + enPressureCalibrationStep=enPressureCalibGoBackToStep; + } + break; + } + case PRESSURE_CALIB_CHECK_COMMAND_FROM_PF300: + { + if (uiCalibrationTimeOut==0) + { + // Time-out in reception !! + ucIndexAnswerFromPF300=0; + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + else if (ReadByteReceive(&cCharValue)==TRUE) + { + // Check last byte received + if (cCharValue=='\r') + { + // End of answer => check buffer content + ucIndexAnswerFromPF300=0; + strcpy(szTempBuf, szAnswerFromPF300); + szTempBuf[ucNumberOfBytesToCheckFromPF300Answer]=0; + if (strcmp(szTempBuf, szExpectedAnswerFromPF300)==0) + { + // Buffer OK !! + enPressureCalibrationStep=enPressureCalibGoBackToStep; + } + else + { + // Buffer wrong !! + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + } + else if (cCharValue=='?') + { + // PF300 is lost => end of calibration + ucIndexAnswerFromPF300=0; + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + else + { + // Store byte from PF300 into buffer + szAnswerFromPF300[ucIndexAnswerFromPF300++]=cCharValue; + if (ucIndexAnswerFromPF300>=SIZE_RX_BUFFER_PF300) + { + // Answer too long !! + ucIndexAnswerFromPF300=0; + enPressureCalibrationStep=PRESSURE_CALIB_FAILURE_COMMAND; + } + else + { + // Add 0 at the end of the string + szAnswerFromPF300[ucIndexAnswerFromPF300]=0; + } + } + } + else + { + // No byte received !! + uiCalibrationTimeOut--; + } + break; + } + default: + case PRESSURE_CALIB_END_OF_CALIBRATION: + { + uiTechnicalDataSet[START_STOP_VENTILATION]=0; + bDisableMaroubraCommCommunication=FALSE; + break; + } + } // switch + + // Every 300ms, send '@*' to inform the handset that the blower works properly + if (uiImHereMsgTimer==0) + { + if (enPressureCalibrationStep!=PRESSURE_CALIB_SEND_COMMAND_TO_PF300) + { + uiImHereMsgTimer=300; + TransferCommandToHandset((char*)szImHere); + } + } + else + uiImHereMsgTimer--; +} + + +/******************************************************************************* +* Function Name : ManageCstPressure +* Description : Manage constant pressure +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageCstPressure(void) +{ + int32_t lError; + int32_t lPropTerm; + int32_t lIntegralTerm; + int32_t lOutputPressure; + + + // Barometric Mode : error computation + lError=(int32_t)uiMLT_PressureSetPoint-(int32_t)uiProximalPressureMes; + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_CPAP_VENTED_PRESSURE_I] * lError; + if (uiMLT_PressureSetPoint<uiVentilationSet[PI_SET]) uiMLT_PressureSetPoint++; + + // Close loop in pressure + if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm) <0) + lIntegral_Pressure_I = INTEGRAL_MAX; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm)>0) + lIntegral_Pressure_I = INTEGRAL_MIN; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) + lIntegral_Pressure_I += lIntegralTerm; + else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) + lIntegral_Pressure_I += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_CPAP_VENTED_PRESSURE_I] * lError; + lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); + + // Add constante value (PWM at the end of the previous inspiration) + //lOutputPressure+=300; + + if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiInspirationBlowerPWMTec = lOutputPressure; + } + + // Update Blower Speed + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + + // Monitoring and Alarm (every 1s) + #ifdef MOTOR_LIFE_TESTING + if (uiAverageMonitoringMLT==0) + { + uiAverageBlowerSpeedMes=ulMLT_SumSpeedMes/MLT_AVERAGE_MONITORING; + uiBreathBlowerCurrentMes=ulMLT_SumCurrentMes/MLT_AVERAGE_MONITORING; + uiAverateMotorTempMes=ulMLT_SumTemperatureMes/MLT_AVERAGE_MONITORING; + uiAverageMotorVoltage=ulMLT_SumBlowerVoltage/MLT_AVERAGE_MONITORING; + + ulMLT_SumSpeedMes=0; + ulMLT_SumCurrentMes=0; + ulMLT_SumTemperatureMes=0; + ulMLT_SumBlowerVoltage=0; + uiAverageMonitoringMLT=MLT_AVERAGE_MONITORING; + } + else + { + ulMLT_SumSpeedMes+=uiBlowerSpeedMes; + ulMLT_SumCurrentMes+=uiBlowerCurrentMes; + ulMLT_SumTemperatureMes+=uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]; + ulMLT_SumBlowerVoltage+=uiTechnicalDataMes[MOTOR_VOLTAGE_TEC_MES]; + uiAverageMonitoringMLT--; + } + + // Alarms management + if (uiMLT_EnableAlarm==0) + { + // High Speed alarm + if (uiAverageBlowerSpeedMes>uiTechnicalDataSet[MLT_HIGH_SPEED_TEC]) + uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_SPEED_ALARM_MASK; + + // Low Speed alarm + if (uiAverageBlowerSpeedMes<uiTechnicalDataSet[MLT_LOW_SPEED_TEC]) + uiFlagsAlarm[ALARM_FLAGS2]|=LOW_BLOWER_SPEED_ALARM_MASK; + + // High blower current alarm + if (uiBreathBlowerCurrentMes>uiTechnicalDataSet[MLT_HIGH_CURRENT_TEC]) + uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_CURRENT_ALARM_MASK; + + // High Blower temperature + if (uiAverateMotorTempMes>uiTechnicalDataSet[MLT_HIGH_TEMPERATURE_TEC]) + uiFlagsAlarm[ALARM_FLAGS2]|=HIGH_BLOWER_TEMP_ALARM_MASK; + + // Low Blower temperature + if (uiAverateMotorTempMes<100) + uiFlagsAlarm[ALARM_FLAGS2]|=LOW_BLOWER_TEMP_ALARM_MASK; + + // High Blower Flow + if (iBlowerFlowSmoothingMesForTrigger>uiTechnicalDataSet[MLT_HIGH_FLOW_TEC] || iBlowerFlowSmoothingMesForTrigger<uiTechnicalDataSet[MLT_LOW_FLOW_TEC]) + uiFlagsAlarm[ALARM_FLAGS2]|=OOR_BLOWER_FLOW_ALARM_MASK; + } + else + uiMLT_EnableAlarm--; + #endif // MOTOR_LIFE_TESTING +} + + +/******************************************************************************* +* Function Name : ManagePACVVentilation +* Description : Manage Bilevel ventilation +* Input : bPSMode=true in PS mode, false in PI mode +* Output : None +* Return : None +*******************************************************************************/ +void ManagePACVVentilation(bool bPSMode) +{ +int32_t lError; +int32_t lPropTerm; +int32_t lIntegralTerm; +int32_t lOutputPressure; +u16 uiPressureSetPoint; +u16 uiTiMax; +u16 uiTiMin; +//u16 uiTeMax; +u16 uiFlowMaxInExpi; + +if (ucVentilationCycle==INSPIRATION_CYCLE) + { + // --------------------------------------------------------------------------- + // - INSPIRATION - + // -------------------------------------------------------------------------- + + // Ti et pressure set point management + if (bPSMode==TRUE) + { + uiPressureSetPoint=uiVentilationSet[PS_SET]; + uiTiMax=uiVentilationSet[TI_MAX_SET]; + } + else + { + uiPressureSetPoint=uiVentilationSet[PI_SET]; + uiTiMax=uiVentilationSet[TI_BARO_SET]; + } + + // Compute Timin + if (uiPatientType==PATIENT_ADULT) + uiTiMin=TiBaroSet_A_MIN; + else + uiTiMin=TiBaroSet_P_MIN; + + // Limit the pressure setting + if (uiVentilationSet[HIGH_PRESSURE_ALARM_SET]<uiPressureSetPoint) + uiPressureSetPoint=uiVentilationSet[HIGH_PRESSURE_ALARM_SET]; + + if (uiTiD==0) + { + // Management Expiratory Trigger + ucTempoTriggerExpiAuto=TEMPO_TRIGGER_EXPI; + ucExpiTriggerTreshold=MIN_THRESHOLD_EXPI_TRIGGER_AUTO; + + // Management Inspiratory slope + switch(uiVentilationSet[SLOPE_BARO_SET]) + { + default: + case 1: + { + // Slope of 5ms/hPa => 0.2hPa/ms + uiIpapSettingTemp=uiVentilationSet[PEEP_SET]+2; + break; + } + case 2: + { + ucIndexTableSlope=0; + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope2Table[ucIndexTableSlope++])/100; + break; + } + case 3: + { + ucIndexTableSlope=0; + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope3Table[ucIndexTableSlope++])/100; + break; + } + case 4: + { + ucIndexTableSlope=0; + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope4Table[ucIndexTableSlope++])/100; + break; + } + } + } + else + { + // Management Inspiratory slope + switch(uiVentilationSet[SLOPE_BARO_SET]) + { + default: + case 1: + { + // Slope of 5ms/hPa => 0.2hPa/ms + uiIpapSettingTemp+=2; + if (uiIpapSettingTemp>uiPressureSetPoint) + uiIpapSettingTemp=uiPressureSetPoint; + break; + } + case 2: + { + if (ucIndexTableSlope<SIZE_SLOPE2_TABLE && (uiTiD%10)==0) + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope2Table[ucIndexTableSlope++])/100; + break; + } + case 3: + { + if (ucIndexTableSlope<SIZE_SLOPE3_TABLE && (uiTiD%10)==0) + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope3Table[ucIndexTableSlope++])/100; + break; + } + case 4: + { + if (ucIndexTableSlope<SIZE_SLOPE4_TABLE && (uiTiD%10)==0) + uiIpapSettingTemp=(uiPressureSetPoint*ucSlope4Table[ucIndexTableSlope++])/100; + break; + } + } + } + + // Barometric Mode : error computation + lError=(int32_t)uiIpapSettingTemp-(int32_t)uiProximalPressureMes; + if (fFirstCycleInspi==FALSE) + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_I] * lError; + else + { + lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_I]>>2) * lError; + uiPWMatTheEndOfInspiration=uiExpirationBlowerPWMTec; + } + + // Close loop in pressure + if ((lIntegral_Pressure_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm) <0) + lIntegral_Pressure_I = INTEGRAL_MAX; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureI==FALSE)) + { + if ((lIntegral_Pressure_I + lIntegralTerm)>0) + lIntegral_Pressure_I = INTEGRAL_MIN; + else + lIntegral_Pressure_I += lIntegralTerm; + } + else if ((lIntegral_Pressure_I<=0) && (lIntegralTerm>=0)) + lIntegral_Pressure_I += lIntegralTerm; + else if ((lIntegral_Pressure_I>=0) && (lIntegralTerm<=0)) + lIntegral_Pressure_I += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_I] * lError; + lOutputPressure = (lIntegral_Pressure_I>>16) + (lPropTerm>>13); + + // Add constante value (PWM at the end of the previous inspiration) + lOutputPressure+=uiPWMatTheEndOfInspiration; + + if (fAlarmPmax==TRUE || fAlarmVtiMax==TRUE) + { + bMaxPIOutputPressureI = TRUE; + } + else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureI = FALSE; + bMinPIOutputPressureI = FALSE; + uiInspirationBlowerPWMTec = lOutputPressure; + } + + // Update Blower Speed + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + + // ************************ CYCLE MANAGEMENT ********************************* + uiTiD++; + if ((uiTiD>=uiTiMax) || + (TestTriggerExpiratoire(uiVentilationSet[TRIG_E_SET], uiVentilationSet[PS_SET])==TRUE && uiTiD>uiVentilationSet[TI_MIN_SET] && bPSMode==TRUE) || + (fAlarmPmax==TRUE && uiTiD>uiTiMin) || + (fAlarmVtiMax==TRUE && uiTiD>uiTiMin)) + { + // Beginning of the expiration + if (fAlarmPmax==FALSE && fAlarmVtiMax==FALSE) + { + fFirstCycleInspi=FALSE; + uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; + } + else + { + fFirstCycleInspi=TRUE; + uiPWMatTheEndOfInspiration=MIN_VOLTAGE_REF; + } + + ucVentilationCycle=EXPIRATION_CYCLE; + uiTiD=0; + + // Reset PI variables for next inspiration + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE=FALSE; + bMinPIOutputPressureE=FALSE; + + fFirstCycleExpi=FALSE; + } + } +else + { + // --------------------------------------------------------------------------- + // - EXPIRATION - + // --------------------------------------------------------------------------- + + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + // ******************** MAIN BLOWER MANAGEMENT ******************************* + if (uiVentilationSet[PEEP_SET]==0) + { + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); + } + else + { + if (uiTeD==0) + { + // First blower current setting + uiEpapSettingTemp=uiVentilationSet[PI_SET]-2; // Slope of 5ms/hPa => 0.2hPa/ms + } + else + { + // we increase the speed of the blower every 1ms + uiEpapSettingTemp-=2; // Slope of 5ms/hPa => 0.2hPa/ms + if (uiEpapSettingTemp<uiVentilationSet[PEEP_SET]) + uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; + } + + // Barometric Mode : error computation + if (fFirstCycleExpi==FALSE) + { + lError=(int32_t)uiEpapSettingTemp-(int32_t)uiProximalPressureMes; + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_E] * lError; + } + else + { + lError=(int32_t)uiVentilationSet[PEEP_SET]-(int32_t)uiProximalPressureMes; + lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_E]>>2) * lError; + } + + // Close loop in pressure + if ((lIntegral_Pressure_E>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureE==FALSE)) + { + if ((lIntegral_Pressure_E + lIntegralTerm) <0) + lIntegral_Pressure_E = INTEGRAL_MAX; + else + lIntegral_Pressure_E += lIntegralTerm; + } + else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureE==FALSE)) + { + if ((lIntegral_Pressure_E + lIntegralTerm)>0) + lIntegral_Pressure_E = INTEGRAL_MIN; + else + lIntegral_Pressure_E += lIntegralTerm; + } + else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm>=0)) + lIntegral_Pressure_E += lIntegralTerm; + else if ((lIntegral_Pressure_E>=0) && (lIntegralTerm<=0)) + lIntegral_Pressure_E += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_E] * lError; + lOutputPressure = (lIntegral_Pressure_E>>16) + (lPropTerm>>13); + + // Add constante value (PWM at the end of the previous expiration) + lOutputPressure+=uiPWMatTheEndOfExpiration; + + // Flow limiting + uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; + if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) + { + // Impossible to maintain the peep (patient disconnection) + if (uiDisconnectionTime==0) + { + fBlockCloseLoop=TRUE; // Block the close loop + if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value + uiExpirationBlowerPWMTec=uiMemoPWMDuringDisconnection; + else + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + uiDisconnectionTime--; + } + else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) + { + // Good pressure : no disconnection + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + if (fBlockCloseLoop==TRUE) + { + // The close loop was block before => unblock it + fBlockCloseLoop=FALSE; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + } + else if (iBlowerFlowSmoothingMes>=0) + { + // Record current PWM + uiMemoPWMDuringDisconnection=uiExpirationBlowerPWMTec; + } + } + + // Unblock the close loop every 4s in case of none recorded PWM value + if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiTeD==0) + { + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + fBlockCloseLoop=FALSE; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + } + + // Update blower PWM + if (fBlockCloseLoop==TRUE) + { + bMaxPIOutputPressureE = TRUE; + } + else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureE = TRUE; + uiExpirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureE = TRUE; + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + uiExpirationBlowerPWMTec = lOutputPressure; + } + SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); + } + + // Expiratory time + uiTeD++; + if (uiTeD>TE_SET_MAX) uiTeD=TE_SET_MAX; + if ((uiTeD>=uiTeBaroSet && bPSMode==FALSE) || TestInspiratoryTrigger(bPSMode, uiTeD, uiVentilationSet[TRIG_I_FLOW_SET])==TRUE) + { + ucVentilationCycle=INSPIRATION_CYCLE; + uiTeD=0; + + // Record PWM value at the end of the expiration + uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + + // Reset PI variables for next inspiration + lIntegral_Pressure_I=0; + bMaxPIOutputPressureI=FALSE; + bMinPIOutputPressureI=FALSE; + } + } +} + + + +/******************************************************************************* +* Function Name : ManageVolumetricVentilation +* Description : Manage Volumetric Ventilation +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ManageVolumetricVentilation(void) +{ +int32_t lError; +int32_t lPropTerm; +int32_t lIntegralTerm; +int32_t lOutputPressure; +int16_t iMaxVtAdjust; +u16 uiFlowMaxInExpi; +u16 uiTiMin; + +if (ucVentilationCycle==INSPIRATION_CYCLE) + { + // --------------------------------------------------------------------------- + // - INSPIRATION - + // --------------------------------------------------------------------------- + + // Compute Timin + if (uiPatientType==PATIENT_ADULT) + uiTiMin=TiVoluSet_A_MIN; + else + uiTiMin=TiVoluSet_P_MIN; + + // ************************** Main Blower MANAGEMENT ************************* + if (uiTiD==0) + { + // Compute Volume adjustment + if (fFirstCycleInspi==FALSE) + { + if ((uiFlagsAlarm[ALARM_FLAGS1]&HIGH_PRESSURE_ALARM_MASK)==0) + { + if (ucCounterHPAlarm==0) + { + iVtAdjust+=(((int16_t)uiVentilationSet[VT_SET]-(int16_t)uiRecordVtiMes>>1)); + if (iVtAdjust>0) + { + iMaxVtAdjust=(int16_t)(uiVentilationSet[VT_SET]>>1); // >0 + if (iVtAdjust>iMaxVtAdjust) + iVtAdjust=iMaxVtAdjust; + } + else if (iVtAdjust<0) + { + iMaxVtAdjust=(int16_t)(~(uiVentilationSet[VT_SET]>>1)+1); // <0 + if (iVtAdjust<iMaxVtAdjust) + iVtAdjust=iMaxVtAdjust; + } + } + else + ucCounterHPAlarm--; + } + else + ucCounterHPAlarm=1; + } + else + iVtAdjust=0; + + ComputeInspiratoryFlowSetPointInAVC(uiPatientType, (u16)((int16_t)uiVentilationSet[VT_SET]+iVtAdjust), uiVentilationSet[TI_VOLU_SET], uiVentilationSet[SHAPE_SET], &ulMaxIFlowSet, &ulMinIFlowSet, &ulDecFlowStep); + } + else + { + if (ulMaxIFlowSet>=ulDecFlowStep) + ulMaxIFlowSet-=ulDecFlowStep; + if (ulMaxIFlowSet<ulMinIFlowSet) + ulMaxIFlowSet=ulMinIFlowSet; + } + + // Volumetric Mode : error computation + //lError=(int32_t)(ulMaxIFlowSet/100)-iBlowerFlowMes; + lError=(int32_t)(ulMaxIFlowSet/100)-iBlowerFlowSmoothingMes; + if (fFirstCycleInspi==FALSE) + { + if (ulMaxIFlowSet<150000 && uiTiD>30000) + lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_FLOW_I]>>1) * lError; + else + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_FLOW_I] * lError; + } + else + lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_FLOW_I]>>2) * lError; + + // Close loop in pressure or flow (PI) + if ((lIntegral_Flow_I>=0) && (lIntegralTerm>=0) && (bMaxPIOutputFlowI==FALSE)) + { + if ((lIntegral_Flow_I + lIntegralTerm) <0) + lIntegral_Flow_I = INTEGRAL_MAX; + else + lIntegral_Flow_I += lIntegralTerm; + } + else if ((lIntegral_Flow_I<=0) && (lIntegralTerm<=0) && (bMinPIOutputFlowI==FALSE)) + { + if ((lIntegral_Flow_I + lIntegralTerm)>0) + lIntegral_Flow_I = INTEGRAL_MIN; + else + lIntegral_Flow_I += lIntegralTerm; + } + else if ((lIntegral_Flow_I<=0) && (lIntegralTerm>=0)) + lIntegral_Flow_I += lIntegralTerm; + else if ((lIntegral_Flow_I>=0) && (lIntegralTerm<=0)) + lIntegral_Flow_I += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_FLOW_I] * lError; + lOutputPressure = (lIntegral_Flow_I>>16) + (lPropTerm>>13); + + // Add constante value (PWM at the end of the previous inspiration) + lOutputPressure+=uiPWMatTheEndOfExpiration; + + if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputFlowI = TRUE; + uiInspirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputFlowI = TRUE; + uiInspirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputFlowI = FALSE; + bMinPIOutputFlowI = FALSE; + uiInspirationBlowerPWMTec = lOutputPressure; + } + + // Update Blower Speed + SS_Xputdw(mdrv, uiInspirationBlowerPWMTec); + + // ************************ CYCLE MANAGEMENT ********************************* + uiTiD++; + if ((uiTiD>=uiVentilationSet[TI_VOLU_SET]) || + (fAlarmPmax==TRUE && uiTiD>uiTiMin)) + { + // Beginning of the expiration + uiPWMatTheEndOfInspiration=uiInspirationBlowerPWMTec; + uiProximalPressureAtTheEndOfInspiration=uiProximalPressureMes; + + ucVentilationCycle=EXPIRATION_CYCLE; + uiTiD=0; + + // Reset PI variables for next inspiration + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE=FALSE; + bMinPIOutputPressureE=FALSE; + + fFirstCycleExpi=FALSE; + fFirstCycleInspi=FALSE; + } + } +else + { + // --------------------------------------------------------------------------- + // - EXPIRATION - + // --------------------------------------------------------------------------- + + // *************************** UPDATE SETTINGS ******************************* + if (ApplyNewVentilationMode()==TRUE) + return; + + // ******************** MAIN BLOWER MANAGEMENT ******************************* + if (uiVentilationSet[PEEP_SET]==0) + { + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); + } + else + { + if (uiTeD==0) + { + // First blower pressure setting + if (uiProximalPressureAtTheEndOfInspiration<uiVentilationSet[PEEP_SET]) + uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; + else if (uiProximalPressureAtTheEndOfInspiration>=2) + uiEpapSettingTemp=uiProximalPressureAtTheEndOfInspiration-2; // Slope of 5ms/hPa => 0.2hPa/ms + else + uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; + } + else + { + // we decrease the speed of the blower every 1ms + if (uiEpapSettingTemp>=2) + uiEpapSettingTemp-=2; // Slope of 5ms/hPa => 0.2hPa/ms + } + + // Pressure set point limitation + if (uiEpapSettingTemp<uiVentilationSet[PEEP_SET]) + uiEpapSettingTemp=uiVentilationSet[PEEP_SET]; + + // Barometric Mode : error computation + if (fFirstCycleExpi==FALSE) + { + lError=(int32_t)uiEpapSettingTemp-(int32_t)uiProximalPressureMes; + lIntegralTerm = (int32_t)uiTechnicalDataSet[KI_VENTED_PRESSURE_E] * lError; + } + else + { + lError=(int32_t)uiVentilationSetTemp[PEEP_SET]-(int32_t)uiProximalPressureMes; + lIntegralTerm = (int32_t)(uiTechnicalDataSet[KI_VENTED_PRESSURE_E]>>2) * lError; + } + + // Close loop in pressure + if ((lIntegral_Pressure_E>=0) && (lIntegralTerm>=0) && (bMaxPIOutputPressureE==FALSE)) + { + if ((lIntegral_Pressure_E + lIntegralTerm) <0) + lIntegral_Pressure_E = INTEGRAL_MAX; + else + lIntegral_Pressure_E += lIntegralTerm; + } + else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm<=0) && (bMinPIOutputPressureE==FALSE)) + { + if ((lIntegral_Pressure_E + lIntegralTerm)>0) + lIntegral_Pressure_E = INTEGRAL_MIN; + else + lIntegral_Pressure_E += lIntegralTerm; + } + else if ((lIntegral_Pressure_E<=0) && (lIntegralTerm>=0)) + lIntegral_Pressure_E += lIntegralTerm; + else if ((lIntegral_Pressure_E>=0) && (lIntegralTerm<=0)) + lIntegral_Pressure_E += lIntegralTerm; + + lPropTerm = (int32_t)uiTechnicalDataSet[KP_VENTED_PRESSURE_E] * lError; + lOutputPressure = (lIntegral_Pressure_E>>16) + (lPropTerm>>13); + + // Add constante value (PWM at the end of the previous expiration) + lOutputPressure+=uiPWMatTheEndOfExpiration; + + // Flow limiting + uiFlowMaxInExpi=uiMaximumFlowInExpiration[uiVentilationSet[PS_CPAP_SET]/10]; + if (lError>5 && iBlowerFlowSmoothingMes>(int16_t)uiFlowMaxInExpi) + { + // Impossible to maintain the peep (patient disconnection) + if (uiDisconnectionTime==0) + { + fBlockCloseLoop=TRUE; // Block the close loop + if (uiMemoPWMDuringDisconnection!=0) // Apply a fixed PWM value + uiExpirationBlowerPWMTec=uiMemoPWMDuringDisconnection; + else + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + uiDisconnectionTime--; + } + else if (iBlowerFlowSmoothingMes<(int16_t)uiFlowMaxInExpi && (lError>(-2) && lError<2)) + { + // Good pressure : no disconnection + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + if (fBlockCloseLoop==TRUE) + { + // The close loop was block before => unblock it + fBlockCloseLoop=FALSE; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + } + else if (iBlowerFlowSmoothingMes>=0) + { + // Record current PWM + uiMemoPWMDuringDisconnection=uiExpirationBlowerPWMTec; + } + } + + // Unblock the close loop every 4s in case of none recorded PWM value + if (fBlockCloseLoop==TRUE && uiMemoPWMDuringDisconnection==0 && uiTeD==0) + { + uiDisconnectionTime=EXPIRATORY_DISCONNECTION_TIME_OUT; + fBlockCloseLoop=FALSE; + lIntegral_Pressure_E=0; + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + lOutputPressure=uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + } + + // Update blower PWM + if (fBlockCloseLoop==TRUE) + { + bMaxPIOutputPressureE = TRUE; + } + else if (lOutputPressure>=((int32_t)MAX_VOLTAGE_REF)) + { + bMaxPIOutputPressureE = TRUE; + uiExpirationBlowerPWMTec=MAX_VOLTAGE_REF; + } + else if (lOutputPressure<((int32_t)MIN_VOLTAGE_REF)) + { + bMinPIOutputPressureE = TRUE; + uiExpirationBlowerPWMTec=MIN_VOLTAGE_REF; + } + else + { + bMaxPIOutputPressureE = FALSE; + bMinPIOutputPressureE = FALSE; + uiExpirationBlowerPWMTec = lOutputPressure; + } + // Update Blower Speed + SS_Xputdw(mdrv, uiExpirationBlowerPWMTec); + } + + // Expiratory time + uiTeD++; + if (uiTeD>=uiTeVoluSet || TestInspiratoryTrigger(FALSE, uiTeD, uiVentilationSet[TRIG_I_FLOW_SET])==TRUE) + { + ucVentilationCycle=INSPIRATION_CYCLE; + uiTeD=0; + + // Record PWM value at the end of the expiration + if (fBlockCloseLoop==FALSE) + uiPWMatTheEndOfExpiration=uiExpirationBlowerPWMTec; + else + uiPWMatTheEndOfExpiration=0; + fBlockCloseLoop=FALSE; + + // Reset PI variables for next inspiration + lIntegral_Flow_I=0; + bMaxPIOutputFlowI=FALSE; + bMinPIOutputFlowI=FALSE; + } + } +} + + + +/******************************************************************************* +* Function Name : LaunchTherapyEngine +* Description : Select and launch the therapy engine +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void LaunchTherapyEngine(void) +{ + if (bMemoStartVentilation==TRUE) + { + // ---- Check new configuration + if (uiTechnicalDataSet[DEVICE_MODE_TEC]!=uiPreviousDeviceMode) + { + UpdateSettings(); + enPreviousMode=NUMBER_OF_MODE; // Force full init of the variables + InitVentilation(); + uiPreviousDeviceMode=uiTechnicalDataSet[DEVICE_MODE_TEC]; + } + + + switch(uiTechnicalDataSet[DEVICE_MODE_TEC]) + { + default: + case VENTILATION_MODE: + { + if (enVentilationMode==PS_MODE) + ManagePACVVentilation(TRUE); + else if (enVentilationMode==APCV_MODE) + ManagePACVVentilation(FALSE); + else if (enVentilationMode==AVC_MODE) + ManageVolumetricVentilation(); + else if (enVentilationMode==CPAP_MODE) + ManageCPAPVentilation(); + break; + } + case ONE_CST_PWM_MODE: + { + ManageOneCstPWM(); + break; + } + case TWO_CST_PWM_MODE: + { + Manage2CstPWM(); + break; + } + case CST_SPEED_MODE: + { + ManageCstSpeed(); + break; + } + case FLOW_CAL_MODE: + { + ManageFlowCalibration(); + break; + } + case PRESSURE_CAL_MODE: + { + ManagePressureCalibration(); + break; + } + case PRESSURE_CST_MODE: + { + ManageCstPressure(); + break; + } + } + } +} + + +/******************************************************************************* +* Function Name : StartStopVentilation +* Description : Detect a start/stop ventilation request +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void StartStopVentilation(void) +{ + #ifndef TEMPERATURE_TRENDS + opstatus_t byOpStatus; + #endif + + // Check if an alarm must stop the ventilation + ucStopVentilationAlarmNumber=ReadStopVentilationAlarmNumber(); + + #ifndef TEMPERATURE_TRENDS + if (uiTechnicalDataSet[START_STOP_VENTILATION]==1 && ucStopVentilationAlarmNumber==SIZE_BLOWER_ALARM) + { + // *************** VENTILATION is ON ************** + if (bMemoStartVentilation==FALSE) + { + switch(ucStartVentilationScheduler) + { + default: + case 0: + { + // Active the HW safety system + ControlHW(BLOWER_ON__PAT_CPLD); + ucStartVentilationScheduler++; + break; + } + case 1: + { + // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 + ControlHW(BLOWER_ON__PAT_CPLD); + + // Read Offset of the Blower current + ComputeADCBlowerCurrent(TRUE); + + ucStartVentilationScheduler++; + break; + } + case 2: + { + // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 + ControlHW(BLOWER_ON__PAT_CPLD); + + // Open motor driver + byOpStatus=SS_Xopen(mdrv); + if (byOpStatus==OPSTATUS_FAIL) + { + uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_FAILURE_ALARM_MASK; + ucStartVentilationScheduler=0; + } + else if (byOpStatus==OPSTATUS_OK) + { + // Force init settings and variables + uiPreviousDeviceMode=0xFF; + + uiTempo1min=TEMPO_1MIN; + #ifdef DATA_LOGGING + uiTrendsSampleTime=RECORD_TRENDS_SAMPLE_TIME; + #endif // DATA_LOGGING + + // Check if ventilation mode is activated + if (uiTechnicalDataSet[DEVICE_MODE_TEC]!=VENTILATION_MODE) + uiFlagsAlarm[ALARM_FLAGS2]|=DEVICE_MODE_ALARM_MASK; + + bMemoStartVentilation=TRUE; + ucStartVentilationScheduler=0; + } + break; + } + } + } + // --- Check Safety system for Motor transistors ---- + else if (IsMotorOK()==FALSE) + { + ControlHW(BLOWER_OFF__STOP_PAT_CPLD); + uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_FAILURE_ALARM_MASK; + } + // --- Test safety system thanks to the "STOP_BLOWER" Input pin + else if (TestStopBlowerInputPin()==OPSTATUS_OK) + { + ControlHW(BLOWER_ON__PAT_CPLD); + uiFlagsAlarm[ALARM_FLAGS2]&=(~HW_SAFETY_ALARM_MASK); + } + else + { + uiFlagsAlarm[ALARM_FLAGS2]|=HW_SAFETY_ALARM_MASK; + } + } + else + #endif // #ifndef TEMPERATURE_TRENDS + { + // *************** VENTILATION is OFF ************** + uiFlagsAlarm[ALARM_FLAGS2]&=(~DEVICE_MODE_ALARM_MASK); + + if (ucStopVentilationAlarmNumber!=SIZE_BLOWER_ALARM) + { + // Stop patting CPLD (WDI_CPLD=0), STOP_BLOWER=0 + ControlHW(BLOWER_OFF__STOP_PAT_CPLD); + } + else + { + // Pat CPLD (WDI_CPLD), STOP_BLOWER=1 + ControlHW(BLOWER_ON__PAT_CPLD); + + // ---- Test STOP_ACTUATOR Input pin Status + if (TestStopBlowerInputPin()==OPSTATUS_FAIL) + uiFlagsAlarm[ALARM_FLAGS2]|=HW_SAFETY_ALARM_MASK; + else + uiFlagsAlarm[ALARM_FLAGS2]&=(~HW_SAFETY_ALARM_MASK); + } + + if (bMemoStartVentilation==TRUE) + { + StopAllActuators(); + ClearAllVentilationAlarms(); + ClearAllMeasures(); + } + + uiTechnicalDataSet[START_STOP_VENTILATION]=0; + bMemoStartVentilation=FALSE; + #ifndef TEMPERATURE_TRENDS + ucStartVentilationScheduler=0; + #endif + bDisableMaroubraCommCommunication=FALSE; + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +/******************************************************************************* +* Function Name : ComputeTe +* Description : Compute expiratory time +* Input : uiF = Breath frequency (bpm) + uiTi = Inspiratory time (ms) +* Output : Expiratory time (ms) +* Return : None +*******************************************************************************/ +#ifndef C_M3_DEVICETEST_TARGET +u16 ComputeTe(u16 uiF, u16 uiTi) +{ + u16 uiTtot; + u16 uiTeTemp=TE_SET_MIN; + + if (uiF!=0) + { + // Compute Ttotal + uiTtot=60000/uiF; + if (uiTtot>uiTi) + { + uiTeTemp=uiTtot-uiTi; + if (uiTeTemp<TE_SET_MIN) + uiTeTemp=TE_SET_MIN; + } + } + else + { + // F=0 => Te=2xTi + uiTeTemp=uiTi<<1; + } + return(uiTeTemp); +} + + +/******************************************************************************* +* Function Name : UpdateSettings +* Description : Update the settings zone with the temporary settings zone +* Input : None +* Output : None +* Return : TRUE if the ventilation mode has changed +*******************************************************************************/ +bool UpdateSettings(void) +{ + u8 ucIndex; + + // Take into account a modification of the PEEP + if (uiVentilationSet[PEEP_SET]!=uiVentilationSetTemp[PEEP_SET] || uiVentilationSet[PS_CPAP_SET]!=uiVentilationSetTemp[PS_CPAP_SET]) + uiMemoPWMDuringDisconnection=0; + + // Transfert data from the setting temporary zone to the settings zone + for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) + uiVentilationSet[ucIndex]=uiVentilationSetTemp[ucIndex]; + + // Update barometric expiratory time + uiTeBaroSet=ComputeTe(uiVentilationSet[BREATH_RATE_BARO_SET], uiVentilationSet[TI_BARO_SET]); + + // Update volumetric expiratory time + uiTeVoluSet=ComputeTe(uiVentilationSet[BREATH_RATE_VOLU_SET], uiVentilationSet[TI_VOLU_SET]); + + // Update Tube configuration type + enTubeConfigType=enTubeConfigTypeTemp; + + // Update Patient type + uiPatientType=uiPatientTypeTemp; + + // Update Ventilation mode + if (enVentilationMode!=enVentilationModeTemp) + { + enVentilationMode=enVentilationModeTemp; + InitVentilation(); + return(TRUE); + } + return(FALSE); +} + + +/******************************************************************************* +* Function Name : ApplyNewVentilationMode +* Description : Update settings and init variables if the ventilation mode has changed +* Input : None +* Output : None +* Return : TRUE if new ventilation mode is applied +*******************************************************************************/ +bool ApplyNewVentilationMode(void) +{ + if (fUpdateTheSettings==TRUE) + { + fUpdateTheSettings=FALSE; + if (UpdateSettings()==TRUE) + { + InitVentilation(); + return(TRUE); + } + } + return(FALSE); +} + + +/******************************************************************************* +* Function Name : ComputeInspiratoryFlowSetPointInAVC +* Description : Compute: + - the inspiratory flow max set point + - the inspiratory flow min set point + - the flow step between the flow max and the flow min during Ti +* Input : uiTypeOfPatient = Adult or Pedia + uiVtc = set point in volume (ml) + uiTi = Ti set point (ms) + uiFlowShape = Flow shape (0 to 4) +* Output : uiMaxFlow = the inspiratory flow max set point (cl/min => 100=1l/min) + uiMinFlow = the inspiratory flow min set point (cl/min => 100=1l/min) + uiFlowStep = the flow step between the flow max and the flow min during Ti (cl/min => 100=1l/min) +* Return : None +*******************************************************************************/ +void ComputeInspiratoryFlowSetPointInAVC(u16 uiTypeOfPatient, u16 uiVtc, u16 uiTi, u16 uiFlowShape, u32 *ulMaxFlow, u32 *ulMinFlow, u32 *ulFlowStep) +{ + u32 ulFlowMax; + u32 ulFlowMin; + u32 ulMaxMaxFlow; + u32 ulMinMinFlow; + u16 uiTiMin; + u32 ulFlowStepTemp; + + // Define min/max flow + if (uiTypeOfPatient==PATIENT_ADULT) + { + ulMinMinFlow=InspiratoryFlowSet_A_MIN; + ulMaxMaxFlow=InspiratoryFlowSet_A_MAX; + uiTiMin=TiVoluSet_A_MIN; + } + else + { + ulMinMinFlow=InspiratoryFlowSet_P_MIN; + ulMaxMaxFlow=InspiratoryFlowSet_P_MAX; + uiTiMin=TiVoluSet_P_MIN; + } + + // Check Ti + if (uiTi==0) + uiTi=uiTiMin; + + // Compute flow max + switch(uiFlowShape) + { + default: + case 0: + { + ulFlowMax=((u32)uiVtc*6000)/uiTi; + break; + } + case 1: + { + ulFlowMax=((u32)uiVtc*7500)/uiTi; + break; + } + case 2: + { + ulFlowMax=((u32)uiVtc*9000)/uiTi; + break; + } + case 3: + { + ulFlowMax=((u32)uiVtc*10500)/uiTi; + break; + } + case 4: + { + ulFlowMax=((u32)uiVtc*12000)/uiTi; + break; + } + } + + // Limitation of the max flow + if (ulFlowMax>ulMaxMaxFlow) + ulFlowMax=ulMaxMaxFlow; + + // Limitation of the min flow + if (ulFlowMax<ulMinMinFlow) + ulFlowMax=ulMinMinFlow; + + // Factor 100 on flow max (and flow min and flow step) + ulFlowMax*=100; + + // Compute flow min and flow step + switch(uiFlowShape) + { + default: + case 0: + { + ulFlowMin=ulFlowMax; + break; + } + case 1: + { + ulFlowMin=(ulFlowMax*3)>>2; + break; + } + case 2: + { + ulFlowMin=ulFlowMax>>1; + break; + } + case 3: + { + ulFlowMin=ulFlowMax>>2; + break; + } + case 4: + { + ulFlowMin=0; + break; + } + } + + // Max flow + *ulMaxFlow=ulFlowMax; + + // Min flow + *ulMinFlow=ulFlowMin; + + // Flow Step + ulFlowStepTemp=(ulFlowMax-ulFlowMin)/uiTi; + //if (uiFlowStepTemp==0 && uiFlowShape!=0) uiFlowStepTemp=1; + *ulFlowStep=ulFlowStepTemp; +} + + + +/******************************************************************************* +* Function Name : TestTriggerExpiratoire +* Description : Manage the expiratory trigger +* Input : ucValeurSeuil = threshold (% of the flow max) to reach in order to cycle +* Output : None +* Return : TRUE if cycling active +*******************************************************************************/ +unsigned char TestTriggerExpiratoire(unsigned char ucValeurSeuil, unsigned int uiPressureSetting) +{ + unsigned char ucSeuil=ucValeurSeuil; + unsigned int uiCalculTemp; + int16_t iConductanceBaseLine=UpdateInspiratoryConductanceAverage(); + // Management automatic expiratory trigger + ucTempoTriggerExpiAuto--; + if (ucTempoTriggerExpiAuto==0) + { + ucTempoTriggerExpiAuto=TEMPO_TRIGGER_EXPI; + ucExpiTriggerTreshold++; + } + + // Test si flow<0?? + if (iBlowerFlowSmoothingMes<0) + { + return(TRUE); + } + // Test if deacring flow?? + else if (iBlowerFlowSmoothingMes<iBlowerFlowSmoothingMaxMes) + { + // Test if Trigger Expi=AUTO ?? + if ((ucValeurSeuil==ExpiTriggerSet_A_MAX && uiPatientType==PATIENT_ADULT) || + (ucValeurSeuil==ExpiTriggerSet_P_MAX && uiPatientType==PATIENT_PEDIA)) + ucSeuil=ucExpiTriggerTreshold; + + u16 conducThresh = 2000; + + if(enTubeConfigType == 1 ) + conducThresh = 750; + else if(enTubeConfigType == 2) + conducThresh = 1500; + + // Test if cycling or not + uiCalculTemp=((unsigned long)iBlowerFlowSmoothingMaxMes*ucSeuil)/100; + if (uiCalculTemp>iBlowerFlowSmoothingMes) + return(TRUE); + else if (uiProximalPressureMes>(uiPressureSetting+20)) + return(TRUE); + else if (uiConductanceCalc < (iConductanceBaseLine - conducThresh)) + { + ResetInspiratoryConductanceAverage(); + return(TRUE); + } + } + return(FALSE); +} + + +/******************************************************************************* +* Function Name : TestInspiratoryTrigger +* Description : Manage the inspiratory trigger +* Input : bSpont = TRUE if spontaneous mode +* uiTe = expiration time (ms) +* uiFlowTreshold = flow threshold (dl/min) +* Output : None +* Return : TRUE if cycling active +*******************************************************************************/ +bool TestInspiratoryTrigger(bool bSpont, u16 uiTe, u16 uiFlowTreshold) +{ + //int16_t iInspiratoryFlowDeltaAverage; + //int16_t iDeltaOfTheDelta1, iDeltaOfTheDelta2, iDeltaOfTheDelta3, iDeltaOfTheDelta4; + bool bTrigger=FALSE; + //int16_t iVirtualFlow; + int16_t iConductanceBaseLine; + + // Manual breath management + if (uiTe>TE_SET_MIN) + { + if (bManualBreath==TRUE) + { + bManualBreath=FALSE; + bDisplayInspiratoryTrigger=TRUE; + return(TRUE); + } + } + + // Trigger management + if ((bSpont==TRUE) || + (bSpont==FALSE && uiFlowTreshold<InspiTriggerFlowSet_A_MAX && uiPatientType==PATIENT_ADULT) || + (bSpont==FALSE && uiFlowTreshold<InspiTriggerFlowSet_P_MAX && uiPatientType==PATIENT_PEDIA)) + { + // Init scheduler + if (uiTe==1) + { + ucInspiTriggerScheduler=0; + iInspiratoryFlowMin=0; + ucMinFlowCounter=NUMBER_MIN_FLOW_VALUE; + ucCounterTriggerValid=NUMBER_TRIGGER_VALID; + bDetectionConstantFlow=FALSE; + } + + iConductanceBaseLine=UpdateInspiratoryConductanceAverage(); + // Manage detection phase + switch(ucInspiTriggerScheduler) + { + default: + case 0: + { + // Update the buffer on the Inspiratory flow average + + // Detect min flow + if (iBlowerFlowSmoothingMesForTrigger<iInspiratoryFlowMin) + { + iInspiratoryFlowMin=iBlowerFlowSmoothingMesForTrigger; + ucMinFlowCounter=NUMBER_MIN_FLOW_VALUE; + } + else + { + ucMinFlowCounter--; + if (ucMinFlowCounter==0) + ucInspiTriggerScheduler=1; + } + break; + } + case 1: + { + //ucTriggerNumber=0; + + if (uiTe>TE_SET_MIN) + { +// // Fast trigger management +// if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]<=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-25]) +// { +// iVirtualFlow=(iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-25]<<1)-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]; +// if (iBlowerFlowSmoothingMesForTrigger>=(iVirtualFlow+(int16_t)(uiFlowTreshold*7))) +// { +// //ucTriggerNumber=1; +// //if (fBlockCloseLoop==FALSE) +// bTrigger=TRUE; +// } +// } +// if (bTrigger==FALSE && iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-100]<=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]) +// { +// iVirtualFlow=(iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-50]<<1)-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-100]; +// if (iBlowerFlowSmoothingMesForTrigger>=(iVirtualFlow+(int16_t)(uiFlowTreshold*15))) +// { +// //ucTriggerNumber=2; +// //if (fBlockCloseLoop==FALSE) +// bTrigger=TRUE; +// } +// } +// +// // Slow trigger management +// if (TestInspiratorySlowTrigger(iFlowBaseLine, uiFlowTreshold*10)==TRUE) +// { +// //ucTriggerNumber=3; +// bTrigger=TRUE; +// } + //Conductance Trigger + if(uiConductanceCalc >= (iConductanceBaseLine + 2000)) + { + bTrigger = TRUE; + } + + // Trigger occurs?? + if (bTrigger==TRUE) + { + ucCounterTriggerValid--; + if (ucCounterTriggerValid==0) + { + bDisplayInspiratoryTrigger=TRUE; + ResetInspiratoryConductanceAverage(); + return(TRUE); + } + } + else + ucCounterTriggerValid=NUMBER_TRIGGER_VALID; + } + break; + } + } + } + return(FALSE); +} + +/******************************************************************************* +* Function Name : UpdateInspiratoryConductanceAverage +* Description : Fill the buffer with the expiratory conductance and compute the average +* Input : None +* Output : None +* Return : Inspiratory flow average +*******************************************************************************/ +u16 conducIndex = 0; +int32_t lSumConductance = 0; +bool bufFilled = FALSE; + +int16_t UpdateInspiratoryConductanceAverage(void) +{ + int16_t oldValue = iBufferIFlow[conducIndex]; + iBufferIFlow[conducIndex] = uiConductanceCalc; + lSumConductance += uiConductanceCalc; + conducIndex++; + + if(conducIndex > SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER) + { + conducIndex = 0; + bufFilled = TRUE; + } + + if(bufFilled) + { + lSumConductance -= oldValue; + return (lSumConductance/SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER); + } + else + { + return (lSumConductance/conducIndex); + } +} + +/******************************************************************************* +* Function Name : ResetInspiratoryConductanceAverage +* Description : Fill the buffer with the expiratory conductance and compute the average +* Input : None +* Output : None +* Return : Inspiratory flow average +*******************************************************************************/ + +void ResetInspiratoryConductanceAverage(void) +{ + conducIndex = 0; + lSumConductance = 0; + bufFilled = FALSE; +} + +/******************************************************************************* +* Function Name : UpdateInspiratoryFlowAverage +* Description : Fill the buffer with the inspiratory flow and compute the average +* Input : None +* Output : None +* Return : Inspiratory flow average +*******************************************************************************/ +int16_t UpdateInspiratoryFlowAverage(void) +{ + u16 uiIndex; + int32_t lSumIFlow=0; + + // Roll the buffer + for(uiIndex=1; uiIndex<SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER; uiIndex++) + { + iBufferIFlow[uiIndex-1]=iBufferIFlow[uiIndex]; // Upate the Inspiratory Flow buffer + lSumIFlow+=iBufferIFlow[uiIndex-1]; // Sum the Inspiratory Flow + } + + // Add new flow value + iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]=iBlowerFlowSmoothingMesForTrigger; // Upate the Inspiratory Flow buffer + lSumIFlow+=iBlowerFlowSmoothingMesForTrigger; // Sum the Inspiratory Flow + + return(lSumIFlow/SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER); +} + + +/******************************************************************************* +* Function Name : TestInspiratorySlowTrigger +* Description : Compute flow base line and test trigger +* Input : FlowTreshold = flow threshold (cl/min) +* Output : None +* Return : TRUE if trigger occurs +*******************************************************************************/ +bool TestInspiratorySlowTrigger(int16_t iTheFlowBaseLine, u16 uiFlowTreshold) +{ + int16_t iFlowDelta1, iFlowDelta2, iFlowDelta3; + + if (bDetectionConstantFlow==FALSE) + { + // Detection constant flow + if (iBufferIFlow[0]<iTheFlowBaseLine) + iFlowDelta1=iTheFlowBaseLine-iBufferIFlow[0]; + else + iFlowDelta1=iBufferIFlow[0]-iTheFlowBaseLine; + + if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]<iTheFlowBaseLine) + iFlowDelta2=iTheFlowBaseLine-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]; + else + iFlowDelta2=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER>>1]-iTheFlowBaseLine; + + if (iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]<iTheFlowBaseLine) + iFlowDelta3=iTheFlowBaseLine-iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]; + else + iFlowDelta3=iBufferIFlow[SIZE_INSPIRATORY_FLOW_AVERAGE_BUFFER-1]-iTheFlowBaseLine; + + if (iFlowDelta1<60 && iFlowDelta2<60 && iFlowDelta3<60) + { + iFlowBaseLineReference=iTheFlowBaseLine; + bDetectionConstantFlow=TRUE; + } + } + else + { + // Detect trigger + if (iBlowerFlowSmoothingMesForTrigger>=(iFlowBaseLineReference+(int16_t)uiFlowTreshold)) + { + return(TRUE); + } + } + return(FALSE); +} + + +/******************************************************************************* +* Function Name : ApplyDefaultValueToTemporaryVentilationSettings +* Description : Init temporary ventilation settings with default values +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ApplyDefaultValueToTemporaryVentilationSettings(void) +{ + u8 ucIndex; + + enVentilationModeTemp=VentilationMode_DEF; + uiPatientTypeTemp=PatientType_DEF; + enTubeConfigTypeTemp=(enMaroubraTubeConfigurationList)ReturnDefaultTubeConfiguration(VentilationMode_DEF); + + // Init all temporary settings + if (uiPatientType==PATIENT_ADULT) + { + for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) + uiVentilationSetTemp[ucIndex]=sLRSGroup[ucIndex].uiDefault_Adult; + } + else + { + for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) + uiVentilationSetTemp[ucIndex]=sLRSGroup[ucIndex].uiDefault_Pedia; + } +} + + +/******************************************************************************* +* Function Name : CheckTemporaryVentilationSettingRange +* Description : Check all the temporary settings range +* Input : None +* Output : None +* Return : FALSE if one the settings is out of range +*******************************************************************************/ +opstatus_t CheckTemporaryVentilationSettingRange(void) +{ + u8 ucIndex; + + if ((uiPatientTypeTemp==PATIENT_PEDIA || uiPatientTypeTemp==PATIENT_ADULT) && enVentilationModeTemp<NUMBER_OF_MODE && enTubeConfigTypeTemp<NUMBER_OF_TUBE_CONFIGURATION) + { + for (ucIndex=0; ucIndex<SIZE_LRS_GROUP; ucIndex++) + { + // Check data range + if (uiPatientTypeTemp==PATIENT_PEDIA) + { + if (uiVentilationSetTemp[ucIndex]<sLRSGroup[ucIndex].uiMin_Pedia) + return(OPSTATUS_FAIL); + else if (uiVentilationSetTemp[ucIndex]>sLRSGroup[ucIndex].uiMax_Pedia) + return(OPSTATUS_FAIL); + } + else + { + if (uiVentilationSetTemp[ucIndex]<sLRSGroup[ucIndex].uiMin_Adult) + return(OPSTATUS_FAIL); + else if (uiVentilationSetTemp[ucIndex]>sLRSGroup[ucIndex].uiMax_Adult) + return(OPSTATUS_FAIL); + } + } + return(OPSTATUS_OK); + } + return(OPSTATUS_FAIL); +} + + + +/******************************************************************************* +* Function Name : ApplyDefaultValueToTechnicalSettings +* Description : Init technical settings with default values +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ApplyDefaultValueToTechnicalSettings(void) +{ + u8 ucIndex; + + // Init all temporary settings + for (ucIndex=0; ucIndex<SIZE_LRTS_GROUP; ucIndex++) + uiTechnicalDataSet[ucIndex]=sLRTSGroup[ucIndex].uiDefault; +} + + +/******************************************************************************* +* Function Name : CheckTechnicalSettingsRange +* Description : Check all the technical settings range +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void CheckTechnicalSettingsRange(void) +{ + u8 ucIndex; + bool fError=FALSE; + + for (ucIndex=0; ucIndex<SIZE_LRTS_GROUP; ucIndex++) + { + if (uiTechnicalDataSet[ucIndex]<sLRTSGroup[ucIndex].uiMin || uiTechnicalDataSet[ucIndex]>sLRTSGroup[ucIndex].uiMax) + { + uiTechnicalDataSet[ucIndex]=sLRTSGroup[ucIndex].uiDefault; + fError=TRUE; + //break; + } + } + + if (fError==TRUE) + uiFlagsAlarm[ALARM_FLAGS2]|=TECHNICAL_SETTINGS_RANGE_ALARM_MASK; + else + uiFlagsAlarm[ALARM_FLAGS2]&=(~TECHNICAL_SETTINGS_RANGE_ALARM_MASK); +} + + +/******************************************************************************* +* Function Name : CheckFlowLUTRange +* Description : Check the flow LUT +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void CheckFlowLUTRange(void) +{ + u16 uiIndex; + bool fError=FALSE; + + if (stLUTFlowSensor.uiLUT_TableSize<(FLOW_CALIB_NUMBER_OF_SAMPLES>>1) || stLUTFlowSensor.uiLUT_TableSize>FLOW_CALIB_NUMBER_OF_SAMPLES) + { + ApplyDefaultFlowLUT(); + fError=TRUE; + } + else + { + for (uiIndex=1; uiIndex<stLUTFlowSensor.uiLUT_TableSize; uiIndex++) + { + if (stLUTFlowSensor.uiFlowValue[uiIndex]<=stLUTFlowSensor.uiFlowValue[uiIndex-1] || + stLUTFlowSensor.uiFlowSensorTicks[uiIndex]<=stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]) + { + ApplyDefaultFlowLUT(); + fError=TRUE; + break; + } + } + } + + if (fError==TRUE) + uiFlagsAlarm[ALARM_FLAGS2]|=NO_FLOW_LUT_ALARM_MASK; + else + uiFlagsAlarm[ALARM_FLAGS2]&=(~NO_FLOW_LUT_ALARM_MASK); +} + + +/******************************************************************************* +* Function Name : ApplyDefaultFlowLUT +* Description : Apply default value for the flow LUT +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ApplyDefaultFlowLUT(void) +{ + u16 uiIndex; + + stLUTFlowSensor.uiLUT_TableSize=stDefaultLUTFlowSensor.uiLUT_TableSize; + for (uiIndex=0; uiIndex<FLOW_CALIB_NUMBER_OF_SAMPLES; uiIndex++) + { + stLUTFlowSensor.uiFlowValue[uiIndex]=stDefaultLUTFlowSensor.uiFlowValue[uiIndex]; + stLUTFlowSensor.uiFlowSensorTicks[uiIndex]=stDefaultLUTFlowSensor.uiFlowSensorTicks[uiIndex]; + } +} + + +/******************************************************************************* +* Function Name : ReturnDefaultTubeConfiguration +* Description : The default tubing configuration according to the current ventilation mode +* Input : a ventilation mode +* Output : None +* Return : The tube configuration +*******************************************************************************/ +u16 ReturnDefaultTubeConfiguration(u16 uiMode) +{ + u8 ucIndex; + + for (ucIndex=0; ucIndex<NUMBER_OF_TUBE_CONFIGURATION; ucIndex++) + { + if (ucTubeConfigurationTable[ucIndex][uiMode]==TUBE_DEFAULT) + { + return(ucIndex); + } + } + return(0); +} + + +/******************************************************************************* +* Function Name : ApplyAllDefaultValues +* Description : Apply all default values in the technical and settings zones +* : BE CARFUL this function call "ControlHW" function +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ApplyAllDefaultValues(void) +{ + // Init ventilation settings + ApplyDefaultValueToTemporaryVentilationSettings(); + + // Init technical settings + ApplyDefaultValueToTechnicalSettings(); + + // Init flow LUT + ApplyDefaultFlowLUT(); + + // Default value for the device/patient time counter + ulDeviceTimeCounter=0; + ulPatientTimeCounter=0; + + // Default value for the blower revolution counter + ulBlowerRevolutionCounter=0; + + bComputeOffsetSensors=TRUE; +} +#endif // C_M3_DEVICETEST_TARGET + +/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ + + +
--- a/main.cpp Tue Jun 09 22:57:20 2020 +0000 +++ b/main.cpp Thu Jun 11 22:55:06 2020 +0000 @@ -1,167 +1,46 @@ #include "mbed.h" #include "TS_DISCO_F429ZI.h" #include "LCD_DISCO_F429ZI.h" +#include "Screens.h" +#include "Touch.h" +#include "main.h" #define y_max 310 DigitalOut led1(LED1); + Ticker ts_service; - AnalogIn pdiff(PC_5); AnalogIn p_guage(PC_4); LCD_DISCO_F429ZI lcd; TS_DISCO_F429ZI ts; + //PwmOut led(LED1); PwmOut motor(PB_0); -TS_StateTypeDef TS_State; -TS_StateTypeDef Old_TS_State; + uint8_t text[30]; -uint8_t status; - -uint16_t x, y = 0; -uint16_t touch_x, touch_y = 0; -bool press_detected = false; uint16_t setPressure = 0; -uint8_t isr_text[30]; -uint8_t display_screen = 1; - -int showScreen(uint8_t screen) -{ - switch(screen) - { - case 1 : - BSP_LCD_SetFont(&Font20); - setPressure = (y*20)/y_max; - sprintf((char*)isr_text, "SetP=%2d", setPressure); - lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&isr_text, CENTER_MODE); - sprintf((char*)isr_text, "PDIFF=%.2f", (pdiff.read()*6.0f)-0.8f); - lcd.DisplayStringAt(0, LINE(2), (uint8_t *)&isr_text, CENTER_MODE); - sprintf((char*)isr_text, "PGUAGE=%.2f", (p_guage.read()*38.0f)-10.0f); - lcd.DisplayStringAt(0, LINE(3), (uint8_t *)&isr_text, CENTER_MODE); - - BSP_LCD_SetFont(&Font12); - lcd.DrawRect(5, 100, 70, 50); - lcd.DrawRect(85, 100, 70, 50); - lcd.DrawRect(165, 100, 70, 50); - sprintf((char*)isr_text, " Start"); - lcd.DisplayStringAt(10, 130, (uint8_t *)&isr_text, LEFT_MODE); - sprintf((char*)isr_text, "Settings"); - lcd.DisplayStringAt(95, 130, (uint8_t *)&isr_text, LEFT_MODE); - sprintf((char*)isr_text, "Stop"); - lcd.DisplayStringAt(170, 130, (uint8_t *)&isr_text, LEFT_MODE); - - lcd.DrawRect(5, 160, 70, 50); - lcd.DrawRect(85, 160, 70, 50); - lcd.DrawRect(165, 160, 70, 50); - - lcd.DrawRect(5, 220, 70, 50); - lcd.DrawRect(85, 220, 70, 50); - lcd.DrawRect(165, 220, 70, 50); - break; - case 2 : - BSP_LCD_SetFont(&Font20); - setPressure = (y*20)/y_max; - sprintf((char*)isr_text, "SetPress=%2d", setPressure); - lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&isr_text, CENTER_MODE); - sprintf((char*)isr_text, "PDIFF=%.2f", pdiff.read()*6.0f); - lcd.DisplayStringAt(0, LINE(2), (uint8_t *)&isr_text, CENTER_MODE); - sprintf((char*)isr_text, "PGUAGE=%.2f", p_guage.read()*38.0f); - lcd.DisplayStringAt(0, LINE(3), (uint8_t *)&isr_text, CENTER_MODE); - - BSP_LCD_SetFont(&Font12); - lcd.DrawRect(5, 100, 70, 50); - lcd.DrawRect(85, 100, 70, 50); - lcd.DrawRect(165, 100, 70, 50); - sprintf((char*)isr_text, " Start"); - lcd.DisplayStringAt(10, 130, (uint8_t *)&isr_text, LEFT_MODE); - sprintf((char*)isr_text, "Settings"); - lcd.DisplayStringAt(95, 130, (uint8_t *)&isr_text, LEFT_MODE); - sprintf((char*)isr_text, " Stop"); - lcd.DisplayStringAt(165, 130, (uint8_t *)&isr_text, LEFT_MODE); - - lcd.DrawRect(5, 160, 70, 50); - lcd.DrawRect(85, 160, 70, 50); - lcd.DrawRect(165, 160, 70, 50); - - lcd.DrawRect(5, 220, 70, 50); - lcd.DrawRect(85, 220, 70, 50); - lcd.DrawRect(165, 220, 70, 50); - } - return screen; -} - -void CheckPress() -{ - if(press_detected) - { - display_screen = 2; - } - -} - -void CheckTs() -{ - ts.GetState(&TS_State); - if (TS_State.TouchDetected) - { - x = TS_State.X; - y = TS_State.Y; - } - if ((Old_TS_State.TouchDetected) && (!TS_State.TouchDetected)) - { - touch_x = x; - touch_y = y; - press_detected = true; - } - Old_TS_State = TS_State; -} +ScreenState display_screen = StartUp; // StartScreen +uint8_t status = 0; int main() { motor.period(0.1f); - - BSP_LCD_SetFont(&Font20); - - lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN", CENTER_MODE); - lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"DEMO", CENTER_MODE); - - + + ts_service.attach(&CheckTs, 0.1); // the address of the function to be attached (flip) and the interval (2 seconds) + status= ts.Init(lcd.GetXSize(), lcd.GetYSize()); + wait(1); - - status = ts.Init(lcd.GetXSize(), lcd.GetYSize()); - - if (status != TS_OK) - { - lcd.Clear(LCD_COLOR_RED); - lcd.SetBackColor(LCD_COLOR_RED); - lcd.SetTextColor(LCD_COLOR_WHITE); - lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN", CENTER_MODE); - lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"INIT FAIL", CENTER_MODE); - } - else - { - lcd.Clear(LCD_COLOR_GREEN); - lcd.SetBackColor(LCD_COLOR_GREEN); - lcd.SetTextColor(LCD_COLOR_WHITE); - lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN", CENTER_MODE); - lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"INIT OK", CENTER_MODE); - } - - wait(1); - lcd.Clear(LCD_COLOR_BLUE); - lcd.SetBackColor(LCD_COLOR_BLUE); + lcd.Clear(LCD_COLOR_DARKGRAY); + lcd.SetBackColor(LCD_COLOR_DARKGRAY); lcd.SetTextColor(LCD_COLOR_WHITE); - - ts_service.attach(&CheckTs, 0.2); // the address of the function to be attached (flip) and the interval (2 seconds) while(1) { - led1 = !led1; - wait(0.2); - CheckPress(); - showScreen(display_screen); + CheckPress(display_screen); + showScreen(display_screen,lcd); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.h Thu Jun 11 22:55:06 2020 +0000 @@ -0,0 +1,18 @@ +#ifndef __MAIN_H +#define __MAIN_H +#ifdef TARGET_DISCO_F429ZI +#include "TS_DISCO_F429ZI.h" +#include "LCD_DISCO_F429ZI.h" +#include "Screens.h" + +/*******************************Variables**************************/ +extern ScreenState display_screen; // Screen State Variable +extern uint16_t setPressure ; // Pressure Setting +extern Ticker ts_service; +extern TS_DISCO_F429ZI ts; + +#else +#error "This class must be used with DISCO_F429ZI board only." +#endif // TARGET_DISCO_F429ZI + +#endif \ No newline at end of file