ARM: implement analog-arm.c.

Very simple, because the LPC1114 features a hardware scan mode,
which automatically scans a given set of pins in freerunning mode
and stores all the values separately. No need for an interrupt!

Not yet done: configure not PIO1_0 and PIO1_1, but the pins
actually defined in the board file.

For testing, add this to ifclock(clock_flag_1s) in clock.c:
  uint8_t i;

  for (i = 0; i <= 7; i++) {
    sersendf_P(PSTR("%lu "), analog_read(i));
  }
  serial_writechar('\n');

This should print all 8 ADC values repeatedly. Only two pins are
actually set up, these values should change depending on the
thermistor temperature. More precisely: depending on the voltage
on the pin.
This commit is contained in:
Markus Hitter 2015-08-06 00:39:33 +02:00
parent 56f6b381fd
commit f81000a4b6
4 changed files with 85 additions and 4 deletions

View File

@ -100,8 +100,9 @@ TARGET = $(PROGRAM).hex
SOURCES = mendel.c cpu.c serial.c sermsg.c sersendf.c delay.c
SOURCES += gcode_parse.c gcode_process.c pinio.c timer.c clock.c
SOURCES += dda_queue.c dda_maths.c dda_kinematics.c dda.c dda_lookahead.c
SOURCES += analog.c
# Sources left:
# analog.c home.c crc.c intercom.c debug.c spi.c usb_serial.c
# home.c crc.c intercom.c debug.c spi.c usb_serial.c
# graycode.c pff.c temp.c watchdog.c heater.c pff_diskio.c
ifeq ($(MCU), lpc1114)

80
analog-arm.c Normal file
View File

@ -0,0 +1,80 @@
/** \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 __ARMEL__
#include "cmsis-lpc11xx.h"
#include "arduino.h"
#include "temp.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 (NUM_TEMP_SENSORS) { // 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.
*/
// TODO: enable only the channels we use.
LPC_ADC->CR = (0xFF << 0) // All pins on (for now).
| ((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.
// TODO: set up the channels configured, not two arbitrary ones.
LPC_IOCON->PIO1_0_CMSIS = (0x2 << 0) // Function AD1.
| (0 << 3) // Pullup inactive.
| (0 << 7); // Analog input mode.
LPC_IOCON->PIO1_1_CMSIS = (0x2 << 0) // Function AD2.
| (0 << 3) // Pullup inactive.
| (0 << 7); // Analog input mode.
}
}
/** Read analog value.
\param channel Channel to be read.
\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) {
return (LPC_ADC->DR[index] & 0xFFC0) >> 6;
}
#endif /* defined TEACUP_C_INCLUDE && defined __ARMEL__ */

View File

@ -7,7 +7,7 @@
#define TEACUP_C_INCLUDE
#include "analog-avr.c"
//#include "analog-arm.c"
#include "analog-arm.c"
#undef TEACUP_C_INCLUDE
// No common code so far.

View File

@ -39,8 +39,8 @@
#include "watchdog.h"
#include "debug.h"
#include "heater.h"
#include "analog.h"
#endif /* __ARMEL_NOTYET__ */
#include "analog.h"
#include "pinio.h"
#include "clock.h"
#ifndef __ARMEL_NOTYET__
@ -105,11 +105,11 @@ void init(void) {
// set up dda
dda_init();
#ifndef __ARMEL_NOTYET__
// start up analog read interrupt loop,
// if any of the temp sensors in your config.h use analog interface
analog_init();
#ifndef __ARMEL_NOTYET__
// set up temperature inputs
temp_init();