OpenMPTL - STM32F10X
C++ Microprocessor Template Library
adc.hpp
Go to the documentation of this file.
1 /*
2  * OpenMPTL - C++ Microprocessor Template Library
3  *
4  * Copyright (C) 2012-2017 Axel Burri <axel@tty0.ch>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef ARCH_ADC_HPP_INCLUDED
22 #define ARCH_ADC_HPP_INCLUDED
23 
24 #include <arch/rcc.hpp>
25 #include <arch/reg/adc.hpp>
26 #include <type_traits>
27 
28 namespace mptl {
29 
30 
31 template<unsigned adc_no>
32 class adc
33 {
34  static_assert((adc_no >= 1) && (adc_no <= 3), "invalid ADC number");
35 
36  using ADCx = ADC< adc_no >;
37 
38 public:
40 
41  /** Sample time, for regular_channel_config<> */
42  enum class sample_time {
43  cycles_1_5 = 0, /**< 000: 1.5 cycles */
44  cycles_7_5 = 1, /**< 001: 7.5 cycles */
45  cycles_13_5 = 2, /**< 010: 13.5 cycles */
46  cycles_28_5 = 3, /**< 011: 28.5 cycles */
47  cycles_41_5 = 4, /**< 100: 41.5 cycles */
48  cycles_55_5 = 5, /**< 101: 55.5 cycles */
49  cycles_71_5 = 6, /**< 110: 71.5 cycles */
50  cycles_239_5 = 7 /**< 111: 239.5 cycles */
51  };
52 
53 private:
54 
55  /** CR1::DUALMOD is only valid for ADC1 */
56  template< unsigned value >
57  using dualmod_impl =
58  typename std::enable_if<
59  (adc_no == 1) || (value == 0),
61  >::type;
62 
63  template< unsigned timer, unsigned cc >
64  struct capture_compare_impl {
65  static constexpr uint32_t value =
66  (adc_no < 3) && (timer == 1) && (cc == 1) ? 0 :
67  (adc_no < 3) && (timer == 1) && (cc == 2) ? 1 :
68  (adc_no < 3) && (timer == 1) && (cc == 3) ? 2 :
69  (adc_no < 3) && (timer == 2) && (cc == 1) ? 3 :
70  (adc_no < 3) && (timer == 4) && (cc == 4) ? 6 :
71  (adc_no == 3) && (timer == 3) && (cc == 1) ? 0 :
72  (adc_no == 3) && (timer == 2) && (cc == 3) ? 1 :
73  (adc_no == 3) && (timer == 1) && (cc == 3) ? 2 :
74  (adc_no == 3) && (timer == 8) && (cc == 1) ? 3 :
75  (adc_no == 3) && (timer == 5) && (cc == 1) ? 5 :
76  (adc_no == 3) && (timer == 5) && (cc == 3) ? 6 :
77  0xff;
78  static_assert((value & 0x7) == value, "invalid timer / cc combination");
80  };
81 
82  template<unsigned timer>
83  struct trigger_output_impl {
84  static constexpr uint32_t value =
85  (adc_no < 3) && (timer == 3) ? 4 :
86  (adc_no == 3) && (timer == 8) ? 4 :
87 #if defined (STM32F10X_XL)
88  (adc_no < 3) && (timer == 8) ? 6 :
89 #endif
90  0xff;
91  static_assert((value & 0x7) == value, "invalid timer");
93  };
94 
95  template<unsigned channel, unsigned rank, sample_time _sample_time>
96  struct regular_channel_config_impl {
97  static constexpr unsigned smp_value = (unsigned)_sample_time;
98 
99  static_assert(channel <= 17, "invalid channel");
100  static_assert((rank >= 1) && (rank <= 16), "invalid rank");
101  static_assert(smp_value < 8, "invalid sample_time");
102 
103  using type = reglist<
106  >;
107  };
108 
109 public: /* ------ configuration traits ------ */
110 
111  /** Dual mode selection. */
112  struct dual_mode
113  {
114  using independent = typename dualmod_impl< 0 >::type; /**< 0000: Independent mode. */
115  using regular_simultaneous_injected = typename dualmod_impl< 1 >::type; /**< 0001: Combined regular simultaneous + injected simultaneous mode */
116  using regular_simultaneous_alternate_trigger = typename dualmod_impl< 2 >::type; /**< 0010: Combined regular simultaneous + alternate trigger mode */
117  using injected_simultaneous_fast_interleaved = typename dualmod_impl< 3 >::type; /**< 0011: Combined injected simultaneous + fast interleaved mode */
118  using injected_simultaneous_slow_interleaved = typename dualmod_impl< 4 >::type; /**< 0100: Combined injected simultaneous + slow Interleaved mode */
119  using injected_simultaneous = typename dualmod_impl< 5 >::type; /**< 0101: Injected simultaneous mode only */
120  using regular_simultaneous = typename dualmod_impl< 6 >::type; /**< 0110: Regular simultaneous mode only */
121  using fast_interleaved = typename dualmod_impl< 7 >::type; /**< 0111: Fast interleaved mode only */
122  using slow_interleaved = typename dualmod_impl< 8 >::type; /**< 1000: Slow interleaved mode only */
123  using alternate_trigger = typename dualmod_impl< 9 >::type; /**< 1001: Alternate trigger mode only */
124  };
125 
126  /**
127  * In Scan mode, the inputs selected through the ADC_SQRx or
128  * ADC_JSQRx registers are converted.
129  */
131 
132  /**
133  * Continuous conversion.
134  * If set conversion takes place continuously.
135  */
137 
138  /**
139  * External event select for regular group.
140  * Select the external event used to trigger the start of
141  * conversion of a regular group:
142  */
144  {
145  /** SWSTART */
147 
148  /** CCx */
149  template<unsigned timer, unsigned cc>
151 
152  /* TRGO */
153  template<unsigned timer>
155 
156  using exti_line11 =
157  typename std::enable_if<
158  (adc_no < 3),
160  >::type;
161  };
162 
163  /** Data alignment */
164  struct data_align
165  {
168  };
169 
170  /** Regular channel sequence length 1<=n<=16 (SQR1[23:20] L) */
171  template<unsigned value>
173  typename std::enable_if<
174  (value >= 1) && (value <= 16),
175  regval< typename ADCx::SQR1::L, value - 1 >
176  >::type;
177 
178  /** Regular channel configuration */
179  template<unsigned channel, unsigned rank, sample_time _sample_time>
181 
182 
183 public: /* ------ static member functions ------ */
184 
185  /**
186  * Configure ADC register using Tp type traits.
187  *
188  * NOTE: make sure no communication is ongoing when calling this function.
189  */
190  template< typename... Tp >
191  static void configure(void) {
192  reglist< Tp... >::template strict_reset_to<
193  typename ADCx::CR1,
194  typename ADCx::CR2,
195  typename ADCx::SMPR1,
196  typename ADCx::SMPR2,
197  typename ADCx::SQR1,
198  typename ADCx::SQR2,
199  typename ADCx::SQR3
200  >();
201  }
202 
203  static void reset(void) {
204  switch(adc_no) {
205  case 1:
208  break;
209  case 2:
212  }
213  }
214 
215  static void enable(void) {
216  ADCx::CR2::ADON::set();
217  }
218  static void disable(void) {
219  ADCx::CR2::ADON::clear();
220  }
221 
222  /**
223  * - Enable ADC conversion on external event
224  * - Start ADC conversion
225  */
227  ADCx::CR2::template set<
228  typename ADCx::CR2::EXTTRIG,
229  typename ADCx::CR2::SWSTART
230  >();
231  }
232 
233  /**
234  * - Stop ADC conversion
235  * - Disable ADC conversion on external event
236  */
238  ADCx::CR2::template clear<
239  typename ADCx::CR2::EXTTRIG,
240  typename ADCx::CR2::SWSTART
241  >();
242  }
243 
244  static void wait_eoc(void) {
245  while(ADCx::SR::EOC::test() == false);
246  }
247 
248  static uint16_t get_conversion_value(void) {
249  return ADCx::DR::load();
250  }
251 
252 };
253 
254 } // namespace mptl
255 
256 #endif // ARCH_ADC_HPP_INCLUDED
typename std::enable_if<(adc_no< 3), regval< typename ADCx::CR2::EXTSEL, 6 > >::type exti_line11
Definition: adc.hpp:160
regbits< type, 20, 4 > L
Regular channel sequence length.
Definition: adc.hpp:204
typename std::enable_if<(value >=1) &&(value<=16), regval< typename ADCx::SQR1::L, value - 1 > >::type regular_channel_sequence_length
Regular channel sequence length 1<=n<=16 (SQR1[23:20] L)
Definition: adc.hpp:176
static void enable_software_start_conversion(void)
Definition: adc.hpp:226
static void disable(void)
Definition: adc.hpp:218
static void disable_software_start_conversion(void)
Definition: adc.hpp:237
Definition: rcc.hpp:223
typename regular_channel_config_impl< channel, rank, _sample_time >::type regular_channel_config
Regular channel configuration.
Definition: adc.hpp:180
static void configure(void)
Configure ADC register using Tp type traits.
Definition: adc.hpp:191
Control register 2.
Definition: adc.hpp:89
sample_time
Sample time, for regular_channel_config<>
Definition: adc.hpp:42
Data alignment.
Definition: adc.hpp:164
typename dualmod_impl< 9 >::type alternate_trigger
1001: Alternate trigger mode only
Definition: adc.hpp:123
Regular sequence register 1.
Definition: adc.hpp:199
static void reset(void)
Definition: adc.hpp:203
Definition: adc.hpp:32
typename dualmod_impl< 8 >::type slow_interleaved
1000: Slow interleaved mode only
Definition: adc.hpp:122
typename dualmod_impl< 2 >::type regular_simultaneous_alternate_trigger
0010: Combined regular simultaneous + alternate trigger mode
Definition: adc.hpp:116
Sample time register 1.
Definition: adc.hpp:112
typename dualmod_impl< 7 >::type fast_interleaved
0111: Fast interleaved mode only
Definition: adc.hpp:121
static uint16_t get_conversion_value(void)
Definition: adc.hpp:248
Regular sequence register 2.
Definition: adc.hpp:214
static void enable(void)
Definition: adc.hpp:215
typename dualmod_impl< 1 >::type regular_simultaneous_injected
0001: Combined regular simultaneous + injected simultaneous mode
Definition: adc.hpp:115
regbits< type, 20, 1 > EXTTRIG
External trigger conversion mode for regular channels.
Definition: adc.hpp:97
typename dualmod_impl< 4 >::type injected_simultaneous_slow_interleaved
0100: Combined injected simultaneous + slow Interleaved mode
Definition: adc.hpp:118
typename capture_compare_impl< timer, cc >::type capture_compare
CCx.
Definition: adc.hpp:150
Sample time register 2.
Definition: adc.hpp:130
typename dualmod_impl< 0 >::type independent
0000: Independent mode.
Definition: adc.hpp:114
typename dualmod_impl< 5 >::type injected_simultaneous
0101: Injected simultaneous mode only
Definition: adc.hpp:119
Regular sequence register 3.
Definition: adc.hpp:230
typename trigger_output_impl< timer >::type trigger_output
Definition: adc.hpp:154
Dual mode selection.
Definition: adc.hpp:112
typename dualmod_impl< 3 >::type injected_simultaneous_fast_interleaved
0011: Combined injected simultaneous + fast interleaved mode
Definition: adc.hpp:117
External event select for regular group.
Definition: adc.hpp:143
typename dualmod_impl< 6 >::type regular_simultaneous
0110: Regular simultaneous mode only
Definition: adc.hpp:120
Analog-to-digital converter (ADC)
Definition: adc.hpp:38
regbits< type, 22, 1 > SWSTART
Start conversion of regular channels.
Definition: adc.hpp:95
static void wait_eoc(void)
Definition: adc.hpp:244
Control register 1.
Definition: adc.hpp:66