text: /* --COPYRIGHT--,BSD
   * Copyright (c) 2014, Texas Instruments Incorporated
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * *  Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * *  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.
   *
   * *  Neither the name of Texas Instruments Incorporated 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 OWNER 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.
   * --/COPYRIGHT--*/
  //*****************************************************************************
  //
  // adc12_a.c - Driver for the adc12_a Module.
  //
  //*****************************************************************************
  
  //*****************************************************************************
  //
  //! \addtogroup adc12_a_api adc12_a
  //! @{
  //
  //*****************************************************************************
  
  #include "inc/hw_memmap.h"
  
  #ifdef __MSP430_HAS_ADC12_PLUS__
  #include "adc12_a.h"
  
  #include <assert.h>
  
  bool ADC12_A_init(uint16_t baseAddress,
                    uint16_t sampleHoldSignalSourceSelect,
                    uint8_t clockSourceSelect,
                    uint16_t clockSourceDivider)
  {
      //Make sure the ENC bit is cleared before initializing the ADC12_A
      HWREG8(baseAddress + OFS_ADC12CTL0_L) &= ~ADC12ENC;
  
      bool retVal = STATUS_SUCCESS;
  
      //Turn OFF ADC12_A Module & Clear Interrupt Registers
      HWREG16(baseAddress + OFS_ADC12CTL0) &= ~(ADC12ON + ADC12OVIE + ADC12TOVIE
                                                + ADC12ENC + ADC12SC);
      HWREG16(baseAddress + OFS_ADC12IE) &= 0x0000;   //Reset ALL interrupt enables
      HWREG16(baseAddress + OFS_ADC12IFG) &= 0x0000;  //Reset ALL interrupt flags
  
      //Set ADC12_A Control 1
      HWREG16(baseAddress + OFS_ADC12CTL1) =
          sampleHoldSignalSourceSelect //Setup the Sample-and-Hold Source
          + (clockSourceDivider & ADC12DIV_7) //Set Clock Divider
          + clockSourceSelect; //Setup Clock Source
  
      //Set ADC12_A Control 2
      HWREG16(baseAddress + OFS_ADC12CTL2) =
          (clockSourceDivider & ADC12PDIV) //Set Clock Pre-Divider
          + ADC12RES_2; //Default resolution to 12-bits
  
      return (retVal);
  }
  
  void ADC12_A_enable(uint16_t baseAddress)
  {
      //Enable the ADC12_A Module
      HWREG8(baseAddress + OFS_ADC12CTL0_L) |= ADC12ON;
  }
  
  void ADC12_A_disable(uint16_t baseAddress)
  {
      //Disable ADC12_A module
      HWREG8(baseAddress + OFS_ADC12CTL0_L) &= ~ADC12ON;
  }
  
  void ADC12_A_setupSamplingTimer(uint16_t baseAddress,
                                  uint16_t clockCycleHoldCountLowMem,
                                  uint16_t clockCycleHoldCountHighMem,
                                  uint16_t multipleSamplesEnabled)
  {
      HWREG16(baseAddress + OFS_ADC12CTL1) |= ADC12SHP;
  
      //Reset clock cycle hold counts and msc bit before setting them
      HWREG16(baseAddress + OFS_ADC12CTL0) &=
          ~(ADC12SHT0_15 + ADC12SHT1_15 + ADC12MSC);
  
      //Set clock cycle hold counts and msc bit
      HWREG16(baseAddress + OFS_ADC12CTL0) |= clockCycleHoldCountLowMem
                                              + (clockCycleHoldCountHighMem << 4)
                                              + multipleSamplesEnabled;
  }
  
  void ADC12_A_disableSamplingTimer(uint16_t baseAddress)
  {
      HWREG16(baseAddress + OFS_ADC12CTL1) &= ~(ADC12SHP);
  }
  
  void ADC12_A_configureMemory(uint16_t baseAddress,
                               ADC12_A_configureMemoryParam *param)
  {
      //Set the offset in respect to ADC12MCTL0
      uint16_t memoryBufferControlOffset =
          (OFS_ADC12MCTL0 + param->memoryBufferControlIndex);
  
      //Reset the memory buffer control and Set the input source
      HWREG8(baseAddress + memoryBufferControlOffset) =
          param->inputSourceSelect //Set Input Source
          + param->positiveRefVoltageSourceSelect //Set Vref+
          + param->negativeRefVoltageSourceSelect //Set Vref-
          + param->endOfSequence; //Set End of Sequence
  }
  
  void ADC12_A_enableInterrupt(uint16_t baseAddress,
                               uint32_t interruptMask)
  {
      if(interruptMask & ADC12_A_CONVERSION_TIME_OVERFLOW_IE)
      {
          HWREG16(baseAddress + OFS_ADC12CTL0) |= ADC12TOVIE;
          interruptMask &= ~ADC12_A_CONVERSION_TIME_OVERFLOW_IE;
      }
      if(interruptMask & ADC12_A_OVERFLOW_IE)
      {
          HWREG16(baseAddress + OFS_ADC12CTL0) |= ADC12OVIE;
          interruptMask &= ~ADC12_A_OVERFLOW_IE;
      }
  
      HWREG16(baseAddress + OFS_ADC12IE) |= interruptMask;
  }
  
  void ADC12_A_disableInterrupt(uint16_t baseAddress,
                                uint32_t interruptMask)
  {
      if(interruptMask & ADC12_A_CONVERSION_TIME_OVERFLOW_IE)
      {
          HWREG16(baseAddress + OFS_ADC12CTL0) &= ~(ADC12TOVIE);
          interruptMask &= ~ADC12_A_CONVERSION_TIME_OVERFLOW_IE;
      }
      if(interruptMask & ADC12_A_OVERFLOW_IE)
      {
          HWREG16(baseAddress + OFS_ADC12CTL0) &= ~(ADC12OVIE);
          interruptMask &= ~ADC12_A_OVERFLOW_IE;
      }
  
      HWREG16(baseAddress + OFS_ADC12IE) &= ~(interruptMask);
  }
  
  void ADC12_A_clearInterrupt(uint16_t baseAddress,
                              uint16_t memoryInterruptFlagMask)
  {
      HWREG16(baseAddress + OFS_ADC12IFG) &= ~(memoryInterruptFlagMask);
  }
  
  uint8_t ADC12_A_getInterruptStatus(uint16_t baseAddress,
                                     uint16_t memoryInterruptFlagMask)
  {
      return (HWREG16(baseAddress + OFS_ADC12IFG) & memoryInterruptFlagMask);
  }
  
  void ADC12_A_startConversion(uint16_t baseAddress,
                               uint16_t startingMemoryBufferIndex,
                               uint8_t conversionSequenceModeSelect)
  {
      //Reset the ENC bit to set the starting memory address and conversion mode
      //sequence
      HWREG8(baseAddress + OFS_ADC12CTL0_L) &= ~(ADC12ENC);
      //Reset the bits about to be set
      HWREG16(baseAddress +
              OFS_ADC12CTL1) &= ~(ADC12CSTARTADD_15 + ADC12CONSEQ_3);
  
      HWREG8(baseAddress + OFS_ADC12CTL1_H) |= (startingMemoryBufferIndex << 4);
      HWREG8(baseAddress + OFS_ADC12CTL1_L) |= conversionSequenceModeSelect;
      HWREG8(baseAddress + OFS_ADC12CTL0_L) |= ADC12ENC + ADC12SC;
  }
  
  void ADC12_A_disableConversions(uint16_t baseAddress,
                                  bool preempt)
  {
      if(ADC12_A_PREEMPTCONVERSION == preempt)
      {
          HWREG8(baseAddress + OFS_ADC12CTL1_L) &= ~(ADC12CONSEQ_3);
          //Reset conversion sequence mode to single-channel, single-conversion
      }
      else if(~(HWREG8(baseAddress + OFS_ADC12CTL1_L) & ADC12CONSEQ_3))
      {
          //To prevent preemoption of a single-channel, single-conversion we must
          //wait for the ADC core to finish the conversion.
          while(ADC12_A_isBusy(baseAddress))
          {
              ;
          }
      }
  
      HWREG8(baseAddress + OFS_ADC12CTL0_L) &= ~(ADC12ENC);
  }
  
  uint16_t ADC12_A_getResults(uint16_t baseAddress,
                              uint8_t memoryBufferIndex)
  {
      //(0x20 + (memoryBufferIndex * 2)) == offset of ADC12MEMx
      return (HWREG16(baseAddress + (0x20 + (memoryBufferIndex * 2))));
  }
  
  void ADC12_A_setResolution(uint16_t baseAddress,
                             uint8_t resolutionSelect)
  {
      HWREG8(baseAddress + OFS_ADC12CTL2_L) &= ~(ADC12RES_3);
      HWREG8(baseAddress + OFS_ADC12CTL2_L) |= resolutionSelect;
  }
  
  void ADC12_A_setSampleHoldSignalInversion(uint16_t baseAddress,
                                            uint16_t invertedSignal)
  {
      HWREG16(baseAddress + OFS_ADC12CTL1) &= ~(ADC12ISSH);
      HWREG16(baseAddress + OFS_ADC12CTL1) |= invertedSignal;
  }
  
  void ADC12_A_setDataReadBackFormat(uint16_t baseAddress,
                                     uint8_t readBackFormat)
  {
      HWREG8(baseAddress + OFS_ADC12CTL2_L) &= ~(ADC12DF);
      HWREG8(baseAddress + OFS_ADC12CTL2_L) |= readBackFormat;
  }
  
  void ADC12_A_enableReferenceBurst(uint16_t baseAddress)
  {
      HWREG8(baseAddress + OFS_ADC12CTL2_L) |= ADC12REFBURST;
  }
  
  void ADC12_A_disableReferenceBurst(uint16_t baseAddress)
  {
      HWREG8(baseAddress + OFS_ADC12CTL2_L) &= ~(ADC12REFBURST);
  }
  
  void ADC12_A_setReferenceBufferSamplingRate(uint16_t baseAddress,
                                              uint8_t samplingRateSelect)
  {
      HWREG8(baseAddress + OFS_ADC12CTL2_L) &= ~(ADC12SR);
      HWREG8(baseAddress + OFS_ADC12CTL2_L) |= samplingRateSelect;
  }
  
  uint32_t ADC12_A_getMemoryAddressForDMA(uint16_t baseAddress,
                                          uint8_t memoryIndex)
  {
      return (baseAddress + (0x20 + (memoryIndex * 2)));
  }
  
  uint16_t ADC12_A_isBusy(uint16_t baseAddress)
  {
      return (HWREG8(baseAddress + OFS_ADC12CTL1_L) & ADC12BUSY);
  }
  
  #endif
  //*****************************************************************************
  //
  //! Close the doxygen group for adc12_a_api
  //! @}
  //
  //*****************************************************************************
  