@@ -15,6 +15,14 @@ namespace klib::core::lpc175x::io {
1515 // amount of bits in the ADC
1616 constexpr static uint32_t bits = 12 ;
1717
18+ // using for the array of callbacks
19+ using interrupt_callback = void (*)();
20+
21+ protected:
22+ // callback when a adc interrupt
23+ static inline interrupt_callback adc_callback = nullptr ;
24+
25+ public:
1826 /* *
1927 * @brief Start sampling the input pins
2028 *
@@ -34,17 +42,13 @@ namespace klib::core::lpc175x::io {
3442 }
3543
3644 /* *
37- * @brief Returns if the adc is busy sampling. Only valid after starting
38- * a sample request.
39- *
40- * @warning Undefined value is returned if calling this function before
41- * starting a measurement
45+ * @brief Returns if the adc has data to read.
4246 *
4347 * @note This value is cleared after reading
4448 *
4549 * @return status
4650 */
47- static bool is_busy () {
51+ static bool has_data () {
4852 return !(Adc::port->GDR & (0x1 << 31 ));
4953 }
5054
@@ -63,12 +67,71 @@ namespace klib::core::lpc175x::io {
6367 // bit.
6468 Adc::port->CR = (0x1 << 21 );
6569
70+ // disable the interrupts the adc might trigger
71+ Adc::port->INTEN = 0x00 ;
72+
6673 // Configure the ADC FreeRun enables burst mode.
6774 // That will allow conversions up to 200 kHz
6875 Adc::port->CR = (
6976 (Divider << 8 ) | (0x1 << 21 ) | (FreeRun << 16 )
7077 );
7178 }
79+
80+ /* *
81+ * @brief Init the adc peripheral with a interrupt callback
82+ *
83+ * @tparam FreeRun
84+ * @tparam Divider
85+ * @param callback
86+ */
87+ template <bool FreeRun = false , uint8_t Divider = 0 >
88+ static void init (const interrupt_callback& callback) {
89+ init<FreeRun, Divider>();
90+
91+ if constexpr (!FreeRun) {
92+ // register the global done interrupt
93+ Adc::port->INTEN = 0x1 << 8 ;
94+ }
95+ else {
96+ // register all the individual channels
97+ Adc::port->INTEN = 0xff ;
98+ }
99+
100+ // set the callback
101+ adc_callback = callback;
102+
103+ // register the interrupt
104+ target::irq::register_irq<Adc::interrupt_id>(interrupt_handler);
105+
106+ // enable the interrupt
107+ target::enable_irq<Adc::interrupt_id>();
108+ }
109+
110+ public:
111+ /* *
112+ * @brief Interrupt handler for the ADC
113+ *
114+ */
115+ static void interrupt_handler () {
116+ if (adc_callback) {
117+ adc_callback ();
118+ }
119+
120+ // clear interrupt by reading the data register(s)
121+ if (Adc::port->CR & (0x1 << 16 )) {
122+ // burst/freerun: read each enabled channel DR to clear DONE flags
123+ const uint32_t channels = Adc::port->CR & 0xff ;
124+ for (uint32_t i = 0 ; i < 8 ; i++) {
125+ if (channels & (0x1 << i)) {
126+ (void )Adc::port->DR [i];
127+ }
128+ }
129+ }
130+ else {
131+ // single conversion: read GDR to clear global DONE interrupt
132+ (void )Adc::port->GDR ;
133+ }
134+ }
72135 };
73136
74137 template <typename Adc, typename Pin>
@@ -114,16 +177,14 @@ namespace klib::core::lpc175x::io {
114177 }
115178
116179 /* *
117- * @brief Returns if the adc is busy sampling. Only valid after starting
118- * a sample request.
180+ * @brief Returns if the adc channel has data to read.
119181 *
120- * @warning Undefined value is returned if calling this function before
121- * starting a measurement
182+ * @note This value is cleared after reading
122183 *
123184 * @return status
124185 */
125- static bool is_busy () {
126- return ! (Adc::port->STAT & (0x1 << Pin::analog_number));
186+ static bool has_data () {
187+ return (Adc::port->STAT & (0x1 << Pin::analog_number));
127188 }
128189
129190 /* *
@@ -143,7 +204,7 @@ namespace klib::core::lpc175x::io {
143204 sample ();
144205
145206 // wait until the current channel is done
146- while (is_busy ()) {
207+ while (! has_data ()) {
147208 // do nothing
148209 }
149210 }
0 commit comments