summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2020-03-18 22:01:06 +0100
committerDaniel Friesel <derf@finalrewind.org>2020-03-18 22:01:06 +0100
commitde23a47009bb301518417d097b3360253a01c635 (patch)
treeefbe470365a62c52345b6d3fd100f338f3cf2ad7
parent7588f9c2ada3f4b10586826ee95eb8795fb69729 (diff)
Arduino: Add ADC driver
-rw-r--r--include/arch/arduino-nano/driver/adc.h17
-rw-r--r--src/arch/arduino-nano-168/Makefile.inc8
-rw-r--r--src/arch/arduino-nano/Makefile.inc4
-rw-r--r--src/arch/arduino-nano/driver/adc.cc76
4 files changed, 105 insertions, 0 deletions
diff --git a/include/arch/arduino-nano/driver/adc.h b/include/arch/arduino-nano/driver/adc.h
new file mode 100644
index 0000000..4af64b8
--- /dev/null
+++ b/include/arch/arduino-nano/driver/adc.h
@@ -0,0 +1,17 @@
+#ifndef ADC_H
+#define ADC_H
+
+class AVRADC {
+ private:
+ AVRADC(AVRADC const &copy);
+
+ public:
+ AVRADC() {}
+
+ int16_t getTemp_mdegC(int16_t offset = 205);
+ uint16_t getVCC_mV();
+};
+
+extern AVRADC adc;
+
+#endif
diff --git a/src/arch/arduino-nano-168/Makefile.inc b/src/arch/arduino-nano-168/Makefile.inc
index f57914e..70392e1 100644
--- a/src/arch/arduino-nano-168/Makefile.inc
+++ b/src/arch/arduino-nano-168/Makefile.inc
@@ -37,6 +37,10 @@ else ifneq ($(findstring i2c,${arch_drivers}), )
CXX_TARGETS += src/arch/arduino-nano/driver/i2c.cc
endif
+ifneq ($(findstring adc,${arch_drivers}), )
+ CXX_TARGETS += src/arch/arduino-nano/driver/adc.cc
+endif
+
ifneq ($(findstring spi,${arch_drivers}), )
CXX_TARGETS += src/arch/arduino-nano/driver/spi.cc
endif
@@ -53,6 +57,10 @@ ifneq ($(findstring counter,${arch_drivers}), )
CXX_TARGETS += src/arch/arduino-nano/driver/counter.cc
endif
+ifneq ($(findstring neopixel,${arch_drivers}), )
+ CXX_TARGETS += src/arch/arduino-nano/driver/neopixel.cc
+endif
+
ifeq (${cpu_freq}, 16000000)
uart_baud = 57600
else ifeq (${cpu_freq}, 8000000)
diff --git a/src/arch/arduino-nano/Makefile.inc b/src/arch/arduino-nano/Makefile.inc
index ebc77ea..a664a30 100644
--- a/src/arch/arduino-nano/Makefile.inc
+++ b/src/arch/arduino-nano/Makefile.inc
@@ -37,6 +37,10 @@ else ifneq ($(findstring i2c,${arch_drivers}), )
CXX_TARGETS += src/arch/arduino-nano/driver/i2c.cc
endif
+ifneq ($(findstring adc,${arch_drivers}), )
+ CXX_TARGETS += src/arch/arduino-nano/driver/adc.cc
+endif
+
ifneq ($(findstring spi,${arch_drivers}), )
CXX_TARGETS += src/arch/arduino-nano/driver/spi.cc
endif
diff --git a/src/arch/arduino-nano/driver/adc.cc b/src/arch/arduino-nano/driver/adc.cc
new file mode 100644
index 0000000..1583b15
--- /dev/null
+++ b/src/arch/arduino-nano/driver/adc.cc
@@ -0,0 +1,76 @@
+#include <avr/io.h>
+
+#include "arch.h"
+#include "driver/adc.h"
+
+int16_t AVRADC::getTemp_mdegC(int16_t offset)
+{
+ // Measure temperature probe with 1.1V bandgap reference
+ ADMUX = _BV(REFS1) | _BV(REFS0) | 0x08;
+
+ // Enable ADC with /64 prescaler
+ ADCSRA = _BV(ADEN) | _BV(ADPS2);
+
+ // Wait for bandgap to stabilise (70us according to datasheet table 28-3)
+ arch.delay_ms(1);
+
+ // Start conversion
+ ADCSRA |= _BV(ADSC);
+
+ // Wait for conversion to complete
+ while (ADCSRA & _BV(ADSC)) ;
+
+ // typical values: 242 mV @ -45 degC
+ // typical values: 314 mV @ +25 degC
+ // typical values: 380 mV @ +85 degC
+ // slope: 0.9090.. degC / mV at 25 .. 85 degC
+ // -> approx. 286.5 mV @ 0 degC / approx -260.45 degC @ 0 mV
+ // -> T[degC] = ADC[mV] * 0.91 - 261
+ // -> T[mdegC] = ADC[mV] * 91 - 26100
+ // slope: 0.9722.. mV / degC at -45 .. 25 degC
+ // slope: 0.942 mV / degC at -45 .. 85 degC
+ uint8_t adcr_l = ADCL;
+ uint8_t adcr_h = ADCH;
+ uint16_t adcr = adcr_l + (adcr_h << 8);
+ uint16_t vadc = 1100L * adcr / 1023L;
+
+ // adjust for chip-specific variations
+ vadc += offset;
+
+ int16_t temp_mdegc = vadc * 91 - 26100L;
+
+ // Disable ADC
+ ADCSRA &= ~_BV(ADEN);
+
+ return temp_mdegc;
+}
+
+uint16_t AVRADC::getVCC_mV()
+{
+ // Measure internal 1.1V bandgap using VCC as reference
+ ADMUX = _BV(REFS0) | 0x0e;
+
+ // Enable ADC with /64 prescaler
+ ADCSRA = _BV(ADEN) | _BV(ADPS2);
+
+ // Wait for bandgap to stabilise (70us according to datasheet table 28-3)
+ arch.delay_ms(1);
+
+ // Start conversion
+ ADCSRA |= _BV(ADSC);
+
+ // Wait for conversion to complete
+ while (ADCSRA & _BV(ADSC)) ;
+
+ uint8_t adcr_l = ADCL;
+ uint8_t adcr_h = ADCH;
+ uint16_t adcr = adcr_l + (adcr_h << 8);
+ uint16_t vcc = 1100L * 1023 / adcr;
+
+ // Disable ADC
+ ADCSRA &= ~_BV(ADEN);
+
+ return vcc;
+}
+
+AVRADC adc;