Started a gui menuflow

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI BSP_DISCO_F429ZI

Monitoring.txt

Committer:
ahaas92
Date:
2020-06-11
Revision:
3:b029a3f73a9e

File content as of revision 3:b029a3f73a9e:

/*********************************************************************/

/* 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****/