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