stm8_tsl_multichannelkey.c

来自「STM8s」· C语言 代码 · 共 1,875 行 · 第 1/4 页

C
1,875
字号
    }
  }
  else
  {
    TSL_MCKey_BackToIdleState();
  }

}


/**
  ******************************************************************************
  * @brief During calibration, calculates the new reference.
  * @par Parameters:
  * None
  * @retval void None
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
void TSL_MCKey_CalibrationTreatment(void)
{

  for (ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++)
  {
#if !defined(CHARGE_TRANSFER)
    if (pMCKeyStruct->Channel[ChannelIndex].LastMeasRejectNb <= MAX_REJECTED_MEASUREMENTS)
    {
      pMCKeyStruct->Channel[ChannelIndex].Reference += pMCKeyStruct->Channel[ChannelIndex].LastMeas;
    }
    else
    {
      return;
    }
#else
    pMCKeyStruct->Channel[ChannelIndex].Reference += pMCKeyStruct->Channel[ChannelIndex].LastMeas;
#endif
  }

  pMCKeyStruct->Counter--;

  if (!pMCKeyStruct->Counter)
  {
    for (ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++)
    {
      // Warning: Must be divided by MCKEY_CALIBRATION_COUNT_DEFAULT !!!
      pMCKeyStruct->Channel[ChannelIndex].Reference = (pMCKeyStruct->Channel[ChannelIndex].Reference >> 3);
    }
    TSL_MCKey_SetIdleState();
  }

}


/**
  ******************************************************************************
  * @brief Calculates the position on the MCKey.
  * @par Parameters:
  * None
  * @retval u8 Returns 0x00 if no change, 0xFF is new position detected
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
u8 TSL_MCKey_Position(void)
{

  u8 Index1, Index2;
#if CHANNEL_PER_MCKEY == 8
  u8 Index3;
#endif
  u16 Major, Minor, SectorComputation;
  s16 NewPosition;
  u8 uNewPosition;
  u32 tmpdelta;
  u8 PositionCorrection;
  u8 retval = 0x00;

  Delta1 = 0;
  Delta2 = 0;
  Delta3 = 0;

  Index1 = 0;
  Index2 = 0;
#if CHANNEL_PER_MCKEY == 8
  Index3 = 0;
#endif

  for (ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++)
  {

    TSL_MCKey_DeltaCalculation(ChannelIndex);

    // Delta must be positive only otherwise it is noise
    if (Delta < 0)
    {
      Delta = 0;
    }

    /* We normalize the Delta */
    tmpdelta = (u32)(Delta * (u32)(pMCKeyStruct->Channel[0].Reference));
    tmpdelta = tmpdelta / pMCKeyStruct->Channel[ChannelIndex].Reference;
    Delta = (s16)tmpdelta;

    /* Apply a fixed coefficient */
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 1
    if (KeyIndex == 0) // MCKEY1
    {
#endif
      if (MCKEY1_DELTA_COEFF[ChannelIndex] != 0x0100)
      {
        tmpdelta = (u32)(Delta * MCKEY1_DELTA_COEFF[ChannelIndex]);
        Delta = (s16)(tmpdelta >> (u8)8);
      }
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 1
    }
    else // MCKEY2
    {
      if (MCKEY2_DELTA_COEFF[ChannelIndex] != 0x0100)
      {
        tmpdelta = (u32)(Delta * MCKEY2_DELTA_COEFF[ChannelIndex]);
        Delta = (s16)(tmpdelta >> (u8)8);
      }
    }
#endif

    /* Sort the biggest, middle and lowest signals measured
       - Delta1 and Index1 = biggest
       - Delta2 and Index2 = middle
       - Delta3 and Index3 = lowest */
    if (Delta > Delta1)
    {
      Delta3 = Delta2;
      Delta2 = Delta1;
      Delta1 = Delta;
#if CHANNEL_PER_MCKEY == 8
      Index3 = Index2;
#endif
      Index2 = Index1;
      Index1 = ChannelIndex;
    }
    else
    {
      if (Delta > Delta2)
      {
        Delta3 = Delta2;
        Delta2 = Delta;
#if CHANNEL_PER_MCKEY == 8
        Index3 = Index2;
#endif
        Index2 = ChannelIndex;
      }
      else
      {
        if (Delta > Delta3)
        {
#if CHANNEL_PER_MCKEY == 8
          Index3 = ChannelIndex;
#endif
          Delta3 = Delta;
        }
      }
    }

  } /* for all channels */

  /* Noise filter: we need at least two significant Delta measurements */
  if (Delta2 < ((u8)(pMCKeyStruct->EndDetectThreshold >> 1)) - 1)
  {
    return retval;
  }

  //----------------------------------------------------------------------------
  // Position calculation...
  //----------------------------------------------------------------------------

  /*----------------------------------------------------------------------------
    B = Biggest signal measured (Delta1/Index1)
    M = Middle signal measured (Delta2/Index2)
    S = Smallest signal measured (Delta3/Index3)
    
    - The equation to find the position is:
      Position = Offset +/- [ Sector_Size x ( Major / (Major + Minor) ) ]
   
    - The Offset is the position of the middle of the Middle signal segment.
      All the Offset values are stored in the ROM table Table_POSITION_OFFSET.
   
    - Major = Biggest - Smallest signals
      Minor = Middle - Smallest signals
   
    - The Sector_Size depends of the number of channels used
  ----------------------------------------------------------------------------*/

  /* Calculates the Major and Minor parameters */
  Minor = Delta2 - Delta3; // Middle - Smallest signals
  Major = Delta1 - Delta3; // Biggest - Smallest signals

#if NUMBER_OF_MULTI_CHANNEL_KEYS > 1
  if (KeyIndex == 0) // MCKEY1
  {
#endif
    NewPosition = MCKEY1_TABLE_POSITION_OFFSET[Index1][Index2];
    SectorComputation = MCKEY1_SECTOR_COMPUTATION;
    PositionCorrection = MCKEY1_POSITION_CORRECTION;
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 1
  }
  else // MCKEY2
  {
    NewPosition = MCKEY2_TABLE_POSITION_OFFSET[Index1][Index2];
    SectorComputation = MCKEY2_SECTOR_COMPUTATION;
    PositionCorrection = MCKEY2_POSITION_CORRECTION;
  }
#endif

  /* Calculates: [ Sector_Size x ( Major / (Major + Minor) ) ] */
  SectorComputation = Major * SectorComputation;
  SectorComputation = SectorComputation / (Major + Minor);

  // Use the sign bit from table to define the interpretation direction.
  // The NewPosition is multiplied by 2 because the Offset stored in the ROM
  // table is divided by 2...
  if (NewPosition > 0)   // means Offset is > 0 in the ROM table
  {
    NewPosition = (s16)(NewPosition << 1); /*lint !e701 suppress info on this line only */
    NewPosition += SectorComputation;
  }
  else // means Offset is <= 0 in the ROM table
  {
    NewPosition = (s16)((-NewPosition) << 1); /*lint !e701 suppress info on this line only */
    NewPosition -= SectorComputation;
  }

  if (pMCKeyStruct->Setting.b.MCKEY_TYPE) // It's a Slider...
  {

    /* First adjustment used to shift all the values to obtain the "zero" */
    if (NewPosition > 0)
    {
      NewPosition -= PositionCorrection;
    }
    else
    {
      NewPosition = NewPosition + 256 - PositionCorrection;
    }

    /* Second adjustment used to clamp the values at extremities of slider */
    if (NewPosition < 0)
    {
      NewPosition = 0;
    }

    if (NewPosition > 255)
    {
      NewPosition = 255;
    }

  }
  else // It's a Wheel: we keep only the low byte
  {
    NewPosition = (u8)NewPosition;
  }

  //----------------------------------------------------------------------------
  // Direction Change Process
  //----------------------------------------------------------------------------

#if MCKEY_DIRECTION_CHANGE_ENABLED > 0

  if (pMCKeyStruct->Setting.b.DIRECTION) // Anticlockwise direction ...
  {

    // Check Direction changed and Position overflow from 0x00 to 0xFF not realized !
    if (((u8)NewPosition > pMCKeyStruct->UnScaledPosition) && (((u8)NewPosition - pMCKeyStruct->UnScaledPosition) < MCKEY_DIRECTION_CHANGE_MAX_DISPLACEMENT))
    {
      if (NewPosition < (u16)(pMCKeyStruct->UnScaledPosition + pMCKeyStruct->DirectionChangeThreshold))
      {
        pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
        return retval;
      }
      else
      {
        pMCKeyStruct->Channel[1].IntegratorCounter--;
        if (!pMCKeyStruct->Channel[1].IntegratorCounter)
        {
          pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
          pMCKeyStruct->Setting.b.DIRECTION = 0;  // New direction accepted: clockwise.
        }
        else
        {
          return retval;
        }
      }
    }

    // Check position overflow from 0xFF to 0x00 to be filtered !
    if ((NewPosition + MCKEY_DIRECTION_CHANGE_MAX_DISPLACEMENT) < pMCKeyStruct->UnScaledPosition)
    {
      if ((NewPosition + MCKEY_DIRECTION_CHANGE_TOTAL_STEPS) < (u16)(pMCKeyStruct->UnScaledPosition + pMCKeyStruct->DirectionChangeThreshold))
      {
        pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
        return retval;
      }
      else
      {
        pMCKeyStruct->Channel[1].IntegratorCounter--;
        if (!pMCKeyStruct->Channel[1].IntegratorCounter)
        {
          pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
          pMCKeyStruct->Setting.b.DIRECTION = 0;  // New direction accepted: clockwise.
        }
        else
        {
          return retval;
        }
      }
    }

  }
  else // Clockwise direction... DEFAULT SETTING !
  {

    // Check Direction changed and Position overflow from 0xFF to 0x00 not realized !
    if (((u8)NewPosition < pMCKeyStruct->UnScaledPosition) && ((pMCKeyStruct->UnScaledPosition - (u8)NewPosition) < MCKEY_DIRECTION_CHANGE_MAX_DISPLACEMENT))
    {
      if ((NewPosition + pMCKeyStruct->DirectionChangeThreshold) > pMCKeyStruct->UnScaledPosition)
      {
        pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
        return retval;
      }
      else
      {
        pMCKeyStruct->Channel[1].IntegratorCounter--;
        if (!pMCKeyStruct->Channel[1].IntegratorCounter)
        {
          pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
          pMCKeyStruct->Setting.b.DIRECTION = 1;  // New direction accepted: anticlockwise.
        }
        else
        {
          return retval;
        }
      }
    }

    // Check position overflow from 0x00 to 0xFF to be filtered !
    if (NewPosition > (u16)(pMCKeyStruct->UnScaledPosition + MCKEY_DIRECTION_CHANGE_MAX_DISPLACEMENT))
    {
      if ((NewPosition + pMCKeyStruct->DirectionChangeThreshold) > (u16)(pMCKeyStruct->UnScaledPosition + MCKEY_DIRECTION_CHANGE_TOTAL_STEPS))
      {
        pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
        return retval;
      }
      else
      {
        pMCKeyStruct->Channel[1].IntegratorCounter--;
        if (!pMCKeyStruct->Channel[1].IntegratorCounter)
        {
          pMCKeyStruct->Channel[1].IntegratorCounter = pMCKeyStruct->DirectionChangeIntegrator;
          pMCKeyStruct->Setting.b.DIRECTION = 1;  // New direction accepted: anticlockwise.
        }
        else
        {
          return retval;
        }
      }
    }

  }

#endif // MCKEY_DIRECTION_CHANGE_ENABLED

  //----------------------------------------------------------------------------
  // Final result...
  //----------------------------------------------------------------------------

  // The UnScaledPosition parameter is always updated
  // The Position parameter is updated only if different from the previous one

  pMCKeyStruct->UnScaledPosition = (u8)NewPosition;

  uNewPosition = (u8)((u8)NewPosition >> (MCKEY_RESOLUTION_CALCULATION - pMCKeyStruct->Resolution));

  if (pMCKeyStruct->Position != uNewPosition)
  {
    pMCKeyStruct->Position = uNewPosition;
    pMCKeyStruct->Setting.b.POSCHANGED = 1; /* Warning: Application layer must reset this flag */
    retval = 0xFF;
  }

  return retval;

}


/**
  ******************************************************************************
  * @brief Check for customer code setting and adapt key state.
  * @par Parameters:
  * None
  * @retval void None
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
void TSL_MCKey_CheckDisabled(void)
{

  if (!pMCKeyStruct->Setting.b.ENABLED)
  {
    TSL_MCKey_SetDisabledState();
  }

}


/**
  ******************************************************************************
  * @brief Check for customer code setting and adapt key state.
  * @par Parameters:
  * None
  * @retval void None
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
void TSL_MCKey_CheckEnabled(void)
{

  if (pMCKeyStruct->Setting.b.ENABLED && pMCKeyStruct->Setting.b.IMPLEMENTED)
  {
    TSL_MCKey_SetCalibrationState();
  }

}


/**
  ******************************************************************************
  * @brief Verify the last burst sequence gave a result within the authorized range.
  * @par Parameters:
  * None
  * @retval u8 Return 0 if OK, 0xFF if Error.
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
u8 TSL_MCKey_CheckErrorCondition(void)
{

  for (ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++)
  {
    if ((pMCKeyStruct->Channel[ChannelIndex].LastMeas < MCKEY_MIN_ACQUISITION)
        || (pMCKeyStruct->Channel[ChannelIndex].LastMeas > MCKEY_MAX_ACQUISITION))
    {
      return 0xFF;  // Error case !
    }
  }

  return 0;

}

#endif /* CONDITIONAL COMPILING FOR MCKEYS */

/* Public functions ----------------------------------------------------------*/

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?