Use BDCMotor_class.h instead of motor_class.h

Dependents:   HelloWorld_IHM04A1

Fork of X_NUCLEO_IHM04A1 by ST

Revision:
0:2cb6ce8e07bd
Child:
1:2597a6165252
diff -r 000000000000 -r 2cb6ce8e07bd Components/l6206/l6206_class.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Components/l6206/l6206_class.cpp	Tue May 03 11:16:57 2016 +0000
@@ -0,0 +1,1258 @@
+/**
+  ******************************************************************************
+  * @file    l6206_class.cpp
+  * @author  IPC Rennes
+  * @version V1.1.0
+  * @date    March 02, 2016
+  * @brief   L6206 driver (dual full bridge driver)
+  * @note     (C) COPYRIGHT 2015 STMicroelectronics
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+
+/* Generated with STM32CubeTOO -----------------------------------------------*/
+
+
+/* Revision ------------------------------------------------------------------*/
+/*
+	Repository:       http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev
+	Branch/Trunk/Tag: trunk
+	Based on:         X-CUBE-SPN4/trunk/Drivers/BSP/Components/l6206/l6206.c
+	Revision:         0
+*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "l6206_class.h"
+#include "l6206.h"
+#include "string.h"
+
+/* Private constants  ---------------------------------------------------------*/
+    
+    
+/* Private variables ---------------------------------------------------------*/
+static uint8_t l6206ArrayNbMaxMotorsByConfig[PARALLELING_END_ENUM] = {2,3,3,4,2,3,2,3,2,1,2,1,1};
+
+/* Private constant ---------------------------------------------------------*/
+
+/** @defgroup L6206_Private_Constants L6206 Private Constants
+  * @{
+  */       
+    
+/// Max numbers of supported motors depending of the parraleling bridges configuration
+
+
+/* Function prototypes -----------------------------------------------*/
+
+/** @defgroup L6206_Exported_Functions L6206 Exported Functions
+  * @{
+  */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup L6206_Private_functions L6206 Private functions
+  * @{
+  */  
+/** @defgroup L6206_Exported_Variables L6206 Exported Variables
+  * @{
+  */       
+
+/** @defgroup L6206_Exported_Functions L6206 Exported Functions
+  * @{
+  */   
+
+/******************************************************//**
+ * @brief  Attaches a user callback to the error Handler.
+ * The call back will be then called each time the library 
+ * detects an error
+ * @param[in] callback Name of the callback to attach 
+ * to the error Hanlder
+ * @retval None
+ **********************************************************/
+void L6206::L6206_AttachErrorHandler(void (*callback)(uint16_t error))
+{
+	errorHandlerCallback = (void (*)(uint16_t error)) callback;
+}
+
+/******************************************************//**
+ * @brief  Attaches a user callback to the flag Interrupt
+ * The call back will be then called each time the status 
+ * flag pin will be pulled down due to the occurrence of 
+ * a programmed alarms ( OCD, thermal alert)
+ * @param[in] callback Name of the callback to attach 
+ * to the Flag Interrupt
+ * @retval None
+ **********************************************************/
+void L6206::L6206_AttachFlagInterrupt(void (*callback)(void))
+{
+	flagInterruptCallback = (void (*)(void))callback;
+}
+
+/******************************************************//**
+ * @brief Disable the specified bridge
+ * @param[in] bridgeId (from 0 for bridge A to 1 for bridge B)
+ * @retval None
+ * @note  When input of different brigdes are parallelized 
+ * together, the disabling of one bridge leads to the disabling
+ * of the second one
+ **********************************************************/
+void L6206::L6206_DisableBridge(uint8_t bridgeId)
+{
+  L6206_Board_DisableBridge(bridgeId);
+
+  devicePrm.bridgeEnabled[bridgeId] = FALSE;
+  if (devicePrm.config >= PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR)
+  {
+    if (bridgeId == BRIDGE_A) 
+    {
+      L6206_Board_DisableBridge(BRIDGE_B);
+      devicePrm.bridgeEnabled[BRIDGE_B] = FALSE;
+    }
+    else 
+    {
+      L6206_Board_DisableBridge(BRIDGE_A);
+      devicePrm.bridgeEnabled[BRIDGE_A] = FALSE;
+    }    
+  }  
+}
+
+/******************************************************//**
+ * @brief Enable the specified bridge
+ * @param[in] bridgeId (from 0 for bridge A to 1 for bridge B)
+ * @retval None
+ * @note  When input of different brigdes are parallelized 
+ * together, the enabling of one bridge leads to the enabling
+ * of the second one
+ **********************************************************/
+void L6206::L6206_EnableBridge(uint8_t bridgeId)
+{
+  devicePrm.bridgeEnabled[bridgeId] = TRUE;
+  if (devicePrm.config >= PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR)
+  {
+    L6206_Board_EnableBridge(bridgeId, 0);
+    if (bridgeId == BRIDGE_A) 
+    {
+      L6206_Board_EnableBridge(BRIDGE_B, 1);
+      devicePrm.bridgeEnabled[BRIDGE_B] = TRUE;
+    }
+    else 
+    {
+      L6206_Board_EnableBridge(BRIDGE_A, 1);
+      devicePrm.bridgeEnabled[BRIDGE_A] = TRUE;
+    }    
+  }
+  else
+  {
+    L6206_Board_EnableBridge(bridgeId, 1);
+  }
+}
+
+/******************************************************//**
+ * @brief Start the L6206 library
+ * @param[in] init pointer to the initialization data
+ * @retval None
+ **********************************************************/
+Status_t L6206::L6206_Init(void *init)
+{
+	deviceInstance++;
+
+	/* Initialise the GPIOs */
+	L6206_Board_GpioInit();
+
+	if (init == NULL)
+	{
+		/* Set context variables to the predefined values from l6206_target_config.h */
+		/* Set GPIO according to these values */
+		L6206_SetDeviceParamsToPredefinedValues();
+	}
+	else
+	{
+		L6206_SetDeviceParamsToGivenValues((L6206_Init_t*) init);
+	}
+
+	/* Initialise input bridges PWMs */
+	L6206_SetDualFullBridgeConfig(devicePrm.config);
+
+	return COMPONENT_OK;
+}
+
+/******************************************************//**
+ * @brief  Get the PWM frequency of the specified bridge 
+ * @param[in] bridgeId 0 for bridge A, 1 for bridge B
+ * @retval Freq in Hz
+ **********************************************************/
+uint32_t L6206::L6206_GetBridgeInputPwmFreq(uint8_t bridgeId)
+{
+	return (devicePrm.pwmFreq[(bridgeId << 1)]);
+}
+
+/******************************************************//**
+ * @brief  Returns the current speed of the specified motor
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval current speed in % from 0 to 100
+ **********************************************************/
+uint16_t L6206::L6206_GetCurrentSpeed(uint8_t motorId)
+{                                                  
+	uint16_t speed = 0;
+
+  if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }
+  else if (devicePrm.motionState[motorId] != INACTIVE)
+  {
+    speed = devicePrm.speed[motorId];
+  }
+  
+  return (speed);
+}
+
+/******************************************************//**
+ * @brief Returns the device state
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval State (STEADY or INACTIVE)
+ **********************************************************/
+motorState_t L6206::L6206_GetDeviceState(uint8_t motorId)
+{
+	motorState_t state =  INACTIVE;
+
+  if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }
+  else
+  {
+    state =  devicePrm.motionState[motorId];
+  }
+  return (state);  
+}
+
+/******************************************************//**
+ * @brief Returns the FW version of the library
+ * @retval L6206_FW_VERSION
+ **********************************************************/
+uint8_t L6206::L6206_GetFwVersion(void)
+{
+  return (L6206_FW_VERSION);
+}
+
+/******************************************************//**
+ * @brief  Returns the max  speed of the specified motor
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval maxSpeed in % from 0 to 100
+ **********************************************************/
+uint16_t L6206::L6206_GetMaxSpeed(uint8_t motorId)
+{
+	uint16_t speed = 0;
+  if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }
+  else
+  {
+    speed =  devicePrm.speed[motorId];
+  }
+  return (speed);
+}
+
+
+/******************************************************//**
+ * @brief  Get the status of the bridge enabling of the corresponding bridge
+ * @param[in] bridgeId from 0 for bridge A to 1 for bridge B
+ * @retval State of the Enable&Flag pin of the corresponding bridge (1 set, 0 for reset)
+  **********************************************************/
+uint16_t L6206::L6206_GetBridgeStatus(uint8_t bridgeId)
+{
+  uint16_t status = L6206_Board_GetFlagPinState(bridgeId);
+  
+  return (status);
+}
+
+/******************************************************//**
+ * @brief  Immediatly stops the motor and disable the power bridge
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval None
+ * @note  if two motors uses the same power bridge, the 
+ * power bridge will be disable only if the two motors are
+ * stopped
+ **********************************************************/
+void L6206::L6206_HardHiz(uint8_t motorId)
+{
+	if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }
+  else
+  {
+     /* Get bridge Id of the corresponding motor */
+    uint8_t bridgeId = L6206_GetBridgeIdUsedByMotorId(motorId);
+    
+    if (devicePrm.bridgeEnabled[bridgeId] != FALSE)
+    {
+      bool skip = FALSE;
+
+      /* Check if another motor is currently running by using the same bridge */
+      switch (devicePrm.config)
+      {
+        case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+          if ((motorId > 0) && (devicePrm.motionState[1] == STEADY) && (devicePrm.motionState[2] == STEADY))
+          {
+            skip = TRUE;
+          }
+          break;
+        case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+          if ((motorId < 2) && (devicePrm.motionState[0] == STEADY) && (devicePrm.motionState[1] == STEADY))
+          {
+            skip = TRUE;
+          }
+          break;          
+        case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+          if (((motorId < 2) && (devicePrm.motionState[0] == STEADY) && (devicePrm.motionState[1] == STEADY))||
+              ((motorId > 1) && (devicePrm.motionState[2] == STEADY) && (devicePrm.motionState[3] == STEADY)))
+          {
+            skip = TRUE;
+          }
+          break;          
+        case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+          if ((motorId > 0) && (devicePrm.motionState[1] == STEADY) && (devicePrm.motionState[2] == STEADY))
+          {
+            skip = TRUE;
+          }
+          break;          
+        case PARALLELING_IN1B_IN2B__2_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+          if ((motorId < 2) && (devicePrm.motionState[0] == STEADY) && (devicePrm.motionState[1] == STEADY))
+          {
+            skip = TRUE;
+          }
+          break;          
+        case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_UNDIR_MOTOR_BRIDGE_1A__1_UNDIR_MOTOR_BRIDGE_2A:
+          if ((devicePrm.motionState[0] == STEADY) && (devicePrm.motionState[1] == STEADY))
+          {
+            skip = TRUE;
+          }
+          break;          
+        default:
+          break;
+      }      
+
+      if (skip == FALSE)
+      {
+        /* Disable the bridge */
+        L6206_DisableBridge(bridgeId);
+      }  
+    }
+    /* Disable the PWM */
+    L6206_HardStop(motorId);
+  }
+}
+
+/******************************************************//**
+ * @brief  Stops the motor without disabling the bridge
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval none
+ **********************************************************/
+void L6206::L6206_HardStop(uint8_t motorId)
+{	
+	if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+	{
+		L6206_ErrorHandler(L6206_ERROR_1);
+	}
+	else if (devicePrm.motionState[motorId] != INACTIVE)
+	{
+		uint8_t bridgeInput;
+    
+		/* Get bridge input of the corresponding motor */
+		bridgeInput = L6206_GetBridgeInputUsedByMotorId(motorId);
+    
+		/* Disable corresponding PWM */
+		L6206_Board_PwmStop(bridgeInput);
+
+		/* for bidirectionnal motor, disable second PWM*/
+		if (L6206_IsBidirectionnalMotor(motorId))
+		{
+			bridgeInput = L6206_GetSecondBridgeInputUsedByMotorId(motorId);
+			L6206_Board_PwmStop(bridgeInput);
+		}
+		/* Set inactive state */
+		devicePrm.motionState[motorId] = INACTIVE;
+	}
+}
+
+/******************************************************//**
+ * @brief Read id
+ * @retval Id of the l6206 Driver Instance
+ **********************************************************/
+Status_t L6206::L6206_ReadId(uint8_t *id)
+{
+	*id = deviceInstance;
+
+	return COMPONENT_OK;
+}
+
+/******************************************************//**
+ * @brief  Runs the motor
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @param[in] direction FORWARD or BACKWARD
+ * @retval None
+ * @note  For unidirectionnal motor, direction parameter has 
+ * no effect
+ **********************************************************/
+void L6206::L6206_Run(uint8_t motorId, motorDir_t direction)
+{
+	if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }  
+  else if ((devicePrm.motionState[motorId] == INACTIVE) ||
+           (devicePrm.direction[motorId] != direction))
+  {
+    uint8_t bridgeId;
+    uint8_t bridgeInput;
+    
+    /* Eventually deactivate motor */
+    if (devicePrm.motionState[motorId] != INACTIVE)
+    {
+      L6206_HardStop(motorId);
+    }
+   
+    /* Store new direction */
+    devicePrm.direction[motorId] = direction;
+    
+    /* Switch to steady state */
+    devicePrm.motionState[motorId] = STEADY;
+    
+   /* Get bridge Id of the corresponding motor */
+    bridgeId = L6206_GetBridgeIdUsedByMotorId(motorId);
+        
+    /* Get bridge input of the corresponding motor */
+    bridgeInput = L6206_GetBridgeInputUsedByMotorId(motorId);
+    
+    /* Enable bridge */
+    L6206_EnableBridge(bridgeId);
+    
+    /* Set PWM */
+    if (L6206_IsBidirectionnalMotor(motorId))
+    {
+      /* for bidirectionnal motor */
+      L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],(100 - devicePrm.speed[motorId]));
+      bridgeInput = L6206_GetSecondBridgeInputUsedByMotorId(motorId);
+      L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],100);
+    }
+    else
+    {
+      /* for unidirectionnal motor */
+      L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],devicePrm.speed[motorId]);
+    }
+  }
+}
+/******************************************************//**
+ * @brief Set dual full bridge parallelling configuration
+ * @param[in] newConfig bridge configuration to apply from 
+ * dualFullBridgeConfig_t enum
+ * @retval None
+ **********************************************************/
+void L6206::L6206_SetDualFullBridgeConfig(uint8_t newConfig)
+{
+	devicePrm.config = (dualFullBridgeConfig_t)newConfig;
+
+  /* Start to reset all else if several inits are used successively */
+  /* they will fail */
+  L6206_Board_PwmDeInit(INPUT_1A);
+  L6206_Board_PwmDeInit(INPUT_2A);
+  L6206_Board_PwmDeInit(INPUT_1B);
+  L6206_Board_PwmDeInit(INPUT_2B);
+  
+  
+  /* Initialise the bridges inputs PWMs --------------------------------------*/
+  switch (devicePrm.config)
+  {
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:   
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:  
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:      
+        L6206_Board_PwmInit(INPUT_1A);
+        L6206_Board_PwmInit(INPUT_2A);
+        L6206_Board_PwmInit(INPUT_1B);
+        L6206_Board_PwmInit(INPUT_2B);
+      break;
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+        L6206_Board_PwmDeInit(INPUT_2A);
+        L6206_Board_PwmInit(INPUT_1A);
+        L6206_Board_PwmInit(INPUT_1B);
+        L6206_Board_PwmInit(INPUT_2B);
+      break;         
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1B_IN2B__2_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+        L6206_Board_PwmDeInit(INPUT_2B);
+        L6206_Board_PwmInit(INPUT_1A);
+        L6206_Board_PwmInit(INPUT_2A);
+        L6206_Board_PwmInit(INPUT_1B);
+      break;      
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+        L6206_Board_PwmDeInit(INPUT_2A);
+        L6206_Board_PwmDeInit(INPUT_2B);
+        L6206_Board_PwmInit(INPUT_1A);
+        L6206_Board_PwmInit(INPUT_1B);
+      break;       
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_UNDIR_MOTOR_BRIDGE_1A__1_UNDIR_MOTOR_BRIDGE_2A:
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+        L6206_Board_PwmDeInit(INPUT_1B);
+        L6206_Board_PwmDeInit(INPUT_2B);
+        L6206_Board_PwmInit(INPUT_1A);
+        L6206_Board_PwmInit(INPUT_2A);
+      break;      
+    case PARALLELING_ALL_WITH_IN1A___1_UNDIR_MOTOR:
+        L6206_Board_PwmDeInit(INPUT_2A);
+        L6206_Board_PwmDeInit(INPUT_1B);
+        L6206_Board_PwmDeInit(INPUT_2B);
+        L6206_Board_PwmInit(INPUT_1A);
+      break;
+    default:
+    break;       
+  }  
+}
+/******************************************************//**
+ * @brief  Changes the max speed of the specified device
+ * @param[in] motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @param[in] newMaxSpeed in % from 0 to 100
+ * @retval true if the command is successfully executed, else false
+ **********************************************************/
+bool L6206::L6206_SetMaxSpeed(uint8_t motorId, uint16_t newMaxSpeed)
+{
+	bool cmdExecuted = FALSE;
+
+  if (motorId > l6206ArrayNbMaxMotorsByConfig[devicePrm.config])
+  {
+    L6206_ErrorHandler(L6206_ERROR_1);
+  }
+  else
+  {
+    devicePrm.speed[motorId] = newMaxSpeed;
+    if (devicePrm.motionState[motorId] != INACTIVE)
+    {
+      uint8_t bridgeInput;
+          
+      /* Get Bridge input of the corresponding motor */
+      bridgeInput = L6206_GetBridgeInputUsedByMotorId(motorId);
+      
+      /* Set PWM frequency*/
+      if (L6206_IsBidirectionnalMotor(motorId))
+      {
+        /* for bidirectionnal motor */
+        L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],(100 - devicePrm.speed[motorId]));
+      }
+      else
+      {
+        /* for unidirectionnal motor */
+        L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],devicePrm.speed[motorId]);
+      }      
+    }
+    cmdExecuted = TRUE;
+  }
+  return cmdExecuted;
+}                                                     
+
+/******************************************************//**
+ * @brief  Changes the PWM frequency of the bridge input
+ * @param[in] bridgeId 0 for bridge A, 1 for bridge B
+ * @param[in] newFreq in Hz
+ * @retval None
+ **********************************************************/
+void L6206::L6206_SetBridgeInputPwmFreq(uint8_t bridgeId, uint32_t newFreq)
+{
+	uint8_t loop;
+  
+  if (newFreq > L6206_MAX_PWM_FREQ)
+  {
+    newFreq = L6206_MAX_PWM_FREQ;
+  }
+  for (loop = 0; loop < 2;loop ++)
+  {
+    uint8_t motorId;
+    uint8_t bridgeInput = (bridgeId << 1) + loop; 
+    devicePrm.pwmFreq[bridgeInput] = newFreq;
+    
+    /* Get motor Id using this bridge */
+    motorId = L6206_GetMotorIdUsingbridgeInput(bridgeInput);
+
+    /* Immediatly update frequency if motor is running */
+    if (devicePrm.motionState[motorId] != INACTIVE)
+    {
+      /* Test if motor is bidir */
+      if (L6206_IsBidirectionnalMotor(motorId))
+      {
+        if (bridgeInput !=  L6206_GetSecondBridgeInputUsedByMotorId(motorId))
+        {
+        /* Set PWM frequency for bidirectionnal motor of the first bridge*/
+        L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],(100 - devicePrm.speed[motorId]));
+        }
+        else
+        {
+          /* Set PWM frequency for bidirectionnal motor of the second bridge */
+          L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],100);
+        }
+      }
+      else
+      {
+        /* Set PWM frequency  for unidirectionnal motor */
+        L6206_Board_PwmSetFreq(bridgeInput, devicePrm.pwmFreq[bridgeInput],devicePrm.speed[motorId]);
+      }
+    }
+  }
+}
+/******************************************************//**
+ * @brief  Sets the number of devices to be used
+ * @param[in] nbDevices (from 1 to MAX_NUMBER_OF_DEVICES)
+ * @retval TRUE if successfull, FALSE if failure, attempt to set a number of
+ * devices greater than MAX_NUMBER_OF_DEVICES
+ **********************************************************/
+bool L6206::L6206_SetNbDevices(uint8_t nbDevices)
+{
+  if (nbDevices <= MAX_NUMBER_OF_DEVICES)
+  {
+    return TRUE;
+  }
+  else
+  {
+    return FALSE;
+  }
+}
+
+
+/******************************************************//**
+ * @brief Error handler which calls the user callback (if defined)
+ * @param[in] error Number of the error
+ * @retval None
+ **********************************************************/
+void L6206::L6206_ErrorHandler(uint16_t error)
+{
+	if (errorHandlerCallback != 0)
+  {
+    (void) errorHandlerCallback(error);
+  }
+  else   
+  {
+    while(1)
+    {
+      /* Infinite loop */
+    }
+  }
+}
+
+/******************************************************//**
+ * @brief  Handlers of the flag interrupt which calls the user callback (if defined)
+ * @retval None
+ **********************************************************/
+void L6206::L6206_FlagInterruptHandler(void)
+{
+	bool status;
+  
+  status = L6206_GetBridgeStatus(BRIDGE_A);
+  if (status != devicePrm.bridgeEnabled[BRIDGE_A])
+  {
+    devicePrm.bridgeEnabled[BRIDGE_A] = status;
+  }
+  
+  status = L6206_GetBridgeStatus(BRIDGE_B);
+  if (status != devicePrm.bridgeEnabled[BRIDGE_B])
+  {
+    devicePrm.bridgeEnabled[BRIDGE_B] = status;
+  }  
+  
+  if (flagInterruptCallback != 0)
+  {
+	  flagInterruptCallback();
+  }
+}
+
+/******************************************************//**
+ * @brief  Get the bridges Id used by a given motor
+ * @param motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval bridgeId 0 for bridge A , 1 for bridge B
+ **********************************************************/
+uint8_t L6206::L6206_GetBridgeIdUsedByMotorId(uint8_t motorId)
+{
+	uint8_t bridgeId;
+
+  switch (devicePrm.config)
+  {
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:        
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if (motorId == 0)
+      {
+        bridgeId = 0;
+      }
+      else
+      {
+        bridgeId = 1;
+      }
+      break;  
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1B_IN2B__2_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if (motorId < 2)
+      {
+        bridgeId = 0;
+      }
+      else
+      {
+        bridgeId = 1;
+      }
+      break;          
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_UNDIR_MOTOR_BRIDGE_1A__1_UNDIR_MOTOR_BRIDGE_2A:
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+    case PARALLELING_ALL_WITH_IN1A___1_UNDIR_MOTOR:
+    default:
+        bridgeId = 0;
+      break;        
+  }  
+  return (bridgeId);
+}
+
+/******************************************************//**
+ * @brief  Get the motor Id which is using the specified bridge input
+ * @param bridgeInput 0 for bridgeInput 1A, 1 for 2A, 2 for 1B, 3 for 3B
+ * @retval bridgeId 0 for bridge A , 1 for bridge B
+ **********************************************************/
+uint8_t L6206::L6206_GetMotorIdUsingbridgeInput(uint8_t bridgeInput)
+{
+	uint8_t motorId;
+  
+  switch (devicePrm.config)
+  {
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:      
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:      
+      if (bridgeInput >= INPUT_1B) 
+      {
+        motorId = 1;
+      }
+      else
+      {
+        motorId = 0;
+      }
+      break;  
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+    case   PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:      
+      if (bridgeInput == INPUT_2B) 
+      {
+        motorId = 2;
+      }
+      else if (bridgeInput == INPUT_1B) 
+      {
+        motorId = 1;
+      }
+      else
+      {
+        motorId = 0;
+      }      
+      break;        
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1B_IN2B__2_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:      
+      if (bridgeInput >= INPUT_1B) 
+      {
+        motorId = 2;
+      }
+      else if (bridgeInput == INPUT_2A) 
+      {
+        motorId = 1;
+      }
+      else
+      {
+        motorId = 0;
+      }      
+      break;           
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+      if (bridgeInput == INPUT_2B) 
+      {
+        motorId = 3;
+      }
+      else if (bridgeInput == INPUT_1B) 
+      {
+        motorId = 2;
+      }
+      else if (bridgeInput == INPUT_2A) 
+      {
+        motorId = 1;
+      }      
+      else
+      {
+        motorId = 0;
+      }      
+      break;           
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_UNDIR_MOTOR_BRIDGE_1A__1_UNDIR_MOTOR_BRIDGE_2A:
+      if ((bridgeInput == INPUT_2A) || (bridgeInput == INPUT_2B))
+      {
+        motorId = 1;
+      }
+      else
+      {
+        motorId = 0;
+      }    
+      break;
+    case   PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+    case   PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+    case   PARALLELING_ALL_WITH_IN1A___1_UNDIR_MOTOR:
+    default:
+      motorId = 0;  
+      break;        
+  }
+  
+  return (motorId);
+}
+/******************************************************//**
+ * @brief  Get the PWM input used by a given motor
+ * @param motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval PWM input 0 for 1A, 1 for 2A, 2 for 1B, 3 for 3B
+ **********************************************************/
+uint8_t L6206::L6206_GetBridgeInputUsedByMotorId(uint8_t motorId)
+{
+	uint8_t bridgeInput;
+
+  switch (devicePrm.config)
+  {
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_1A;
+         }
+         else
+         {
+           bridgeInput = INPUT_2A;
+         }
+      }
+      else
+      { 
+         if (devicePrm.direction[1] == FORWARD)
+         {
+           bridgeInput = INPUT_1B;
+         }
+         else
+         {
+           bridgeInput = INPUT_2B;
+         }
+      }  
+      break;
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_1A;
+         }
+         else
+         {
+           bridgeInput = INPUT_2A;
+         }
+      }
+      else if  (motorId == 1)
+      { 
+        
+        bridgeInput = INPUT_1B;
+      }
+      else
+      {
+        bridgeInput = INPUT_2B;        
+      }
+      break;        
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;
+      }
+      else if (motorId == 1)
+      {   
+        bridgeInput = INPUT_2A;
+      }
+      else 
+      { 
+         if (devicePrm.direction[2] == FORWARD)
+         {
+           bridgeInput = INPUT_1B;
+         }
+         else
+         {
+           bridgeInput = INPUT_2B;
+         }        
+      }
+      break;   
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;
+      }
+      else if (motorId == 1)
+      {   
+        bridgeInput = INPUT_2A;
+      }
+      else if  (motorId == 2)
+      { 
+        bridgeInput = INPUT_1B;
+      }
+      else
+      {
+        bridgeInput = INPUT_2B;
+      }        
+      break;     
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;
+      }
+      else 
+      {  
+         if (devicePrm.direction[1] == FORWARD)
+        {   
+          bridgeInput = INPUT_1B;
+        }
+        else
+        {   
+          bridgeInput = INPUT_2B;
+        }
+      }
+      break;     
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;
+      }
+      else if  (motorId == 1)
+      {  
+        bridgeInput = INPUT_1B;
+      }
+      else
+      {   
+        bridgeInput = INPUT_2B;
+      }
+      break;         
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_1A;
+         }
+         else
+         {
+           bridgeInput = INPUT_2A;
+         }
+      }
+      else
+      { 
+        bridgeInput = INPUT_1B;
+      }  
+      break;
+    case PARALLELING_IN1B_IN2B__2_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;        
+      }
+      else if  (motorId == 1)
+      { 
+        bridgeInput = INPUT_2A;        
+      }        
+      else
+      {
+        bridgeInput = INPUT_1B;        
+      }
+      break;      
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_UNDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        bridgeInput = INPUT_1A;        
+      }
+      else
+      {
+        bridgeInput = INPUT_1B;        
+      }
+      break;      
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+      if (devicePrm.direction[0] == FORWARD)
+       {
+         bridgeInput = INPUT_1A;
+       }
+       else
+       {
+         bridgeInput = INPUT_1B;
+       }
+      break;       
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_UNDIR_MOTOR_BRIDGE_1A__1_UNDIR_MOTOR_BRIDGE_2A:
+      if (motorId == 0)
+      {
+        bridgeInput = INPUT_1A;
+      }
+      else
+      {
+        bridgeInput = INPUT_2A;
+      }      
+      break;
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+      if (devicePrm.direction[0] == FORWARD)
+      {
+        bridgeInput = INPUT_1A;
+      }
+      else
+      {
+        bridgeInput = INPUT_2A;
+      }  
+      break;      
+    case PARALLELING_ALL_WITH_IN1A___1_UNDIR_MOTOR:
+    default:
+      bridgeInput = INPUT_1A;
+      break;       
+  }  
+  return (bridgeInput);
+}
+
+/******************************************************//**
+ * @brief  Get the second PWM input used by a given bidirectionnal motor
+ * @param motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval PWM input 0 for 1A, 1 for 2A, 2 for 1B, 3 for 3B
+ **********************************************************/
+uint8_t L6206::L6206_GetSecondBridgeInputUsedByMotorId(uint8_t motorId)
+{
+	uint8_t bridgeInput = 0xFF;
+  
+  switch (devicePrm.config)
+  {
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_2A;
+         }
+         else
+         {
+           bridgeInput = INPUT_1A;
+         }
+      }
+      else
+      { 
+         if (devicePrm.direction[1] == FORWARD)
+         {
+           bridgeInput = INPUT_2B;
+         }
+         else
+         {
+           bridgeInput = INPUT_1B;
+         }
+      }  
+      break;
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_2A;
+         }
+         else
+         {
+           bridgeInput = INPUT_1A;
+         }
+      }
+      break;        
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if (motorId == 2)
+      { 
+         if (devicePrm.direction[2] == FORWARD)
+         {
+           bridgeInput = INPUT_2B;
+         }
+         else
+         {
+           bridgeInput = INPUT_1B;
+         }        
+      }
+      break;   
+
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 1)
+      {  
+         if (devicePrm.direction[1] == FORWARD)
+        {   
+          bridgeInput = INPUT_2B;
+        }
+        else
+        {   
+          bridgeInput = INPUT_1B;
+        }
+      }
+      break;     
+
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+         if (devicePrm.direction[0] == FORWARD)
+         {
+           bridgeInput = INPUT_2A;
+         }
+         else
+         {
+           bridgeInput = INPUT_1A;
+         }
+      }
+      break;
+    case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+      if (devicePrm.direction[0] == FORWARD)
+       {
+         bridgeInput = INPUT_1B;
+       }
+       else
+       {
+         bridgeInput = INPUT_1A;
+       }
+      break;       
+    
+    case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+      if (devicePrm.direction[0] == FORWARD)
+      {
+        bridgeInput = INPUT_2A;
+      }
+      else
+      {
+        bridgeInput = INPUT_1A;
+      }  
+      break;      
+    default:
+      bridgeInput = 0XFF;
+      break;       
+  }  
+  if (bridgeInput == 0XFF)
+  {
+    L6206_ErrorHandler(L6206_ERROR_2);
+  }
+  
+  return (bridgeInput);
+}        
+        
+/******************************************************//**
+ * @brief  Test if motor is bidirectionnal
+ * @param motorId from 0 to MAX_NUMBER_OF_BRUSH_DC_MOTORS 
+ * @retval True if motor is bidirectionnal, else false
+ **********************************************************/
+bool L6206::L6206_IsBidirectionnalMotor(uint8_t motorId)
+{
+	bool isBiDir = FALSE;
+
+  switch (devicePrm.config)
+  {
+      case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      case PARALLELING_IN1A_IN2A__IN1B_IN2B__1_BIDIR_MOTOR:
+      case PARALLELING_IN1A_IN1B__IN2A_IN2B__1_BIDIR_MOTOR:
+        isBiDir = TRUE;
+      break;      
+  
+    case PARALLELING_NONE___1_BIDIR_MOTOR_BRIDGE_A__2_UNDIR_MOTOR_BRIDGE_B:
+    case PARALLELING_IN1B_IN2B__1_BIDIR_MOTOR_BRIDGE_A__1_UNDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 0)
+      { 
+        isBiDir = TRUE;
+      }
+      break;        
+    case PARALLELING_NONE___2_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 2)
+      { 
+        isBiDir = TRUE;
+      }
+      break;   
+    case PARALLELING_IN1A_IN2A__1_UNDIR_MOTOR_BRIDGE_A__1_BIDIR_MOTOR_BRIDGE_B:
+      if  (motorId == 1)
+      { 
+        isBiDir = TRUE;
+      }
+      break;     
+  
+    default:
+      break;       
+  }    
+  
+  return (isBiDir);
+}
+
+
+/******************************************************//**
+ * @brief  Sets the parameters of the device to predefined values
+ * from l6206_target_config.h
+ * @retval None
+ **********************************************************/
+void L6206::L6206_SetDeviceParamsToPredefinedValues(void)
+{
+	uint32_t i;
+
+  memset(&devicePrm, 0, sizeof(devicePrm));
+
+  devicePrm.config = L6206_CONF_PARAM_PARALLE_BRIDGES;
+
+  devicePrm.pwmFreq[INPUT_1A] = L6206_CONF_PARAM_FREQ_PWM1A;
+  devicePrm.pwmFreq[INPUT_2A] = L6206_CONF_PARAM_FREQ_PWM2A;
+  devicePrm.pwmFreq[INPUT_1B] = L6206_CONF_PARAM_FREQ_PWM1B;
+  devicePrm.pwmFreq[INPUT_2B] = L6206_CONF_PARAM_FREQ_PWM2B;
+  
+  for (i = 0; i < MAX_NUMBER_OF_BRUSH_DC_MOTORS; i++)
+  {
+    devicePrm.speed[i] = 100;
+    devicePrm.direction[i] = FORWARD;
+    devicePrm.motionState[i] = INACTIVE;
+  }
+  for (i = 0; i < L6206_NB_MAX_BRIDGES; i++)
+  {  
+    devicePrm.bridgeEnabled[i] = FALSE;
+  }
+}
+
+
+/******************************************************//**
+ * @brief  Set the parameters of the device to values of initDevicePrm structure
+ * Set GPIO according to these values
+ * @param initDevicePrm structure containing values to initialize the device
+ * parameters
+ * @retval None
+ **********************************************************/
+void L6206::L6206_SetDeviceParamsToGivenValues(L6206_Init_t* initDevicePrm)
+{
+	memcpy(&devicePrm, initDevicePrm, sizeof(devicePrm));
+}
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+