Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of rgb_sensor by
rgb_sensor.cpp
- Committer:
- meriac
- Date:
- 2014-06-25
- Revision:
- 0:576e43bd193d
- Child:
- 2:4545984e62b6
File content as of revision 0:576e43bd193d:
/* Discrete RGB color sensor
*
* - uses single-channel light-dependent resistor (via ADC)
* and a RGB LED.
* - compensates background light
*
* Copyright (c) 2014 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <mbed.h>
#include <pinmap.h>
#include "rgb_sensor.h"
static const PinMap RGB_Sensor__PinMap_ADC[] = {
{P0_23, ADC0_0, 1},
{P0_24, ADC0_1, 1},
{P0_25, ADC0_2, 1},
{P0_26, ADC0_3, 1},
{P1_30, ADC0_4, 3},
{P1_31, ADC0_5, 3},
{P0_2, ADC0_7, 2},
{P0_3, ADC0_6, 2},
{NC, NC, 0}
};
DigitalOut g_dbg(LED1);
/* initialize globally */
RGB_Sensor* RGB_Sensor::m_global = NULL;
RGB_Sensor::RGB_Sensor(PinName red, PinName green, PinName blue, PinName adc)
:m_red(red), m_green(green), m_blue(blue)
{
uint32_t clkdiv;
m_done=true;
/* allow only one instance */
if(m_global)
{
m_adc_channel = (ADCName)NC;
return;
}
/* disable LED's */
m_red = 1;
m_green = 1;
m_blue = 1;
// enable ADC power
LPC_SC->PCONP |= (1<<12);
// set ADC clock to PCLK
LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & ~(0x3UL<<24)) | (0x1UL<<24);
// determine mapping
m_adc_channel = (ADCName)pinmap_peripheral(adc, RGB_Sensor__PinMap_ADC);
if (m_adc_channel == (ADCName)NC)
return;
// initialize ADC
clkdiv = ((SystemCoreClock+RGB_MAX_ADC_CLK-1)/RGB_MAX_ADC_CLK)-1;
LPC_ADC->ADCR = (1UL<<m_adc_channel) | (clkdiv<<8) | (1UL<<21);
// set up ADC IRQ
NVIC_SetVector(ADC_IRQn, (uint32_t)&__adc_irq);
LPC_ADC->ADINTEN = (1UL<<m_adc_channel);
NVIC_EnableIRQ(ADC_IRQn);
// propagate pin setting
pinmap_pinout(adc, RGB_Sensor__PinMap_ADC);
// remember this instance
m_global = this;
}
RGB_Sensor::~RGB_Sensor(void)
{
/* only deal with fully initialized objects */
if(m_adc_channel == (ADCName)NC)
return;
/* wait for completion */
wait();
/* reset global reference */
m_global = NULL;
/* turn off ADC */
LPC_ADC->ADINTEN = 0;
LPC_ADC->ADCR = 0;
LPC_SC->PCONP &= ~(1UL<<12);
}
void RGB_Sensor::__adc_irq(void)
{
if(m_global)
m_global->adc_irq();
}
void RGB_Sensor::adc_irq(void)
{
uint32_t sample, status;
status = LPC_ADC->ADSTAT;
if(status & (1UL<<m_adc_channel))
{
/* always read sample to acknowledge IRQ */
sample = (((&LPC_ADC->ADDR0)[m_adc_channel])>>4) & 0xFFF;
if(!m_done)
{
m_adc_aggregation[m_rgb_channel] += sample;
m_adc_count++;
if(m_adc_count>=RGB_OVERSAMPLING)
{
m_adc_count=0;
m_rgb_channel++;
/* prepare LEDs for upcoming channel */
switch(m_rgb_channel)
{
case 1:
m_red = 0;
break;
case 2:
m_red = 1;
m_green = 0;
break;
case 3:
m_green = 1;
m_blue= 0;
break;
default:
m_blue= 1;
m_done = true;
/* stop data aquisition */
LPC_ADC->ADCR &= ~(1UL<<16);
}
}
}
}
LPC_ADC->ADSTAT = status;
}
bool RGB_Sensor::capture(void)
{
/* ignore mis-configurations */
if(m_adc_channel==(ADCName)NC)
return false;
m_done = false;
m_adc_count = m_rgb_channel = 0;
memset((void*)&m_adc_aggregation, 0, sizeof(m_adc_aggregation));
/* start ADC burst mode */
LPC_ADC->ADCR |= (1UL<<16);
return true;
}
bool RGB_Sensor::wait(void)
{
/* ignore mis-configurations */
if(m_adc_channel==(ADCName)NC)
return false;
while(!m_done)
__WFE();
return true;
}
bool RGB_Sensor::capture(TRGB &rgb)
{
if(!(capture() && wait()))
return false;
/* correct "DC" offset by subdstracting
* environment light
*/
rgb.ch.red = m_adc_aggregation[1] - m_adc_aggregation[0];
rgb.ch.green = m_adc_aggregation[2] - m_adc_aggregation[0];
rgb.ch.blue = m_adc_aggregation[3] - m_adc_aggregation[0];
return true;
}
