• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_OPAMP_DRV_H
9 #define HPM_OPAMP_DRV_H
10 
11 #include "hpm_common.h"
12 #include "hpm_opamp_regs.h"
13 #include "hpm_soc_feature.h"
14 
15 /**
16  * @brief OPMAP driver APIs
17  * @defgroup opamp_interface OPAMP driver APIs
18  * @ingroup io_interfaces
19  * @{
20  *
21  */
22 #define OPAMP_MODE_FOLLOW_KEY   (0x06)
23 #define OPAMP_MODE_INVERT_INDEX0_KEY   (0x08)
24 #define OPAMP_MODE_INVERT_INDEX1_KEY   (0x18)
25 #define OPAMP_MODE_NON_INVERT_INDEX0_KEY   (0x01)
26 #define OPAMP_MODE_NON_INVERT_INDEX1_KEY   (0x09)
27 #define OPAMP_MODE_NON_INVERT_INDEX2_KEY   (0x11)
28 #define OPAMP_MODE_NON_INVERT_INDEX3_KEY   (0x19)
29 #define OPAMP_MODE_NON_INVERT_INDEX4_KEY   (0x09)
30 #define OPAMP_MODE_USER_DEFINE_KEY  (0x04)
31 
32 /**
33  * @brief Reverse Input Pin Selection
34  *
35  */
36 typedef enum {
37     inm_pad_vim0 = 0,    /**< Connect pad vim0 */
38     inm_pad_vim1 = 1,    /**< Connect pad vim1 */
39     inm_pad_vim2 = 2,    /**< Connect pad vim2 */
40     inm_pad_dac = 3,    /**< Connect pad vim dac */
41     inm_pad_floating = 4    /**< Connect inm floating */
42 } opamp_inm_pad_t;
43 
44 /**
45  * @brief Gain multiplier selection
46  *
47  */
48 typedef enum {
49     gain_x_2 = 0,     /**< gain x2 */
50     gain_x_4 = 1,
51     gain_x_8 = 2,
52     gain_x_16 = 3,
53     gain_x_32 = 4,
54     gain_x_64 = 5,
55     gain_x_128 = 6,   /**< gain x128 */
56 } opamp_gain_t;
57 
58 /**
59  * @brief Miller Capacitor Selection
60  *
61  */
62 typedef enum {
63     miller_cap_x_7 = 0, /**< 7 unit cap */
64     miller_cap_x_8 = 1,
65     miller_cap_x_10 = 2,
66     miller_cap_x_13 = 3,
67     miller_cap_x_15 = 4,    /**< 15 unit cap */
68     miller_cap_x_18 = 5,
69     miller_cap_x_5 = 6,
70     miller_cap_x_6 = 7, /**< 6 unit cap */
71 } opamp_miller_cap_t;
72 
73 /**
74  * @brief Positive Input Pin Selection
75  *
76  */
77 typedef enum {
78     inp_pad_vip0 = 0,    /**< Connect pad vip0 */
79     inp_pad_vip1 = 1,    /**< Connect pad vip1 */
80     inp_pad_vip2 = 2,    /**< Connect pad vip2 */
81     inp_pad_dac = 3,    /**< Connect pad vip dac */
82     inp_pad_vsupply_x_0_25 = 4,    /**< Connect reference = 0.25 * vsupply */
83     inp_pad_vsupply_x_0_5 = 5,    /**< Connect reference = 0.5 * vsupply */
84     inp_pad_vsupply_x_0_75 = 6,    /**< Connect reference = 0.75 * vsupply */
85     inp_pad_floating = 7    /**< Connect inp floating */
86 } opamp_inp_pad_t;
87 
88 /**
89  * @brief opamp preset channel
90  *
91  */
92 typedef enum {
93     cfg_preset_0 = OPAMP_CFG_PRESET0,
94     cfg_preset_1 = OPAMP_CFG_PRESET1,
95     cfg_preset_2 = OPAMP_CFG_PRESET2,
96     cfg_preset_3 = OPAMP_CFG_PRESET3,
97     cfg_preset_4 = OPAMP_CFG_PRESET4,
98     cfg_preset_5 = OPAMP_CFG_PRESET5,
99     cfg_preset_6 = OPAMP_CFG_PRESET6,
100     cfg_preset_7 = OPAMP_CFG_PRESET7,
101 } opamp_cfg_preset_chn_t;
102 
103 /**
104  * @brief operational amplifier
105  *
106  */
107 typedef enum {
108     mode_follow = 0,  /**< opamp follow mode */
109     mode_invert_intern_vol = 1,   /**< inverting opamp */
110     mode_invert_extern_vol = 2,   /**< inverted amplification mode, external reference voltage */
111     mode_invert_dac_vol = 3,      /**< inverted amplification mode, DAC output reference voltage */
112     mode_non_invert_gnd_vol = 4,   /**< forward amplification mode, GND is the reference voltage */
113     mode_non_invert_extern_vol = 5,   /**< forward amplification mode, external reference voltage */
114     mode_non_invert_dac_vol = 6,  /**< forward amplification mode, DAC output reference voltage */
115     mode_user = 7,    /**< custom Mode */
116 } opamp_mode_t;
117 
118 /**
119  * @brief opamp configuration preset0
120  *
121  */
122 typedef union opamp_cfg_preset0 {
123     struct {
124         uint32_t vip_select: 3;
125         uint32_t vim_select: 3;
126         uint32_t vswitch_select: 3;
127         uint32_t cap_select: 4;
128         uint32_t reserve: 19;
129     };
130     uint32_t val;
131 } opamp_ctrl_cfg_preset0_t;
132 
133 /**
134  * @brief opamp configuration preset1
135  *
136  */
137 typedef union opamp_cfg_preset1 {
138     struct {
139         uint32_t res_select: 3;
140         uint32_t function_mode: 5;
141         uint32_t iref_select: 2;
142         uint32_t opaout_select: 2;
143         uint32_t is_vssa_disconnect: 1;
144         uint32_t en_lv: 1;
145         uint32_t hw_trig_en: 1;
146         uint32_t reserve: 17;
147     };
148     uint32_t val;
149 } opamp_ctrl_cfg_preset1_t;
150 
151 typedef struct opamp_cfg {
152     opamp_mode_t mode;
153     opamp_inm_pad_t negative_input_pin;
154     opamp_inp_pad_t positive_input_pin;
155     opamp_gain_t gain;
156     opamp_miller_cap_t miller_cap;
157     bool enable_extern_filter_cap;
158     bool enable_phase_margin_cap;
159 } opamp_cfg_t;
160 
161 #ifdef __cplusplus
162 extern "C" {
163 #endif
164 
165 /**
166  * @brief opamp initialisation functions
167  *      Use this function to initialise the op-amp to different modes
168  * @param opamp @ref OPAMP_Type
169  * @param cfg @ref opamp_cfg_t
170  * @return  @ref hpm_stat_t
171  */
172 hpm_stat_t opamp_init(OPAMP_Type *opamp, opamp_cfg_t *cfg);
173 /**
174  * @brief enable opamp function
175  *
176  * @param opamp @ref OPAMP_Type
177  */
opamp_enable(OPAMP_Type * opamp)178 static inline void opamp_enable(OPAMP_Type *opamp)
179 {
180     opamp->CTRL0 |= OPAMP_CTRL0_EN_LV_MASK;
181 }
182 
183 /**
184  * @brief preset enable opamp function
185  *
186  * @param opamp @ref OPAMP_Type
187  * @param preset_chn preset channel
188  */
opamp_preset_opamp_enable(OPAMP_Type * opamp,uint8_t preset_chn)189 static inline void opamp_preset_opamp_enable(OPAMP_Type *opamp, uint8_t preset_chn)
190 {
191     opamp->CFG[preset_chn].CFG1 |= OPAMP_CFG_CFG1_EN_LV_MASK;
192 }
193 
194 /**
195  * @brief disable opamp function
196  *
197  * @param opamp @ref OPAMP_Type
198  */
opamp_disable(OPAMP_Type * opamp)199 static inline void opamp_disable(OPAMP_Type *opamp)
200 {
201     opamp->CTRL0 &= ~OPAMP_CTRL0_EN_LV_MASK;
202 }
203 
204 /**
205  * @brief preset disable opamp function
206  *
207  * @param opamp @ref OPAMP_Type
208  * @param preset_chn preset channel
209  */
opamp_preset_opamp_disable(OPAMP_Type * opamp,uint8_t preset_chn)210 static inline void opamp_preset_opamp_disable(OPAMP_Type *opamp, uint8_t preset_chn)
211 {
212     opamp->CFG[preset_chn].CFG1 &= ~OPAMP_CFG_CFG1_EN_LV_MASK;
213 }
214 
215 /**
216  * @brief opamp miller cap selection
217  *
218  * @param opamp @ref OPAMP_Type
219  * @param select @ref opamp_iref_select_t
220  */
opamp_miller_cap_select(OPAMP_Type * opamp,opamp_miller_cap_t select)221 static inline void opamp_miller_cap_select(OPAMP_Type *opamp, opamp_miller_cap_t select)
222 {
223     opamp->CTRL0 = (opamp->CTRL0 & (~OPAMP_CTRL0_MILLER_SEL_MASK)) | OPAMP_CTRL0_MILLER_SEL_SET(select);
224 }
225 
226 /**
227  * @brief opamp miller cap selection preset
228  *
229  * @param opamp @ref OPAMP_Type
230  * @param preset_chn preset channel
231  * @param select @ref opamp_iref_select_t
232  */
opamp_preset_miller_cap_select(OPAMP_Type * opamp,uint8_t preset_chn,opamp_miller_cap_t select)233 static inline void opamp_preset_miller_cap_select(OPAMP_Type *opamp, uint8_t preset_chn, opamp_miller_cap_t select)
234 {
235     opamp->CFG[preset_chn].CFG0 = (opamp->CFG[preset_chn].CFG0 & (~OPAMP_CFG_CFG0_MILLER_SEL_MASK)) | OPAMP_CFG_CFG0_MILLER_SEL_SET(select);
236 }
237 
238 /**
239  * @brief enable phase margin compensation cap
240  *
241  * @param opamp @ref OPAMP_Type
242  */
opamp_phase_margin_cap_enable(OPAMP_Type * opamp)243 static inline void opamp_phase_margin_cap_enable(OPAMP_Type *opamp)
244 {
245     opamp->CTRL0 &= ~OPAMP_CTRL0_DISABLE_PM_CAP_MASK;
246 }
247 
248 /**
249  * @brief enable phase margin compensation cap preset
250  *
251  * @param opamp @ref OPAMP_Type
252  * @param preset_chn preset channel
253  */
opamp_preset_phase_margin_cap_enable(OPAMP_Type * opamp,uint8_t preset_chn)254 static inline void opamp_preset_phase_margin_cap_enable(OPAMP_Type *opamp, uint8_t preset_chn)
255 {
256     opamp->CFG[preset_chn].CFG0 &= ~OPAMP_CFG_CFG0_DISABLE_PM_CAP_MASK;
257 }
258 
259 /**
260  * @brief disable phase margin compensation cap
261  *
262  * @param opamp @ref OPAMP_Type
263  */
opamp_phase_margin_cap_disable(OPAMP_Type * opamp)264 static inline void opamp_phase_margin_cap_disable(OPAMP_Type *opamp)
265 {
266     opamp->CTRL0 |= OPAMP_CTRL0_DISABLE_PM_CAP_MASK;
267 }
268 
269 /**
270  * @brief disable phase margin compensation cap preset
271  *
272  * @param opamp @ref OPAMP_Type
273  * @param preset_chn preset channel
274  */
opamp_preset_phase_margin_cap_disable(OPAMP_Type * opamp,uint8_t preset_chn)275 static inline void opamp_preset_phase_margin_cap_disable(OPAMP_Type *opamp, uint8_t preset_chn)
276 {
277     opamp->CFG[preset_chn].CFG0 |= OPAMP_CFG_CFG0_DISABLE_PM_CAP_MASK;
278 }
279 
280 /**
281  * @brief opamp core inm connect pad
282  *
283  * @param opamp @ref OPAMP_Type
284  * @param select @ref opamp_inm_pad_t
285  */
opamp_inn_pad_select(OPAMP_Type * opamp,opamp_inm_pad_t select)286 static inline void opamp_inn_pad_select(OPAMP_Type *opamp, opamp_inm_pad_t select)
287 {
288     opamp->CTRL0 = (opamp->CTRL0 & (~OPAMP_CTRL0_VIM_SEL_MASK)) | OPAMP_CTRL0_VIM_SEL_SET(select);
289 }
290 
291 /**
292  * @brief opamp core inm connect pad preset
293  *
294  * @param opamp @ref OPAMP_Type
295  * @param preset_chn preset channel
296  * @param select @ref opamp_inm_pad_t
297  */
opamp_preset_inn_pad_select(OPAMP_Type * opamp,uint8_t preset_chn,opamp_inm_pad_t select)298 static inline void opamp_preset_inn_pad_select(OPAMP_Type *opamp, uint8_t preset_chn, opamp_inm_pad_t select)
299 {
300     opamp->CFG[preset_chn].CFG0 = (opamp->CFG[preset_chn].CFG0 & (~OPAMP_CFG_CFG0_VIM_SEL_MASK)) | OPAMP_CFG_CFG0_VIM_SEL_SET(select);
301 }
302 
303 /**
304  * @brief main string resistor selection
305  *
306  * @param opamp @ref OPAMP_Type
307  * @param select @ref opamp_gain_t
308  *
309  */
opamp_gain_select(OPAMP_Type * opamp,opamp_gain_t select)310 static inline void opamp_gain_select(OPAMP_Type *opamp, opamp_gain_t select)
311 {
312     opamp->CTRL0 = (opamp->CTRL0 & (~OPAMP_CTRL0_GAIN_SEL_MASK)) | OPAMP_CTRL0_GAIN_SEL_SET(select);
313 }
314 
315 /**
316  * @brief main string resistor selection preset
317  *
318  * @param opamp @ref OPAMP_Type
319  * @param preset_chn preset channel
320  * @param select @ref opamp_gain_t
321  *
322  */
opamp_preset_gain_select(OPAMP_Type * opamp,uint8_t preset_chn,opamp_gain_t select)323 static inline void opamp_preset_gain_select(OPAMP_Type *opamp, uint8_t preset_chn, opamp_gain_t select)
324 {
325     opamp->CFG[preset_chn].CFG1 = (opamp->CFG[preset_chn].CFG1 & (~OPAMP_CFG_CFG1_GAIN_SEL_MASK)) | OPAMP_CFG_CFG1_GAIN_SEL_SET(select);
326 }
327 
328 /**
329  * @brief disconnect the main series resistor and VSSA
330  *
331  * @param opamp @ref OPAMP_Type
332  */
opamp_disconnect_vssa(OPAMP_Type * opamp)333 static inline void opamp_disconnect_vssa(OPAMP_Type *opamp)
334 {
335     opamp->CTRL0 |= OPAMP_CTRL0_VBYPASS_MASK;
336 }
337 
338 /**
339  * @brief disconnect the main series resistor and VSSA preset
340  *
341  * @param opamp @ref OPAMP_Type
342  * @param preset_chn preset channel
343  */
opamp_preset_disconnect_vssa(OPAMP_Type * opamp,uint8_t preset_chn)344 static inline void opamp_preset_disconnect_vssa(OPAMP_Type *opamp, uint8_t preset_chn)
345 {
346     opamp->CFG[preset_chn].CFG1 |= OPAMP_CFG_CFG1_VBYPASS_LV_MASK;
347 }
348 
349 /**
350  * @brief connect the main series resistor and VSSA
351  *
352  * @param opamp @ref OPAMP_Type
353  */
opamp_connect_vssa(OPAMP_Type * opamp)354 static inline void opamp_connect_vssa(OPAMP_Type *opamp)
355 {
356     opamp->CTRL0 &= ~OPAMP_CTRL0_VBYPASS_MASK;
357 }
358 
359 /**
360  * @brief connect the main series resistor and VSSA preset
361  *
362  * @param opamp @ref OPAMP_Type
363  * @param preset_chn preset channel
364  */
opamp_preset_connect_vssa(OPAMP_Type * opamp,uint8_t preset_chn)365 static inline void opamp_preset_connect_vssa(OPAMP_Type *opamp, uint8_t preset_chn)
366 {
367     opamp->CFG[preset_chn].CFG1 &= ~OPAMP_CFG_CFG1_VBYPASS_LV_MASK;
368 }
369 
370 /**
371  * @brief opamp inp select
372  *
373  * @param opamp @ref OPAMP_Type
374  * @param select @ref opamp_inp_pad_t
375  */
opamp_inp_pad_select(OPAMP_Type * opamp,opamp_inp_pad_t select)376 static inline void opamp_inp_pad_select(OPAMP_Type *opamp, opamp_inp_pad_t select)
377 {
378     opamp->CTRL0 = (opamp->CTRL0 & (~OPAMP_CTRL0_VIP_SEL_MASK)) | OPAMP_CTRL0_VIP_SEL_SET(select);
379 }
380 
381 /**
382  * @brief opamp inp select preset
383  *
384  * @param opamp @ref OPAMP_Type
385  * @param preset_chn preset channel
386  * @param select @ref opamp_inp_pad_t
387  */
opamp_preset_inp_pad_select(OPAMP_Type * opamp,uint8_t preset_chn,opamp_inp_pad_t select)388 static inline void opamp_preset_inp_pad_select(OPAMP_Type *opamp, uint8_t preset_chn, opamp_inp_pad_t select)
389 {
390     opamp->CFG[preset_chn].CFG0 = (opamp->CFG[preset_chn].CFG0 & (~OPAMP_CFG_CFG0_VIP_SEL_MASK)) | OPAMP_CFG_CFG0_VIP_SEL_SET(select);
391 }
392 
393 
394 /**
395  * @brief opamp get current preset
396  *
397  * @param opamp @ref OPAMP_Type
398  * @return value
399  */
opamp_get_cur_preset(OPAMP_Type * opamp)400 static inline uint8_t opamp_get_cur_preset(OPAMP_Type *opamp)
401 {
402     return OPAMP_STATUS_CUR_PRESET_GET(opamp->STATUS);
403 }
404 
405 /**
406  * @brief get the current preset value
407  *
408  * @param opamp @ref OPAMP_Type
409  * @return true one of cur_preset is selected for opamp
410  * @return false opamp use cfg0 parameters
411  */
opamp_get_is_preset(OPAMP_Type * opamp)412 static inline bool opamp_get_is_preset(OPAMP_Type *opamp)
413 {
414     return OPAMP_STATUS_PRESET_ACT_GET(opamp->STATUS);
415 }
416 
417 /**
418  * @brief Get the trigger conflict status
419  *
420  * @param opamp @ref OPAMP_Type
421  * @return  if more than one hardware trigger is set, will put all trigger input there.
422  */
opamp_get_trig_conflict_status(OPAMP_Type * opamp)423 static inline uint8_t opamp_get_trig_conflict_status(OPAMP_Type *opamp)
424 {
425     return OPAMP_STATUS_TRIG_CONFLICT_GET(opamp->STATUS);
426 }
427 
428 /**
429  * @brief Clear the trigger conflict status
430  *
431  * @param opamp @ref OPAMP_Type
432  */
opamp_clear_conflict_status(OPAMP_Type * opamp)433 static inline void opamp_clear_conflict_status(OPAMP_Type *opamp)
434 {
435     opamp->STATUS = OPAMP_STATUS_TRIG_CONFLICT_MASK;
436 }
437 
438 /**
439  * @brief Set opamp preset value
440  *
441  * @param opamp @ref OPAMP_Type
442  * @param val @ref opamp_cfg_preset_chn_t
443  */
opamp_set_sw_preset_val(OPAMP_Type * opamp,opamp_cfg_preset_chn_t val)444 static inline void opamp_set_sw_preset_val(OPAMP_Type *opamp, opamp_cfg_preset_chn_t val)
445 {
446     opamp->CTRL1 = (opamp->CTRL1 & (~OPAMP_CTRL1_SW_SEL_MASK)) | OPAMP_CTRL1_SW_SEL_SET(val);
447 }
448 
449 /**
450  * @brief Enable software preset
451  *
452  * @param opamp @ref OPAMP_Type
453  */
opamp_enable_sw_preset(OPAMP_Type * opamp)454 static inline void opamp_enable_sw_preset(OPAMP_Type *opamp)
455 {
456     opamp->CTRL1 |= OPAMP_CTRL1_SW_PRESET_MASK;
457 }
458 
459 /**
460  * @brief Disable software preset
461  *
462  * @param opamp @ref OPAMP_Type
463  */
opamp_disable_sw_preset(OPAMP_Type * opamp)464 static inline void opamp_disable_sw_preset(OPAMP_Type *opamp)
465 {
466     opamp->CTRL1 &= ~OPAMP_CTRL1_SW_PRESET_MASK;
467 }
468 
469 
470 /**
471  * @brief Set preset x channel value
472  *
473  * @param opamp @ref OPAMP_Type
474  * @param preset_chn preset channel
475  * @param chn channel
476  */
opamp_set_preset_x_chn(OPAMP_Type * opamp,uint8_t preset_chn,uint8_t chn)477 static inline void opamp_set_preset_x_chn(OPAMP_Type *opamp, uint8_t preset_chn, uint8_t chn)
478 {
479     opamp->CFG[preset_chn].CFG2 = OPAMP_CFG_CFG2_CHANNEL_SET(chn);
480 }
481 
482 /**
483  * @brief Set preset cfg
484  *
485  * @param opamp @ref OPAMP_Type
486  * @param preset_chn preset channel
487  * @param cfg @ref opamp_cfg_t
488  * @return hpm_stat_t
489  */
490 hpm_stat_t opamp_set_preset_cfg(OPAMP_Type *opamp, uint8_t preset_chn, opamp_cfg_t *cfg);
491 
492 /**
493  * @brief opamp enable preset hardware trig
494  *
495  * @param opamp @ref OPAMP_Type
496  * @param preset_chn preset channel
497  */
opamp_preset_enable_hw_trig(OPAMP_Type * opamp,uint8_t preset_chn)498 static inline void opamp_preset_enable_hw_trig(OPAMP_Type *opamp, uint8_t preset_chn)
499 {
500     opamp->CFG[preset_chn].CFG1 |= OPAMP_CFG_CFG1_HW_TRIG_EN_MASK;
501 }
502 
503 /**
504  * @brief opamp disable preset hardware trig
505  *
506  * @param opamp @ref OPAMP_Type
507  * @param preset_chn preset channel
508  */
opamp_preset_disable_hw_trig(OPAMP_Type * opamp,uint8_t preset_chn)509 static inline void opamp_preset_disable_hw_trig(OPAMP_Type *opamp, uint8_t preset_chn)
510 {
511     opamp->CFG[preset_chn].CFG1 &= ~OPAMP_CFG_CFG1_HW_TRIG_EN_MASK;
512 }
513 
514 /**
515  * @brief opamp set mode
516  *
517  * @param opamp @ref OPAMP_Type
518  * @param mode @ref OPAMP_MODE_XX
519  */
opamp_mode_set(OPAMP_Type * opamp,uint8_t mode)520 static inline void opamp_mode_set(OPAMP_Type *opamp, uint8_t mode)
521 {
522     opamp->CTRL0 = (opamp->CTRL0 & (~OPAMP_CTRL0_MODE_MASK)) | OPAMP_CTRL0_MODE_SET(mode);
523 }
524 
525 /**
526  * @brief opamp preset set mode
527  *
528  * @param opamp @ref OPAMP_Type
529  * @param preset_chn preset channel
530  * @param mode @ref OPAMP_MODE_XX
531  */
opamp_preset_mode_set(OPAMP_Type * opamp,uint8_t preset_chn,uint8_t mode)532 static inline void opamp_preset_mode_set(OPAMP_Type *opamp, uint8_t preset_chn, uint8_t mode)
533 {
534     opamp->CFG[preset_chn].CFG1 = (opamp->CFG[preset_chn].CFG1 & (~OPAMP_CFG_CFG1_MODE_MASK)) | OPAMP_CFG_CFG1_MODE_SET(mode);
535 }
536 
537 /**
538  * @}
539  *
540  */
541 
542 #ifdef __cplusplus
543 }
544 #endif
545 
546 #endif /* HPM_ACMP_DRV_H */
547