Started a gui menuflow

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI BSP_DISCO_F429ZI

Revision:
2:5828e6917e75
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Monitoring.c	Tue Jun 09 22:57:20 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****/
+
+
+