Mike R / Mbed 2 deprecated Pinscape_Controller_V2

Dependencies:   mbed FastIO FastPWM USBDevice

Fork of Pinscape_Controller by Mike R

Committer:
mjr
Date:
Thu Feb 18 07:32:20 2016 +0000
Revision:
47:df7a88cd249c
Parent:
45:c42166b2878c
Child:
48:058ace2aed1d
3-channel linked DMA scheme for CCD image capture working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 43:7a6364d82a41 1 #ifndef ALTANALOGIN_H
mjr 43:7a6364d82a41 2 #define ALTANALOGIN_H
mjr 43:7a6364d82a41 3
mjr 43:7a6364d82a41 4 // This is a slightly modified version of Scissors's FastAnalogIn.
mjr 43:7a6364d82a41 5 //
mjr 43:7a6364d82a41 6 // This version is optimized for reading from multiple inputs. The KL25Z has
mjr 43:7a6364d82a41 7 // multiple ADC channels, but the multiplexer hardware only allows sampling one
mjr 43:7a6364d82a41 8 // at a time. The entire sampling process from start to finish is serialized
mjr 43:7a6364d82a41 9 // in the multiplexer, so we unfortunately can't overlap the sampling times
mjr 43:7a6364d82a41 10 // for multiple channels - we have to wait in sequence for the sampling period
mjr 43:7a6364d82a41 11 // on each channel, one after the other.
mjr 43:7a6364d82a41 12 //
mjr 43:7a6364d82a41 13 // The base version of FastAnalogIn uses the hardware's continuous conversion
mjr 43:7a6364d82a41 14 // feature to speed up sampling. When sampling multiple inputs, that feature
mjr 43:7a6364d82a41 15 // becomes useless, and in fact the way FastAnalogIn uses it creates additional
mjr 43:7a6364d82a41 16 // overhead for multiple input sampling. But FastAnalogIn still has some speed
mjr 43:7a6364d82a41 17 // advantages over the base mbed AnalogIn implementation, since it sets all of
mjr 43:7a6364d82a41 18 // the other conversion settings to the fastest options. This version keeps the
mjr 43:7a6364d82a41 19 // other speed-ups from FastAnalogIn, but dispenses with the continuous sampling.
mjr 43:7a6364d82a41 20
mjr 43:7a6364d82a41 21 /*
mjr 43:7a6364d82a41 22 * Includes
mjr 43:7a6364d82a41 23 */
mjr 43:7a6364d82a41 24 #include "mbed.h"
mjr 43:7a6364d82a41 25 #include "pinmap.h"
mjr 45:c42166b2878c 26 #include "SimpleDMA.h"
mjr 45:c42166b2878c 27
mjr 45:c42166b2878c 28 // KL25Z definitions
mjr 45:c42166b2878c 29 #if defined TARGET_KLXX
mjr 45:c42166b2878c 30
mjr 45:c42166b2878c 31 // Maximum ADC clock for KL25Z in 12-bit mode - 18 MHz per the data sheet
mjr 45:c42166b2878c 32 #define MAX_FADC_12BIT 18000000
mjr 45:c42166b2878c 33
mjr 45:c42166b2878c 34 #define CHANNELS_A_SHIFT 5 // bit position in ADC channel number of A/B mux
mjr 45:c42166b2878c 35 #define ADC_CFG1_ADLSMP 0x10 // long sample time mode
mjr 45:c42166b2878c 36 #define ADC_SC1_AIEN 0x40 // interrupt enable
mjr 45:c42166b2878c 37 #define ADC_SC2_ADLSTS(mode) (mode) // long sample time select - bits 1:0 of CFG2
mjr 45:c42166b2878c 38 #define ADC_SC2_DMAEN 0x04 // DMA enable
mjr 45:c42166b2878c 39 #define ADC_SC3_CONTINUOUS 0x08 // continuous conversion mode
mjr 45:c42166b2878c 40
mjr 47:df7a88cd249c 41 #define ADC_8BIT 0 // 8-bit resolution
mjr 47:df7a88cd249c 42 #define ADC_12BIT 1 // 12-bit resolution
mjr 47:df7a88cd249c 43 #define ADC_10BIT 2 // 10-bit resolution
mjr 47:df7a88cd249c 44 #define ADC_16BIT 3 // 16-bit resolution
mjr 47:df7a88cd249c 45
mjr 45:c42166b2878c 46 #else
mjr 45:c42166b2878c 47 #error "This target is not currently supported"
mjr 45:c42166b2878c 48 #endif
mjr 43:7a6364d82a41 49
mjr 43:7a6364d82a41 50 #if !defined TARGET_LPC1768 && !defined TARGET_KLXX && !defined TARGET_LPC408X && !defined TARGET_LPC11UXX && !defined TARGET_K20D5M
mjr 43:7a6364d82a41 51 #error "Target not supported"
mjr 43:7a6364d82a41 52 #endif
mjr 43:7a6364d82a41 53
mjr 45:c42166b2878c 54 /** A class similar to AnalogIn, but much faster. This class is optimized
mjr 45:c42166b2878c 55 * for taking a string of readings from a single input.
mjr 43:7a6364d82a41 56 *
mjr 45:c42166b2878c 57 * This is a heavily modified version of the popular FastAnalogIn class.
mjr 45:c42166b2878c 58 * Like FastAnalogIn, this class uses the continuous conversion mode to
mjr 45:c42166b2878c 59 * achieve faster read times. It adds interrupt callbacks on each
mjr 45:c42166b2878c 60 * conversion, and DMA transfer of the input data to memory (or to another
mjr 45:c42166b2878c 61 * peripheral) using the SimpleDMA class. DMA makes a huge difference -
mjr 45:c42166b2878c 62 * it speeds up the sampling time by about 3x and gets us fairly close to
mjr 45:c42166b2878c 63 * the speeds claimed by the manufacturer. Reading through the MCU code
mjr 45:c42166b2878c 64 * seems to add at least a few microseconds per sample, which is significant
mjr 45:c42166b2878c 65 * when trying to get close to the theoretical speed limits for the ADC
mjr 45:c42166b2878c 66 * hardware, which are around 1.5us.
mjr 43:7a6364d82a41 67 *
mjr 45:c42166b2878c 68 * This class can be used with or without DMA. By default, you take samples
mjr 45:c42166b2878c 69 * directly. Call start() to initiate sampling, and call one of the
mjr 45:c42166b2878c 70 * read routines (read() or read_u16()) to wait for the sample to complete
mjr 45:c42166b2878c 71 * and fetch the value. In this mode, samples are taken individually.
mjr 45:c42166b2878c 72 * The start() and read routines are separated so that the caller can
mjr 45:c42166b2878c 73 * perform other work, if desired, while the ADC hardware takes the sample.
mjr 43:7a6364d82a41 74 *
mjr 45:c42166b2878c 75 * To use with DMA, set up a SimpleDMA object, and call initDMA() to tie
mjr 45:c42166b2878c 76 * it to the analog input. Call startDMA() to initiate a transfer. We'll
mjr 45:c42166b2878c 77 * start reading the analog input in continuous mode; each time a sample
mjr 45:c42166b2878c 78 * completes, it will trigger a DMA transfer to the destination. startDMA()
mjr 45:c42166b2878c 79 * returns immediately, so the caller can continue with other tasks while
mjr 45:c42166b2878c 80 * the samples are taken.
mjr 43:7a6364d82a41 81 *
mjr 45:c42166b2878c 82 * IMPORTANT! This class does not play nicely with regular AnalogIn objects,
mjr 45:c42166b2878c 83 * nor with the original FastAnalogIn, because all of these classes set global
mjr 45:c42166b2878c 84 * configuration registers in the ADC hardware at setup time and then will
mjr 45:c42166b2878c 85 * assume that no one else is messing with them. Each library requires
mjr 45:c42166b2878c 86 * exclusive access to and control over the hardware, so they can't be mixed
mjr 45:c42166b2878c 87 * in the same program.
mjr 45:c42166b2878c 88 */
mjr 43:7a6364d82a41 89 class AltAnalogIn {
mjr 43:7a6364d82a41 90
mjr 43:7a6364d82a41 91 public:
mjr 43:7a6364d82a41 92 /** Create an AltAnalogIn, connected to the specified pin
mjr 43:7a6364d82a41 93 *
mjr 43:7a6364d82a41 94 * @param pin AnalogIn pin to connect to
mjr 43:7a6364d82a41 95 * @param enabled Enable the ADC channel (default = true)
mjr 43:7a6364d82a41 96 */
mjr 45:c42166b2878c 97 AltAnalogIn(PinName pin, bool continuous = false);
mjr 43:7a6364d82a41 98
mjr 43:7a6364d82a41 99 ~AltAnalogIn( void )
mjr 43:7a6364d82a41 100 {
mjr 43:7a6364d82a41 101 }
mjr 43:7a6364d82a41 102
mjr 45:c42166b2878c 103 // Initialize DMA. This connects the analog in port to the
mjr 45:c42166b2878c 104 // given DMA object.
mjr 45:c42166b2878c 105 //
mjr 45:c42166b2878c 106 // DMA transfers from the analog in port often use continuous
mjr 45:c42166b2878c 107 // conversion mode. Note, however, that we don't automatically
mjr 45:c42166b2878c 108 // assume this - single sample mode is the default, which means
mjr 45:c42166b2878c 109 // that you must manually start each sample. If you want to use
mjr 45:c42166b2878c 110 // continuous mode, you need to set that separately (via the
mjr 45:c42166b2878c 111 // constructor).
mjr 45:c42166b2878c 112 void initDMA(SimpleDMA *dma);
mjr 45:c42166b2878c 113
mjr 43:7a6364d82a41 114 /** Start a sample. This sets the ADC multiplexer to read from
mjr 43:7a6364d82a41 115 * this input and activates the sampler.
mjr 43:7a6364d82a41 116 */
mjr 43:7a6364d82a41 117 inline void start()
mjr 43:7a6364d82a41 118 {
mjr 43:7a6364d82a41 119 // update the MUX bit in the CFG2 register only if necessary
mjr 43:7a6364d82a41 120 static int lastMux = -1;
mjr 43:7a6364d82a41 121 if (lastMux != ADCmux)
mjr 43:7a6364d82a41 122 {
mjr 43:7a6364d82a41 123 // remember the new register value
mjr 43:7a6364d82a41 124 lastMux = ADCmux;
mjr 43:7a6364d82a41 125
mjr 43:7a6364d82a41 126 // select the multiplexer for our ADC channel
mjr 43:7a6364d82a41 127 if (ADCmux)
mjr 43:7a6364d82a41 128 ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK;
mjr 43:7a6364d82a41 129 else
mjr 43:7a6364d82a41 130 ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK;
mjr 43:7a6364d82a41 131 }
mjr 43:7a6364d82a41 132
mjr 45:c42166b2878c 133 // update the SC2 and SC3 bits only if we're changing inputs
mjr 45:c42166b2878c 134 static uint32_t lastid = 0;
mjr 45:c42166b2878c 135 if (id != lastid)
mjr 45:c42166b2878c 136 {
mjr 45:c42166b2878c 137 // set our ADC0 SC2 and SC3 configuration bits
mjr 45:c42166b2878c 138 ADC0->SC2 = sc2;
mjr 45:c42166b2878c 139 ADC0->SC3 = sc3;
mjr 45:c42166b2878c 140
mjr 45:c42166b2878c 141 // we're the active one now
mjr 45:c42166b2878c 142 lastid = id;
mjr 45:c42166b2878c 143 }
mjr 45:c42166b2878c 144
mjr 45:c42166b2878c 145 // set our SC1 bits - this initiates the sample
mjr 45:c42166b2878c 146 ADC0->SC1[0] = sc1;
mjr 43:7a6364d82a41 147 }
mjr 43:7a6364d82a41 148
mjr 45:c42166b2878c 149 // stop sampling
mjr 45:c42166b2878c 150 void stop()
mjr 45:c42166b2878c 151 {
mjr 45:c42166b2878c 152 // set the channel bits to binary 11111 to disable sampling
mjr 45:c42166b2878c 153 ADC0->SC1[0] = 0x1F;
mjr 45:c42166b2878c 154 }
mjr 45:c42166b2878c 155
mjr 45:c42166b2878c 156 // wait for the current sample to complete
mjr 45:c42166b2878c 157 inline void wait()
mjr 45:c42166b2878c 158 {
mjr 45:c42166b2878c 159 while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) == 0);
mjr 45:c42166b2878c 160 }
mjr 43:7a6364d82a41 161
mjr 43:7a6364d82a41 162
mjr 43:7a6364d82a41 163 /** Returns the raw value
mjr 43:7a6364d82a41 164 *
mjr 43:7a6364d82a41 165 * @param return Unsigned integer with converted value
mjr 43:7a6364d82a41 166 */
mjr 43:7a6364d82a41 167 inline uint16_t read_u16()
mjr 43:7a6364d82a41 168 {
mjr 43:7a6364d82a41 169 // wait for the hardware to signal that the sample is completed
mjr 45:c42166b2878c 170 wait();
mjr 43:7a6364d82a41 171
mjr 43:7a6364d82a41 172 // return the result register value
mjr 43:7a6364d82a41 173 return (uint16_t)ADC0->R[0] << 4; // convert 12-bit to 16-bit, padding with zeroes
mjr 43:7a6364d82a41 174 }
mjr 43:7a6364d82a41 175
mjr 43:7a6364d82a41 176 /** Returns the scaled value
mjr 43:7a6364d82a41 177 *
mjr 43:7a6364d82a41 178 * @param return Float with scaled converted value to 0.0-1.0
mjr 43:7a6364d82a41 179 */
mjr 43:7a6364d82a41 180 float read(void)
mjr 43:7a6364d82a41 181 {
mjr 43:7a6364d82a41 182 unsigned short value = read_u16();
mjr 43:7a6364d82a41 183 return value / 65535.0f;
mjr 43:7a6364d82a41 184 }
mjr 43:7a6364d82a41 185
mjr 43:7a6364d82a41 186 /** An operator shorthand for read()
mjr 43:7a6364d82a41 187 */
mjr 43:7a6364d82a41 188 operator float() { return read(); }
mjr 43:7a6364d82a41 189
mjr 43:7a6364d82a41 190
mjr 43:7a6364d82a41 191 private:
mjr 45:c42166b2878c 192 uint32_t id; // unique ID
mjr 45:c42166b2878c 193 SimpleDMA *dma; // DMA controller, if used
mjr 45:c42166b2878c 194 FunctionPointer _callback; // interrupt callback
mjr 45:c42166b2878c 195 char ADCnumber; // ADC number of our input pin
mjr 45:c42166b2878c 196 char ADCmux; // multiplexer for our input pin (0=A, 1=B)
mjr 45:c42166b2878c 197 uint32_t sc1; // SC1 register settings for this input
mjr 45:c42166b2878c 198 uint32_t sc2; // SC2 register settings for this input
mjr 45:c42166b2878c 199 uint32_t sc3; // SC3 register settings for this input
mjr 43:7a6364d82a41 200 };
mjr 43:7a6364d82a41 201
mjr 43:7a6364d82a41 202 #endif