mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_Cypress/TARGET_PSOC6/analogout_api.c
- Revision:
- 188:bcfe06ba3d64
- Child:
- 189:f392fc9709a3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/TARGET_Cypress/TARGET_PSOC6/analogout_api.c Thu Nov 08 11:46:34 2018 +0000 @@ -0,0 +1,150 @@ +/* + * 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; +} + +#endif // DEVICE_ANALOGIN +