libOpenCM3 opamp config routines and definitions for STM32F303

opamp.h 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #pragma once
  2. #include <libopencm3/cm3/common.h>
  3. #include <libopencm3/stm32/f3/memorymap.h>
  4. // Opamp base address (just one register)
  5. #define OPAMP1_BASE OPAMP_BASE + 0x38
  6. #define OPAMP2_BASE OPAMP_BASE + 0x3C
  7. #define OPAMP3_BASE OPAMP_BASE + 0x40
  8. #define OPAMP4_BASE OPAMP_BASE + 0x44
  9. // opamp constants
  10. #define OPAMP1 OPAMP1_BASE
  11. #define OPAMP2 OPAMP2_BASE
  12. #define OPAMP3 OPAMP3_BASE
  13. #define OPAMP4 OPAMP4_BASE
  14. #define OPAMP_CSR(opamp_base) MMIO32(opamp_base + 0)
  15. #define OPAMP_CSR_LOCK (1 << 31)
  16. #define OPAMP_CSR_OUTCAL (1 << 30)
  17. #define OPAMP_CSR_TSTREF (1 << 29)
  18. // trim registers
  19. #define OPAMP_CSR_TRIMOFFSETN_SHIFT 24
  20. #define OPAMP_CSR_TRIMOFFSETP_SHIFT 19
  21. #define OPAMP_CSR_TRIMOFFSETN_MSK (0x1F << OPAMP_CSR_TRIMOFFSETN_SHIFT)
  22. #define OPAMP_CSR_TRIMOFFSETP_MSK (0x1F << OPAMP_CSR_TRIMOFFSETP_SHIFT)
  23. // user trim
  24. #define OPAMP_CSR_USER_TRIM (1 << 18)
  25. // PGA gain
  26. #define OPAMP_CSR_PGA_GAIN_SHIFT 14
  27. #define OPAMP_CSR_PGA_GAIN_MSK (0b0011 << OPAMP_CSR_PGA_GAIN_SHIFT)
  28. #define OPAMP_CSR_PGA_MIDPOINT_MSK (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
  29. // lower two bits
  30. enum OPAMP_PGA_GAIN {
  31. OPAMP_PGA_GAIN_2 = (0 << OPAMP_CSR_PGA_GAIN_SHIFT),
  32. OPAMP_PGA_GAIN_4 = (1 << OPAMP_CSR_PGA_GAIN_SHIFT),
  33. OPAMP_PGA_GAIN_8 = (2 << OPAMP_CSR_PGA_GAIN_SHIFT),
  34. OPAMP_PGA_GAIN_16 = (3 << OPAMP_CSR_PGA_GAIN_SHIFT)
  35. };
  36. // Masks that can be used to adjust PGA value
  37. enum OPAMP_PGA_MIDPOINT {
  38. OPAMP_PGA_MIDPOINT_NONE = 0,
  39. OPAMP_PGA_MIDPOINT_VM0 = (0b1000 << OPAMP_CSR_PGA_GAIN_SHIFT),
  40. OPAMP_PGA_MIDPOINT_VM1 = (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
  41. };
  42. // Calibration select
  43. #define OPAMP_CSR_CALSEL_SHIFT 12
  44. #define OPAMP_CSR_CALSEL_MSK (0b11 << OPAMP_CSR_CALSEL_SHIFT)
  45. enum OPAMP_CALSEL {
  46. OPAMP_CALSEL_3P3 = (0 << OPAMP_CSR_CALSEL_SHIFT),
  47. OPAMP_CALSEL_10 = (1 << OPAMP_CSR_CALSEL_SHIFT),
  48. OPAMP_CALSEL_50 = (2 << OPAMP_CSR_CALSEL_SHIFT),
  49. OPAMP_CALSEL_90 = (3 << OPAMP_CSR_CALSEL_SHIFT),
  50. };
  51. // Cal On
  52. #define OPAMP_CSR_CALON (1 << 11)
  53. // Non-inverting input, secondary
  54. #define OPAMP_CSR_VPS_SEL_SHIFT 9
  55. #define OPAMP_CSR_VPS_SEL_MSK (0b11 << OPAMP_CSR_VPS_SEL_SHIFT)
  56. enum OPAMP_VPS_SEL {
  57. OPAMP_VPS_SEL_VP0 = (0 << OPAMP_CSR_VPS_SEL_SHIFT),
  58. OPAMP_VPS_SEL_VP1 = (1 << OPAMP_CSR_VPS_SEL_SHIFT),
  59. OPAMP_VPS_SEL_VP2 = (2 << OPAMP_CSR_VPS_SEL_SHIFT),
  60. OPAMP_VPS_SEL_VP3 = (3 << OPAMP_CSR_VPS_SEL_SHIFT),
  61. // The following are just aliases for convenience, mapped for F303.
  62. // probably should not be included in the library, as they're too specific.
  63. // same for the following enums.
  64. OPAMP1_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP0,
  65. OPAMP1_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
  66. OPAMP1_VPS_SEL_PA3 = OPAMP_VPS_SEL_VP2,
  67. OPAMP1_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP3,
  68. OPAMP2_VPS_SEL_PD14 = OPAMP_VPS_SEL_VP0,
  69. OPAMP2_VPS_SEL_PB14 = OPAMP_VPS_SEL_VP1,
  70. OPAMP2_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP2,
  71. OPAMP2_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP3,
  72. OPAMP3_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP0,
  73. OPAMP3_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
  74. OPAMP3_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP2,
  75. OPAMP3_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP3,
  76. OPAMP4_VPS_SEL_PD11 = OPAMP_VPS_SEL_VP0,
  77. OPAMP4_VPS_SEL_PB11 = OPAMP_VPS_SEL_VP1,
  78. OPAMP4_VPS_SEL_PA4 = OPAMP_VPS_SEL_VP2,
  79. OPAMP4_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP3
  80. };
  81. // Inverting input, secondary
  82. #define OPAMP_CSR_VMS_SEL_SHIFT 8
  83. #define OPAMP_CSR_VMS_SEL_MSK (1 << OPAMP_CSR_VMS_SEL_SHIFT)
  84. enum OPAMP_VMS_SEL {
  85. OPAMP_VMS_SEL_VM0 = (0 << OPAMP_CSR_VMS_SEL_SHIFT),
  86. OPAMP_VMS_SEL_VM1 = (1 << OPAMP_CSR_VMS_SEL_SHIFT),
  87. OPAMP1_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
  88. OPAMP1_VMS_SEL_PA3 = OPAMP_VMS_SEL_VM1,
  89. OPAMP2_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
  90. OPAMP2_VMS_SEL_PA5 = OPAMP_VMS_SEL_VM1,
  91. OPAMP3_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
  92. OPAMP3_VMS_SEL_PB2 = OPAMP_VMS_SEL_VM1,
  93. OPAMP4_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
  94. OPAMP4_VMS_SEL_PD8 = OPAMP_VMS_SEL_VM1,
  95. };
  96. // Cal On
  97. #define OPAMP_CSR_TCM_EN (1 << 7)
  98. // Inverting input, primary
  99. #define OPAMP_CSR_VM_SEL_SHIFT 5
  100. #define OPAMP_CSR_VM_SEL_MSK (0b11 << OPAMP_CSR_VM_SEL_SHIFT)
  101. enum OPAMP_VM_SEL {
  102. OPAMP_VM_SEL_VM0 = (0 << OPAMP_CSR_VM_SEL_SHIFT),
  103. OPAMP_VM_SEL_VM1 = (1 << OPAMP_CSR_VM_SEL_SHIFT),
  104. OPAMP_VM_SEL_PGA = (2 << OPAMP_CSR_VM_SEL_SHIFT),
  105. OPAMP_VM_SEL_FLW = (3 << OPAMP_CSR_VM_SEL_SHIFT),
  106. OPAMP1_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
  107. OPAMP1_VM_SEL_PA3 = OPAMP_VM_SEL_VM1,
  108. OPAMP1_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
  109. OPAMP1_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
  110. OPAMP2_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
  111. OPAMP2_VM_SEL_PA5 = OPAMP_VM_SEL_VM1,
  112. OPAMP2_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
  113. OPAMP2_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
  114. OPAMP3_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
  115. OPAMP3_VM_SEL_PB2 = OPAMP_VM_SEL_VM1,
  116. OPAMP3_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
  117. OPAMP3_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
  118. OPAMP4_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
  119. OPAMP4_VM_SEL_PD8 = OPAMP_VM_SEL_VM1,
  120. OPAMP4_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
  121. OPAMP4_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
  122. };
  123. // Non-inverting input, primary
  124. #define OPAMP_CSR_VP_SEL_SHIFT 2
  125. #define OPAMP_CSR_VP_SEL_MSK (0b11 << OPAMP_CSR_VP_SEL_SHIFT)
  126. enum OPAMP_VP_SEL {
  127. OPAMP_VP_SEL_VP0 = (0 << OPAMP_CSR_VP_SEL_SHIFT),
  128. OPAMP_VP_SEL_VP1 = (1 << OPAMP_CSR_VP_SEL_SHIFT),
  129. OPAMP_VP_SEL_VP2 = (2 << OPAMP_CSR_VP_SEL_SHIFT),
  130. OPAMP_VP_SEL_VP3 = (3 << OPAMP_CSR_VP_SEL_SHIFT),
  131. OPAMP1_VP_SEL_PA7 = OPAMP_VP_SEL_VP0,
  132. OPAMP1_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
  133. OPAMP1_VP_SEL_PA3 = OPAMP_VP_SEL_VP2,
  134. OPAMP1_VP_SEL_PA1 = OPAMP_VP_SEL_VP3,
  135. OPAMP2_VP_SEL_PD14 = OPAMP_VP_SEL_VP0,
  136. OPAMP2_VP_SEL_PB14 = OPAMP_VP_SEL_VP1,
  137. OPAMP2_VP_SEL_PB0 = OPAMP_VP_SEL_VP2,
  138. OPAMP2_VP_SEL_PA7 = OPAMP_VP_SEL_VP3,
  139. OPAMP3_VP_SEL_PB13 = OPAMP_VP_SEL_VP0,
  140. OPAMP3_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
  141. OPAMP3_VP_SEL_PA1 = OPAMP_VP_SEL_VP2,
  142. OPAMP3_VP_SEL_PB0 = OPAMP_VP_SEL_VP3,
  143. OPAMP4_VP_SEL_PD11 = OPAMP_VP_SEL_VP0,
  144. OPAMP4_VP_SEL_PB11 = OPAMP_VP_SEL_VP1,
  145. OPAMP4_VP_SEL_PA4 = OPAMP_VP_SEL_VP2,
  146. OPAMP4_VP_SEL_PB13 = OPAMP_VP_SEL_VP3
  147. };
  148. // Forve VP - VP connected to calibration reference
  149. #define OPAMP_CSR_FORCE_VP (1 << 1)
  150. // Enable opamp
  151. #define OPAMP_CSR_OPAMPEN (1 << 0)
  152. // -------------- Functions ----------------
  153. /** Lock the opamp config. No way to unlock until restart. */
  154. void opamp_lock(uint32_t opamp);
  155. /**
  156. * Enable OPAMP
  157. * Must also enable RCC_SYSCFG_COMP in RCC
  158. */
  159. void opamp_enable(uint32_t opamp);
  160. /** Disable OPAMP */
  161. void opamp_disable(uint32_t opamp);
  162. /** Send reference to ADC input channel */
  163. void opamp_ref_to_adc(uint32_t opamp, bool yes);
  164. /** Send reference to non-inverting input */
  165. void opamp_ref_to_vp(uint32_t opamp, bool yes);
  166. /**
  167. * Set PGA gain.
  168. * To use PGA, call opamp_mode_pga() first.
  169. */
  170. void opamp_pga_set_gain(uint32_t opamp, enum OPAMP_PGA_GAIN gain);
  171. /** Set PGA midpoint routing */
  172. void opamp_pga_set_midpoint(uint32_t opamp, enum OPAMP_PGA_MIDPOINT midpoint);
  173. /** Connect VM pin (can be used to select follower and PGA mode) */
  174. void opamp_vm_select(uint32_t opamp, enum OPAMP_VM_SEL vm);
  175. /** Connect the VP pin */
  176. void opamp_vp_select(uint32_t opamp, enum OPAMP_VP_SEL vp);
  177. /**
  178. * Set opamp to PGA mode (shortcut function)
  179. * Midpoint can be connected to VM pins with opamp_pga_set_midpoint()
  180. */
  181. void opamp_mode_pga(uint32_t opamp);
  182. /**
  183. * Set opamp to follower mode (shortcut function).
  184. * VM is not connected to GPIO in this mode.
  185. */
  186. void opamp_mode_follower(uint32_t opamp);
  187. /** Select reference value to use */
  188. void opamp_ref_select(uint32_t opamp, enum OPAMP_CALSEL ref);
  189. /** Calibrate an OpAmp */
  190. bool opamp_calibrate(uint32_t opamp);