Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Silicon_Labs/TARGET_EFM32/analogout_api.c@165:2dd56e6daeec, 2017-05-23 (annotated)
- Committer:
- ranaumarnaeem
- Date:
- Tue May 23 12:54:50 2017 +0000
- Revision:
- 165:2dd56e6daeec
- Parent:
- 150:02e0a0aed4ec
jhjg
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 144:ef7eb2e8f9f7 | 1 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 2 | * @file analogout_aoi.c |
<> | 144:ef7eb2e8f9f7 | 3 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 4 | * @section License |
<> | 144:ef7eb2e8f9f7 | 5 | * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> |
<> | 144:ef7eb2e8f9f7 | 6 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 7 | * |
<> | 144:ef7eb2e8f9f7 | 8 | * SPDX-License-Identifier: Apache-2.0 |
<> | 144:ef7eb2e8f9f7 | 9 | * |
<> | 144:ef7eb2e8f9f7 | 10 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
<> | 144:ef7eb2e8f9f7 | 11 | * not use this file except in compliance with the License. |
<> | 144:ef7eb2e8f9f7 | 12 | * You may obtain a copy of the License at |
<> | 144:ef7eb2e8f9f7 | 13 | * |
<> | 144:ef7eb2e8f9f7 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
<> | 144:ef7eb2e8f9f7 | 15 | * |
<> | 144:ef7eb2e8f9f7 | 16 | * Unless required by applicable law or agreed to in writing, software |
<> | 144:ef7eb2e8f9f7 | 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
<> | 144:ef7eb2e8f9f7 | 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
<> | 144:ef7eb2e8f9f7 | 19 | * See the License for the specific language governing permissions and |
<> | 144:ef7eb2e8f9f7 | 20 | * limitations under the License. |
<> | 144:ef7eb2e8f9f7 | 21 | * |
<> | 144:ef7eb2e8f9f7 | 22 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 23 | |
<> | 144:ef7eb2e8f9f7 | 24 | #include "device.h" |
<> | 144:ef7eb2e8f9f7 | 25 | #if DEVICE_ANALOGOUT |
<> | 144:ef7eb2e8f9f7 | 26 | |
<> | 144:ef7eb2e8f9f7 | 27 | #include "mbed_assert.h" |
<> | 150:02e0a0aed4ec | 28 | #include "mbed_error.h" |
<> | 144:ef7eb2e8f9f7 | 29 | #include "analogout_api.h" |
<> | 144:ef7eb2e8f9f7 | 30 | #include "pinmap.h" |
<> | 144:ef7eb2e8f9f7 | 31 | #include "pinmap_function.h" |
<> | 144:ef7eb2e8f9f7 | 32 | #include "PeripheralPins.h" |
<> | 144:ef7eb2e8f9f7 | 33 | #include "clocking.h" |
<> | 144:ef7eb2e8f9f7 | 34 | |
<> | 144:ef7eb2e8f9f7 | 35 | #include "em_dac.h" |
<> | 144:ef7eb2e8f9f7 | 36 | #include "em_cmu.h" |
<> | 144:ef7eb2e8f9f7 | 37 | |
<> | 144:ef7eb2e8f9f7 | 38 | static uint8_t dac_initialized = 0; |
<> | 144:ef7eb2e8f9f7 | 39 | |
<> | 144:ef7eb2e8f9f7 | 40 | void analogout_init(dac_t *obj, PinName pin) |
<> | 144:ef7eb2e8f9f7 | 41 | { |
<> | 144:ef7eb2e8f9f7 | 42 | /* init in-memory structure */ |
<> | 144:ef7eb2e8f9f7 | 43 | obj->dac = (DAC_TypeDef *) pinmap_peripheral(pin, PinMap_DAC); |
<> | 144:ef7eb2e8f9f7 | 44 | MBED_ASSERT((int) obj->dac != NC); |
<> | 144:ef7eb2e8f9f7 | 45 | |
<> | 144:ef7eb2e8f9f7 | 46 | obj->channel = pin_location(pin, PinMap_DAC); |
<> | 144:ef7eb2e8f9f7 | 47 | MBED_ASSERT((int) obj->channel != NC); |
<> | 144:ef7eb2e8f9f7 | 48 | |
<> | 144:ef7eb2e8f9f7 | 49 | pin_mode(pin, Disabled); |
<> | 144:ef7eb2e8f9f7 | 50 | |
<> | 144:ef7eb2e8f9f7 | 51 | if (!dac_initialized) { |
<> | 144:ef7eb2e8f9f7 | 52 | /* Initialize the DAC. Will disable both DAC channels, so should only be done once */ |
<> | 144:ef7eb2e8f9f7 | 53 | /* Use default settings */ |
<> | 144:ef7eb2e8f9f7 | 54 | CMU_ClockEnable(cmuClock_DAC0, true); |
<> | 144:ef7eb2e8f9f7 | 55 | |
<> | 144:ef7eb2e8f9f7 | 56 | DAC_Init_TypeDef init = DAC_INIT_DEFAULT; |
<> | 144:ef7eb2e8f9f7 | 57 | |
<> | 144:ef7eb2e8f9f7 | 58 | /* Calculate the DAC clock prescaler value that will result in a DAC clock |
<> | 144:ef7eb2e8f9f7 | 59 | * close to 500kHz. Second parameter is zero. This uses the current HFPERCLK |
<> | 144:ef7eb2e8f9f7 | 60 | * frequency instead of setting a new one. */ |
<> | 144:ef7eb2e8f9f7 | 61 | init.prescale = DAC_PrescaleCalc(500000, REFERENCE_FREQUENCY); |
<> | 144:ef7eb2e8f9f7 | 62 | |
<> | 144:ef7eb2e8f9f7 | 63 | /* Set reference voltage to VDD */ |
<> | 144:ef7eb2e8f9f7 | 64 | init.reference = dacRefVDD; |
<> | 144:ef7eb2e8f9f7 | 65 | |
<> | 144:ef7eb2e8f9f7 | 66 | DAC_Init(obj->dac, &init); |
<> | 144:ef7eb2e8f9f7 | 67 | dac_initialized = 1; |
<> | 144:ef7eb2e8f9f7 | 68 | } |
<> | 144:ef7eb2e8f9f7 | 69 | /* Use default channel settings */ |
<> | 144:ef7eb2e8f9f7 | 70 | DAC_InitChannel_TypeDef initChannel = DAC_INITCHANNEL_DEFAULT; |
<> | 144:ef7eb2e8f9f7 | 71 | initChannel.enable = true; |
<> | 144:ef7eb2e8f9f7 | 72 | DAC_InitChannel(obj->dac, &initChannel, obj->channel); |
<> | 144:ef7eb2e8f9f7 | 73 | } |
<> | 144:ef7eb2e8f9f7 | 74 | |
<> | 144:ef7eb2e8f9f7 | 75 | void analogout_free(dac_t *obj) |
<> | 144:ef7eb2e8f9f7 | 76 | { |
<> | 144:ef7eb2e8f9f7 | 77 | //Reset channel by re-initializing |
<> | 144:ef7eb2e8f9f7 | 78 | DAC_InitChannel_TypeDef initChannel = DAC_INITCHANNEL_DEFAULT; |
<> | 144:ef7eb2e8f9f7 | 79 | initChannel.enable = false; |
<> | 144:ef7eb2e8f9f7 | 80 | DAC_InitChannel(obj->dac, &initChannel, obj->channel); |
<> | 144:ef7eb2e8f9f7 | 81 | |
<> | 144:ef7eb2e8f9f7 | 82 | //Check all channels to see if we can disable the DAC completely |
<> | 144:ef7eb2e8f9f7 | 83 | if((DAC0->CH0CTRL & DAC_CH0CTRL_EN) == 0 && (DAC0->CH1CTRL & DAC_CH1CTRL_EN) == 0) { |
<> | 144:ef7eb2e8f9f7 | 84 | CMU_ClockEnable(cmuClock_DAC0, false); |
<> | 144:ef7eb2e8f9f7 | 85 | dac_initialized = 0; |
<> | 144:ef7eb2e8f9f7 | 86 | } |
<> | 144:ef7eb2e8f9f7 | 87 | } |
<> | 144:ef7eb2e8f9f7 | 88 | |
<> | 144:ef7eb2e8f9f7 | 89 | static inline void dac_write(dac_t *obj, int value) |
<> | 144:ef7eb2e8f9f7 | 90 | { |
<> | 144:ef7eb2e8f9f7 | 91 | switch (obj->channel) { |
<> | 144:ef7eb2e8f9f7 | 92 | case 0: |
<> | 144:ef7eb2e8f9f7 | 93 | obj->dac->CH0DATA = value; |
<> | 144:ef7eb2e8f9f7 | 94 | break; |
<> | 144:ef7eb2e8f9f7 | 95 | case 1: |
<> | 144:ef7eb2e8f9f7 | 96 | obj->dac->CH1DATA = value; |
<> | 144:ef7eb2e8f9f7 | 97 | break; |
<> | 144:ef7eb2e8f9f7 | 98 | } |
<> | 144:ef7eb2e8f9f7 | 99 | } |
<> | 144:ef7eb2e8f9f7 | 100 | |
<> | 144:ef7eb2e8f9f7 | 101 | static inline int dac_read(dac_t *obj) |
<> | 144:ef7eb2e8f9f7 | 102 | { |
<> | 144:ef7eb2e8f9f7 | 103 | switch (obj->channel) { |
<> | 144:ef7eb2e8f9f7 | 104 | case 0: |
<> | 144:ef7eb2e8f9f7 | 105 | return obj->dac->CH0DATA; |
<> | 144:ef7eb2e8f9f7 | 106 | break; |
<> | 144:ef7eb2e8f9f7 | 107 | case 1: |
<> | 144:ef7eb2e8f9f7 | 108 | return obj->dac->CH1DATA; |
<> | 144:ef7eb2e8f9f7 | 109 | break; |
<> | 144:ef7eb2e8f9f7 | 110 | default: |
<> | 144:ef7eb2e8f9f7 | 111 | error("AnalogOut pin error. Invalid channel"); |
<> | 144:ef7eb2e8f9f7 | 112 | return -1; |
<> | 144:ef7eb2e8f9f7 | 113 | break; |
<> | 144:ef7eb2e8f9f7 | 114 | } |
<> | 144:ef7eb2e8f9f7 | 115 | } |
<> | 144:ef7eb2e8f9f7 | 116 | |
<> | 144:ef7eb2e8f9f7 | 117 | void analogout_write(dac_t *obj, float value) |
<> | 144:ef7eb2e8f9f7 | 118 | { |
<> | 144:ef7eb2e8f9f7 | 119 | /* We multiply the float value with 0xFFF because the DAC has 12-bit resolution. |
<> | 144:ef7eb2e8f9f7 | 120 | * Ie. accepts values between 0 and 0xFFF (4096). */ |
<> | 144:ef7eb2e8f9f7 | 121 | dac_write(obj, value*0xFFF); |
<> | 144:ef7eb2e8f9f7 | 122 | } |
<> | 144:ef7eb2e8f9f7 | 123 | |
<> | 144:ef7eb2e8f9f7 | 124 | void analogout_write_u16(dac_t *obj, uint16_t value) |
<> | 144:ef7eb2e8f9f7 | 125 | { |
<> | 144:ef7eb2e8f9f7 | 126 | /* The DAC has 12 bit resolution, so we remove the 4 least significant bits */ |
<> | 144:ef7eb2e8f9f7 | 127 | dac_write(obj, value >> 4); |
<> | 144:ef7eb2e8f9f7 | 128 | } |
<> | 144:ef7eb2e8f9f7 | 129 | |
<> | 144:ef7eb2e8f9f7 | 130 | float analogout_read(dac_t *obj) |
<> | 144:ef7eb2e8f9f7 | 131 | { |
<> | 144:ef7eb2e8f9f7 | 132 | /* dac_read returns a number between 0 and 0xFFF. Division gives us a float between 0 and 1 */ |
<> | 144:ef7eb2e8f9f7 | 133 | return dac_read(obj)/(float)0xFFF; |
<> | 144:ef7eb2e8f9f7 | 134 | } |
<> | 144:ef7eb2e8f9f7 | 135 | |
<> | 144:ef7eb2e8f9f7 | 136 | uint16_t analogout_read_u16(dac_t *obj) |
<> | 144:ef7eb2e8f9f7 | 137 | { |
<> | 144:ef7eb2e8f9f7 | 138 | /* dac_read returns a number with 12 significant digits, |
<> | 144:ef7eb2e8f9f7 | 139 | * so we shift in 0s from right to make it a 16 bit number */ |
<> | 144:ef7eb2e8f9f7 | 140 | return dac_read(obj) << 4; |
<> | 144:ef7eb2e8f9f7 | 141 | } |
<> | 144:ef7eb2e8f9f7 | 142 | |
<> | 144:ef7eb2e8f9f7 | 143 | #endif |