Skip to content

Commit db96af9

Browse files
committed
lpc1756 changed api for adc and added interrupt support
1 parent 076162d commit db96af9

1 file changed

Lines changed: 74 additions & 13 deletions

File tree

targets/core/nxp/lpc175x/adc.hpp

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)