blob: 3d78b5c66ee4a351ecbe2dbe1f7ec266264ec098 [file] [log] [blame]
/*
* Copyright (c) 2016-2017, 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.
*/
/*
* By default disable both asserts and log for this module.
* This must be done before DebugP.h is included.
*/
#ifndef DebugP_ASSERT_ENABLED
#define DebugP_ASSERT_ENABLED 0
#endif
#ifndef DebugP_LOG_ENABLED
#define DebugP_LOG_ENABLED 0
#endif
#include <stdint.h>
#include <ti/drivers/dpl/DebugP.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/adc/ADCCC32XX.h>
#include <ti/devices/cc32xx/inc/hw_memmap.h>
#include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
#include <ti/devices/cc32xx/inc/hw_types.h>
#include <ti/devices/cc32xx/driverlib/rom.h>
#include <ti/devices/cc32xx/driverlib/rom_map.h>
#include <ti/devices/cc32xx/driverlib/rom_patch.h>
#include <ti/devices/cc32xx/driverlib/adc.h>
#include <ti/devices/cc32xx/driverlib/pin.h>
/* Pad configuration register defaults */
#define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
#define PAD_RESET_DRIVE PIN_STRENGTH_6MA
#define PAD_RESET_TYPE PIN_TYPE_STD
#define PAD_RESET_STATE 0xC61
#define PinConfigChannel(config) (((config) >> 8) & 0xff)
#define PinConfigPin(config) ((config) & 0xff)
void ADCCC32XX_close(ADC_Handle handle);
int_fast16_t ADCCC32XX_control(ADC_Handle handle, uint_fast16_t cmd, void *arg);
int_fast16_t ADCCC32XX_convert(ADC_Handle handle, uint16_t *value);
uint32_t ADCCC32XX_convertToMicroVolts(ADC_Handle handle,
uint16_t adcValue);
void ADCCC32XX_init(ADC_Handle handle);
ADC_Handle ADCCC32XX_open(ADC_Handle handle, ADC_Params *params);
/* ADC function table for ADCCC32XX implementation */
const ADC_FxnTable ADCCC32XX_fxnTable = {
ADCCC32XX_close,
ADCCC32XX_control,
ADCCC32XX_convert,
ADCCC32XX_convertToMicroVolts,
ADCCC32XX_init,
ADCCC32XX_open
};
/* Internal ADC status structure */
static ADCCC32XX_State state = {
.baseAddr = ADC_BASE,
.numOpenChannels = 0
};
/*
* ======== ADCCC32XX_close ========
*/
void ADCCC32XX_close(ADC_Handle handle)
{
uintptr_t key;
uint32_t pin;
uint32_t padRegister;
ADCCC32XX_Object *object = handle->object;
ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
pin = PinConfigChannel(hwAttrs->adcPin);
key = HwiP_disable();
MAP_ADCChannelDisable(state.baseAddr, pin);
state.numOpenChannels--;
if (state.numOpenChannels == 0) {
MAP_ADCDisable(state.baseAddr);
}
HwiP_restore(key);
/* Call PinConfigSet to de-isolate the input */
pin = PinConfigPin(hwAttrs->adcPin);
MAP_PinConfigSet(pin, PAD_RESET_DRIVE, PAD_RESET_TYPE);
/* Set reset state for the pad register */
padRegister = (PinToPadGet(pin)<<2) + PAD_CONFIG_BASE;
HWREG(padRegister) = PAD_RESET_STATE;
object->isOpen = false;
DebugP_log0("ADC: (%p) closed");
}
/*
* ======== ADCCC32XX_control ========
*/
int_fast16_t ADCCC32XX_control(ADC_Handle handle, uint_fast16_t cmd, void *arg)
{
/* No implementation yet */
return (ADC_STATUS_UNDEFINEDCMD);
}
/*
* ======== ADCCC32XX_convert ========
*/
int_fast16_t ADCCC32XX_convert(ADC_Handle handle, uint16_t *value)
{
uintptr_t key;
uint16_t adcSample = 0;
uint_fast16_t adcChannel;
ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
adcChannel = PinConfigChannel(hwAttrs->adcPin);
key = HwiP_disable();
/* Wait until the FIFO is not empty */
while (MAP_ADCFIFOLvlGet(state.baseAddr, adcChannel) == 0) {
HwiP_restore(key);
key = HwiP_disable();
}
adcSample = MAP_ADCFIFORead(ADC_BASE, adcChannel);
HwiP_restore(key);
/* Strip time stamp & reserve bits from ADC sample */
*value = ((adcSample >> 2) & 0x0FFF);
return (ADC_STATUS_SUCCESS);
}
/*
* ======== ADCCC32XX_convertToMicroVolts ========
*/
uint32_t ADCCC32XX_convertToMicroVolts(ADC_Handle handle,
uint16_t adcValue)
{
/* Internal voltage reference is 1.467V (1467000 uV) */
return ((uint_fast32_t)(adcValue * (1467000.0 / 4095.0)));
}
/*
* ======== ADCCC32XX_init ========
*/
void ADCCC32XX_init(ADC_Handle handle)
{
/* Mark the object as available */
((ADCCC32XX_Object *) handle->object)->isOpen = false;
}
/*
* ======== ADCCC32XX_open ========
*/
ADC_Handle ADCCC32XX_open(ADC_Handle handle, ADC_Params *params)
{
uintptr_t key;
uint32_t pin;
ADCCC32XX_Object *object = handle->object;
ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
uint32_t i;
key = HwiP_disable();
if (object->isOpen) {
HwiP_restore(key);
DebugP_log1("ADC: (%p) already opened", (uintptr_t) handle);
return (NULL);
}
object->isOpen = true;
state.numOpenChannels++;
HwiP_restore(key);
/* Configure pin as ADC input */
pin = PinConfigPin(hwAttrs->adcPin);
MAP_PinTypeADC(pin, PIN_MODE_255);
/* Enable ADC Peripheral and ADC Channel */
pin = PinConfigChannel(hwAttrs->adcPin);
MAP_ADCEnable(state.baseAddr);
MAP_ADCChannelEnable(state.baseAddr, pin);
/* Empty 5 samples from the FIFO */
for (i = 0; i < 5; i++) {
while (MAP_ADCFIFOLvlGet(state.baseAddr, pin) == 0){
}
MAP_ADCFIFORead(state.baseAddr, pin);
}
DebugP_log1("ADC: (%p) instance opened.", (uintptr_t) handle);
return (handle);
}