diff --git a/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.cpp b/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.cpp index 61eadff..8650b33 100644 --- a/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.cpp +++ b/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.cpp @@ -1,94 +1,96 @@ -/**************************************************************************/ -/*! - @file Adafruit_APDS9960.cpp - @author Ladyada, Dean Miller (Adafruit Industries) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2017, Adafruit Industries - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/**************************************************************************/ +/*! + * @file Adafruit_APDS9960.cpp + * + * @mainpage Adafruit APDS9960 Proximity, Light, RGB, and Gesture Sensor + * + * @section author Author + * + * Ladyada, Dean Miller (Adafruit Industries) + * + * @section license License + * + * Software License Agreement (BSD License) + * + * Copyright (c) 2017, Adafruit Industries + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifdef __AVR - #include +#include #elif defined(ESP8266) - #include +#include #endif -#include #include +#include #include "Adafruit_APDS9960.h" -/*========================================================================*/ -/* PRIVATE FUNCTIONS */ -/*========================================================================*/ - -/**************************************************************************/ /*! - @brief Implements missing powf function -*/ -/**************************************************************************/ -float powf(const float x, const float y) -{ + * @brief Implements missing powf function + * @param x + * Base number + * @param y + * Exponent + * @return x raised to the power of y + */ +float powf(const float x, const float y) { return (float)(pow((double)x, (double)y)); } -/**************************************************************************/ /*! - Enables the device - Disables the device (putting it in lower power sleep mode) -*/ -/**************************************************************************/ -void Adafruit_APDS9960::enable(boolean en) -{ + * @brief Enables the device + * Disables the device (putting it in lower power sleep mode) + * @param en + * Enable (True/False) + */ +void Adafruit_APDS9960::enable(boolean en) { _enable.PON = en; this->write8(APDS9960_ENABLE, _enable.get()); } -/*========================================================================*/ -/* PUBLIC FUNCTIONS */ -/*========================================================================*/ - -/**************************************************************************/ /*! - Initializes I2C and configures the sensor (call this function before - doing anything else) -*/ -/**************************************************************************/ -boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, uint8_t addr) -{ + * @brief Initializes I2C and configures the sensor + * @param iTimeMS + * Integration time + * @param aGain + * Gain + * @param addr + * I2C address + * @param *theWire + * Wire object + * @return True if initialization was successful, otherwise false. + */ +boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, + uint8_t addr, TwoWire *theWire) { + _wire = theWire; _i2c_init(); _i2caddr = addr; - + /* Make sure we're actually connected */ uint8_t x = read8(APDS9960_ID); - if (x != 0xAB) - { + if (x != 0xAB) { return false; } @@ -100,7 +102,7 @@ boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, uint8_ enableGesture(false); enableProximity(false); enableColor(false); - + disableColorInterrupt(); disableProximityInterrupt(); clearInterrupt(); @@ -110,43 +112,47 @@ boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, uint8_ delay(10); enable(true); delay(10); - - //default to all gesture dimensions + + // default to all gesture dimensions setGestureDimensions(APDS9960_DIMENSIONS_ALL); setGestureFIFOThreshold(APDS9960_GFIFO_4); setGestureGain(APDS9960_GGAIN_4); setGestureProximityThreshold(50); resetCounts(); - + _gpulse.GPLEN = APDS9960_GPULSE_32US; - _gpulse.GPULSE = 9; //10 pulses + _gpulse.GPULSE = 9; // 10 pulses this->write8(APDS9960_GPULSE, _gpulse.get()); - + return true; } - -/**************************************************************************/ + /*! - Sets the integration time for the ADC of the APDS9960, in millis -*/ -/**************************************************************************/ -void Adafruit_APDS9960::setADCIntegrationTime(uint16_t iTimeMS) -{ + * @brief Sets the integration time for the ADC of the APDS9960, in millis + * @param iTimeMS + * Integration time + */ +void Adafruit_APDS9960::setADCIntegrationTime(uint16_t iTimeMS) { float temp; // convert ms into 2.78ms increments temp = iTimeMS; temp /= 2.78; temp = 256 - temp; - if (temp > 255) temp = 255; - if (temp < 0) temp = 0; - + if (temp > 255) + temp = 255; + if (temp < 0) + temp = 0; + /* Update the timing register */ write8(APDS9960_ATIME, (uint8_t)temp); } -float Adafruit_APDS9960::getADCIntegrationTime(void) -{ +/*! + * @brief Returns the integration time for the ADC of the APDS9960, in millis + * @return Integration time + */ +float Adafruit_APDS9960::getADCIntegrationTime() { float temp; temp = read8(APDS9960_ATIME); @@ -157,158 +163,221 @@ float Adafruit_APDS9960::getADCIntegrationTime(void) return temp; } -/**************************************************************************/ /*! - Adjusts the color/ALS gain on the APDS9960 (adjusts the sensitivity to light) -*/ -/**************************************************************************/ -void Adafruit_APDS9960::setADCGain(apds9960AGain_t aGain) -{ + * @brief Adjusts the color/ALS gain on the APDS9960 (adjusts the sensitivity + * to light) + * @param aGain + * Gain + */ +void Adafruit_APDS9960::setADCGain(apds9960AGain_t aGain) { _control.AGAIN = aGain; /* Update the timing register */ write8(APDS9960_CONTROL, _control.get()); } -apds9960AGain_t Adafruit_APDS9960::getADCGain(void) -{ - return (apds9960AGain_t) ( read8(APDS9960_CONTROL) & 0x03 ); +/*! + * @brief Returns the ADC gain + * @return ADC gain + */ +apds9960AGain_t Adafruit_APDS9960::getADCGain() { + return (apds9960AGain_t)(read8(APDS9960_CONTROL) & 0x03); } - -/**************************************************************************/ /*! - Adjusts the Proximity gain on the APDS9960 -*/ -/**************************************************************************/ -void Adafruit_APDS9960::setProxGain(apds9960PGain_t pGain) -{ + * @brief Adjusts the Proximity gain on the APDS9960 + * @param pGain + * Gain + */ +void Adafruit_APDS9960::setProxGain(apds9960PGain_t pGain) { _control.PGAIN = pGain; /* Update the timing register */ write8(APDS9960_CONTROL, _control.get()); } -apds9960PGain_t Adafruit_APDS9960::getProxGain(void) -{ - return (apds9960PGain_t) ( read8(APDS9960_CONTROL) & 0x0C ); +/*! + * @brief Returns the Proximity gain on the APDS9960 + * @return Proxmity gain + */ +apds9960PGain_t Adafruit_APDS9960::getProxGain() { + return (apds9960PGain_t)(read8(APDS9960_CONTROL) & 0x0C); } +/*! + * @brief Sets number of proxmity pulses + * @param pLen + * Pulse Length + * @param pulses + * Number of pulses + */ void Adafruit_APDS9960::setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses) { - if (pulses < 1) pulses = 1; - if (pulses > 64) pulses = 64; + if (pulses < 1) + pulses = 1; + if (pulses > 64) + pulses = 64; pulses--; - + _ppulse.PPLEN = pLen; _ppulse.PPULSE = pulses; - - write8(APDS9960_PPULSE, _ppulse.get()); -} -/**************************************************************************/ + write8(APDS9960_PPULSE, _ppulse.get()); +} + /*! - Enable proximity readings on APDS9960 -*/ -/**************************************************************************/ -void Adafruit_APDS9960::enableProximity(boolean en) -{ + * @brief Enable proximity readings on APDS9960 + * @param en + * Enable (True/False) + */ +void Adafruit_APDS9960::enableProximity(boolean en) { _enable.PEN = en; write8(APDS9960_ENABLE, _enable.get()); } +/*! + * @brief Enable proximity interrupts + */ void Adafruit_APDS9960::enableProximityInterrupt() { - _enable.PIEN = 1; - write8(APDS9960_ENABLE, _enable.get()); - clearInterrupt(); + _enable.PIEN = 1; + write8(APDS9960_ENABLE, _enable.get()); + clearInterrupt(); } +/*! + * @brief Disable proximity interrupts + */ void Adafruit_APDS9960::disableProximityInterrupt() { - _enable.PIEN = 0; - write8(APDS9960_ENABLE, _enable.get()); + _enable.PIEN = 0; + write8(APDS9960_ENABLE, _enable.get()); } -void Adafruit_APDS9960::setProximityInterruptThreshold(uint8_t low, uint8_t high, uint8_t persistance){ - write8(APDS9960_PILT, low); - write8(APDS9960_PIHT, high); - - if (persistance > 7) persistance = 7; - _pers.PPERS = persistance; - write8(APDS9960_PERS,_pers.get()); +/*! + * @brief Set proxmity interrupt thresholds + * @param low + * Low threshold + * @param high + * High threshold + * @param persistance + * Persistance + */ +void Adafruit_APDS9960::setProximityInterruptThreshold(uint8_t low, + uint8_t high, + uint8_t persistance) { + write8(APDS9960_PILT, low); + write8(APDS9960_PIHT, high); + + if (persistance > 7) + persistance = 7; + _pers.PPERS = persistance; + write8(APDS9960_PERS, _pers.get()); } -bool Adafruit_APDS9960::getProximityInterrupt() -{ - _status.set(this->read8(APDS9960_STATUS)); - return _status.PINT; +/*! + * @brief Returns proxmity interrupt status + * @return True if enabled, false otherwise. + */ +bool Adafruit_APDS9960::getProximityInterrupt() { + _status.set(this->read8(APDS9960_STATUS)); + return _status.PINT; }; -/**************************************************************************/ /*! - Read proximity data -*/ -/**************************************************************************/ -uint8_t Adafruit_APDS9960::readProximity(void) -{ - return read8(APDS9960_PDATA); -} + * @brief Read proximity data + * @return Proximity + */ +uint8_t Adafruit_APDS9960::readProximity() { return read8(APDS9960_PDATA); } - -bool Adafruit_APDS9960::gestureValid() -{ - _gstatus.set(this->read8(APDS9960_GSTATUS)); - return _gstatus.GVALID; -} - -void Adafruit_APDS9960::setGestureDimensions(uint8_t dims) -{ - _gconf3.GDIMS = dims; - this->write8(APDS9960_GCONF3, _gconf3.get()); -} - -void Adafruit_APDS9960::setGestureFIFOThreshold(uint8_t thresh) -{ - _gconf1.GFIFOTH = thresh; - this->write8(APDS9960_GCONF1, _gconf1.get()); -} - -void Adafruit_APDS9960::setGestureGain(uint8_t gain) -{ - _gconf2.GGAIN = gain; - this->write8(APDS9960_GCONF2, _gconf2.get()); -} - -void Adafruit_APDS9960::setGestureProximityThreshold(uint8_t thresh) -{ - this->write8(APDS9960_GPENTH, thresh); -} - -void Adafruit_APDS9960::setGestureOffset(uint8_t offset_up, uint8_t offset_down, uint8_t offset_left, uint8_t offset_right) -{ - this->write8(APDS9960_GOFFSET_U, offset_up); - this->write8(APDS9960_GOFFSET_D, offset_down); - this->write8(APDS9960_GOFFSET_L, offset_left); - this->write8(APDS9960_GOFFSET_R, offset_right); -} - -/**************************************************************************/ /*! - Enable gesture readings on APDS9960 -*/ -/**************************************************************************/ -void Adafruit_APDS9960::enableGesture(boolean en) -{ - if(!en){ - _gconf4.GMODE = 0; - write8(APDS9960_GCONF4, _gconf4.get()); + * @brief Returns validity status of a gesture + * @return Status (True/False) + */ +bool Adafruit_APDS9960::gestureValid() { + _gstatus.set(this->read8(APDS9960_GSTATUS)); + return _gstatus.GVALID; +} + +/*! + * @brief Sets gesture dimensions + * @param dims + * Dimensions (APDS9960_DIMENSIONS_ALL, APDS9960_DIMENSIONS_UP_DOWM, + * APDS9960_DIMENSIONS_UP_DOWN, APGS9960_DIMENSIONS_LEFT_RIGHT) + */ +void Adafruit_APDS9960::setGestureDimensions(uint8_t dims) { + _gconf3.GDIMS = dims; + this->write8(APDS9960_GCONF3, _gconf3.get()); +} + +/*! + * @brief Sets gesture FIFO Threshold + * @param thresh + * Threshold (APDS9960_GFIFO_1, APDS9960_GFIFO_4, APDS9960_GFIFO_8, + * APDS9960_GFIFO_16) + */ +void Adafruit_APDS9960::setGestureFIFOThreshold(uint8_t thresh) { + _gconf1.GFIFOTH = thresh; + this->write8(APDS9960_GCONF1, _gconf1.get()); +} + +/*! + * @brief Sets gesture sensor gain + * @param gain + * Gain (APDS9960_GAIN_1, APDS9960_GAIN_2, APDS9960_GAIN_4, + * APDS9960_GAIN_8) + */ +void Adafruit_APDS9960::setGestureGain(uint8_t gain) { + _gconf2.GGAIN = gain; + this->write8(APDS9960_GCONF2, _gconf2.get()); +} + +/*! + * @brief Sets gesture sensor threshold + * @param thresh + * Threshold + */ +void Adafruit_APDS9960::setGestureProximityThreshold(uint8_t thresh) { + this->write8(APDS9960_GPENTH, thresh); +} + +/*! + * @brief Sets gesture sensor offset + * @param offset_up + * Up offset + * @param offset_down + * Down offset + * @param offset_left + * Left offset + * @param offset_right + * Right offset + */ +void Adafruit_APDS9960::setGestureOffset(uint8_t offset_up, uint8_t offset_down, + uint8_t offset_left, + uint8_t offset_right) { + this->write8(APDS9960_GOFFSET_U, offset_up); + this->write8(APDS9960_GOFFSET_D, offset_down); + this->write8(APDS9960_GOFFSET_L, offset_left); + this->write8(APDS9960_GOFFSET_R, offset_right); +} + +/*! + * @brief Enable gesture readings on APDS9960 + * @param en + * Enable (True/False) + */ +void Adafruit_APDS9960::enableGesture(boolean en) { + if (!en) { + _gconf4.GMODE = 0; + write8(APDS9960_GCONF4, _gconf4.get()); } _enable.GEN = en; write8(APDS9960_ENABLE, _enable.get()); resetCounts(); } -void Adafruit_APDS9960::resetCounts() -{ +/*! + * @brief Resets gesture counts + */ +void Adafruit_APDS9960::resetCounts() { gestCnt = 0; UCount = 0; DCount = 0; @@ -316,125 +385,144 @@ void Adafruit_APDS9960::resetCounts() RCount = 0; } -uint8_t Adafruit_APDS9960::readGesture(void) -{ - uint8_t toRead, bytesRead; - uint8_t buf[256]; - unsigned long t; - uint8_t gestureReceived; - while(1){ - int up_down_diff = 0; - int left_right_diff = 0; - gestureReceived = 0; - if(!gestureValid()) return 0; - - delay(30); - toRead = this->read8(APDS9960_GFLVL); - - bytesRead = this->read(APDS9960_GFIFO_U, buf, toRead); +/*! + * @brief Reads gesture + * @return Received gesture (APDS9960_DOWN APDS9960_UP, APDS9960_LEFT + * APDS9960_RIGHT) + */ +uint8_t Adafruit_APDS9960::readGesture() { + uint8_t toRead, bytesRead; + uint8_t buf[256]; + unsigned long t = 0; + uint8_t gestureReceived; + while (1) { + int up_down_diff = 0; + int left_right_diff = 0; + gestureReceived = 0; + if (!gestureValid()) + return 0; - if(abs((int)buf[0] - (int)buf[1]) > 13) + delay(30); + toRead = this->read8(APDS9960_GFLVL); + + // bytesRead is unused but produces sideffects needed for readGesture to work + bytesRead = this->read(APDS9960_GFIFO_U, buf, toRead); + + if (abs((int)buf[0] - (int)buf[1]) > 13) up_down_diff += (int)buf[0] - (int)buf[1]; - if(abs((int)buf[2] - (int)buf[3]) > 13) + if (abs((int)buf[2] - (int)buf[3]) > 13) left_right_diff += (int)buf[2] - (int)buf[3]; - if(up_down_diff != 0){ - if(up_down_diff < 0){ - if( DCount > 0){ - gestureReceived = APDS9960_UP; - } - else UCount++; - } - else if(up_down_diff > 0){ - if( UCount > 0){ - gestureReceived = APDS9960_DOWN; - } - else DCount++; - } - } - - if(left_right_diff != 0){ - if(left_right_diff < 0){ - if( RCount > 0){ - gestureReceived = APDS9960_LEFT; - } - else LCount++; - } - else if(left_right_diff > 0){ - if( LCount > 0){ - gestureReceived = APDS9960_RIGHT; - } - else RCount++; - } - } - - if(up_down_diff != 0 || left_right_diff != 0) t = millis(); - - if(gestureReceived || millis() - t > 300){ - resetCounts(); - return gestureReceived; - } - } + if (up_down_diff != 0) { + if (up_down_diff < 0) { + if (DCount > 0) { + gestureReceived = APDS9960_UP; + } else + UCount++; + } else if (up_down_diff > 0) { + if (UCount > 0) { + gestureReceived = APDS9960_DOWN; + } else + DCount++; + } + } + + if (left_right_diff != 0) { + if (left_right_diff < 0) { + if (RCount > 0) { + gestureReceived = APDS9960_LEFT; + } else + LCount++; + } else if (left_right_diff > 0) { + if (LCount > 0) { + gestureReceived = APDS9960_RIGHT; + } else + RCount++; + } + } + + if (up_down_diff != 0 || left_right_diff != 0) + t = millis(); + + if (gestureReceived || millis() - t > 300) { + resetCounts(); + return gestureReceived; + } + } } -/**************************************************************************/ /*! - Set LED brightness for proximity/gesture -*/ -/**************************************************************************/ -void Adafruit_APDS9960::setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost) { + * @brief Set LED brightness for proximity/gesture + * @param drive + * LED Drive + * @param boost + * LED Boost + */ +void Adafruit_APDS9960::setLED(apds9960LedDrive_t drive, + apds9960LedBoost_t boost) { // set BOOST _config2.LED_BOOST = boost; write8(APDS9960_CONFIG2, _config2.get()); - + _control.LDRIVE = drive; write8(APDS9960_CONTROL, _control.get()); } -/**************************************************************************/ /*! - Enable proximity readings on APDS9960 -*/ -/**************************************************************************/ -void Adafruit_APDS9960::enableColor(boolean en) -{ + * @brief Enable proximity readings on APDS9960 + * @param en + * Enable (True/False) + */ +void Adafruit_APDS9960::enableColor(boolean en) { _enable.AEN = en; write8(APDS9960_ENABLE, _enable.get()); } -bool Adafruit_APDS9960::colorDataReady() -{ - _status.set(this->read8(APDS9960_STATUS)); - return _status.AVALID; +/*! + * @brief Returns status of color data + * @return True if color data ready, False otherwise + */ +bool Adafruit_APDS9960::colorDataReady() { + _status.set(this->read8(APDS9960_STATUS)); + return _status.AVALID; } -/**************************************************************************/ /*! - @brief Reads the raw red, green, blue and clear channel values -*/ -/**************************************************************************/ -void Adafruit_APDS9960::getColorData (uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c) -{ - + * @brief Reads the raw red, green, blue and clear channel values + * @param *r + * Red value + * @param *g + * Green value + * @param *b + * Blue value + * @param *c + * Clear channel value + */ +void Adafruit_APDS9960::getColorData(uint16_t *r, uint16_t *g, uint16_t *b, + uint16_t *c) { + *c = read16R(APDS9960_CDATAL); *r = read16R(APDS9960_RDATAL); *g = read16R(APDS9960_GDATAL); *b = read16R(APDS9960_BDATAL); - } -/**************************************************************************/ /*! - @brief Converts the raw R/G/B values to color temperature in degrees - Kelvin -*/ -/**************************************************************************/ -uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b) -{ - float X, Y, Z; /* RGB to XYZ correlation */ - float xc, yc; /* Chromaticity co-ordinates */ - float n; /* McCamy's formula */ + * @brief Converts the raw R/G/B values to color temperature in degrees Kelvin + * @param r + * Red value + * @param g + * Green value + * @param b + * Blue value + * @return Color temperature + */ +uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, + uint16_t b) { + float X, Y, Z; /* RGB to XYZ correlation */ + float xc, yc; /* Chromaticity co-ordinates */ + float n; /* McCamy's formula */ float cct; /* 1. Map RGB values to their XYZ counterparts. */ @@ -443,7 +531,7 @@ uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, ui /* Note: Y = Illuminance or lux */ X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b); Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b); - Z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b); + Z = (-0.68202F * r) + (0.77073F * g) + (0.56332F * b); /* 2. Calculate the chromaticity co-ordinates */ xc = (X) / (X + Y + Z); @@ -453,20 +541,24 @@ uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, ui n = (xc - 0.3320F) / (0.1858F - yc); /* Calculate the final CCT */ - cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F; + cct = + (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F; /* Return the results in degrees Kelvin */ return (uint16_t)cct; } -/**************************************************************************/ /*! - @brief Calculate ambient light values -*/ -/**************************************************************************/ - -uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b) -{ + * @brief Calculate ambient light values + * @param r + * Red value + * @param g + * Green value + * @param b + * Blue value + * @return LUX value + */ +uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b) { float illuminance; /* This only uses RGB ... how can we integrate clear or calculate lux */ @@ -476,102 +568,159 @@ uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b) return (uint16_t)illuminance; } +/*! + * @brief Enables color interrupt + */ void Adafruit_APDS9960::enableColorInterrupt() { _enable.AIEN = 1; write8(APDS9960_ENABLE, _enable.get()); } +/*! + * @brief Disables color interrupt + */ void Adafruit_APDS9960::disableColorInterrupt() { - _enable.AIEN = 0; - write8(APDS9960_ENABLE, _enable.get()); + _enable.AIEN = 0; + write8(APDS9960_ENABLE, _enable.get()); } -void Adafruit_APDS9960::clearInterrupt(void) { +/*! + * @brief Clears interrupt + */ +void Adafruit_APDS9960::clearInterrupt() { this->write(APDS9960_AICLEAR, NULL, 0); } - +/*! + * @brief Sets interrupt limits + * @param low + * Low limit + * @param high + * High limit + */ void Adafruit_APDS9960::setIntLimits(uint16_t low, uint16_t high) { - write8(APDS9960_AILTIL, low & 0xFF); - write8(APDS9960_AILTH, low >> 8); - write8(APDS9960_AIHTL, high & 0xFF); - write8(APDS9960_AIHTH, high >> 8); + write8(APDS9960_AILTIL, low & 0xFF); + write8(APDS9960_AILTH, low >> 8); + write8(APDS9960_AIHTL, high & 0xFF); + write8(APDS9960_AIHTH, high >> 8); } -void Adafruit_APDS9960::write8(byte reg, byte value) -{ - this->write(reg, &value, 1); +/*! + * @brief Writes specified value to given register + * @param reg + * Register to write to + * @param value + * Value to write + */ +void Adafruit_APDS9960::write8(byte reg, byte value) { + this->write(reg, &value, 1); } -uint8_t Adafruit_APDS9960::read8(byte reg) -{ - uint8_t ret; - this->read(reg, &ret, 1); - - return ret; +/*! + * @brief Reads 8 bits from specified register + * @param reg + * Register to write to + * @return Value in register + */ +uint8_t Adafruit_APDS9960::read8(byte reg) { + uint8_t ret; + this->read(reg, &ret, 1); + + return ret; } -uint32_t Adafruit_APDS9960::read32(uint8_t reg) -{ - uint8_t ret[4]; - this->read(reg, ret, 4); - - return (ret[0] << 24) | (ret[1] << 16) | (ret[2] << 8) | ret[3]; +/*! + * @brief Reads 32 bits from specified register + * @param reg + * Register to write to + * @return Value in register + */ +uint32_t Adafruit_APDS9960::read32(uint8_t reg) { + uint8_t ret[4]; + this->read(reg, ret, 4); + + return (ret[0] << 24) | (ret[1] << 16) | (ret[2] << 8) | ret[3]; } -uint16_t Adafruit_APDS9960::read16(uint8_t reg) -{ - uint8_t ret[2]; - this->read(reg, ret, 2); - - return (ret[0] << 8) | ret[1]; -} - -uint16_t Adafruit_APDS9960::read16R(uint8_t reg) -{ +/*! + * @brief Reads 16 bites from specified register + * @param reg + * Register to write to + * @return Value in register + */ +uint16_t Adafruit_APDS9960::read16(uint8_t reg) { uint8_t ret[2]; this->read(reg, ret, 2); - + + return (ret[0] << 8) | ret[1]; +} + +/*! + * @brief Reads 16 bites from specified register + * @param reg + * Register to write to + * @return Value in register + */ +uint16_t Adafruit_APDS9960::read16R(uint8_t reg) { + uint8_t ret[2]; + this->read(reg, ret, 2); + return (ret[1] << 8) | ret[0]; } -void Adafruit_APDS9960::_i2c_init() -{ - Wire.begin(); +/*! + * @brief Begins I2C communication + */ +void Adafruit_APDS9960::_i2c_init() { _wire->begin(); } + +/*! + * @brief Reads num bytes from specified register into a given buffer + * @param reg + * Register + * @param *buf + * Buffer + * @param num + * Number of bytes + * @return Position after reading + */ +uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num) { + uint8_t pos = 0; + bool eof = false; + + // on arduino we need to read in 32 byte chunks + while (pos < num && !eof) { + + uint8_t read_now = min(32, num - pos); + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg + pos); + _wire->endTransmission(); + + _wire->requestFrom((uint8_t)_i2caddr, read_now); + + for (int i = 0; i < read_now; i++) { + if (!_wire->available()) { + eof = true; + break; + } + buf[pos] = _wire->read(); + pos++; + } + } + return pos; } -uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num) -{ - uint8_t value; - uint8_t pos = 0; - bool eof = false; - - //on arduino we need to read in 32 byte chunks - while(pos < num && !eof){ - - uint8_t read_now = min(32, num - pos); - Wire.beginTransmission((uint8_t)_i2caddr); - Wire.write((uint8_t)reg + pos); - Wire.endTransmission(); - - Wire.requestFrom((uint8_t)_i2caddr, read_now); - - for(int i=0; ibeginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->write((uint8_t *)buf, num); + _wire->endTransmission(); } diff --git a/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.h b/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.h index 177a202..1ba957d 100644 --- a/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.h +++ b/firmware/libraries/Adafruit_APDS9960_Library/Adafruit_APDS9960.h @@ -1,558 +1,531 @@ -/**************************************************************************/ -/*! - @file Adafruit_APDS9960.h - @author Ladyada, Dean Miller (Adafruit Industries) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2017, Adafruit Industries - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/**************************************************************************/ +/*! + * @file Adafruit_APDS9960.h + * + * Software License Agreement (BSD License) + * + * Copyright (c) 2017, Adafruit Industries + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _APDS9960_H_ #define _APDS9960_H_ #include #include -#define I2CDEBUG +#define APDS9960_ADDRESS (0x39) /**< I2C Address */ -/*========================================================================= - I2C ADDRESS/BITS - -----------------------------------------------------------------------*/ - #define APDS9960_ADDRESS (0x39) -/*=========================================================================*/ - -/*========================================================================= - REGISTERS - -----------------------------------------------------------------------*/ - - enum - { - APDS9960_RAM = 0x00, - APDS9960_ENABLE = 0x80, - APDS9960_ATIME = 0x81, - APDS9960_WTIME = 0x83, - APDS9960_AILTIL = 0x84, - APDS9960_AILTH = 0x85, - APDS9960_AIHTL = 0x86, - APDS9960_AIHTH = 0x87, - APDS9960_PILT = 0x89, - APDS9960_PIHT = 0x8B, - APDS9960_PERS = 0x8C, - APDS9960_CONFIG1 = 0x8D, - APDS9960_PPULSE = 0x8E, - APDS9960_CONTROL = 0x8F, - APDS9960_CONFIG2 = 0x90, - APDS9960_ID = 0x92, - APDS9960_STATUS = 0x93, - APDS9960_CDATAL = 0x94, - APDS9960_CDATAH = 0x95, - APDS9960_RDATAL = 0x96, - APDS9960_RDATAH = 0x97, - APDS9960_GDATAL = 0x98, - APDS9960_GDATAH = 0x99, - APDS9960_BDATAL = 0x9A, - APDS9960_BDATAH = 0x9B, - APDS9960_PDATA = 0x9C, - APDS9960_POFFSET_UR = 0x9D, - APDS9960_POFFSET_DL = 0x9E, - APDS9960_CONFIG3 = 0x9F, - APDS9960_GPENTH = 0xA0, - APDS9960_GEXTH = 0xA1, - APDS9960_GCONF1 = 0xA2, - APDS9960_GCONF2 = 0xA3, - APDS9960_GOFFSET_U = 0xA4, - APDS9960_GOFFSET_D = 0xA5, - APDS9960_GOFFSET_L = 0xA7, - APDS9960_GOFFSET_R = 0xA9, - APDS9960_GPULSE = 0xA6, - APDS9960_GCONF3 = 0xAA, - APDS9960_GCONF4 = 0xAB, - APDS9960_GFLVL = 0xAE, - APDS9960_GSTATUS = 0xAF, - APDS9960_IFORCE = 0xE4, - APDS9960_PICLEAR = 0xE5, - APDS9960_CICLEAR = 0xE6, - APDS9960_AICLEAR = 0xE7, - APDS9960_GFIFO_U = 0xFC, - APDS9960_GFIFO_D = 0xFD, - APDS9960_GFIFO_L = 0xFE, - APDS9960_GFIFO_R = 0xFF, - }; - - -/*=========================================================================*/ - -typedef enum -{ - APDS9960_AGAIN_1X = 0x00, /**< No gain */ - APDS9960_AGAIN_4X = 0x01, /**< 2x gain */ - APDS9960_AGAIN_16X = 0x02, /**< 16x gain */ - APDS9960_AGAIN_64X = 0x03 /**< 64x gain */ -} -apds9960AGain_t; - - -typedef enum -{ - APDS9960_PGAIN_1X = 0x00, /**< 1x gain */ - APDS9960_PGAIN_2X = 0x04, /**< 2x gain */ - APDS9960_PGAIN_4X = 0x08, /**< 4x gain */ - APDS9960_PGAIN_8X = 0x0C /**< 8x gain */ -} -apds9960PGain_t; - - -typedef enum -{ - APDS9960_PPULSELEN_4US = 0x00, /**< 4uS */ - APDS9960_PPULSELEN_8US = 0x40, /**< 8uS */ - APDS9960_PPULSELEN_16US = 0x80, /**< 16uS */ - APDS9960_PPULSELEN_32US = 0xC0 /**< 32uS */ -} -apds9960PPulseLen_t; - - -typedef enum -{ - APDS9960_LEDDRIVE_100MA = 0x00, /**< 100mA */ - APDS9960_LEDDRIVE_50MA = 0x40, /**< 50mA */ - APDS9960_LEDDRIVE_25MA = 0x80, /**< 25mA */ - APDS9960_LEDDRIVE_12MA = 0xC0 /**< 12.5mA */ -} -apds9960LedDrive_t; - - -typedef enum -{ - APDS9960_LEDBOOST_100PCNT = 0x00, /**< 100% */ - APDS9960_LEDBOOST_150PCNT = 0x10, /**< 150% */ - APDS9960_LEDBOOST_200PCNT = 0x20, /**< 200% */ - APDS9960_LEDBOOST_300PCNT = 0x30 /**< 300% */ -} -apds9960LedBoost_t; - -enum -{ - APDS9960_DIMENSIONS_ALL = 0x00, - APDS9960_DIMENSIONS_UP_DOWM = 0x01, - APGS9960_DIMENSIONS_LEFT_RIGHT = 0x02, +/** I2C Registers */ +enum { + APDS9960_RAM = 0x00, + APDS9960_ENABLE = 0x80, + APDS9960_ATIME = 0x81, + APDS9960_WTIME = 0x83, + APDS9960_AILTIL = 0x84, + APDS9960_AILTH = 0x85, + APDS9960_AIHTL = 0x86, + APDS9960_AIHTH = 0x87, + APDS9960_PILT = 0x89, + APDS9960_PIHT = 0x8B, + APDS9960_PERS = 0x8C, + APDS9960_CONFIG1 = 0x8D, + APDS9960_PPULSE = 0x8E, + APDS9960_CONTROL = 0x8F, + APDS9960_CONFIG2 = 0x90, + APDS9960_ID = 0x92, + APDS9960_STATUS = 0x93, + APDS9960_CDATAL = 0x94, + APDS9960_CDATAH = 0x95, + APDS9960_RDATAL = 0x96, + APDS9960_RDATAH = 0x97, + APDS9960_GDATAL = 0x98, + APDS9960_GDATAH = 0x99, + APDS9960_BDATAL = 0x9A, + APDS9960_BDATAH = 0x9B, + APDS9960_PDATA = 0x9C, + APDS9960_POFFSET_UR = 0x9D, + APDS9960_POFFSET_DL = 0x9E, + APDS9960_CONFIG3 = 0x9F, + APDS9960_GPENTH = 0xA0, + APDS9960_GEXTH = 0xA1, + APDS9960_GCONF1 = 0xA2, + APDS9960_GCONF2 = 0xA3, + APDS9960_GOFFSET_U = 0xA4, + APDS9960_GOFFSET_D = 0xA5, + APDS9960_GOFFSET_L = 0xA7, + APDS9960_GOFFSET_R = 0xA9, + APDS9960_GPULSE = 0xA6, + APDS9960_GCONF3 = 0xAA, + APDS9960_GCONF4 = 0xAB, + APDS9960_GFLVL = 0xAE, + APDS9960_GSTATUS = 0xAF, + APDS9960_IFORCE = 0xE4, + APDS9960_PICLEAR = 0xE5, + APDS9960_CICLEAR = 0xE6, + APDS9960_AICLEAR = 0xE7, + APDS9960_GFIFO_U = 0xFC, + APDS9960_GFIFO_D = 0xFD, + APDS9960_GFIFO_L = 0xFE, + APDS9960_GFIFO_R = 0xFF, }; -enum -{ - APDS9960_GFIFO_1 = 0x00, - APDS9960_GFIFO_4 = 0x01, - APDS9960_GFIFO_8 = 0x02, - APDS9960_GFIFO_16 = 0x03, +/** ADC gain settings */ +typedef enum { + APDS9960_AGAIN_1X = 0x00, /**< No gain */ + APDS9960_AGAIN_4X = 0x01, /**< 2x gain */ + APDS9960_AGAIN_16X = 0x02, /**< 16x gain */ + APDS9960_AGAIN_64X = 0x03 /**< 64x gain */ +} apds9960AGain_t; + +/** Proxmity gain settings */ +typedef enum { + APDS9960_PGAIN_1X = 0x00, /**< 1x gain */ + APDS9960_PGAIN_2X = 0x04, /**< 2x gain */ + APDS9960_PGAIN_4X = 0x08, /**< 4x gain */ + APDS9960_PGAIN_8X = 0x0C /**< 8x gain */ +} apds9960PGain_t; + +/** Pulse length settings */ +typedef enum { + APDS9960_PPULSELEN_4US = 0x00, /**< 4uS */ + APDS9960_PPULSELEN_8US = 0x40, /**< 8uS */ + APDS9960_PPULSELEN_16US = 0x80, /**< 16uS */ + APDS9960_PPULSELEN_32US = 0xC0 /**< 32uS */ +} apds9960PPulseLen_t; + +/** LED drive settings */ +typedef enum { + APDS9960_LEDDRIVE_100MA = 0x00, /**< 100mA */ + APDS9960_LEDDRIVE_50MA = 0x40, /**< 50mA */ + APDS9960_LEDDRIVE_25MA = 0x80, /**< 25mA */ + APDS9960_LEDDRIVE_12MA = 0xC0 /**< 12.5mA */ +} apds9960LedDrive_t; + +/** LED boost settings */ +typedef enum { + APDS9960_LEDBOOST_100PCNT = 0x00, /**< 100% */ + APDS9960_LEDBOOST_150PCNT = 0x10, /**< 150% */ + APDS9960_LEDBOOST_200PCNT = 0x20, /**< 200% */ + APDS9960_LEDBOOST_300PCNT = 0x30 /**< 300% */ +} apds9960LedBoost_t; + +/** Dimensions */ +enum { + APDS9960_DIMENSIONS_ALL = 0x00, // All dimensions + APDS9960_DIMENSIONS_UP_DOWN = 0x01, // Up/Down dimensions + APGS9960_DIMENSIONS_LEFT_RIGHT = 0x02, // Left/Right dimensions }; -enum -{ - APDS9960_GGAIN_1 = 0x00, - APDS9960_GGAIN_2 = 0x01, - APDS9960_GGAIN_4 = 0x02, - APDS9960_GGAIN_8 = 0x03, +/** FIFO Interrupts */ +enum { + APDS9960_GFIFO_1 = 0x00, // Generate interrupt after 1 dataset in FIFO + APDS9960_GFIFO_4 = 0x01, // Generate interrupt after 2 datasets in FIFO + APDS9960_GFIFO_8 = 0x02, // Generate interrupt after 3 datasets in FIFO + APDS9960_GFIFO_16 = 0x03, // Generate interrupt after 4 datasets in FIFO }; -enum -{ - APDS9960_GPULSE_4US = 0x00, - APDS9960_GPULSE_8US = 0x01, - APDS9960_GPULSE_16US = 0x02, - APDS9960_GPULSE_32US = 0x03, +/** Gesture Gain */ +enum { + APDS9960_GGAIN_1 = 0x00, // Gain 1x + APDS9960_GGAIN_2 = 0x01, // Gain 2x + APDS9960_GGAIN_4 = 0x02, // Gain 4x + APDS9960_GGAIN_8 = 0x03, // Gain 8x }; -#define APDS9960_TIME_MULT 2.78 //millisec +/** Pulse Lenghts */ +enum { + APDS9960_GPULSE_4US = 0x00, // Pulse 4us + APDS9960_GPULSE_8US = 0x01, // Pulse 8us + APDS9960_GPULSE_16US = 0x02, // Pulse 16us + APDS9960_GPULSE_32US = 0x03, // Pulse 32us +}; -#define APDS9960_UP 0x01 -#define APDS9960_DOWN 0x02 -#define APDS9960_LEFT 0x03 -#define APDS9960_RIGHT 0x04 +#define APDS9960_UP 0x01 /**< Gesture Up */ +#define APDS9960_DOWN 0x02 /**< Gesture Down */ +#define APDS9960_LEFT 0x03 /**< Gesture Left */ +#define APDS9960_RIGHT 0x04 /**< Gesture Right */ +/*! + * @brief Class that stores state and functions for interacting with + * APDS9960 Sensor + */ class Adafruit_APDS9960 { - public: - Adafruit_APDS9960(void) {}; - ~Adafruit_APDS9960(void) {}; - - boolean begin(uint16_t iTimeMS = 10, apds9960AGain_t = APDS9960_AGAIN_4X, uint8_t addr = APDS9960_ADDRESS); - void setADCIntegrationTime(uint16_t iTimeMS); - float getADCIntegrationTime(void); - void setADCGain(apds9960AGain_t gain); - apds9960AGain_t getADCGain(void); - void setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost); +public: + Adafruit_APDS9960(){}; + ~Adafruit_APDS9960(){}; + + boolean begin(uint16_t iTimeMS = 10, apds9960AGain_t = APDS9960_AGAIN_4X, + uint8_t addr = APDS9960_ADDRESS, TwoWire *theWire = &Wire); + void setADCIntegrationTime(uint16_t iTimeMS); + float getADCIntegrationTime(); + void setADCGain(apds9960AGain_t gain); + apds9960AGain_t getADCGain(); + void setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost); // proximity - void enableProximity(boolean en = true); - void setProxGain(apds9960PGain_t gain); - apds9960PGain_t getProxGain(void); - void setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses); - void enableProximityInterrupt(); - void disableProximityInterrupt(); - uint8_t readProximity(void); - void setProximityInterruptThreshold(uint8_t low, uint8_t high, uint8_t persistance = 4); - bool getProximityInterrupt(); + void enableProximity(boolean en = true); + void setProxGain(apds9960PGain_t gain); + apds9960PGain_t getProxGain(); + void setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses); + void enableProximityInterrupt(); + void disableProximityInterrupt(); + uint8_t readProximity(); + void setProximityInterruptThreshold(uint8_t low, uint8_t high, + uint8_t persistance = 4); + bool getProximityInterrupt(); // gesture - void enableGesture(boolean en = true); - bool gestureValid(); - void setGestureDimensions(uint8_t dims); - void setGestureFIFOThreshold(uint8_t thresh); - void setGestureGain(uint8_t gain); - void setGestureProximityThreshold(uint8_t thresh); - void setGestureOffset(uint8_t offset_up, uint8_t offset_down, uint8_t offset_left, uint8_t offset_right); - uint8_t readGesture(void); - void resetCounts(); + void enableGesture(boolean en = true); + bool gestureValid(); + void setGestureDimensions(uint8_t dims); + void setGestureFIFOThreshold(uint8_t thresh); + void setGestureGain(uint8_t gain); + void setGestureProximityThreshold(uint8_t thresh); + void setGestureOffset(uint8_t offset_up, uint8_t offset_down, + uint8_t offset_left, uint8_t offset_right); + uint8_t readGesture(); + void resetCounts(); // light & color - void enableColor(boolean en = true); - bool colorDataReady(); - void getColorData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c); + void enableColor(boolean en = true); + bool colorDataReady(); + void getColorData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c); uint16_t calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b); uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b); void enableColorInterrupt(); void disableColorInterrupt(); - void clearInterrupt(void); + void clearInterrupt(); void setIntLimits(uint16_t l, uint16_t h); // turn on/off elements - void enable(boolean en = true); + void enable(boolean en = true); - - private: +private: uint8_t _i2caddr; - + TwoWire *_wire; + uint32_t read32(uint8_t reg); uint16_t read16(uint8_t reg); uint16_t read16R(uint8_t reg); - - void write8(byte reg, byte value); - uint8_t read8(byte reg); - + + void write8(byte reg, byte value); + uint8_t read8(byte reg); + uint8_t gestCnt; - + uint8_t UCount; uint8_t DCount; - + uint8_t LCount; uint8_t RCount; - + uint8_t read(uint8_t reg, uint8_t *buf, uint8_t num); void write(uint8_t reg, uint8_t *buf, uint8_t num); void _i2c_init(); - + struct enable { - - //power on - uint8_t PON : 1; - - //ALS enable - uint8_t AEN : 1; - - //Proximity detect enable - uint8_t PEN : 1; - - //wait timer enable - uint8_t WEN : 1; - - //ALS interrupt enable - uint8_t AIEN : 1; - - //proximity interrupt enable - uint8_t PIEN : 1; - - //gesture enable - uint8_t GEN : 1; - - uint8_t get() { - return (GEN << 6) | (PIEN << 5) | (AIEN << 4) | (WEN << 3) | (PEN << 2) | (AEN << 1) | PON; - }; - }; - struct enable _enable; - - struct pers { - //ALS Interrupt Persistence. Controls rate of Clear channel interrupt to the host processor - uint8_t APERS : 4; - - //proximity interrupt persistence, controls rate of prox interrupt to host processor - uint8_t PPERS : 4; - - uint8_t get(){ - return (PPERS << 4) | APERS; - }; - }; - pers _pers; - - struct config1 { - uint8_t WLONG : 1; - - uint8_t get(){ - return WLONG << 1; - }; - }; - config1 _config1; - - struct ppulse { - - /*Proximity Pulse Count. Specifies the number of proximity pulses to be generated on LDR. - Number of pulses is set by PPULSE value plus 1. - */ - uint8_t PPULSE : 6; - - //Proximity Pulse Length. Sets the LED-ON pulse width during a proximity LDR pulse. - uint8_t PPLEN : 2; - - uint8_t get(){ - return (PPLEN << 6) | PPULSE; - } - }; - ppulse _ppulse; - - struct control { - //ALS and Color gain control - uint8_t AGAIN : 2; - - //proximity gain control - uint8_t PGAIN : 2; - - //led drive strength - uint8_t LDRIVE : 2; - - uint8_t get(){ - return (LDRIVE << 6) | (PGAIN << 2) | AGAIN; - } - }; - control _control; - - struct config2 { - /* Additional LDR current during proximity and gesture LED pulses. Current value, set by LDRIVE, - is increased by the percentage of LED_BOOST. - */ - uint8_t LED_BOOST : 2; - - //clear photodiode saturation int enable - uint8_t CPSIEN : 1; - - //proximity saturation interrupt enable - uint8_t PSIEN : 1; - - uint8_t get(){ - return (PSIEN << 7) | (CPSIEN << 6) | (LED_BOOST << 4) | 1; - } - }; - config2 _config2; - - struct status { - /* ALS Valid. Indicates that an ALS cycle has completed since AEN was asserted or since a read - from any of the ALS/Color data registers. - */ - uint8_t AVALID : 1; - - /* Proximity Valid. Indicates that a proximity cycle has completed since PEN was asserted or since - PDATA was last read. A read of PDATA automatically clears PVALID. - */ - uint8_t PVALID : 1; - - /* Gesture Interrupt. GINT is asserted when GFVLV becomes greater than GFIFOTH or if GVALID - has become asserted when GMODE transitioned to zero. The bit is reset when FIFO is - completely emptied (read). - */ - uint8_t GINT : 1; - - //ALS Interrupt. This bit triggers an interrupt if AIEN in ENABLE is set. - uint8_t AINT : 1; - - //Proximity Interrupt. This bit triggers an interrupt if PIEN in ENABLE is set. - uint8_t PINT : 1; - - /* Indicates that an analog saturation event occurred during a previous proximity or gesture - cycle. Once set, this bit remains set until cleared by clear proximity interrupt special function - command (0xE5 PICLEAR) or by disabling Prox (PEN=0). This bit triggers an interrupt if PSIEN - is set. - */ - uint8_t PGSAT : 1; - - /* Clear Photodiode Saturation. When asserted, the analog sensor was at the upper end of its - dynamic range. The bit can be de-asserted by sending a Clear channel interrupt command - (0xE6 CICLEAR) or by disabling the ADC (AEN=0). This bit triggers an interrupt if CPSIEN is set. - */ - uint8_t CPSAT : 1; - - void set(uint8_t data){ - AVALID = data & 0x01; - PVALID = (data >> 1) & 0x01; - GINT = (data >> 2) & 0x01; - AINT = (data >> 4) & 0x01; - PINT = (data >> 5) & 0x01; - PGSAT = (data >> 6) & 0x01; - CPSAT = (data >> 7) & 0x01; - } - }; - status _status; - - struct config3 { - //proximity mask - uint8_t PMASK_R : 1; - uint8_t PMASK_L : 1; - uint8_t PMASK_D : 1; - uint8_t PMASK_U : 1; - - /* Sleep After Interrupt. When enabled, the device will automatically enter low power mode - when the INT pin is asserted and the state machine has progressed to the SAI decision block. - Normal operation is resumed when INT pin is cleared over I2C. - */ - uint8_t SAI : 1; - - /* Proximity Gain Compensation Enable. This bit provides gain compensation when proximity - photodiode signal is reduced as a result of sensor masking. If only one diode of the diode pair - is contributing, then only half of the signal is available at the ADC; this results in a maximum - ADC value of 127. Enabling PCMP enables an additional gain of 2X, resulting in a maximum - ADC value of 255. - */ - uint8_t PCMP : 1; - - uint8_t get(){ - return (PCMP << 5) | (SAI << 4) | (PMASK_U << 3) | (PMASK_D << 2) | (PMASK_L << 1) | PMASK_R; - } - }; - config3 _config3; - - struct gconf1 { - /* Gesture Exit Persistence. When a number of consecutive “gesture end” occurrences become - equal or greater to the GEPERS value, the Gesture state machine is exited. - */ - uint8_t GEXPERS : 2; - - /* Gesture Exit Mask. Controls which of the gesture detector photodiodes (UDLR) will be included - to determine a “gesture end” and subsequent exit of the gesture state machine. Unmasked - UDLR data will be compared with the value in GTHR_OUT. Field value bits correspond to UDLR - detectors. - */ - uint8_t GEXMSK : 4; - - /* Gesture FIFO Threshold. This value is compared with the FIFO Level (i.e. the number of UDLR - datasets) to generate an interrupt (if enabled). - */ - uint8_t GFIFOTH : 2; - - uint8_t get(){ - return (GFIFOTH << 6) | (GEXMSK << 2) | GEXPERS; - } - }; - gconf1 _gconf1; - - struct gconf2 { - /* Gesture Wait Time. The GWTIME controls the amount of time in a low power mode between - gesture detection cycles. - */ - uint8_t GWTIME : 3; - - //Gesture LED Drive Strength. Sets LED Drive Strength in gesture mode. - uint8_t GLDRIVE : 2; - - //Gesture Gain Control. Sets the gain of the proximity receiver in gesture mode. - uint8_t GGAIN : 2; - - uint8_t get(){ - return (GGAIN << 5) | (GLDRIVE << 3) | GWTIME; - } - }; - gconf2 _gconf2; - - struct gpulse { - /* Number of Gesture Pulses. Specifies the number of pulses to be generated on LDR. - Number of pulses is set by GPULSE value plus 1. - */ - uint8_t GPULSE : 6; - - //Gesture Pulse Length. Sets the LED_ON pulse width during a Gesture LDR Pulse. - uint8_t GPLEN : 2; - - uint8_t get(){ - return (GPLEN << 6) | GPULSE; - } - }; - gpulse _gpulse; - - struct gconf3 { - /* Gesture Dimension Select. Selects which gesture photodiode pairs are enabled to gather - results during gesture. - */ - uint8_t GDIMS : 2; - - uint8_t get(){ - return GDIMS; - } - }; - gconf3 _gconf3; - - struct gconf4 { - /* Gesture Mode. Reading this bit reports if the gesture state machine is actively running, 1 - = Gesture, 0= ALS, Proximity, Color. Writing a 1 to this bit causes immediate entry in to the - gesture state machine (as if GPENTH had been exceeded). Writing a 0 to this bit causes exit of - gesture when current analog conversion has finished (as if GEXTH had been exceeded). - */ - uint8_t GMODE : 1; - - /* Gesture interrupt enable. Gesture Interrupt Enable. When asserted, all gesture related - interrupts are unmasked. - */ - uint8_t GIEN : 2; - - uint8_t get(){ - return (GIEN << 1) | GMODE; - } - void set(uint8_t data){ - GIEN = (data >> 1) & 0x01; - GMODE = data & 0x01; - } - }; - gconf4 _gconf4; - - struct gstatus { - /* Gesture FIFO Data. GVALID bit is sent when GFLVL becomes greater than GFIFOTH (i.e. FIFO has - enough data to set GINT). GFIFOD is reset when GMODE = 0 and the GFLVL=0 (i.e. All FIFO data - has been read). - */ - uint8_t GVALID : 1; - - /* Gesture FIFO Overflow. A setting of 1 indicates that the FIFO has filled to capacity and that new - gesture detector data has been lost. - */ - uint8_t GFOV : 1; - - void set(uint8_t data){ - GFOV = (data >> 1) & 0x01; - GVALID = data & 0x01; - } - }; - gstatus _gstatus; - + + // power on + uint8_t PON : 1; + + // ALS enable + uint8_t AEN : 1; + + // Proximity detect enable + uint8_t PEN : 1; + + // wait timer enable + uint8_t WEN : 1; + + // ALS interrupt enable + uint8_t AIEN : 1; + + // proximity interrupt enable + uint8_t PIEN : 1; + + // gesture enable + uint8_t GEN : 1; + + uint8_t get() { + return (GEN << 6) | (PIEN << 5) | (AIEN << 4) | (WEN << 3) | (PEN << 2) | + (AEN << 1) | PON; + }; + }; + struct enable _enable; + + struct pers { + // ALS Interrupt Persistence. Controls rate of Clear channel interrupt to + // the host processor + uint8_t APERS : 4; + + // proximity interrupt persistence, controls rate of prox interrupt to host + // processor + uint8_t PPERS : 4; + + uint8_t get() { return (PPERS << 4) | APERS; }; + }; + pers _pers; + + struct config1 { + uint8_t WLONG : 1; + + uint8_t get() { return WLONG << 1; }; + }; + config1 _config1; + + struct ppulse { + + /*Proximity Pulse Count. Specifies the number of proximity pulses to be + generated on LDR. Number of pulses is set by PPULSE value plus 1. + */ + uint8_t PPULSE : 6; + + // Proximity Pulse Length. Sets the LED-ON pulse width during a proximity + // LDR pulse. + uint8_t PPLEN : 2; + + uint8_t get() { return (PPLEN << 6) | PPULSE; } + }; + ppulse _ppulse; + + struct control { + // ALS and Color gain control + uint8_t AGAIN : 2; + + // proximity gain control + uint8_t PGAIN : 2; + + // led drive strength + uint8_t LDRIVE : 2; + + uint8_t get() { return (LDRIVE << 6) | (PGAIN << 2) | AGAIN; } + }; + control _control; + + struct config2 { + /* Additional LDR current during proximity and gesture LED pulses. Current + value, set by LDRIVE, is increased by the percentage of LED_BOOST. + */ + uint8_t LED_BOOST : 2; + + // clear photodiode saturation int enable + uint8_t CPSIEN : 1; + + // proximity saturation interrupt enable + uint8_t PSIEN : 1; + + uint8_t get() { + return (PSIEN << 7) | (CPSIEN << 6) | (LED_BOOST << 4) | 1; + } + }; + config2 _config2; + + struct status { + /* ALS Valid. Indicates that an ALS cycle has completed since AEN was + asserted or since a read from any of the ALS/Color data registers. + */ + uint8_t AVALID : 1; + + /* Proximity Valid. Indicates that a proximity cycle has completed since PEN + was asserted or since PDATA was last read. A read of PDATA automatically + clears PVALID. + */ + uint8_t PVALID : 1; + + /* Gesture Interrupt. GINT is asserted when GFVLV becomes greater than + GFIFOTH or if GVALID has become asserted when GMODE transitioned to zero. + The bit is reset when FIFO is completely emptied (read). + */ + uint8_t GINT : 1; + + // ALS Interrupt. This bit triggers an interrupt if AIEN in ENABLE is set. + uint8_t AINT : 1; + + // Proximity Interrupt. This bit triggers an interrupt if PIEN in ENABLE is + // set. + uint8_t PINT : 1; + + /* Indicates that an analog saturation event occurred during a previous + proximity or gesture cycle. Once set, this bit remains set until cleared by + clear proximity interrupt special function command (0xE5 PICLEAR) or by + disabling Prox (PEN=0). This bit triggers an interrupt if PSIEN is set. + */ + uint8_t PGSAT : 1; + + /* Clear Photodiode Saturation. When asserted, the analog sensor was at the + upper end of its dynamic range. The bit can be de-asserted by sending a + Clear channel interrupt command (0xE6 CICLEAR) or by disabling the ADC + (AEN=0). This bit triggers an interrupt if CPSIEN is set. + */ + uint8_t CPSAT : 1; + + void set(uint8_t data) { + AVALID = data & 0x01; + PVALID = (data >> 1) & 0x01; + GINT = (data >> 2) & 0x01; + AINT = (data >> 4) & 0x01; + PINT = (data >> 5) & 0x01; + PGSAT = (data >> 6) & 0x01; + CPSAT = (data >> 7) & 0x01; + } + }; + status _status; + + struct config3 { + // proximity mask + uint8_t PMASK_R : 1; + uint8_t PMASK_L : 1; + uint8_t PMASK_D : 1; + uint8_t PMASK_U : 1; + + /* Sleep After Interrupt. When enabled, the device will automatically enter + low power mode when the INT pin is asserted and the state machine has + progressed to the SAI decision block. Normal operation is resumed when INT + pin is cleared over I2C. + */ + uint8_t SAI : 1; + + /* Proximity Gain Compensation Enable. This bit provides gain compensation + when proximity photodiode signal is reduced as a result of sensor masking. + If only one diode of the diode pair is contributing, then only half of the + signal is available at the ADC; this results in a maximum ADC value of 127. + Enabling PCMP enables an additional gain of 2X, resulting in a maximum ADC + value of 255. + */ + uint8_t PCMP : 1; + + uint8_t get() { + return (PCMP << 5) | (SAI << 4) | (PMASK_U << 3) | (PMASK_D << 2) | + (PMASK_L << 1) | PMASK_R; + } + }; + config3 _config3; + + struct gconf1 { + /* Gesture Exit Persistence. When a number of consecutive “gesture end” + occurrences become equal or greater to the GEPERS value, the Gesture state + machine is exited. + */ + uint8_t GEXPERS : 2; + + /* Gesture Exit Mask. Controls which of the gesture detector photodiodes + (UDLR) will be included to determine a “gesture end” and subsequent exit + of the gesture state machine. Unmasked UDLR data will be compared with the + value in GTHR_OUT. Field value bits correspond to UDLR detectors. + */ + uint8_t GEXMSK : 4; + + /* Gesture FIFO Threshold. This value is compared with the FIFO Level (i.e. + the number of UDLR datasets) to generate an interrupt (if enabled). + */ + uint8_t GFIFOTH : 2; + + uint8_t get() { return (GFIFOTH << 6) | (GEXMSK << 2) | GEXPERS; } + }; + gconf1 _gconf1; + + struct gconf2 { + /* Gesture Wait Time. The GWTIME controls the amount of time in a low power + mode between gesture detection cycles. + */ + uint8_t GWTIME : 3; + + // Gesture LED Drive Strength. Sets LED Drive Strength in gesture mode. + uint8_t GLDRIVE : 2; + + // Gesture Gain Control. Sets the gain of the proximity receiver in gesture + // mode. + uint8_t GGAIN : 2; + + uint8_t get() { return (GGAIN << 5) | (GLDRIVE << 3) | GWTIME; } + }; + gconf2 _gconf2; + + struct gpulse { + /* Number of Gesture Pulses. Specifies the number of pulses to be generated + on LDR. Number of pulses is set by GPULSE value plus 1. + */ + uint8_t GPULSE : 6; + + // Gesture Pulse Length. Sets the LED_ON pulse width during a Gesture LDR + // Pulse. + uint8_t GPLEN : 2; + + uint8_t get() { return (GPLEN << 6) | GPULSE; } + }; + gpulse _gpulse; + + struct gconf3 { + /* Gesture Dimension Select. Selects which gesture photodiode pairs are + enabled to gather results during gesture. + */ + uint8_t GDIMS : 2; + + uint8_t get() { return GDIMS; } + }; + gconf3 _gconf3; + + struct gconf4 { + /* Gesture Mode. Reading this bit reports if the gesture state machine is + actively running, 1 = Gesture, 0= ALS, Proximity, Color. Writing a 1 to this + bit causes immediate entry in to the gesture state machine (as if GPENTH had + been exceeded). Writing a 0 to this bit causes exit of gesture when current + analog conversion has finished (as if GEXTH had been exceeded). + */ + uint8_t GMODE : 1; + + /* Gesture interrupt enable. Gesture Interrupt Enable. When asserted, all + gesture related interrupts are unmasked. + */ + uint8_t GIEN : 2; + + uint8_t get() { return (GIEN << 1) | GMODE; } + void set(uint8_t data) { + GIEN = (data >> 1) & 0x01; + GMODE = data & 0x01; + } + }; + gconf4 _gconf4; + + struct gstatus { + /* Gesture FIFO Data. GVALID bit is sent when GFLVL becomes greater than + GFIFOTH (i.e. FIFO has enough data to set GINT). GFIFOD is reset when GMODE + = 0 and the GFLVL=0 (i.e. All FIFO data has been read). + */ + uint8_t GVALID : 1; + + /* Gesture FIFO Overflow. A setting of 1 indicates that the FIFO has filled + to capacity and that new gesture detector data has been lost. + */ + uint8_t GFOV : 1; + + void set(uint8_t data) { + GFOV = (data >> 1) & 0x01; + GVALID = data & 0x01; + } + }; + gstatus _gstatus; }; #endif diff --git a/firmware/libraries/Adafruit_APDS9960_Library/README.md b/firmware/libraries/Adafruit_APDS9960_Library/README.md new file mode 100644 index 0000000..b115d7c --- /dev/null +++ b/firmware/libraries/Adafruit_APDS9960_Library/README.md @@ -0,0 +1,18 @@ +# Adafruit APDS9960 Library [![Build Status](https://travis-ci.com/adafruit/Adafruit_APDS9960.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_APDS9960) + + + +This is the Adafruit APDS9960 Proximity, Light, RGB, and Gesture sensor Library + +Tested and works great with the Adafruit APDS9960 Board +* http://www.adafruit.com/products/3595 + +This chip uses I2C to communicate, 2 pins are required to interface + +Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! + +Written by Dean Miller, Limor Fried for Adafruit Industries. +BSD license, check license.txt for more information +All text above must be included in any redistribution + +To install, use the Arduino Library Manager and search for "Adafruit APDS9960 Library" and install the library. diff --git a/firmware/libraries/Adafruit_APDS9960_Library/assets/board.jpg b/firmware/libraries/Adafruit_APDS9960_Library/assets/board.jpg new file mode 100644 index 0000000..dafb0d3 Binary files /dev/null and b/firmware/libraries/Adafruit_APDS9960_Library/assets/board.jpg differ diff --git a/firmware/libraries/Adafruit_APDS9960_Library/code-of-conduct.md b/firmware/libraries/Adafruit_APDS9960_Library/code-of-conduct.md new file mode 100644 index 0000000..8ee6e44 --- /dev/null +++ b/firmware/libraries/Adafruit_APDS9960_Library/code-of-conduct.md @@ -0,0 +1,127 @@ +# Adafruit Community Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and leaders pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level or type of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +We are committed to providing a friendly, safe and welcoming environment for +all. + +Examples of behavior that contributes to creating a positive environment +include: + +* Be kind and courteous to others +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Collaborating with other community members +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and sexual attention or advances +* The use of inappropriate images, including in a community member's avatar +* The use of inappropriate language, including in a community member's nickname +* Any spamming, flaming, baiting or other attention-stealing behavior +* Excessive or unwelcome helping; answering outside the scope of the question + asked +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate + +The goal of the standards and moderation guidelines outlined here is to build +and maintain a respectful community. We ask that you don’t just aim to be +"technically unimpeachable", but rather try to be your best self. + +We value many things beyond technical expertise, including collaboration and +supporting others within our community. Providing a positive experience for +other community members can have a much more significant impact than simply +providing the correct answer. + +## Our Responsibilities + +Project leaders are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project leaders have the right and responsibility to remove, edit, or +reject messages, comments, commits, code, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any community member for other behaviors that they deem +inappropriate, threatening, offensive, or harmful. + +## Moderation + +Instances of behaviors that violate the Adafruit Community Code of Conduct +may be reported by any member of the community. Community members are +encouraged to report these situations, including situations they witness +involving other community members. + +You may report in the following ways: + +In any situation, you may send an email to . + +On the Adafruit Discord, you may send an open message from any channel +to all Community Helpers by tagging @community helpers. You may also send an +open message from any channel, or a direct message to @kattni#1507, +@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or +@Andon#8175. + +Email and direct message reports will be kept confidential. + +In situations on Discord where the issue is particularly egregious, possibly +illegal, requires immediate action, or violates the Discord terms of service, +you should also report the message directly to Discord. + +These are the steps for upholding our community’s standards of conduct. + +1. Any member of the community may report any situation that violates the +Adafruit Community Code of Conduct. All reports will be reviewed and +investigated. +2. If the behavior is an egregious violation, the community member who +committed the violation may be banned immediately, without warning. +3. Otherwise, moderators will first respond to such behavior with a warning. +4. Moderators follow a soft "three strikes" policy - the community member may +be given another chance, if they are receptive to the warning and change their +behavior. +5. If the community member is unreceptive or unreasonable when warned by a +moderator, or the warning goes unheeded, they may be banned for a first or +second offense. Repeated offenses will result in the community member being +banned. + +## Scope + +This Code of Conduct and the enforcement policies listed above apply to all +Adafruit Community venues. This includes but is not limited to any community +spaces (both public and private), the entire Adafruit Discord server, and +Adafruit GitHub repositories. Examples of Adafruit Community spaces include +but are not limited to meet-ups, audio chats on the Adafruit Discord, or +interaction at a conference. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. As a community +member, you are representing our community, and are expected to behave +accordingly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +, +and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). + +For other projects adopting the Adafruit Community Code of +Conduct, please contact the maintainers of those projects for enforcement. +If you wish to use this code of conduct for your own project, consider +explicitly mentioning your moderation policy or making a copy with your +own moderation policy so as to avoid confusion. diff --git a/firmware/libraries/Adafruit_APDS9960_Library/library.properties b/firmware/libraries/Adafruit_APDS9960_Library/library.properties index 87306de..4302f99 100644 --- a/firmware/libraries/Adafruit_APDS9960_Library/library.properties +++ b/firmware/libraries/Adafruit_APDS9960_Library/library.properties @@ -1,5 +1,5 @@ name=Adafruit APDS9960 Library -version=1.0.5 +version=1.1.1 author=Adafruit maintainer=Adafruit sentence=This is a library for the Adafruit APDS9960 gesture/proximity/color/light sensor. diff --git a/firmware/libraries/Adafruit_APDS9960_Library/license.txt b/firmware/libraries/Adafruit_APDS9960_Library/license.txt new file mode 100644 index 0000000..f6a0f22 --- /dev/null +++ b/firmware/libraries/Adafruit_APDS9960_Library/license.txt @@ -0,0 +1,26 @@ +Software License Agreement (BSD License) + +Copyright (c) 2012, Adafruit Industries +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holders nor the +names of its contributors may be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp b/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp index 373b5a7..7b89736 100644 --- a/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp +++ b/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp @@ -1,530 +1,560 @@ -/*************************************************************************** - This is a library for the BME280 humidity, temperature & pressure sensor - - Designed specifically to work with the Adafruit BME280 Breakout - ----> http://www.adafruit.com/products/2650 - - These sensors use I2C or SPI to communicate, 2 or 4 pins are required - to interface. - - Adafruit invests time and resources providing this open source code, - please support Adafruit andopen-source hardware by purchasing products - from Adafruit! - - Written by Limor Fried & Kevin Townsend for Adafruit Industries. - BSD license, all text above must be included in any redistribution - ***************************************************************************/ -#include "Arduino.h" -#include -#include -#include "Adafruit_BME280.h" - -/*************************************************************************** - PRIVATE FUNCTIONS - ***************************************************************************/ -Adafruit_BME280::Adafruit_BME280() - : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) -{ } - -Adafruit_BME280::Adafruit_BME280(int8_t cspin) - : _cs(cspin), _mosi(-1), _miso(-1), _sck(-1) -{ } - -Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin) - : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) -{ } - - -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings -*/ -/**************************************************************************/ -bool Adafruit_BME280::begin(TwoWire *theWire) -{ - _wire = theWire; - _i2caddr = BME280_ADDRESS; - return init(); + * @file Adafruit_BME280.cpp + * + * @mainpage Adafruit BME280 humidity, temperature & pressure sensor + * + * @section intro_sec Introduction + * + * Driver for the BME280 humidity, temperature & pressure sensor + * + * These sensors use I2C or SPI to communicate, 2 or 4 pins are required + * to interface. + * + * Designed specifically to work with the Adafruit BME280 Breakout + * ----> http://www.adafruit.com/products/2652 + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * @section author Author + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * @section license License + * + * BSD license, all text here must be included in any redistribution. + * See the LICENSE file for details. + * + */ + +#include "Adafruit_BME280.h" +#include "Arduino.h" +#include +#include + +/*! + * @brief class constructor + */ +Adafruit_BME280::Adafruit_BME280() : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) {} + +/*! + * @brief class constructor if using hardware SPI + * @param cspin the chip select pin to use + * @param *theSPI + * optional SPI object + */ +Adafruit_BME280::Adafruit_BME280(int8_t cspin, SPIClass *theSPI) { + _cs = cspin; + _mosi = _miso = _sck = -1; + _spi = theSPI; } -bool Adafruit_BME280::begin(uint8_t addr) -{ - _i2caddr = addr; - _wire = &Wire; - return init(); +/*! + * @brief class constructor if using software SPI + * @param cspin the chip select pin to use + * @param mosipin the MOSI pin to use + * @param misopin the MISO pin to use + * @param sckpin the SCK pin to use + */ +Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, + int8_t sckpin) + : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) {} + +/*! + * @brief Initialise sensor with given parameters / settings + * @param theWire the I2C object to use + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(TwoWire *theWire) { + _wire = theWire; + _i2caddr = BME280_ADDRESS; + return init(); } -bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) -{ - _i2caddr = addr; - _wire = theWire; - return init(); +/*! + * @brief Initialise sensor with given parameters / settings + * @param addr the I2C address the device can be found on + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(uint8_t addr) { + _i2caddr = addr; + _wire = &Wire; + return init(); } -bool Adafruit_BME280::begin(void) -{ - _i2caddr = BME280_ADDRESS; - _wire = &Wire; - return init(); +/*! + * @brief Initialise sensor with given parameters / settings + * @param addr the I2C address the device can be found on + * @param theWire the I2C object to use + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) { + _i2caddr = addr; + _wire = theWire; + return init(); } -bool Adafruit_BME280::init() -{ - // init I2C or SPI sensor interface - if (_cs == -1) { - // I2C - _wire -> begin(); +/*! + * @brief Initialise sensor with given parameters / settings + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(void) { + bool status = false; + _i2caddr = BME280_ADDRESS; + _wire = &Wire; + status = init(); + if (!status) { + _i2caddr = BME280_ADDRESS_ALTERNATE; + status = init(); + } + return status; +} + +/*! + * @brief Initialise sensor with given parameters / settings + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::init() { + // init I2C or SPI sensor interface + if (_cs == -1) { + // I2C + _wire->begin(); + } else { + digitalWrite(_cs, HIGH); + pinMode(_cs, OUTPUT); + if (_sck == -1) { + // hardware SPI + _spi->begin(); } else { - digitalWrite(_cs, HIGH); - pinMode(_cs, OUTPUT); - if (_sck == -1) { - // hardware SPI - SPI.begin(); - } else { - // software SPI - pinMode(_sck, OUTPUT); - pinMode(_mosi, OUTPUT); - pinMode(_miso, INPUT); - } + // software SPI + pinMode(_sck, OUTPUT); + pinMode(_mosi, OUTPUT); + pinMode(_miso, INPUT); } + } - // check if sensor, i.e. the chip ID is correct - if (read8(BME280_REGISTER_CHIPID) != 0x60) - return false; + // check if sensor, i.e. the chip ID is correct + _sensorID = read8(BME280_REGISTER_CHIPID); + if (_sensorID != 0x60) + return false; - // reset the device using soft-reset - // this makes sure the IIR is off, etc. - write8(BME280_REGISTER_SOFTRESET, 0xB6); + // reset the device using soft-reset + // this makes sure the IIR is off, etc. + write8(BME280_REGISTER_SOFTRESET, 0xB6); - // wait for chip to wake up. - delay(300); - - // if chip is still reading calibration, delay - while (isReadingCalibration()) - delay(100); - - readCoefficients(); // read trimming parameters, see DS 4.2.2 - - setSampling(); // use defaults + // wait for chip to wake up. + delay(300); + // if chip is still reading calibration, delay + while (isReadingCalibration()) delay(100); - return true; + readCoefficients(); // read trimming parameters, see DS 4.2.2 + + setSampling(); // use defaults + + delay(100); + + return true; } -/**************************************************************************/ /*! - @brief setup sensor with given parameters / settings - - This is simply a overload to the normal begin()-function, so SPI users - don't get confused about the library requiring an address. -*/ -/**************************************************************************/ + * @brief setup sensor with given parameters / settings + * + * This is simply a overload to the normal begin()-function, so SPI users + * don't get confused about the library requiring an address. + * @param mode the power mode to use for the sensor + * @param tempSampling the temp samping rate to use + * @param pressSampling the pressure sampling rate to use + * @param humSampling the humidity sampling rate to use + * @param filter the filter mode to use + * @param duration the standby duration to use + */ +void Adafruit_BME280::setSampling(sensor_mode mode, + sensor_sampling tempSampling, + sensor_sampling pressSampling, + sensor_sampling humSampling, + sensor_filter filter, + standby_duration duration) { + _measReg.mode = mode; + _measReg.osrs_t = tempSampling; + _measReg.osrs_p = pressSampling; + _humReg.osrs_h = humSampling; + _configReg.filter = filter; + _configReg.t_sb = duration; -void Adafruit_BME280::setSampling(sensor_mode mode, - sensor_sampling tempSampling, - sensor_sampling pressSampling, - sensor_sampling humSampling, - sensor_filter filter, - standby_duration duration) { - _measReg.mode = mode; - _measReg.osrs_t = tempSampling; - _measReg.osrs_p = pressSampling; - - - _humReg.osrs_h = humSampling; - _configReg.filter = filter; - _configReg.t_sb = duration; - - - // you must make sure to also set REGISTER_CONTROL after setting the - // CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3) - write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); - write8(BME280_REGISTER_CONFIG, _configReg.get()); - write8(BME280_REGISTER_CONTROL, _measReg.get()); + // you must make sure to also set REGISTER_CONTROL after setting the + // CONTROLHUMID register, otherwise the values won't be applied (see + // DS 5.4.3) + write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); + write8(BME280_REGISTER_CONFIG, _configReg.get()); + write8(BME280_REGISTER_CONTROL, _measReg.get()); } - -/**************************************************************************/ /*! - @brief Encapsulate hardware and software SPI transfer into one function -*/ -/**************************************************************************/ + * @brief Encapsulate hardware and software SPI transfer into one + * function + * @param x the data byte to transfer + * @returns the data byte read from the device + */ uint8_t Adafruit_BME280::spixfer(uint8_t x) { - // hardware SPI - if (_sck == -1) - return SPI.transfer(x); + // hardware SPI + if (_sck == -1) + return _spi->transfer(x); - // software SPI - uint8_t reply = 0; - for (int i=7; i>=0; i--) { - reply <<= 1; - digitalWrite(_sck, LOW); - digitalWrite(_mosi, x & (1<= 0; i--) { + reply <<= 1; + digitalWrite(_sck, LOW); + digitalWrite(_mosi, x & (1 << i)); + digitalWrite(_sck, HIGH); + if (digitalRead(_miso)) + reply |= 1; + } + return reply; } - -/**************************************************************************/ /*! - @brief Writes an 8 bit value over I2C or SPI -*/ -/**************************************************************************/ + * @brief Writes an 8 bit value over I2C or SPI + * @param reg the register address to write to + * @param value the value to write to the register + */ void Adafruit_BME280::write8(byte reg, byte value) { - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> write((uint8_t)value); - _wire -> endTransmission(); - } else { - if (_sck == -1) - SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); - digitalWrite(_cs, LOW); - spixfer(reg & ~0x80); // write, bit 7 low - spixfer(value); - digitalWrite(_cs, HIGH); + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->write((uint8_t)value); + _wire->endTransmission(); + } else { if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } + _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); + digitalWrite(_cs, LOW); + spixfer(reg & ~0x80); // write, bit 7 low + spixfer(value); + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } } - -/**************************************************************************/ /*! - @brief Reads an 8 bit value over I2C or SPI -*/ -/**************************************************************************/ + * @brief Reads an 8 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the data byte read from the device + */ uint8_t Adafruit_BME280::read8(byte reg) { - uint8_t value; - - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)1); - value = _wire -> read(); - } else { - if (_sck == -1) - SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); - digitalWrite(_cs, LOW); - spixfer(reg | 0x80); // read, bit 7 high - value = spixfer(0); - digitalWrite(_cs, HIGH); - if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } - return value; + uint8_t value; + + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)1); + value = _wire->read(); + } else { + if (_sck == -1) + _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); + digitalWrite(_cs, LOW); + spixfer(reg | 0x80); // read, bit 7 high + value = spixfer(0); + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } + return value; } - -/**************************************************************************/ /*! - @brief Reads a 16 bit value over I2C or SPI -*/ -/**************************************************************************/ -uint16_t Adafruit_BME280::read16(byte reg) -{ - uint16_t value; + * @brief Reads a 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +uint16_t Adafruit_BME280::read16(byte reg) { + uint16_t value; - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)2); - value = (_wire -> read() << 8) | _wire -> read(); - } else { - if (_sck == -1) - SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); - digitalWrite(_cs, LOW); - spixfer(reg | 0x80); // read, bit 7 high - value = (spixfer(0) << 8) | spixfer(0); - digitalWrite(_cs, HIGH); - if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)2); + value = (_wire->read() << 8) | _wire->read(); + } else { + if (_sck == -1) + _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); + digitalWrite(_cs, LOW); + spixfer(reg | 0x80); // read, bit 7 high + value = (spixfer(0) << 8) | spixfer(0); + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } - return value; + return value; } - -/**************************************************************************/ /*! - -*/ -/**************************************************************************/ + * @brief Reads a signed 16 bit little endian value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ uint16_t Adafruit_BME280::read16_LE(byte reg) { - uint16_t temp = read16(reg); - return (temp >> 8) | (temp << 8); + uint16_t temp = read16(reg); + return (temp >> 8) | (temp << 8); } - -/**************************************************************************/ /*! - @brief Reads a signed 16 bit value over I2C or SPI -*/ -/**************************************************************************/ -int16_t Adafruit_BME280::readS16(byte reg) -{ - return (int16_t)read16(reg); + * @brief Reads a signed 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); } + +/*! + * @brief Reads a signed little endian 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16_LE(byte reg) { + return (int16_t)read16_LE(reg); } - -/**************************************************************************/ /*! - -*/ -/**************************************************************************/ -int16_t Adafruit_BME280::readS16_LE(byte reg) -{ - return (int16_t)read16_LE(reg); + * @brief Reads a 24 bit value over I2C + * @param reg the register address to read from + * @returns the 24 bit data value read from the device + */ +uint32_t Adafruit_BME280::read24(byte reg) { + uint32_t value; + + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)3); + + value = _wire->read(); + value <<= 8; + value |= _wire->read(); + value <<= 8; + value |= _wire->read(); + } else { + if (_sck == -1) + _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); + digitalWrite(_cs, LOW); + spixfer(reg | 0x80); // read, bit 7 high + + value = spixfer(0); + value <<= 8; + value |= spixfer(0); + value <<= 8; + value |= spixfer(0); + + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } + + return value; } - -/**************************************************************************/ /*! - @brief Reads a 24 bit value over I2C -*/ -/**************************************************************************/ -uint32_t Adafruit_BME280::read24(byte reg) -{ - uint32_t value; - - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)3); - - value = _wire -> read(); - value <<= 8; - value |= _wire -> read(); - value <<= 8; - value |= _wire -> read(); - } else { - if (_sck == -1) - SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); - digitalWrite(_cs, LOW); - spixfer(reg | 0x80); // read, bit 7 high - - value = spixfer(0); - value <<= 8; - value |= spixfer(0); - value <<= 8; - value |= spixfer(0); - - digitalWrite(_cs, HIGH); - if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } - - return value; + * @brief Take a new measurement (only possible in forced mode) + */ +void Adafruit_BME280::takeForcedMeasurement() { + // If we are in forced mode, the BME sensor goes back to sleep after each + // measurement and we need to set it to forced mode once at this point, so + // it will take the next measurement and then return to sleep again. + // In normal mode simply does new measurements periodically. + if (_measReg.mode == MODE_FORCED) { + // set to forced mode, i.e. "take next measurement" + write8(BME280_REGISTER_CONTROL, _measReg.get()); + // wait until measurement has been completed, otherwise we would read + // the values from the last measurement + while (read8(BME280_REGISTER_STATUS) & 0x08) + delay(1); + } } - -/**************************************************************************/ /*! - @brief Take a new measurement (only possible in forced mode) -*/ -/**************************************************************************/ -void Adafruit_BME280::takeForcedMeasurement() -{ - // If we are in forced mode, the BME sensor goes back to sleep after each - // measurement and we need to set it to forced mode once at this point, so - // it will take the next measurement and then return to sleep again. - // In normal mode simply does new measurements periodically. - if (_measReg.mode == MODE_FORCED) { - // set to forced mode, i.e. "take next measurement" - write8(BME280_REGISTER_CONTROL, _measReg.get()); - // wait until measurement has been completed, otherwise we would read - // the values from the last measurement - while (read8(BME280_REGISTER_STATUS) & 0x08) - delay(1); - } + * @brief Reads the factory-set coefficients + */ +void Adafruit_BME280::readCoefficients(void) { + _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); + _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); + _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); + + _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); + _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); + _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); + _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); + _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); + _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); + _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); + _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); + _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); + + _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); + _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); + _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); + _bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) | + (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); + _bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5 + 1) << 4) | + (read8(BME280_REGISTER_DIG_H5) >> 4); + _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); } - -/**************************************************************************/ /*! - @brief Reads the factory-set coefficients -*/ -/**************************************************************************/ -void Adafruit_BME280::readCoefficients(void) -{ - _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); - _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); - _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); - - _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); - _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); - _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); - _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); - _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); - _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); - _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); - _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); - _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); - - _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); - _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); - _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); - _bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4+1) & 0xF); - _bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5+1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4); - _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); -} - -/**************************************************************************/ -/*! - @brief return true if chip is busy reading cal data -*/ -/**************************************************************************/ -bool Adafruit_BME280::isReadingCalibration(void) -{ + * @brief return true if chip is busy reading cal data + * @returns true if reading calibration, false otherwise + */ +bool Adafruit_BME280::isReadingCalibration(void) { uint8_t const rStatus = read8(BME280_REGISTER_STATUS); return (rStatus & (1 << 0)) != 0; } - -/**************************************************************************/ /*! - @brief Returns the temperature from the sensor -*/ -/**************************************************************************/ -float Adafruit_BME280::readTemperature(void) -{ - int32_t var1, var2; + * @brief Returns the temperature from the sensor + * @returns the temperature read from the device + */ +float Adafruit_BME280::readTemperature(void) { + int32_t var1, var2; - int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); - if (adc_T == 0x800000) // value in case temp measurement was disabled - return NAN; - adc_T >>= 4; + int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); + if (adc_T == 0x800000) // value in case temp measurement was disabled + return NAN; + adc_T >>= 4; - var1 = ((((adc_T>>3) - ((int32_t)_bme280_calib.dig_T1 <<1))) * - ((int32_t)_bme280_calib.dig_T2)) >> 11; - - var2 = (((((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1)) * - ((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1))) >> 12) * - ((int32_t)_bme280_calib.dig_T3)) >> 14; + var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib.dig_T1 << 1))) * + ((int32_t)_bme280_calib.dig_T2)) >> + 11; - t_fine = var1 + var2; + var2 = (((((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1)) * + ((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1))) >> + 12) * + ((int32_t)_bme280_calib.dig_T3)) >> + 14; - float T = (t_fine * 5 + 128) >> 8; - return T/100; + t_fine = var1 + var2; + + float T = (t_fine * 5 + 128) >> 8; + return T / 100; } - -/**************************************************************************/ /*! - @brief Returns the temperature from the sensor -*/ -/**************************************************************************/ + * @brief Returns the pressure from the sensor + * @returns the pressure value (in Pascal) read from the device + */ float Adafruit_BME280::readPressure(void) { - int64_t var1, var2, p; + int64_t var1, var2, p; - readTemperature(); // must be done first to get t_fine + readTemperature(); // must be done first to get t_fine - int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); - if (adc_P == 0x800000) // value in case pressure measurement was disabled - return NAN; - adc_P >>= 4; + int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); + if (adc_P == 0x800000) // value in case pressure measurement was disabled + return NAN; + adc_P >>= 4; - var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; - var2 = var2 + ((var1*(int64_t)_bme280_calib.dig_P5)<<17); - var2 = var2 + (((int64_t)_bme280_calib.dig_P4)<<35); - var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3)>>8) + - ((var1 * (int64_t)_bme280_calib.dig_P2)<<12); - var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bme280_calib.dig_P1)>>33; + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; + var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) << 17); + var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) + + ((var1 * (int64_t)_bme280_calib.dig_P2) << 12); + var1 = + (((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 33; - if (var1 == 0) { - return 0; // avoid exception caused by division by zero - } - p = 1048576 - adc_P; - p = (((p<<31) - var2)*3125) / var1; - var1 = (((int64_t)_bme280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25; - var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; + if (var1 == 0) { + return 0; // avoid exception caused by division by zero + } + p = 1048576 - adc_P; + p = (((p << 31) - var2) * 3125) / var1; + var1 = (((int64_t)_bme280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7)<<4); - return (float)p/256; + p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7) << 4); + return (float)p / 256; } - -/**************************************************************************/ /*! - @brief Returns the humidity from the sensor -*/ -/**************************************************************************/ + * @brief Returns the humidity from the sensor + * @returns the humidity value read from the device + */ float Adafruit_BME280::readHumidity(void) { - readTemperature(); // must be done first to get t_fine + readTemperature(); // must be done first to get t_fine - int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); - if (adc_H == 0x8000) // value in case humidity measurement was disabled - return NAN; - - int32_t v_x1_u32r; + int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); + if (adc_H == 0x8000) // value in case humidity measurement was disabled + return NAN; - v_x1_u32r = (t_fine - ((int32_t)76800)); + int32_t v_x1_u32r; - v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - - (((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * - (((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + - ((int32_t)2097152)) * ((int32_t)_bme280_calib.dig_H2) + 8192) >> 14)); + v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)_bme280_calib.dig_H1)) >> 4)); + v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - + (((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + + ((int32_t)16384)) >> + 15) * + (((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * + (((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + + ((int32_t)32768))) >> + 10) + + ((int32_t)2097152)) * + ((int32_t)_bme280_calib.dig_H2) + + 8192) >> + 14)); - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; - v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - float h = (v_x1_u32r>>12); - return h / 1024.0; + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * + ((int32_t)_bme280_calib.dig_H1)) >> + 4)); + + v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; + v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; + float h = (v_x1_u32r >> 12); + return h / 1024.0; } - -/**************************************************************************/ /*! - Calculates the altitude (in meters) from the specified atmospheric - pressure (in hPa), and sea-level pressure (in hPa). + * Calculates the altitude (in meters) from the specified atmospheric + * pressure (in hPa), and sea-level pressure (in hPa). + * @param seaLevel Sea-level pressure in hPa + * @returns the altitude value read from the device + */ +float Adafruit_BME280::readAltitude(float seaLevel) { + // Equation taken from BMP180 datasheet (page 16): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf - @param seaLevel Sea-level pressure in hPa - @param atmospheric Atmospheric pressure in hPa -*/ -/**************************************************************************/ -float Adafruit_BME280::readAltitude(float seaLevel) -{ - // Equation taken from BMP180 datasheet (page 16): - // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 - // Note that using the equation from wikipedia can give bad results - // at high altitude. See this thread for more information: - // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 - - float atmospheric = readPressure() / 100.0F; - return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); + float atmospheric = readPressure() / 100.0F; + return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); } - -/**************************************************************************/ /*! - Calculates the pressure at sea level (in hPa) from the specified altitude - (in meters), and atmospheric pressure (in hPa). - @param altitude Altitude in meters - @param atmospheric Atmospheric pressure in hPa -*/ -/**************************************************************************/ -float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) -{ - // Equation taken from BMP180 datasheet (page 17): - // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + * Calculates the pressure at sea level (in hPa) from the specified + * altitude (in meters), and atmospheric pressure (in hPa). + * @param altitude Altitude in meters + * @param atmospheric Atmospheric pressure in hPa + * @returns the pressure at sea level (in hPa) from the specified altitude + */ +float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) { + // Equation taken from BMP180 datasheet (page 17): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf - // Note that using the equation from wikipedia can give bad results - // at high altitude. See this thread for more information: - // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 - return atmospheric / pow(1.0 - (altitude/44330.0), 5.255); + return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255); } + +/*! + * Returns Sensor ID found by init() for diagnostics + * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 + */ +uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; } diff --git a/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.h b/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.h index 61aeeed..930afc1 100644 --- a/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.h +++ b/firmware/libraries/Adafruit_BME280_Library/Adafruit_BME280.h @@ -1,106 +1,108 @@ -/*************************************************************************** - This is a library for the BME280 humidity, temperature & pressure sensor +/*! + * @file Adafruit_BME280.h + * + * Designed specifically to work with the Adafruit BME280 Breakout + * ----> http://www.adafruit.com/products/2650 + * + * These sensors use I2C or SPI to communicate, 2 or 4 pins are required + * to interface. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * See the LICENSE file for details. + * + */ - Designed specifically to work with the Adafruit BME280 Breakout - ----> http://www.adafruit.com/products/2650 - - These sensors use I2C or SPI to communicate, 2 or 4 pins are required - to interface. - - Adafruit invests time and resources providing this open source code, - please support Adafruit andopen-source hardware by purchasing products - from Adafruit! - - Written by Limor Fried & Kevin Townsend for Adafruit Industries. - BSD license, all text above must be included in any redistribution - ***************************************************************************/ #ifndef __BME280_H__ #define __BME280_H__ -#if (ARDUINO >= 100) - #include "Arduino.h" -#else - #include "WProgram.h" -#endif +#include "Arduino.h" #include +#include #include -/*========================================================================= - I2C ADDRESS/BITS - -----------------------------------------------------------------------*/ - #define BME280_ADDRESS (0x77) -/*=========================================================================*/ +/*! + * @brief default I2C address + */ +#define BME280_ADDRESS (0x77) // Primary I2C Address + /*! + * @brief alternate I2C address + */ +#define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address -/*========================================================================= - REGISTERS - -----------------------------------------------------------------------*/ - enum - { - BME280_REGISTER_DIG_T1 = 0x88, - BME280_REGISTER_DIG_T2 = 0x8A, - BME280_REGISTER_DIG_T3 = 0x8C, +/*! + * @brief Register addresses + */ +enum { + BME280_REGISTER_DIG_T1 = 0x88, + BME280_REGISTER_DIG_T2 = 0x8A, + BME280_REGISTER_DIG_T3 = 0x8C, - BME280_REGISTER_DIG_P1 = 0x8E, - BME280_REGISTER_DIG_P2 = 0x90, - BME280_REGISTER_DIG_P3 = 0x92, - BME280_REGISTER_DIG_P4 = 0x94, - BME280_REGISTER_DIG_P5 = 0x96, - BME280_REGISTER_DIG_P6 = 0x98, - BME280_REGISTER_DIG_P7 = 0x9A, - BME280_REGISTER_DIG_P8 = 0x9C, - BME280_REGISTER_DIG_P9 = 0x9E, + BME280_REGISTER_DIG_P1 = 0x8E, + BME280_REGISTER_DIG_P2 = 0x90, + BME280_REGISTER_DIG_P3 = 0x92, + BME280_REGISTER_DIG_P4 = 0x94, + BME280_REGISTER_DIG_P5 = 0x96, + BME280_REGISTER_DIG_P6 = 0x98, + BME280_REGISTER_DIG_P7 = 0x9A, + BME280_REGISTER_DIG_P8 = 0x9C, + BME280_REGISTER_DIG_P9 = 0x9E, - BME280_REGISTER_DIG_H1 = 0xA1, - BME280_REGISTER_DIG_H2 = 0xE1, - BME280_REGISTER_DIG_H3 = 0xE3, - BME280_REGISTER_DIG_H4 = 0xE4, - BME280_REGISTER_DIG_H5 = 0xE5, - BME280_REGISTER_DIG_H6 = 0xE7, + BME280_REGISTER_DIG_H1 = 0xA1, + BME280_REGISTER_DIG_H2 = 0xE1, + BME280_REGISTER_DIG_H3 = 0xE3, + BME280_REGISTER_DIG_H4 = 0xE4, + BME280_REGISTER_DIG_H5 = 0xE5, + BME280_REGISTER_DIG_H6 = 0xE7, - BME280_REGISTER_CHIPID = 0xD0, - BME280_REGISTER_VERSION = 0xD1, - BME280_REGISTER_SOFTRESET = 0xE0, + BME280_REGISTER_CHIPID = 0xD0, + BME280_REGISTER_VERSION = 0xD1, + BME280_REGISTER_SOFTRESET = 0xE0, - BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 + BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 - BME280_REGISTER_CONTROLHUMID = 0xF2, - BME280_REGISTER_STATUS = 0XF3, - BME280_REGISTER_CONTROL = 0xF4, - BME280_REGISTER_CONFIG = 0xF5, - BME280_REGISTER_PRESSUREDATA = 0xF7, - BME280_REGISTER_TEMPDATA = 0xFA, - BME280_REGISTER_HUMIDDATA = 0xFD - }; + BME280_REGISTER_CONTROLHUMID = 0xF2, + BME280_REGISTER_STATUS = 0XF3, + BME280_REGISTER_CONTROL = 0xF4, + BME280_REGISTER_CONFIG = 0xF5, + BME280_REGISTER_PRESSUREDATA = 0xF7, + BME280_REGISTER_TEMPDATA = 0xFA, + BME280_REGISTER_HUMIDDATA = 0xFD +}; -/*=========================================================================*/ +/**************************************************************************/ +/*! + @brief calibration data +*/ +/**************************************************************************/ +typedef struct { + uint16_t dig_T1; ///< temperature compensation value + int16_t dig_T2; ///< temperature compensation value + int16_t dig_T3; ///< temperature compensation value -/*========================================================================= - CALIBRATION DATA - -----------------------------------------------------------------------*/ - typedef struct - { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; + uint16_t dig_P1; ///< pressure compensation value + int16_t dig_P2; ///< pressure compensation value + int16_t dig_P3; ///< pressure compensation value + int16_t dig_P4; ///< pressure compensation value + int16_t dig_P5; ///< pressure compensation value + int16_t dig_P6; ///< pressure compensation value + int16_t dig_P7; ///< pressure compensation value + int16_t dig_P8; ///< pressure compensation value + int16_t dig_P9; ///< pressure compensation value - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - - uint8_t dig_H1; - int16_t dig_H2; - uint8_t dig_H3; - int16_t dig_H4; - int16_t dig_H5; - int8_t dig_H6; - } bme280_calib_data; + uint8_t dig_H1; ///< humidity compensation value + int16_t dig_H2; ///< humidity compensation value + uint8_t dig_H3; ///< humidity compensation value + int16_t dig_H4; ///< humidity compensation value + int16_t dig_H5; ///< humidity compensation value + int8_t dig_H6; ///< humidity compensation value +} bme280_calib_data; /*=========================================================================*/ /* @@ -124,177 +126,214 @@ class Adafruit_BME280_Unified : public Adafruit_Sensor */ +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with BME280 IC +*/ +/**************************************************************************/ class Adafruit_BME280 { - public: - enum sensor_sampling { - SAMPLING_NONE = 0b000, - SAMPLING_X1 = 0b001, - SAMPLING_X2 = 0b010, - SAMPLING_X4 = 0b011, - SAMPLING_X8 = 0b100, - SAMPLING_X16 = 0b101 - }; +public: + /**************************************************************************/ + /*! + @brief sampling rates + */ + /**************************************************************************/ + enum sensor_sampling { + SAMPLING_NONE = 0b000, + SAMPLING_X1 = 0b001, + SAMPLING_X2 = 0b010, + SAMPLING_X4 = 0b011, + SAMPLING_X8 = 0b100, + SAMPLING_X16 = 0b101 + }; - enum sensor_mode { - MODE_SLEEP = 0b00, - MODE_FORCED = 0b01, - MODE_NORMAL = 0b11 - }; + /**************************************************************************/ + /*! + @brief power modes + */ + /**************************************************************************/ + enum sensor_mode { + MODE_SLEEP = 0b00, + MODE_FORCED = 0b01, + MODE_NORMAL = 0b11 + }; - enum sensor_filter { - FILTER_OFF = 0b000, - FILTER_X2 = 0b001, - FILTER_X4 = 0b010, - FILTER_X8 = 0b011, - FILTER_X16 = 0b100 - }; + /**************************************************************************/ + /*! + @brief filter values + */ + /**************************************************************************/ + enum sensor_filter { + FILTER_OFF = 0b000, + FILTER_X2 = 0b001, + FILTER_X4 = 0b010, + FILTER_X8 = 0b011, + FILTER_X16 = 0b100 + }; - // standby durations in ms - enum standby_duration { - STANDBY_MS_0_5 = 0b000, - STANDBY_MS_10 = 0b110, - STANDBY_MS_20 = 0b111, - STANDBY_MS_62_5 = 0b001, - STANDBY_MS_125 = 0b010, - STANDBY_MS_250 = 0b011, - STANDBY_MS_500 = 0b100, - STANDBY_MS_1000 = 0b101 - }; - - // constructors - Adafruit_BME280(void); - Adafruit_BME280(int8_t cspin); - Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); - - bool begin(void); - bool begin(TwoWire *theWire); - bool begin(uint8_t addr); - bool begin(uint8_t addr, TwoWire *theWire); - bool init(); + /**************************************************************************/ + /*! + @brief standby duration in ms + */ + /**************************************************************************/ + enum standby_duration { + STANDBY_MS_0_5 = 0b000, + STANDBY_MS_10 = 0b110, + STANDBY_MS_20 = 0b111, + STANDBY_MS_62_5 = 0b001, + STANDBY_MS_125 = 0b010, + STANDBY_MS_250 = 0b011, + STANDBY_MS_500 = 0b100, + STANDBY_MS_1000 = 0b101 + }; - void setSampling(sensor_mode mode = MODE_NORMAL, - sensor_sampling tempSampling = SAMPLING_X16, - sensor_sampling pressSampling = SAMPLING_X16, - sensor_sampling humSampling = SAMPLING_X16, - sensor_filter filter = FILTER_OFF, - standby_duration duration = STANDBY_MS_0_5 - ); - - void takeForcedMeasurement(); - float readTemperature(void); - float readPressure(void); - float readHumidity(void); - - float readAltitude(float seaLevel); - float seaLevelForAltitude(float altitude, float pressure); + // constructors + Adafruit_BME280(); + Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI); + Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, + int8_t sckpin); - - private: - TwoWire *_wire; - void readCoefficients(void); - bool isReadingCalibration(void); - uint8_t spixfer(uint8_t x); + bool begin(); + bool begin(TwoWire *theWire); + bool begin(uint8_t addr); + bool begin(uint8_t addr, TwoWire *theWire); + bool init(); - void write8(byte reg, byte value); - uint8_t read8(byte reg); - uint16_t read16(byte reg); - uint32_t read24(byte reg); - int16_t readS16(byte reg); - uint16_t read16_LE(byte reg); // little endian - int16_t readS16_LE(byte reg); // little endian + void setSampling(sensor_mode mode = MODE_NORMAL, + sensor_sampling tempSampling = SAMPLING_X16, + sensor_sampling pressSampling = SAMPLING_X16, + sensor_sampling humSampling = SAMPLING_X16, + sensor_filter filter = FILTER_OFF, + standby_duration duration = STANDBY_MS_0_5); - uint8_t _i2caddr; - int32_t _sensorID; - int32_t t_fine; + void takeForcedMeasurement(); + float readTemperature(void); + float readPressure(void); + float readHumidity(void); - int8_t _cs, _mosi, _miso, _sck; + float readAltitude(float seaLevel); + float seaLevelForAltitude(float altitude, float pressure); + uint32_t sensorID(void); - bme280_calib_data _bme280_calib; +protected: + TwoWire *_wire; //!< pointer to a TwoWire object + SPIClass *_spi; //!< pointer to SPI object + void readCoefficients(void); + bool isReadingCalibration(void); + uint8_t spixfer(uint8_t x); - // The config register - struct config { - // inactive duration (standby time) in normal mode - // 000 = 0.5 ms - // 001 = 62.5 ms - // 010 = 125 ms - // 011 = 250 ms - // 100 = 500 ms - // 101 = 1000 ms - // 110 = 10 ms - // 111 = 20 ms - unsigned int t_sb : 3; + void write8(byte reg, byte value); + uint8_t read8(byte reg); + uint16_t read16(byte reg); + uint32_t read24(byte reg); + int16_t readS16(byte reg); + uint16_t read16_LE(byte reg); // little endian + int16_t readS16_LE(byte reg); // little endian - // filter settings - // 000 = filter off - // 001 = 2x filter - // 010 = 4x filter - // 011 = 8x filter - // 100 and above = 16x filter - unsigned int filter : 3; + uint8_t _i2caddr; //!< I2C addr for the TwoWire interface + int32_t _sensorID; //!< ID of the BME Sensor + int32_t t_fine; //!< temperature with high resolution, stored as an attribute + //!< as this is used for temperature compensation reading + //!< humidity and pressure - // unused - don't set - unsigned int none : 1; - unsigned int spi3w_en : 1; + int8_t _cs; //!< for the SPI interface + int8_t _mosi; //!< for the SPI interface + int8_t _miso; //!< for the SPI interface + int8_t _sck; //!< for the SPI interface - unsigned int get() { - return (t_sb << 5) | (filter << 3) | spi3w_en; - } - }; - config _configReg; + bme280_calib_data _bme280_calib; //!< here calibration data is stored - - // The ctrl_meas register - struct ctrl_meas { - // temperature oversampling - // 000 = skipped - // 001 = x1 - // 010 = x2 - // 011 = x4 - // 100 = x8 - // 101 and above = x16 - unsigned int osrs_t : 3; + /**************************************************************************/ + /*! + @brief config register + */ + /**************************************************************************/ + struct config { + // inactive duration (standby time) in normal mode + // 000 = 0.5 ms + // 001 = 62.5 ms + // 010 = 125 ms + // 011 = 250 ms + // 100 = 500 ms + // 101 = 1000 ms + // 110 = 10 ms + // 111 = 20 ms + unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode - // pressure oversampling - // 000 = skipped - // 001 = x1 - // 010 = x2 - // 011 = x4 - // 100 = x8 - // 101 and above = x16 - unsigned int osrs_p : 3; + // filter settings + // 000 = filter off + // 001 = 2x filter + // 010 = 4x filter + // 011 = 8x filter + // 100 and above = 16x filter + unsigned int filter : 3; ///< filter settings - // device mode - // 00 = sleep - // 01 or 10 = forced - // 11 = normal - unsigned int mode : 2; + // unused - don't set + unsigned int none : 1; ///< unused - don't set + unsigned int spi3w_en : 1; ///< unused - don't set - unsigned int get() { - return (osrs_t << 5) | (osrs_p << 3) | mode; - } - }; - ctrl_meas _measReg; + /// @return combined config register + unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; } + }; + config _configReg; //!< config register object - - // The ctrl_hum register - struct ctrl_hum { - // unused - don't set - unsigned int none : 5; + /**************************************************************************/ + /*! + @brief ctrl_meas register + */ + /**************************************************************************/ + struct ctrl_meas { + // temperature oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_t : 3; ///< temperature oversampling - // pressure oversampling - // 000 = skipped - // 001 = x1 - // 010 = x2 - // 011 = x4 - // 100 = x8 - // 101 and above = x16 - unsigned int osrs_h : 3; + // pressure oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_p : 3; ///< pressure oversampling - unsigned int get() { - return (osrs_h); - } - }; - ctrl_hum _humReg; + // device mode + // 00 = sleep + // 01 or 10 = forced + // 11 = normal + unsigned int mode : 2; ///< device mode + + /// @return combined ctrl register + unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; } + }; + ctrl_meas _measReg; //!< measurement register object + + /**************************************************************************/ + /*! + @brief ctrl_hum register + */ + /**************************************************************************/ + struct ctrl_hum { + /// unused - don't set + unsigned int none : 5; + + // pressure oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_h : 3; ///< pressure oversampling + + /// @return combined ctrl hum register + unsigned int get() { return (osrs_h); } + }; + ctrl_hum _humReg; //!< hum register object }; #endif diff --git a/firmware/libraries/Adafruit_BME280_Library/LICENSE b/firmware/libraries/Adafruit_BME280_Library/LICENSE new file mode 100644 index 0000000..f4db09c --- /dev/null +++ b/firmware/libraries/Adafruit_BME280_Library/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Limor Fried & Kevin Townsend for Adafruit Industries +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Adafruit Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/firmware/libraries/Adafruit_BME280_Library/README.md b/firmware/libraries/Adafruit_BME280_Library/README.md index ed49542..2ba2668 100644 --- a/firmware/libraries/Adafruit_BME280_Library/README.md +++ b/firmware/libraries/Adafruit_BME280_Library/README.md @@ -1,3 +1,7 @@ +# Adafruit BME280 Library [![Build Status](https://travis-ci.com/adafruit/Adafruit_BME280_Library.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_BME280_Library) + + + This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor Designed specifically to work with the Adafruit BME280 Breakout @@ -25,35 +29,3 @@ You may need to create the libraries subfolder if its your first library. Restar We also have a great tutorial on Arduino library installation at: http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use - - -## Compatibility - -MCU | Tested Works | Doesn't Work | Not Tested | Notes ------------------- | :----------: | :----------: | :---------: | ----- -Atmega328 @ 16MHz | X | | | -Atmega328 @ 12MHz | X | | | -Atmega32u4 @ 16MHz | X | | | Use SDA/SCL on pins D2 & D3 -Atmega32u4 @ 8MHz | X | | | Use SDA/SCL on pins D2 & D3 -ESP8266 | X | | | I2C: just works, SPI: SDA/SCL default to pins 4 & 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL) -ESP32 | X | | | I2C: just works, SPI: SDA/SCL default to pins 4 & 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL) -Atmega2560 @ 16MHz | X | | | Use SDA/SCL on pins 20 & 21 -ATSAM3X8E | X | | | Use SDA/SCL on pins 20 & 21 -ATSAM21D | X | | | -ATtiny85 @ 16MHz | | X | | -ATtiny85 @ 8MHz | | X | | -Intel Curie @ 32MHz | | | X | -STM32F2 | | | X | - - * ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini - * ATmega328 @ 12MHz : Adafruit Pro Trinket 3V - * ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0 - * ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro - * ESP8266 : Adafruit Huzzah - * ATmega2560 @ 16MHz : Arduino Mega - * ATSAM3X8E : Arduino Due - * ATSAM21D : Arduino Zero, M0 Pro - * ATtiny85 @ 16MHz : Adafruit Trinket 5V - * ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V - - diff --git a/firmware/libraries/Adafruit_BME280_Library/assets/board.jpg b/firmware/libraries/Adafruit_BME280_Library/assets/board.jpg new file mode 100644 index 0000000..581f4ba Binary files /dev/null and b/firmware/libraries/Adafruit_BME280_Library/assets/board.jpg differ diff --git a/firmware/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino b/firmware/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino index 68b22b9..b4f0810 100644 --- a/firmware/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino +++ b/firmware/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino @@ -13,6 +13,7 @@ Written by Limor Fried & Kevin Townsend for Adafruit Industries. BSD license, all text above must be included in any redistribution + See the LICENSE file for details. ***************************************************************************/ #include @@ -37,7 +38,7 @@ void setup() { Serial.begin(9600); Serial.println(F("BME280 test")); - if (! bme.begin(&Wire1)) { + if (! bme.begin(&Wire)) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } @@ -101,6 +102,7 @@ void setup() { // = 40ms (25Hz) // with standby time that should really be 24.16913... Hz delayTime = 41; + */ /* // gaming @@ -154,4 +156,4 @@ void printValues() { Serial.println(" %"); Serial.println(); -} \ No newline at end of file +} diff --git a/firmware/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino b/firmware/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino index e8b5563..9fb8c43 100644 --- a/firmware/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino +++ b/firmware/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino @@ -13,6 +13,7 @@ Written by Limor Fried & Kevin Townsend for Adafruit Industries. BSD license, all text above must be included in any redistribution + See the LICENSE file for details. ***************************************************************************/ #include @@ -35,15 +36,21 @@ unsigned long delayTime; void setup() { Serial.begin(9600); + while(!Serial); // time to get serial running Serial.println(F("BME280 test")); - bool status; + unsigned status; // default settings // (you can also pass in a Wire library object like &Wire2) status = bme.begin(); if (!status) { - Serial.println("Could not find a valid BME280 sensor, check wiring!"); + Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); + Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); + Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); + Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); + Serial.print(" ID of 0x60 represents a BME 280.\n"); + Serial.print(" ID of 0x61 represents a BME 680.\n"); while (1); } @@ -79,4 +86,4 @@ void printValues() { Serial.println(" %"); Serial.println(); -} \ No newline at end of file +} diff --git a/firmware/libraries/Adafruit_BME280_Library/library.properties b/firmware/libraries/Adafruit_BME280_Library/library.properties index 189c369..f3ce2ba 100644 --- a/firmware/libraries/Adafruit_BME280_Library/library.properties +++ b/firmware/libraries/Adafruit_BME280_Library/library.properties @@ -1,5 +1,5 @@ name=Adafruit BME280 Library -version=1.0.7 +version=1.0.9 author=Adafruit maintainer=Adafruit sentence=Arduino library for BME280 sensors. diff --git a/firmware/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h b/firmware/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h index 3134ca3..8ac638f 100644 --- a/firmware/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h +++ b/firmware/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h @@ -20,7 +20,9 @@ #ifndef _ADAFRUIT_SENSOR_H #define _ADAFRUIT_SENSOR_H -#if ARDUINO >= 100 +#ifndef ARDUINO + #include +#elif ARDUINO >= 100 #include "Arduino.h" #include "Print.h" #else @@ -72,9 +74,9 @@ typedef struct { }; /* Orientation sensors */ struct { - float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */ - float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */ - float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */ + float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */ + float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */ + float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */ }; }; int8_t status; @@ -143,7 +145,7 @@ class Adafruit_Sensor { virtual ~Adafruit_Sensor() {} // These must be defined by the subclass - /// NOT USED virtual void enableAutoRange(bool enabled) {}; + virtual void enableAutoRange(bool enabled) { (void)enabled; /* suppress unused warning */ }; virtual bool getEvent(sensors_event_t*) = 0; virtual void getSensor(sensor_t*) = 0; diff --git a/firmware/libraries/Adafruit_Unified_Sensor/README.md b/firmware/libraries/Adafruit_Unified_Sensor/README.md index 8388b12..fd99597 100644 --- a/firmware/libraries/Adafruit_Unified_Sensor/README.md +++ b/firmware/libraries/Adafruit_Unified_Sensor/README.md @@ -35,7 +35,18 @@ The following drivers are based on the Adafruit Unified Sensor Driver: - [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library) **Humidity & Temperature** - - [Adafruit\_DHT\_Unified](https://github.com/adafruit/Adafruit_DHT_Unified) + - [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library) + +**Humidity, Temperature, & Barometric Pressure** + - [Adafruit_BME280_Library](https://github.com/adafruit/Adafruit_BME280_Library/) + +**Orientation** + - [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055) + +**All in one device** +- [Adafruit_LSM9DS0](https://github.com/adafruit/Adafruit_LSM9DS0_Library) (accelerometer, gyroscope, magnetometer) +- [Adafruit_LSM9DS1](https://github.com/adafruit/Adafruit_LSM9DS1/) (accelerometer, gyroscope, magnetometer) + ## How Does it Work? ## diff --git a/firmware/libraries/Adafruit_Unified_Sensor/library.properties b/firmware/libraries/Adafruit_Unified_Sensor/library.properties index fa7eefa..e0bcd3e 100644 --- a/firmware/libraries/Adafruit_Unified_Sensor/library.properties +++ b/firmware/libraries/Adafruit_Unified_Sensor/library.properties @@ -1,5 +1,5 @@ name=Adafruit Unified Sensor -version=1.0.2 +version=1.0.3 author=Adafruit maintainer=Adafruit sentence=Required for all Adafruit Unified Sensor based libraries. @@ -7,3 +7,4 @@ paragraph=A unified sensor abstraction layer used by many Adafruit sensor librar category=Sensors url=https://github.com/adafruit/Adafruit_Sensor architectures=* +includes=Adafruit_Sensor.h diff --git a/firmware/sensors.ino b/firmware/sensors.ino old mode 100755 new mode 100644 index fcf1899..18cea4f --- a/firmware/sensors.ino +++ b/firmware/sensors.ino @@ -31,7 +31,7 @@ float fetchLight() { return lux * LIGHT_FACTOR; } -void _anemometerInterrupt() { +ICACHE_RAM_ATTR void _anemometerInterrupt() { anemometerRotations++; #ifdef DEBUG Serial.print("*"); @@ -75,4 +75,3 @@ float isBatCharging() { } #endif -