Library for driving the High Brightness LED present on the Discovery F334C8 board.

Dependents:   DISCO-F334C8_HiBrightLED_demo

HiBrightLED.cpp

Committer:
arostm
Date:
2017-06-08
Revision:
1:eb29c4c2a341
Parent:
0:c95c484b95a9

File content as of revision 1:eb29c4c2a341:

/* Copyright (c) 2010-2011 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#if !defined(TARGET_DISCO_F334C8)
#error "This library must be used on DISCO_F334C8 board only."
#endif

#include "HiBrightLED.h"

/**
  * @brief LED intensity
  */
#define MIN_INTENSITY (625)
#define MAX_INTENSITY (0)


// Constructor
HiBrightLED::HiBrightLED()
{
  // Current table centered around ~250mA in the Power LED
  CurrentSenseTab[0] = 280;
  CurrentSenseTab[1] = 240;
  CurrentSenseTab[2] = 200;
  CurrentSenseTab[3] = 360;
  CurrentSenseTab[4] = 320;
  CurrentSenseTabInit();
  
  DMA_Config();
  DAC_Config();
  COMP_Config();
  HRTIM_Config();
}


// Destructor
HiBrightLED::~HiBrightLED()
{
  // DMA
  DmaHandle.Instance = DMA1_Channel5;
  HAL_DMA_DeInit(&DmaHandle);
  __DMA1_CLK_DISABLE();
  
  // DAC
  DacHandle.Instance = DAC1;
  HAL_DAC_DeInit(&DacHandle);
  __DAC1_CLK_DISABLE();
  
  // COMP
  CompHandle.Instance = COMP4;
  HAL_COMP_DeInit(&CompHandle);
  
  // HRTIM
  HrtimHandle.Instance = HRTIM1;
  HAL_HRTIM_DeInit(&HrtimHandle);
  __HRTIM1_CLK_DISABLE();  
}


//=================================================================================================================
// Public methods
//=================================================================================================================

void HiBrightLED::write(float value)
{
  uint16_t val;
  _value = value; // Save current value
  
  if (value < 0.0f) {
    val = MIN_INTENSITY;
  } else if (value > 1.0f) {
    val = MAX_INTENSITY;
  } else {
    val = (uint16_t)((1.0f - value) * (float)MIN_INTENSITY);
  }

  HRTIM_SetBurstCompare(val);
}

float HiBrightLED::read()
{
  return _value;
}

//=================================================================================================================
// Private methods
//=================================================================================================================

void HiBrightLED::CurrentSenseTabInit(void)
{
  uint8_t index;
  for (index =0; index < 5; index++)
  {
    CurrentSenseTab[index] = (CurrentSenseTab[index] * 4096) / 3300; 
  }
}


void HiBrightLED::DMA_Config(void)
{
  /* Enable DMA1 clock -------------------------------------------------------*/
  __DMA1_CLK_ENABLE();
  
  /* Configure the DMA1 CH5 IRQ Channel */
  DmaHandle.Init.Direction           = DMA_MEMORY_TO_PERIPH; /* M2P transfer mode                 */           
  DmaHandle.Init.PeriphInc           = DMA_PINC_DISABLE;     /* Peripheral increment mode Disable */                 
  DmaHandle.Init.MemInc              = DMA_MINC_ENABLE;      /* Memory increment mode Enable      */                   
  DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;  /* Peripheral data alignment : Word  */    
  DmaHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;  /* memory data alignment : Word      */     
  DmaHandle.Init.Mode                = DMA_CIRCULAR;         /* Circular Normal DMA mode          */  
  DmaHandle.Init.Priority            = DMA_PRIORITY_HIGH;    /* priority level : high             */  

  DmaHandle.Instance                 = DMA1_Channel5;

  if (HAL_DMA_Init(&DmaHandle) != HAL_OK)
  {
    error("HAL_DMA_Init failed");
  }
}


void HiBrightLED::DAC_Config(void)
{
  DAC_ChannelConfTypeDef DAC_ConfigStructure;

#ifdef DEBUG_HIBRIGHT_LED
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure DAC1 OUT1 */ 
  /* GPIO Periph clock enable */
  __GPIOA_CLK_ENABLE();
  
  /* Configure PA4 (DAC1_OUT1) as analog */
  GPIO_InitStructure.Pin  =  GPIO_PIN_4;
  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
  
  /* DAC1 Periph clock enable */
  __DAC1_CLK_ENABLE();
  
  /* DAC1 deinitialize */
  DacHandle.Instance = DAC1;
  if(HAL_DAC_DeInit(&DacHandle) != HAL_OK)
  {
    error("HAL_DAC_DeInit failed");
  }
  
  /* DAC Channel1 Init */
  if(HAL_DAC_Init(&DacHandle) != HAL_OK)
  {
    error("HAL_DAC_Init failed");
  }

  /* Fill DAC ConfigStructure */
  DAC_ConfigStructure.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  DAC_ConfigStructure.DAC_Trigger      = DAC_TRIGGER_NONE;
  if(HAL_DAC_ConfigChannel(&DacHandle, &DAC_ConfigStructure, DAC1_CHANNEL_1) != HAL_OK)
  {
    error("HAL_DAC_ConfigChannel failed");
  }
  
  /* Enable DAC Channel1 */
  if(HAL_DAC_Start(&DacHandle, DAC1_CHANNEL_1) != HAL_OK)
  {
    error("HAL_DAC_Start failed");
  }
  
  /* Set DAC Channel1 DHR register: DAC1_OUT */
  if(HAL_DAC_SetValue(&DacHandle, DAC1_CHANNEL_1, DAC_ALIGN_12B_R, CurrentSenseTab[0]) != HAL_OK)
  {
    error("HAL_DAC_SetValue failed");
  }
}


void HiBrightLED::COMP_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable SYSCFG clock */
  //__SYSCFG_CLK_ENABLE();

  /* GPIOB Peripheral clock enable */
  __GPIOB_CLK_ENABLE();

  /* Configure PB0 in analog mode: PB0 is connected to COMP4 non inverting input */
  GPIO_InitStructure.Pin  =  GPIO_PIN_0;
  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
  
#ifdef DEBUG_HIBRIGHT_LED  
  /* COMP4 output config: PB1 for debug */
  GPIO_InitStructure.Pin       = GPIO_PIN_1;
  GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStructure.Speed     = GPIO_SPEED_HIGH;
  GPIO_InitStructure.Pull      = GPIO_NOPULL;
  /* Alternate function configuration : Comparator4 Out2 / PB1 */ 
  GPIO_InitStructure.Alternate = GPIO_AF8_GPCOMP4;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
  
  /* COMP4 deinitialize */
  CompHandle.Instance = COMP4;
  if(HAL_COMP_DeInit(&CompHandle) != HAL_OK)
  {
    error("HAL_COMP_DeInit failed");
  }
  
  /* COMP4 config */
  CompHandle.Init.InvertingInput    = COMP_INVERTINGINPUT_DAC1;
  CompHandle.Init.NonInvertingInput = 0;
  CompHandle.Init.Output            = COMP_OUTPUT_NONE;
  CompHandle.Init.OutputPol         = COMP_OUTPUTPOL_NONINVERTED;
  CompHandle.Init.Hysteresis        = COMP_HYSTERESIS_NONE;
  CompHandle.Init.Mode              = 0;
  CompHandle.Init.BlankingSrce      = COMP_BLANKINGSRCE_NONE;
  CompHandle.Init.WindowMode        = COMP_WINDOWMODE_DISABLED;
  CompHandle.Init.TriggerMode       = COMP_TRIGGERMODE_NONE;
  if(HAL_COMP_Init(&CompHandle) != HAL_OK)
  {
    error("HAL_COMP_Init failed");
  }
  
  /* Enable COMP4 */
  if(HAL_COMP_Start(&CompHandle) != HAL_OK)
  {
    error("HAL_COMP_Start failed");
  }
}


void HiBrightLED::HRTIM_Config(void)
{
  GPIO_InitTypeDef          GPIO_InitStructure;
  HRTIM_BurstModeCfgTypeDef HRTIM_BurstStructure; 
  HRTIM_CompareCfgTypeDef   HRTIM_CompareStructure;
  HRTIM_EventCfgTypeDef     HRTIM_ExternalEventStructure;
  HRTIM_OutputCfgTypeDef    HRTIM_OutputStructure;
  HRTIM_TimeBaseCfgTypeDef  HRTIM_TimeBaseStructure;
  HRTIM_TimerCfgTypeDef     HRTIM_TimerWaveStructure;

  /* Configure HRTIM TIM C ****************************************************/  
  /* HRTIM output channel configuration : HRTIM_CHC1 (Buck drive) / PB12 */
  GPIO_InitStructure.Pin       = GPIO_PIN_12;
  GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStructure.Speed     = GPIO_SPEED_HIGH;
  GPIO_InitStructure.Pull      = GPIO_NOPULL;
  /* Alternate function configuration : HRTIM_CHC1 / PB12 */
  GPIO_InitStructure.Alternate = GPIO_AF13_HRTIM1;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Use the PLLx2 clock for HRTIM */
  __HAL_RCC_HRTIM1_CONFIG(RCC_HRTIM1CLK_PLLCLK);
  __HRTIM1_CLK_ENABLE();

  HrtimHandle.Instance = HRTIM1;
  HAL_HRTIM_Init(&HrtimHandle);
  
  /* DMA Configuration */
  __HAL_LINKDMA(&HrtimHandle, hdmaTimerC, DmaHandle);
  
  /* HRTIM initialization startup */  
  if(HAL_HRTIM_DLLCalibrationStart(&HrtimHandle, HRTIM_CALIBRATIONRATE_14) != HAL_OK)
  {
    error("HAL_HRTIM_DLLCalibrationStart failed");
  }
  
  if(HAL_HRTIM_PollForDLLCalibration(&HrtimHandle, HAL_MAX_DELAY) != HAL_OK)
  {
    error("HAL_HRTIM_PollForDLLCalibration failed");
  }
   
  /* Configure the output features */  
  HRTIM_OutputStructure.Polarity              = HRTIM_OUTPUTPOLARITY_HIGH; 
  HRTIM_OutputStructure.SetSource             = HRTIM_OUTPUTSET_TIMPER;  
  HRTIM_OutputStructure.ResetSource           = HRTIM_OUTPUTRESET_EEV_2; 
  HRTIM_OutputStructure.IdleMode              = HRTIM_OUTPUTIDLEMODE_IDLE;  
  HRTIM_OutputStructure.IdleLevel             = HRTIM_OUTPUTIDLELEVEL_INACTIVE;          
  HRTIM_OutputStructure.FaultLevel            = HRTIM_OUTPUTFAULTLEVEL_NONE;          
  HRTIM_OutputStructure.ChopperModeEnable     = HRTIM_OUTPUTCHOPPERMODE_DISABLED;        
  HRTIM_OutputStructure.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;

  if(HAL_HRTIM_WaveformOutputConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, 
                                    HRTIM_OUTPUT_TC1, &HRTIM_OutputStructure) != HAL_OK)  
  {
    error("HAL_HRTIM_WaveformOutputConfig failed");
  }

  /* Configure HRTIM1_TIMC Deadtime */
  HRTIM_TimerWaveStructure.InterruptRequests     = (HRTIM_MASTER_IT_NONE | HRTIM_TIM_IT_NONE);
  HRTIM_TimerWaveStructure.DMARequests           = (HRTIM_TIM_DMA_REP | HRTIM_TIM_DMA_CMP1 | HRTIM_TIM_DMA_CMP2 |
                                                    HRTIM_TIM_DMA_CMP3 | HRTIM_TIM_DMA_CMP4);
  HRTIM_TimerWaveStructure.DMASrcAddress         = (uint32_t)CurrentSenseTab;
  HRTIM_TimerWaveStructure.DMADstAddress         = (uint32_t)(&((&DacHandle)->Instance->DHR12R1));
  HRTIM_TimerWaveStructure.DMASize               = 5;
  HRTIM_TimerWaveStructure.HalfModeEnable        = HRTIM_HALFMODE_DISABLED;
  HRTIM_TimerWaveStructure.StartOnSync           = HRTIM_SYNCSTART_DISABLED;
  HRTIM_TimerWaveStructure.ResetOnSync           = HRTIM_SYNCRESET_DISABLED;
  HRTIM_TimerWaveStructure.DACSynchro            = HRTIM_DACSYNC_NONE;
  HRTIM_TimerWaveStructure.PreloadEnable         = HRTIM_PRELOAD_DISABLED;
  HRTIM_TimerWaveStructure.UpdateGating          = HRTIM_UPDATEGATING_INDEPENDENT;
  HRTIM_TimerWaveStructure.BurstMode             = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;
  HRTIM_TimerWaveStructure.RepetitionUpdate      = HRTIM_UPDATEONREPETITION_DISABLED;
  HRTIM_TimerWaveStructure.PushPull              = HRTIM_TIMPUSHPULLMODE_DISABLED;
  HRTIM_TimerWaveStructure.FaultEnable           = HRTIM_TIMFAULTENABLE_NONE;
  HRTIM_TimerWaveStructure.FaultLock             = HRTIM_TIMFAULTLOCK_READWRITE;
  HRTIM_TimerWaveStructure.DeadTimeInsertion     = HRTIM_TIMDEADTIMEINSERTION_DISABLED;
  HRTIM_TimerWaveStructure.DelayedProtectionMode = HRTIM_TIMDELAYEDPROTECTION_DISABLED;
  HRTIM_TimerWaveStructure.UpdateTrigger         = HRTIM_TIMUPDATETRIGGER_TIMER_C; 
  HRTIM_TimerWaveStructure.ResetTrigger          = HRTIM_TIMRESETTRIGGER_NONE; 
  HRTIM_TimerWaveStructure.ResetUpdate           = HRTIM_TIMUPDATEONRESET_DISABLED;
  
  if(HAL_HRTIM_WaveformTimerConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, &HRTIM_TimerWaveStructure) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformTimerConfig failed");
  }
  
  HRTIM_CompareStructure.AutoDelayedMode    = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareStructure.AutoDelayedTimeout = 0; 
  HRTIM_CompareStructure.CompareValue       = 3686; /* 20% time */
  
  if(HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, 
                                     HRTIM_COMPAREUNIT_1, &HRTIM_CompareStructure) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformCompareConfig failed");
  }
  
  HRTIM_CompareStructure.AutoDelayedMode    = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareStructure.AutoDelayedTimeout = 0; 
  HRTIM_CompareStructure.CompareValue       = 7373; /* 40% time */

  if(HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, 
                                     HRTIM_COMPAREUNIT_2, &HRTIM_CompareStructure) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformCompareConfig failed");
  }
  
  HRTIM_CompareStructure.AutoDelayedMode    = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareStructure.AutoDelayedTimeout = 0; 
  HRTIM_CompareStructure.CompareValue       = 11059; /* 60% time */

  if(HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, 
                                     HRTIM_COMPAREUNIT_3, &HRTIM_CompareStructure) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformCompareConfig failed");
  }
  
  HRTIM_CompareStructure.AutoDelayedMode    = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareStructure.AutoDelayedTimeout = 0; 
  HRTIM_CompareStructure.CompareValue       = 14746; /* 80% time */

  if(HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, 
                                     HRTIM_COMPAREUNIT_4, &HRTIM_CompareStructure) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformCompareConfig failed");
  }
  
  HRTIM_TimeBaseStructure.Period            = 18432; /* 1 period = 4 µs = 100% time */
  HRTIM_TimeBaseStructure.RepetitionCounter = 0x00;
  HRTIM_TimeBaseStructure.PrescalerRatio    = HRTIM_PRESCALERRATIO_MUL32; 
  HRTIM_TimeBaseStructure.Mode              = HRTIM_MODE_CONTINUOUS;          
  
  if(HAL_HRTIM_TimeBaseConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_C, &HRTIM_TimeBaseStructure) != HAL_OK)
  {
    error("HAL_HRTIM_TimeBaseConfig failed");
  }
    
  /* Configure External Event Source 2 */
  HRTIM_ExternalEventStructure.Source      = HRTIM_EVENTSRC_2; 
  HRTIM_ExternalEventStructure.Polarity    = HRTIM_EVENTPOLARITY_HIGH; 
  HRTIM_ExternalEventStructure.Sensitivity = HRTIM_EVENTSENSITIVITY_LEVEL;
  HRTIM_ExternalEventStructure.FastMode    = HRTIM_EVENTFASTMODE_ENABLE;
  HRTIM_ExternalEventStructure.Filter      = HRTIM_EVENTFILTER_NONE;
  
  if(HAL_HRTIM_EventConfig(&HrtimHandle, HRTIM_EVENT_2, &HRTIM_ExternalEventStructure) != HAL_OK)
  {
    error("HAL_HRTIM_EventConfig failed");
  }
    
  /* Burst Mode configuration */
  HRTIM_BurstStructure.Mode          = HRTIM_BURSTMODE_CONTINOUS;
  HRTIM_BurstStructure.ClockSource   = HRTIM_BURSTMODECLOCKSOURCE_TIMER_C; 
  HRTIM_BurstStructure.Prescaler     = HRTIM_BURSTMODEPRESCALER_DIV1;
  HRTIM_BurstStructure.PreloadEnable = HRIM_BURSTMODEPRELOAD_ENABLED;
  HRTIM_BurstStructure.Trigger       = HRTIM_BURSTMODETRIGGER_NONE;
  HRTIM_BurstStructure.IdleDuration  = MIN_INTENSITY;
  HRTIM_BurstStructure.Period        = MIN_INTENSITY;  
  
  if(HAL_HRTIM_BurstModeConfig(&HrtimHandle, &HRTIM_BurstStructure) != HAL_OK)
  {
    error("HAL_HRTIM_BurstModeConfig failed");
  }
  
  /* Enable the TC1 output */
  if(HAL_HRTIM_WaveformOutputStart(&HrtimHandle, HRTIM_OUTPUT_TC1) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformOutputStart failed");
  }
  
  if(HAL_HRTIM_BurstModeCtl(&HrtimHandle, HRTIM_BURSTMODECTL_ENABLED) != HAL_OK)
  {
    error("HAL_HRTIM_BurstModeCtl failed");
  }

  /* Start slave*/
  if(HAL_HRTIM_WaveformCounterStart_DMA(&HrtimHandle, HRTIM_TIMERID_TIMER_C) != HAL_OK)
  {
    error("HAL_HRTIM_WaveformCounterStart_DMA failed");
  }
  
  /* Configure and enable HRTIM interrupt */
  HAL_NVIC_SetPriority(HRTIM1_Master_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(HRTIM1_Master_IRQn);

  /* Enable Burst mode period completed interrupt */
  HrtimHandle.Init.HRTIMInterruptResquests = HRTIM_IT_BMPER;

  /* Select Burst Trigger */
  if(HAL_HRTIM_BurstModeSoftwareTrigger(&HrtimHandle) != HAL_OK)
  {
    error("HAL_HRTIM_BurstModeSoftwareTrigger failed");
  }
}


void HiBrightLED::HRTIM_SetBurstCompare(uint16_t BurstCompare)
{
  /* Set Burst Compare value */
  HrtimHandle.Instance->sCommonRegs.BMCMPR = BurstCompare;
}