Class similar to AnalogIn that uses burst mode to run continious background conversions so when the input is read, the last value can immediatly be returned. This slightly modified version allows NC pins.

Dependents:   Pinscape_Controller

Fork of FastAnalogIn by Erik -

Committer:
Sissors
Date:
Sat Jul 12 10:39:37 2014 +0000
Revision:
9:31184aa1449c
Child:
11:234c5cd2b8de
Added K20D50M support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 9:31184aa1449c 1 #if defined(TARGET_KLXX) || defined(TARGET_K20D50M)
Sissors 9:31184aa1449c 2
Sissors 9:31184aa1449c 3 #include "FastAnalogIn.h"
Sissors 9:31184aa1449c 4 #include "clk_freqs.h"
Sissors 9:31184aa1449c 5
Sissors 9:31184aa1449c 6 #define MAX_FADC 6000000
Sissors 9:31184aa1449c 7 #define CHANNELS_A_SHIFT 5
Sissors 9:31184aa1449c 8
Sissors 9:31184aa1449c 9 #ifdef TARGET_K20D50M
Sissors 9:31184aa1449c 10 static const PinMap PinMap_ADC[] = {
Sissors 9:31184aa1449c 11 {PTC2, ADC0_SE4b, 0},
Sissors 9:31184aa1449c 12 {PTD1, ADC0_SE5b, 0},
Sissors 9:31184aa1449c 13 {PTD5, ADC0_SE6b, 0},
Sissors 9:31184aa1449c 14 {PTD6, ADC0_SE7b, 0},
Sissors 9:31184aa1449c 15 {PTB0, ADC0_SE8, 0},
Sissors 9:31184aa1449c 16 {PTB1, ADC0_SE9, 0},
Sissors 9:31184aa1449c 17 {PTB2, ADC0_SE12, 0},
Sissors 9:31184aa1449c 18 {PTB3, ADC0_SE13, 0},
Sissors 9:31184aa1449c 19 {PTC0, ADC0_SE14, 0},
Sissors 9:31184aa1449c 20 {PTC1, ADC0_SE15, 0},
Sissors 9:31184aa1449c 21 {NC, NC, 0}
Sissors 9:31184aa1449c 22 };
Sissors 9:31184aa1449c 23 #endif
Sissors 9:31184aa1449c 24
Sissors 9:31184aa1449c 25 FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
Sissors 9:31184aa1449c 26 {
Sissors 9:31184aa1449c 27 ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
Sissors 9:31184aa1449c 28 if (ADCnumber == (ADCName)NC) {
Sissors 9:31184aa1449c 29 error("ADC pin mapping failed");
Sissors 9:31184aa1449c 30 }
Sissors 9:31184aa1449c 31
Sissors 9:31184aa1449c 32 SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
Sissors 9:31184aa1449c 33
Sissors 9:31184aa1449c 34 uint32_t port = (uint32_t)pin >> PORT_SHIFT;
Sissors 9:31184aa1449c 35 SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
Sissors 9:31184aa1449c 36
Sissors 9:31184aa1449c 37 uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK;
Sissors 9:31184aa1449c 38 if (ADCnumber & (1 << CHANNELS_A_SHIFT)) {
Sissors 9:31184aa1449c 39 cfg2_muxsel = 0;
Sissors 9:31184aa1449c 40 }
Sissors 9:31184aa1449c 41
Sissors 9:31184aa1449c 42 // bus clk
Sissors 9:31184aa1449c 43 uint32_t PCLK = bus_frequency();
Sissors 9:31184aa1449c 44 uint32_t clkdiv;
Sissors 9:31184aa1449c 45 for (clkdiv = 0; clkdiv < 4; clkdiv++) {
Sissors 9:31184aa1449c 46 if ((PCLK >> clkdiv) <= MAX_FADC)
Sissors 9:31184aa1449c 47 break;
Sissors 9:31184aa1449c 48 }
Sissors 9:31184aa1449c 49 if (clkdiv == 4) //Set max div
Sissors 9:31184aa1449c 50 clkdiv = 0x7;
Sissors 9:31184aa1449c 51
Sissors 9:31184aa1449c 52 ADC0->SC1[1] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));
Sissors 9:31184aa1449c 53
Sissors 9:31184aa1449c 54 ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select: (Input Clock)/8
Sissors 9:31184aa1449c 55 | ADC_CFG1_MODE(3) // (16)bits Resolution
Sissors 9:31184aa1449c 56 | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock: (Bus Clock)/2
Sissors 9:31184aa1449c 57
Sissors 9:31184aa1449c 58 ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels
Sissors 9:31184aa1449c 59 | ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable
Sissors 9:31184aa1449c 60 | ADC_CFG2_ADHSC_MASK; // High-Speed Configuration
Sissors 9:31184aa1449c 61
Sissors 9:31184aa1449c 62 ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference
Sissors 9:31184aa1449c 63
Sissors 9:31184aa1449c 64 pinmap_pinout(pin, PinMap_ADC);
Sissors 9:31184aa1449c 65
Sissors 9:31184aa1449c 66 //Enable channel
Sissors 9:31184aa1449c 67 running = false;
Sissors 9:31184aa1449c 68 enable(enabled);
Sissors 9:31184aa1449c 69 }
Sissors 9:31184aa1449c 70
Sissors 9:31184aa1449c 71 void FastAnalogIn::enable(bool enabled)
Sissors 9:31184aa1449c 72 {
Sissors 9:31184aa1449c 73 //If currently not running
Sissors 9:31184aa1449c 74 if (!running) {
Sissors 9:31184aa1449c 75 if (enabled) {
Sissors 9:31184aa1449c 76 //Enable the ADC channel
Sissors 9:31184aa1449c 77 ADC0->SC3 |= ADC_SC3_ADCO_MASK; // Enable continuous conversion
Sissors 9:31184aa1449c 78 ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); //Start conversion
Sissors 9:31184aa1449c 79 running = true;
Sissors 9:31184aa1449c 80 } else
Sissors 9:31184aa1449c 81 disable();
Sissors 9:31184aa1449c 82 }
Sissors 9:31184aa1449c 83 }
Sissors 9:31184aa1449c 84
Sissors 9:31184aa1449c 85 void FastAnalogIn::disable( void )
Sissors 9:31184aa1449c 86 {
Sissors 9:31184aa1449c 87 //If currently running
Sissors 9:31184aa1449c 88 if (running) {
Sissors 9:31184aa1449c 89 ADC0->SC3 &= ~ADC_SC3_ADCO_MASK; // Disable continuous conversion
Sissors 9:31184aa1449c 90 }
Sissors 9:31184aa1449c 91 running = false;
Sissors 9:31184aa1449c 92 }
Sissors 9:31184aa1449c 93
Sissors 9:31184aa1449c 94 uint16_t FastAnalogIn::read_u16()
Sissors 9:31184aa1449c 95 {
Sissors 9:31184aa1449c 96 if (!running)
Sissors 9:31184aa1449c 97 {
Sissors 9:31184aa1449c 98 // start conversion
Sissors 9:31184aa1449c 99 ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));
Sissors 9:31184aa1449c 100 // Wait Conversion Complete
Sissors 9:31184aa1449c 101 while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
Sissors 9:31184aa1449c 102 }
Sissors 9:31184aa1449c 103 if(running && ((ADC0->SC1[0]&ADC_SC1_ADCH_MASK) != (ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)))))
Sissors 9:31184aa1449c 104 {
Sissors 9:31184aa1449c 105 running = false;
Sissors 9:31184aa1449c 106 enable();
Sissors 9:31184aa1449c 107 while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
Sissors 9:31184aa1449c 108 }
Sissors 9:31184aa1449c 109 // Return value
Sissors 9:31184aa1449c 110 return (uint16_t)ADC0->R[0];
Sissors 9:31184aa1449c 111 }
Sissors 9:31184aa1449c 112
Sissors 9:31184aa1449c 113 #endif //defined TARGET_KLXX
Sissors 9:31184aa1449c 114