tweaked detection to use photoresistor through an opamp

Dependents:   rgb_sensor_buffer

Fork of rgb_sensor by Milosch Meriac

Committer:
meriac
Date:
Fri Jun 27 11:36:15 2014 +0000
Revision:
3:50e1ac3c56db
Parent:
2:4545984e62b6
Child:
4:0ffadc2caaf6
Added callback support for asynchronous case

Who changed what in which revision?

UserRevisionLine numberNew contents of line
meriac 0:576e43bd193d 1 /* Discrete RGB color sensor
meriac 0:576e43bd193d 2 *
meriac 0:576e43bd193d 3 * - uses single-channel light-dependent resistor (via ADC)
meriac 0:576e43bd193d 4 * and a RGB LED.
meriac 0:576e43bd193d 5 * - compensates background light
meriac 0:576e43bd193d 6 *
meriac 0:576e43bd193d 7 * Copyright (c) 2014 ARM Limited
meriac 0:576e43bd193d 8 *
meriac 0:576e43bd193d 9 * Licensed under the Apache License, Version 2.0 (the "License");
meriac 0:576e43bd193d 10 * you may not use this file except in compliance with the License.
meriac 0:576e43bd193d 11 * You may obtain a copy of the License at
meriac 0:576e43bd193d 12 *
meriac 0:576e43bd193d 13 * http://www.apache.org/licenses/LICENSE-2.0
meriac 0:576e43bd193d 14 *
meriac 0:576e43bd193d 15 * Unless required by applicable law or agreed to in writing, software
meriac 0:576e43bd193d 16 * distributed under the License is distributed on an "AS IS" BASIS,
meriac 0:576e43bd193d 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
meriac 0:576e43bd193d 18 * See the License for the specific language governing permissions and
meriac 0:576e43bd193d 19 * limitations under the License.
meriac 0:576e43bd193d 20 */
meriac 0:576e43bd193d 21
meriac 0:576e43bd193d 22 #include <mbed.h>
meriac 0:576e43bd193d 23 #include <pinmap.h>
meriac 0:576e43bd193d 24 #include "rgb_sensor.h"
meriac 0:576e43bd193d 25
meriac 0:576e43bd193d 26 static const PinMap RGB_Sensor__PinMap_ADC[] = {
meriac 0:576e43bd193d 27 {P0_23, ADC0_0, 1},
meriac 0:576e43bd193d 28 {P0_24, ADC0_1, 1},
meriac 0:576e43bd193d 29 {P0_25, ADC0_2, 1},
meriac 0:576e43bd193d 30 {P0_26, ADC0_3, 1},
meriac 0:576e43bd193d 31 {P1_30, ADC0_4, 3},
meriac 0:576e43bd193d 32 {P1_31, ADC0_5, 3},
meriac 0:576e43bd193d 33 {P0_2, ADC0_7, 2},
meriac 0:576e43bd193d 34 {P0_3, ADC0_6, 2},
meriac 0:576e43bd193d 35 {NC, NC, 0}
meriac 0:576e43bd193d 36 };
meriac 0:576e43bd193d 37
meriac 0:576e43bd193d 38 DigitalOut g_dbg(LED1);
meriac 0:576e43bd193d 39
meriac 0:576e43bd193d 40 /* initialize globally */
meriac 0:576e43bd193d 41 RGB_Sensor* RGB_Sensor::m_global = NULL;
meriac 0:576e43bd193d 42
meriac 0:576e43bd193d 43 RGB_Sensor::RGB_Sensor(PinName red, PinName green, PinName blue, PinName adc)
meriac 0:576e43bd193d 44 :m_red(red), m_green(green), m_blue(blue)
meriac 0:576e43bd193d 45 {
meriac 0:576e43bd193d 46 uint32_t clkdiv;
meriac 0:576e43bd193d 47
meriac 0:576e43bd193d 48 m_done=true;
meriac 0:576e43bd193d 49
meriac 0:576e43bd193d 50 /* allow only one instance */
meriac 0:576e43bd193d 51 if(m_global)
meriac 0:576e43bd193d 52 {
meriac 0:576e43bd193d 53 m_adc_channel = (ADCName)NC;
meriac 0:576e43bd193d 54 return;
meriac 0:576e43bd193d 55 }
meriac 0:576e43bd193d 56
meriac 0:576e43bd193d 57 /* disable LED's */
meriac 2:4545984e62b6 58 m_red = !RGB_LED_ON;
meriac 2:4545984e62b6 59 m_green = !RGB_LED_ON;
meriac 2:4545984e62b6 60 m_blue = !RGB_LED_ON;
meriac 0:576e43bd193d 61
meriac 0:576e43bd193d 62 // enable ADC power
meriac 0:576e43bd193d 63 LPC_SC->PCONP |= (1<<12);
meriac 0:576e43bd193d 64 // set ADC clock to PCLK
meriac 0:576e43bd193d 65 LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & ~(0x3UL<<24)) | (0x1UL<<24);
meriac 0:576e43bd193d 66
meriac 0:576e43bd193d 67 // determine mapping
meriac 0:576e43bd193d 68 m_adc_channel = (ADCName)pinmap_peripheral(adc, RGB_Sensor__PinMap_ADC);
meriac 0:576e43bd193d 69 if (m_adc_channel == (ADCName)NC)
meriac 0:576e43bd193d 70 return;
meriac 0:576e43bd193d 71
meriac 0:576e43bd193d 72 // initialize ADC
meriac 0:576e43bd193d 73 clkdiv = ((SystemCoreClock+RGB_MAX_ADC_CLK-1)/RGB_MAX_ADC_CLK)-1;
meriac 0:576e43bd193d 74 LPC_ADC->ADCR = (1UL<<m_adc_channel) | (clkdiv<<8) | (1UL<<21);
meriac 0:576e43bd193d 75
meriac 0:576e43bd193d 76 // set up ADC IRQ
meriac 0:576e43bd193d 77 NVIC_SetVector(ADC_IRQn, (uint32_t)&__adc_irq);
meriac 0:576e43bd193d 78 LPC_ADC->ADINTEN = (1UL<<m_adc_channel);
meriac 0:576e43bd193d 79 NVIC_EnableIRQ(ADC_IRQn);
meriac 0:576e43bd193d 80
meriac 0:576e43bd193d 81 // propagate pin setting
meriac 0:576e43bd193d 82 pinmap_pinout(adc, RGB_Sensor__PinMap_ADC);
meriac 0:576e43bd193d 83
meriac 0:576e43bd193d 84 // remember this instance
meriac 0:576e43bd193d 85 m_global = this;
meriac 0:576e43bd193d 86 }
meriac 0:576e43bd193d 87
meriac 0:576e43bd193d 88 RGB_Sensor::~RGB_Sensor(void)
meriac 0:576e43bd193d 89 {
meriac 0:576e43bd193d 90 /* only deal with fully initialized objects */
meriac 0:576e43bd193d 91 if(m_adc_channel == (ADCName)NC)
meriac 0:576e43bd193d 92 return;
meriac 0:576e43bd193d 93 /* wait for completion */
meriac 0:576e43bd193d 94 wait();
meriac 0:576e43bd193d 95 /* reset global reference */
meriac 0:576e43bd193d 96 m_global = NULL;
meriac 0:576e43bd193d 97 /* turn off ADC */
meriac 0:576e43bd193d 98 LPC_ADC->ADINTEN = 0;
meriac 0:576e43bd193d 99 LPC_ADC->ADCR = 0;
meriac 0:576e43bd193d 100 LPC_SC->PCONP &= ~(1UL<<12);
meriac 0:576e43bd193d 101 }
meriac 0:576e43bd193d 102
meriac 0:576e43bd193d 103 void RGB_Sensor::__adc_irq(void)
meriac 0:576e43bd193d 104 {
meriac 0:576e43bd193d 105 if(m_global)
meriac 0:576e43bd193d 106 m_global->adc_irq();
meriac 0:576e43bd193d 107 }
meriac 0:576e43bd193d 108
meriac 0:576e43bd193d 109 void RGB_Sensor::adc_irq(void)
meriac 0:576e43bd193d 110 {
meriac 0:576e43bd193d 111 uint32_t sample, status;
meriac 0:576e43bd193d 112
meriac 0:576e43bd193d 113 status = LPC_ADC->ADSTAT;
meriac 0:576e43bd193d 114 if(status & (1UL<<m_adc_channel))
meriac 0:576e43bd193d 115 {
meriac 0:576e43bd193d 116 /* always read sample to acknowledge IRQ */
meriac 0:576e43bd193d 117 sample = (((&LPC_ADC->ADDR0)[m_adc_channel])>>4) & 0xFFF;
meriac 0:576e43bd193d 118
meriac 0:576e43bd193d 119 if(!m_done)
meriac 0:576e43bd193d 120 {
meriac 0:576e43bd193d 121 m_adc_aggregation[m_rgb_channel] += sample;
meriac 0:576e43bd193d 122
meriac 0:576e43bd193d 123 m_adc_count++;
meriac 0:576e43bd193d 124 if(m_adc_count>=RGB_OVERSAMPLING)
meriac 0:576e43bd193d 125 {
meriac 0:576e43bd193d 126 m_adc_count=0;
meriac 0:576e43bd193d 127 m_rgb_channel++;
meriac 0:576e43bd193d 128
meriac 0:576e43bd193d 129 /* prepare LEDs for upcoming channel */
meriac 0:576e43bd193d 130 switch(m_rgb_channel)
meriac 0:576e43bd193d 131 {
meriac 0:576e43bd193d 132 case 1:
meriac 2:4545984e62b6 133 m_red = RGB_LED_ON;
meriac 0:576e43bd193d 134 break;
meriac 0:576e43bd193d 135
meriac 0:576e43bd193d 136 case 2:
meriac 2:4545984e62b6 137 m_red = !RGB_LED_ON;
meriac 2:4545984e62b6 138 m_green = RGB_LED_ON;
meriac 0:576e43bd193d 139 break;
meriac 0:576e43bd193d 140
meriac 0:576e43bd193d 141 case 3:
meriac 2:4545984e62b6 142 m_green = !RGB_LED_ON;
meriac 2:4545984e62b6 143 m_blue= RGB_LED_ON;
meriac 0:576e43bd193d 144 break;
meriac 0:576e43bd193d 145
meriac 0:576e43bd193d 146 default:
meriac 2:4545984e62b6 147 m_blue= !RGB_LED_ON;
meriac 3:50e1ac3c56db 148 if(!m_callback)
meriac 3:50e1ac3c56db 149 m_done = true;
meriac 3:50e1ac3c56db 150 else
meriac 3:50e1ac3c56db 151 {
meriac 3:50e1ac3c56db 152 TRGB rgb;
meriac 3:50e1ac3c56db 153 convert(rgb);
meriac 3:50e1ac3c56db 154 m_done = !m_callback(rgb);
meriac 3:50e1ac3c56db 155 m_rgb_channel = 0;
meriac 3:50e1ac3c56db 156 }
meriac 0:576e43bd193d 157 /* stop data aquisition */
meriac 3:50e1ac3c56db 158 if(m_done)
meriac 3:50e1ac3c56db 159 LPC_ADC->ADCR &= ~(1UL<<16);
meriac 0:576e43bd193d 160 }
meriac 0:576e43bd193d 161 }
meriac 0:576e43bd193d 162 }
meriac 0:576e43bd193d 163 }
meriac 0:576e43bd193d 164 LPC_ADC->ADSTAT = status;
meriac 0:576e43bd193d 165 }
meriac 0:576e43bd193d 166
meriac 3:50e1ac3c56db 167 bool RGB_Sensor::capture(TRGB_Callback callback)
meriac 0:576e43bd193d 168 {
meriac 0:576e43bd193d 169 /* ignore mis-configurations */
meriac 0:576e43bd193d 170 if(m_adc_channel==(ADCName)NC)
meriac 0:576e43bd193d 171 return false;
meriac 0:576e43bd193d 172
meriac 3:50e1ac3c56db 173 m_callback = callback;
meriac 0:576e43bd193d 174 m_done = false;
meriac 0:576e43bd193d 175 m_adc_count = m_rgb_channel = 0;
meriac 0:576e43bd193d 176 memset((void*)&m_adc_aggregation, 0, sizeof(m_adc_aggregation));
meriac 0:576e43bd193d 177 /* start ADC burst mode */
meriac 0:576e43bd193d 178 LPC_ADC->ADCR |= (1UL<<16);
meriac 0:576e43bd193d 179
meriac 0:576e43bd193d 180 return true;
meriac 0:576e43bd193d 181 }
meriac 0:576e43bd193d 182
meriac 0:576e43bd193d 183 bool RGB_Sensor::wait(void)
meriac 0:576e43bd193d 184 {
meriac 0:576e43bd193d 185 /* ignore mis-configurations */
meriac 0:576e43bd193d 186 if(m_adc_channel==(ADCName)NC)
meriac 0:576e43bd193d 187 return false;
meriac 0:576e43bd193d 188
meriac 0:576e43bd193d 189 while(!m_done)
meriac 0:576e43bd193d 190 __WFE();
meriac 0:576e43bd193d 191
meriac 0:576e43bd193d 192 return true;
meriac 0:576e43bd193d 193 }
meriac 0:576e43bd193d 194
meriac 3:50e1ac3c56db 195 void RGB_Sensor::convert(TRGB &rgb)
meriac 0:576e43bd193d 196 {
meriac 0:576e43bd193d 197 /* correct "DC" offset by subdstracting
meriac 0:576e43bd193d 198 * environment light
meriac 0:576e43bd193d 199 */
meriac 0:576e43bd193d 200 rgb.ch.red = m_adc_aggregation[1] - m_adc_aggregation[0];
meriac 0:576e43bd193d 201 rgb.ch.green = m_adc_aggregation[2] - m_adc_aggregation[0];
meriac 0:576e43bd193d 202 rgb.ch.blue = m_adc_aggregation[3] - m_adc_aggregation[0];
meriac 3:50e1ac3c56db 203 }
meriac 0:576e43bd193d 204
meriac 3:50e1ac3c56db 205 bool RGB_Sensor::capture(TRGB &rgb)
meriac 3:50e1ac3c56db 206 {
meriac 3:50e1ac3c56db 207 if(!(capture(NULL) && wait()))
meriac 3:50e1ac3c56db 208 return false;
meriac 3:50e1ac3c56db 209
meriac 3:50e1ac3c56db 210 convert(rgb);
meriac 0:576e43bd193d 211 return true;
meriac 0:576e43bd193d 212 }