mbed-os/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/analogout_api.c

156 lines
5.0 KiB
C

/*
* mbed Microcontroller Library
* Copyright (c) 2017-2018 Future Electronics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device.h"
#include "analogout_api.h"
#include "cy_ctdac.h"
#include "psoc6_utils.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "platform/mbed_error.h"
#if DEVICE_ANALOGOUT
#define CTDAC_NUM_BITS 12
const uint16_t CTDAC_MAX_VALUE = (uint16_t)((1UL << CTDAC_NUM_BITS) - 1);
const uint32_t CTDAC_BASE_CLOCK_HZ = 500000; // 500 kHz or less
#define CTDAC_DEGLITCH_CYCLES 35
/** Global CTDAC configuration data.
*/
static cy_stc_ctdac_config_t ctdac_config = {
.refSource = CY_CTDAC_REFSOURCE_VDDA, /**< Reference source: Vdda or externally through Opamp1 of CTB */
.formatMode = CY_CTDAC_FORMAT_UNSIGNED, /**< Format of DAC value: signed or unsigned */
.updateMode = CY_CTDAC_UPDATE_BUFFERED_WRITE, /**< Update mode: direct or buffered writes or hardware, edge or level */
.deglitchMode = CY_CTDAC_DEGLITCHMODE_UNBUFFERED, /**< Deglitch mode: disabled, buffered, unbuffered, or both */
.outputMode = CY_CTDAC_OUTPUT_VALUE, /**< Output mode: enabled (value or value + 1), high-z, Vssa, or Vdda */
.outputBuffer = CY_CTDAC_OUTPUT_UNBUFFERED, /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */
.deepSleep = CY_CTDAC_DEEPSLEEP_DISABLE, /**< Enable or disable the CTDAC during Deep Sleep */
.deglitchCycles = CTDAC_DEGLITCH_CYCLES, /**< Number of deglitch cycles from 0 to 63 */
.value = 0, /**< Current DAC value */
.nextValue = 0, /**< Next DAC value for double buffering */
.enableInterrupt = false, /**< If true, enable interrupt when next value register is transferred to value register */
.configClock = false, /**< Configure or ignore clock information */
};
static bool ctdac_initialized = 0;
static void ctdac_init(dac_t *obj)
{
if (!ctdac_initialized) {
uint32_t dac_clock_divider = CY_INVALID_DIVIDER;
ctdac_initialized = true;
// Allocate and setup clock.
dac_clock_divider = cy_clk_allocate_divider(CY_SYSCLK_DIV_8_BIT);
if (dac_clock_divider == CY_INVALID_DIVIDER) {
error("CTDAC clock divider allocation failed.");
return;
}
Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT,
dac_clock_divider,
((CY_CLK_PERICLK_FREQ_HZ + CTDAC_BASE_CLOCK_HZ / 2) / CTDAC_BASE_CLOCK_HZ) - 1);
Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, dac_clock_divider);
Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_8_BIT, dac_clock_divider);
Cy_CTDAC_Init(obj->base, &ctdac_config);
Cy_CTDAC_Enable(obj->base);
}
}
void analogout_init(dac_t *obj, PinName pin)
{
uint32_t dac = 0;
uint32_t dac_function = 0;
MBED_ASSERT(obj);
MBED_ASSERT(pin != (PinName)NC);
dac = pinmap_peripheral(pin, PinMap_DAC);
if (dac != (uint32_t)NC) {
if (cy_reserve_io_pin(pin)) {
error("ANALOG OUT pin reservation conflict.");
}
obj->base = (CTDAC_Type*)CY_PERIPHERAL_BASE(dac);
obj->pin = pin;
// Configure clock.
dac_function = pinmap_function(pin, PinMap_DAC);
obj->clock = CY_PIN_CLOCK(dac_function);
pin_function(pin, dac_function);
ctdac_init(obj);
} else {
error("ANALOG OUT pinout mismatch.");
}
}
void analogout_free(dac_t *obj)
{
// Not supported yet.
}
void analogout_write(dac_t *obj, float value)
{
uint32_t val = 0;
if (value > 1.0) {
val = CTDAC_MAX_VALUE;
} else if (value > 0.0) {
val = value * CTDAC_MAX_VALUE;
}
Cy_CTDAC_SetValueBuffered(obj->base, val);
}
void analogout_write_u16(dac_t *obj, uint16_t value)
{
uint32_t val = 0;
val = (value >> (16 - CTDAC_NUM_BITS)); // Convert from 16-bit range.
Cy_CTDAC_SetValueBuffered(obj->base, val);
}
float analogout_read(dac_t *obj)
{
return (float)analogout_read_u16(obj) / 0xffff;
}
uint16_t analogout_read_u16(dac_t *obj)
{
uint16_t value = (obj->base->CTDAC_VAL_NXT >> CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk;
value <<= (16 - CTDAC_NUM_BITS); // Convert to 16-bit range.
return value;
}
const PinMap *analogout_pinmap()
{
return PinMap_DAC;
}
#endif // DEVICE_ANALOGIN