This repository has been archived by the owner on Aug 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 199
/
analog-lpc.c
88 lines (65 loc) · 3.2 KB
/
analog-lpc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/** \file
\brief Analog subsystem, ARM specific part.
Nice feature of the LPC11xx is, it features a hardware scan mode, which scans
a given set of ADC pins over and over again, without need for an interrupt
to switch between channels. Our code becomes pretty simple: set this
mechanism up at init time and be done for the time being.
Unlike ATmegas, LPC1114 features no analog voltage reference selector, it
always compares against Vdd. This is the equivalent of REFERENCE_AVCC on AVR.
*/
#if defined TEACUP_C_INCLUDE && defined __ARM_LPC1114__
#include "cmsis-lpc11xx.h"
#include "arduino.h"
/** Inititalise the analog subsystem.
Initialise the ADC and start hardware scan loop for all used sensors.
LPC111x User Manual recommends an ADC clock of 4.5 MHz ("typically"), still
we reduce this to 1 MHz, because we're not nearly as much in a hurry. A
conversion needs 11 ADC clocks per channel, so we still get many thousand
conversions/second; we need just 100/s.
*/
void analog_init() {
if (analog_mask) { // At least one channel in use.
LPC_SYSCON->PDRUNCFG &= ~(1 << 4); // Turn on ADC clock.
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 13); // Turn on ADC power.
/**
Register name mapping from LPC111x User Manual to CMSIS headers:
chap. 25.5 cmsis-lpc11xx.h description
AD0CR LPC_ADC->CR A/D control register.
AD0GDR LPC_ADC->GDR A/D global data register.
AD0INTEN LPC_ADC->INTEN A/D interrupt enable register.
AD0DRn LPC_ADC->DR[n] A/D channel n data register.
AD0STAT LPC_ADC->STAT A/D status register.
*/
LPC_ADC->CR = ((uint32_t)analog_mask << 0) // Mask of used pins.
| ((F_CPU / 1000000) << 8) // 1 MHz ADC clock.
| (1 << 16) // Hardware scan mode.
| (0x0 << 17) // Maximum accuracy.
| (0x0 << 24); // Clear START.
LPC_ADC->INTEN = 0; // No interrupt generation.
// Auto-generate pin setup.
#undef DEFINE_TEMP_SENSOR
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) \
LPC_IOCON->pin ## _CMSIS = \
((type == TT_THERMISTOR) || (type == TT_AD595)) ? ( \
(0x2 << 0) /* Function ADx. */ \
| (0 << 3) /* Pullup inactive. */ \
| (0 << 7)) /* Analog input mode. */ \
: LPC_IOCON->pin ## _CMSIS;
#include "config_wrapper.h"
#undef DEFINE_TEMP_SENSOR
} /* analog_mask */
}
/** Read analog value.
\param channel Channel to be read. Channel numbering starts at zero.
\return Analog reading, 10-bit right aligned.
Hardware scan mode nicely saves all the converted values separately, so
there's no need to hold them in a copy.
*/
uint16_t analog_read(uint8_t index) {
uint16_t result = 0;
if (index < sizeof(adc_channel) && adc_channel[index] < 8) {
result = (LPC_ADC->DR[adc_channel[index]] & 0xFFC0) >> 6;
}
return result;
}
#endif /* defined TEACUP_C_INCLUDE && defined __ARM_LPC1114__ */