1 /**************************************************************************//**
2 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-3-16 Wayne First version
9 *
10 ******************************************************************************/
11
12 #include <rtconfig.h>
13
14 #if defined(BSP_USING_DAC)
15
16 #include <rtdevice.h>
17 #include "NuMicro.h"
18
19 /* Private define ---------------------------------------------------------------*/
20 enum
21 {
22 DAC_START = -1,
23 #if defined(BSP_USING_DAC0)
24 DAC0_IDX,
25 #endif
26 #if defined(BSP_USING_DAC1)
27 DAC1_IDX,
28 #endif
29 DAC_CNT
30 };
31
32 /* Private Typedef --------------------------------------------------------------*/
33 struct nu_dac
34 {
35 struct rt_dac_device dev;
36 char *name;
37 DAC_T *base;
38 uint32_t chn_msk;
39 uint32_t max_chn_num;
40 };
41 typedef struct nu_dac *nu_dac_t;
42
43 /* Private functions ------------------------------------------------------------*/
44 static rt_err_t nu_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel);
45 static rt_err_t nu_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel);
46 static rt_err_t nu_dac_convert(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value);
47
48 /* Public functions ------------------------------------------------------------*/
49 int rt_hw_dac_init(void);
50
51 /* Private variables ------------------------------------------------------------*/
52
53 static struct nu_dac nu_dac_arr [] =
54 {
55 #if defined(BSP_USING_DAC0)
56 {
57 .name = "dac0", .base = DAC0, .chn_msk = 0, .max_chn_num = 1,
58 },
59 #endif
60 #if defined(BSP_USING_DAC1)
61 {
62 .name = "dac1", .base = DAC1, .chn_msk = 0, .max_chn_num = 1,
63 },
64 #endif
65 };
66
67 /* nu_dac_enabled - Enable DAC engine and wait for ready */
nu_dac_enabled(struct rt_dac_device * device,rt_uint32_t channel)68 static rt_err_t nu_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
69 {
70 nu_dac_t psNuDAC = (nu_dac_t)device;
71
72 RT_ASSERT(device);
73
74 if (channel >= psNuDAC->max_chn_num)
75 return -(RT_EINVAL);
76
77 if (!(psNuDAC->chn_msk & (0x1 << channel)))
78 {
79 DAC_Open(psNuDAC->base, channel, DAC_SOFTWARE_TRIGGER);
80
81 /* The DAC conversion settling time is 1us */
82 DAC_SetDelayTime(psNuDAC->base, 1);
83
84 DAC_ENABLE_RIGHT_ALIGN(psNuDAC->base);
85
86 psNuDAC->chn_msk |= (0x1 << channel);
87 }
88
89 return RT_EOK;
90 }
91
nu_dac_disabled(struct rt_dac_device * device,rt_uint32_t channel)92 static rt_err_t nu_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
93 {
94 nu_dac_t psNuDAC = (nu_dac_t)device;
95
96 RT_ASSERT(device);
97
98 if (channel >= psNuDAC->max_chn_num)
99 return -(RT_EINVAL);
100
101 if (psNuDAC->chn_msk & (0x1 << channel))
102 {
103 DAC_Close(psNuDAC->base, channel);
104
105 psNuDAC->chn_msk &= ~(0x1 << channel);
106 }
107
108 return RT_EOK;
109 }
110
nu_dac_convert(struct rt_dac_device * device,rt_uint32_t channel,rt_uint32_t * value)111 static rt_err_t nu_dac_convert(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
112 {
113 nu_dac_t psNuDAC = (nu_dac_t)device;
114 rt_err_t ret = -RT_ERROR;
115
116 RT_ASSERT(device);
117 RT_ASSERT(value);
118
119 if (channel >= psNuDAC->max_chn_num)
120 {
121 ret = -RT_EINVAL;
122 goto exit_nu_dac_convert;
123 }
124
125 if (!(psNuDAC->chn_msk & (1 << channel)))
126 {
127 goto exit_nu_dac_convert;
128 }
129
130 /* Set DAC 12-bit holding data */
131 DAC_WRITE_DATA(psNuDAC->base, 0, (uint16_t)*value);
132
133 /* Start A/D conversion */
134 DAC_START_CONV(psNuDAC->base);
135
136 ret = RT_EOK;
137
138 exit_nu_dac_convert:
139
140 return -(ret);
141 }
142
143 static const struct rt_dac_ops nu_dac_ops =
144 {
145 .disabled = nu_dac_disabled,
146 .enabled = nu_dac_enabled,
147 .convert = nu_dac_convert,
148 };
149
rt_hw_dac_init(void)150 int rt_hw_dac_init(void)
151 {
152 int i;
153 rt_err_t result;
154
155 for (i = (DAC_START + 1); i < DAC_CNT; i++)
156 {
157 result = rt_hw_dac_register(&nu_dac_arr[i].dev, nu_dac_arr[i].name, &nu_dac_ops, NULL);
158 RT_ASSERT(result == RT_EOK);
159 }
160
161 return 0;
162 }
163 INIT_BOARD_EXPORT(rt_hw_dac_init);
164
165 #endif //#if defined(BSP_USING_DAC)
166