diff --git a/README.md b/README.md
index 743f9cbc8..7f7118e71 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
-Current version is **5.9.0a** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
+Current version is **5.9.0b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions
@@ -33,23 +33,23 @@ See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum and more user experience.
The following devices are supported:
-- [iTead Sonoff Basic](http://sonoff.itead.cc/en/products/sonoff/sonoff-basic)
-- [iTead Sonoff RF](http://sonoff.itead.cc/en/products/sonoff/sonoff-rf)
-- [iTead Sonoff SV](https://www.itead.cc/sonoff-sv.html)
-- [iTead Sonoff TH10/TH16 with temperature sensor](http://sonoff.itead.cc/en/products/sonoff/sonoff-th)
-- [iTead Sonoff Dual](http://sonoff.itead.cc/en/products/sonoff/sonoff-dual)
-- [iTead Sonoff Pow](http://sonoff.itead.cc/en/products/sonoff/sonoff-pow)
-- [iTead Sonoff 4CH](http://sonoff.itead.cc/en/products/sonoff/sonoff-4ch)
-- [iTead Sonoff 4CH Pro](http://sonoff.itead.cc/en/products/sonoff/sonoff-4ch-pro)
-- [iTead S20 Smart Socket](http://sonoff.itead.cc/en/products/residential/s20-socket)
-- [iTead Slampher](http://sonoff.itead.cc/en/products/residential/slampher-rf)
-- [iTead Sonoff Touch](http://sonoff.itead.cc/en/products/residential/sonoff-touch)
-- [iTead Sonoff T1](http://sonoff.itead.cc/en/products/residential/sonoff-t1)
-- [iTead Sonoff SC](http://sonoff.itead.cc/en/products/residential/sonoff-sc)
-- [iTead Sonoff Led](http://sonoff.itead.cc/en/products/appliances/sonoff-led)
-- [iTead Sonoff BN-SZ01 Ceiling Led](http://sonoff.itead.cc/en/products/appliances/bn-sz01)
-- [iTead Sonoff B1](http://sonoff.itead.cc/en/products/residential/sonoff-b1)
-- [iTead Sonoff RF Bridge 433](http://sonoff.itead.cc/en/products/appliances/sonoff-rf-bridge-433)
+- [iTead Sonoff Basic](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html)
+- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html)
+- [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html)
+- [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html)
+- [iTead Sonoff Dual](https://www.itead.cc/smart-home/sonoff-dual.html)
+- [iTead Sonoff Pow](https://www.itead.cc/smart-home/sonoff-pow.html)
+- [iTead Sonoff 4CH](https://www.itead.cc/smart-home/sonoff-4ch.html)
+- [iTead Sonoff 4CH Pro](https://www.itead.cc/smart-home/sonoff-4ch-pro.html)
+- [iTead S20 Smart Socket](https://www.itead.cc/smart-socket.html)
+- [iTead Slampher](https://www.itead.cc/slampher.html)
+- [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch-eu-local.html)
+- [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html)
+- [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html)
+- [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html)
+- [iTead Sonoff BN-SZ01 Ceiling Led](https://www.itead.cc/bn-sz01.html)
+- [iTead Sonoff B1](https://www.itead.cc/sonoff-b1.html)
+- [iTead Sonoff RF Bridge 433](https://www.itead.cc/sonoff-rf-bridge-433.html)
- [iTead Sonoff Dev](https://www.itead.cc/sonoff-dev.html)
- [iTead 1 Channel Switch 5V / 12V](https://www.itead.cc/smart-home/inching-self-locking-wifi-wireless-switch.html)
- [iTead Motor Clockwise/Anticlockwise](https://www.itead.cc/smart-home/motor-reversing-wifi-wireless-switch.html)
diff --git a/lib/I2Cdevlib-ADS1115/.library.json b/lib/I2Cdevlib-ADS1115/.library.json
new file mode 100644
index 000000000..42719db38
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/.library.json
@@ -0,0 +1,40 @@
+{
+ "name": "I2Cdevlib-ADS1115",
+ "repository": {
+ "url": "https://github.com/jrowberg/i2cdevlib.git",
+ "type": "git"
+ },
+ "platforms": [
+ "atmelavr"
+ ],
+ "frameworks": [
+ "arduino"
+ ],
+ "dependencies": {
+ "frameworks": "arduino",
+ "name": "I2Cdevlib-Core"
+ },
+ "export": {
+ "include": "Arduino/ADS1115"
+ },
+ "version": "3b4c8bda90",
+ "authors": [
+ {
+ "maintainer": false,
+ "name": "Jeff Rowberg",
+ "url": "https://github.com/jrowberg",
+ "email": "jeff@rowberg.net"
+ }
+ ],
+ "keywords": [
+ "i2c",
+ "comparator",
+ "reference",
+ "pga",
+ "oscillator",
+ "mux",
+ "i2cdevlib"
+ ],
+ "id": 95,
+ "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference"
+}
\ No newline at end of file
diff --git a/lib/I2Cdevlib-ADS1115/ADS1115.cpp b/lib/I2Cdevlib-ADS1115/ADS1115.cpp
new file mode 100644
index 000000000..c3d7e873e
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/ADS1115.cpp
@@ -0,0 +1,649 @@
+// I2Cdev library collection - ADS1115 I2C device class
+// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009)
+// Note that the ADS1115 uses 16-bit registers, not 8-bit registers.
+// 8/2/2011 by Jeff Rowberg
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+// 2013-05-05 - Add debug information. Rename methods to match datasheet.
+// 2011-11-06 - added getVoltage, F. Farzanegan
+// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan
+// 2011-08-02 - initial release
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "ADS1115.h"
+
+/** Default constructor, uses default I2C address.
+ * @see ADS1115_DEFAULT_ADDRESS
+ */
+ADS1115::ADS1115() {
+ devAddr = ADS1115_DEFAULT_ADDRESS;
+}
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see ADS1115_DEFAULT_ADDRESS
+ * @see ADS1115_ADDRESS_ADDR_GND
+ * @see ADS1115_ADDRESS_ADDR_VDD
+ * @see ADS1115_ADDRESS_ADDR_SDA
+ * @see ADS1115_ADDRESS_ADDR_SDL
+ */
+ADS1115::ADS1115(uint8_t address) {
+ devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * This device is ready to use automatically upon power-up. It defaults to
+ * single-shot read mode, P0/N1 mux, 2.048v gain, 128 samples/sec, default
+ * comparator with hysterysis, active-low polarity, non-latching comparator,
+ * and comparater-disabled operation.
+ */
+void ADS1115::initialize() {
+ setMultiplexer(ADS1115_MUX_P0_N1);
+ setGain(ADS1115_PGA_2P048);
+ setMode(ADS1115_MODE_SINGLESHOT);
+ setRate(ADS1115_RATE_128);
+ setComparatorMode(ADS1115_COMP_MODE_HYSTERESIS);
+ setComparatorPolarity(ADS1115_COMP_POL_ACTIVE_LOW);
+ setComparatorLatchEnabled(ADS1115_COMP_LAT_NON_LATCHING);
+ setComparatorQueueMode(ADS1115_COMP_QUE_DISABLE);
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool ADS1115::testConnection() {
+ return I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer) == 1;
+}
+
+/** Poll the operational status bit until the conversion is finished
+ * Retry at most 'max_retries' times
+ * conversion is finished, then return true;
+ * @see ADS1115_CFG_OS_BIT
+ * @return True if data is available, false otherwise
+ */
+bool ADS1115::pollConversion(uint16_t max_retries) {
+ for(uint16_t i = 0; i < max_retries; i++) {
+ if (isConversionReady()) return true;
+ }
+ return false;
+}
+
+/** Read differential value based on current MUX configuration.
+ * The default MUX setting sets the device to get the differential between the
+ * AIN0 and AIN1 pins. There are 8 possible MUX settings, but if you are using
+ * all four input pins as single-end voltage sensors, then the default option is
+ * not what you want; instead you will need to set the MUX to compare the
+ * desired AIN* pin with GND. There are shortcut methods (getConversion*) to do
+ * this conveniently, but you can also do it manually with setMultiplexer()
+ * followed by this method.
+ *
+ * In single-shot mode, this register may not have fresh data. You need to write
+ * a 1 bit to the MSB of the CONFIG register to trigger a single read/conversion
+ * before this will be populated with fresh data. This technique is not as
+ * effortless, but it has enormous potential to save power by only running the
+ * comparison circuitry when needed.
+ *
+ * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger
+ * will be executed and the conversion results will be polled.
+ * @return 16-bit signed differential value
+ * @see getConversionP0N1();
+ * @see getConversionPON3();
+ * @see getConversionP1N3();
+ * @see getConversionP2N3();
+ * @see getConversionP0GND();
+ * @see getConversionP1GND();
+ * @see getConversionP2GND();
+ * @see getConversionP3GND);
+ * @see setMultiplexer();
+ * @see ADS1115_RA_CONVERSION
+ * @see ADS1115_MUX_P0_N1
+ * @see ADS1115_MUX_P0_N3
+ * @see ADS1115_MUX_P1_N3
+ * @see ADS1115_MUX_P2_N3
+ * @see ADS1115_MUX_P0_NG
+ * @see ADS1115_MUX_P1_NG
+ * @see ADS1115_MUX_P2_NG
+ * @see ADS1115_MUX_P3_NG
+ */
+int16_t ADS1115::getConversion(bool triggerAndPoll) {
+ if (triggerAndPoll && devMode == ADS1115_MODE_SINGLESHOT) {
+ triggerConversion();
+ pollConversion(I2CDEV_DEFAULT_READ_TIMEOUT);
+ }
+ I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer);
+ return buffer[0];
+}
+/** Get AIN0/N1 differential.
+ * This changes the MUX setting to AIN0/N1 if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP0N1() {
+ if (muxMode != ADS1115_MUX_P0_N1) setMultiplexer(ADS1115_MUX_P0_N1);
+ return getConversion();
+}
+
+/** Get AIN0/N3 differential.
+ * This changes the MUX setting to AIN0/N3 if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP0N3() {
+ if (muxMode != ADS1115_MUX_P0_N3) setMultiplexer(ADS1115_MUX_P0_N3);
+ return getConversion();
+}
+
+/** Get AIN1/N3 differential.
+ * This changes the MUX setting to AIN1/N3 if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP1N3() {
+ if (muxMode != ADS1115_MUX_P1_N3) setMultiplexer(ADS1115_MUX_P1_N3);
+ return getConversion();
+}
+
+/** Get AIN2/N3 differential.
+ * This changes the MUX setting to AIN2/N3 if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP2N3() {
+ if (muxMode != ADS1115_MUX_P2_N3) setMultiplexer(ADS1115_MUX_P2_N3);
+ return getConversion();
+}
+
+/** Get AIN0/GND differential.
+ * This changes the MUX setting to AIN0/GND if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP0GND() {
+ if (muxMode != ADS1115_MUX_P0_NG) setMultiplexer(ADS1115_MUX_P0_NG);
+ return getConversion();
+}
+/** Get AIN1/GND differential.
+ * This changes the MUX setting to AIN1/GND if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP1GND() {
+ if (muxMode != ADS1115_MUX_P1_NG) setMultiplexer(ADS1115_MUX_P1_NG);
+ return getConversion();
+}
+/** Get AIN2/GND differential.
+ * This changes the MUX setting to AIN2/GND if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP2GND() {
+ if (muxMode != ADS1115_MUX_P2_NG) setMultiplexer(ADS1115_MUX_P2_NG);
+ return getConversion();
+}
+/** Get AIN3/GND differential.
+ * This changes the MUX setting to AIN3/GND if necessary, triggers a new
+ * measurement (also only if necessary), then gets the differential value
+ * currently in the CONVERSION register.
+ * @return 16-bit signed differential value
+ * @see getConversion()
+ */
+int16_t ADS1115::getConversionP3GND() {
+ if (muxMode != ADS1115_MUX_P3_NG) setMultiplexer(ADS1115_MUX_P3_NG);
+ return getConversion();
+}
+
+/** Get the current voltage reading
+ * Read the current differential and return it multiplied
+ * by the constant for the current gain. mV is returned to
+ * increase the precision of the voltage
+ * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger
+ * will be executed and the conversion results will be polled.
+ */
+float ADS1115::getMilliVolts(bool triggerAndPoll) {
+ switch (pgaMode) {
+ case ADS1115_PGA_6P144:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_6P144);
+ break;
+ case ADS1115_PGA_4P096:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_4P096);
+ break;
+ case ADS1115_PGA_2P048:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_2P048);
+ break;
+ case ADS1115_PGA_1P024:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_1P024);
+ break;
+ case ADS1115_PGA_0P512:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_0P512);
+ break;
+ case ADS1115_PGA_0P256:
+ case ADS1115_PGA_0P256B:
+ case ADS1115_PGA_0P256C:
+ return (getConversion(triggerAndPoll) * ADS1115_MV_0P256);
+ break;
+ }
+}
+
+/**
+ * Return the current multiplier for the PGA setting.
+ *
+ * This may be directly retreived by using getMilliVolts(),
+ * but this causes an independent read. This function could
+ * be used to average a number of reads from the getConversion()
+ * getConversionx() functions and cut downon the number of
+ * floating-point calculations needed.
+ *
+ */
+
+float ADS1115::getMvPerCount() {
+ switch (pgaMode) {
+ case ADS1115_PGA_6P144:
+ return ADS1115_MV_6P144;
+ break;
+ case ADS1115_PGA_4P096:
+ return ADS1115_MV_4P096;
+ break;
+ case ADS1115_PGA_2P048:
+ return ADS1115_MV_2P048;
+ break;
+ case ADS1115_PGA_1P024:
+ return ADS1115_MV_1P024;
+ break;
+ case ADS1115_PGA_0P512:
+ return ADS1115_MV_0P512;
+ break;
+ case ADS1115_PGA_0P256:
+ case ADS1115_PGA_0P256B:
+ case ADS1115_PGA_0P256C:
+ return ADS1115_MV_0P256;
+ break;
+ }
+}
+
+// CONFIG register
+
+/** Get operational status.
+ * @return Current operational status (false for active conversion, true for inactive)
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_OS_BIT
+ */
+bool ADS1115::isConversionReady() {
+ I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, buffer);
+ return buffer[0];
+}
+/** Trigger a new conversion.
+ * Writing to this bit will only have effect while in power-down mode (no conversions active).
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_OS_BIT
+ */
+void ADS1115::triggerConversion() {
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, 1);
+}
+/** Get multiplexer connection.
+ * @return Current multiplexer connection setting
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_MUX_BIT
+ * @see ADS1115_CFG_MUX_LENGTH
+ */
+uint8_t ADS1115::getMultiplexer() {
+ I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, buffer);
+ muxMode = (uint8_t)buffer[0];
+ return muxMode;
+}
+/** Set multiplexer connection. Continous mode may fill the conversion register
+ * with data before the MUX setting has taken effect. A stop/start of the conversion
+ * is done to reset the values.
+ * @param mux New multiplexer connection setting
+ * @see ADS1115_MUX_P0_N1
+ * @see ADS1115_MUX_P0_N3
+ * @see ADS1115_MUX_P1_N3
+ * @see ADS1115_MUX_P2_N3
+ * @see ADS1115_MUX_P0_NG
+ * @see ADS1115_MUX_P1_NG
+ * @see ADS1115_MUX_P2_NG
+ * @see ADS1115_MUX_P3_NG
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_MUX_BIT
+ * @see ADS1115_CFG_MUX_LENGTH
+ */
+void ADS1115::setMultiplexer(uint8_t mux) {
+ if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, mux)) {
+ muxMode = mux;
+ if (devMode == ADS1115_MODE_CONTINUOUS) {
+ // Force a stop/start
+ setMode(ADS1115_MODE_SINGLESHOT);
+ getConversion();
+ setMode(ADS1115_MODE_CONTINUOUS);
+ }
+ }
+
+}
+/** Get programmable gain amplifier level.
+ * @return Current programmable gain amplifier level
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_PGA_BIT
+ * @see ADS1115_CFG_PGA_LENGTH
+ */
+uint8_t ADS1115::getGain() {
+ I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, buffer);
+ pgaMode=(uint8_t)buffer[0];
+ return pgaMode;
+}
+/** Set programmable gain amplifier level.
+ * Continous mode may fill the conversion register
+ * with data before the gain setting has taken effect. A stop/start of the conversion
+ * is done to reset the values.
+ * @param gain New programmable gain amplifier level
+ * @see ADS1115_PGA_6P144
+ * @see ADS1115_PGA_4P096
+ * @see ADS1115_PGA_2P048
+ * @see ADS1115_PGA_1P024
+ * @see ADS1115_PGA_0P512
+ * @see ADS1115_PGA_0P256
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_PGA_BIT
+ * @see ADS1115_CFG_PGA_LENGTH
+ */
+void ADS1115::setGain(uint8_t gain) {
+ if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, gain)) {
+ pgaMode = gain;
+ if (devMode == ADS1115_MODE_CONTINUOUS) {
+ // Force a stop/start
+ setMode(ADS1115_MODE_SINGLESHOT);
+ getConversion();
+ setMode(ADS1115_MODE_CONTINUOUS);
+ }
+ }
+}
+/** Get device mode.
+ * @return Current device mode
+ * @see ADS1115_MODE_CONTINUOUS
+ * @see ADS1115_MODE_SINGLESHOT
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_MODE_BIT
+ */
+bool ADS1115::getMode() {
+ I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, buffer);
+ devMode = buffer[0];
+ return devMode;
+}
+/** Set device mode.
+ * @param mode New device mode
+ * @see ADS1115_MODE_CONTINUOUS
+ * @see ADS1115_MODE_SINGLESHOT
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_MODE_BIT
+ */
+void ADS1115::setMode(bool mode) {
+ if (I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, mode)) {
+ devMode = mode;
+ }
+}
+/** Get data rate.
+ * @return Current data rate
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_DR_BIT
+ * @see ADS1115_CFG_DR_LENGTH
+ */
+uint8_t ADS1115::getRate() {
+ I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, buffer);
+ return (uint8_t)buffer[0];
+}
+/** Set data rate.
+ * @param rate New data rate
+ * @see ADS1115_RATE_8
+ * @see ADS1115_RATE_16
+ * @see ADS1115_RATE_32
+ * @see ADS1115_RATE_64
+ * @see ADS1115_RATE_128
+ * @see ADS1115_RATE_250
+ * @see ADS1115_RATE_475
+ * @see ADS1115_RATE_860
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_DR_BIT
+ * @see ADS1115_CFG_DR_LENGTH
+ */
+void ADS1115::setRate(uint8_t rate) {
+ I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, rate);
+}
+/** Get comparator mode.
+ * @return Current comparator mode
+ * @see ADS1115_COMP_MODE_HYSTERESIS
+ * @see ADS1115_COMP_MODE_WINDOW
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_MODE_BIT
+ */
+bool ADS1115::getComparatorMode() {
+ I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, buffer);
+ return buffer[0];
+}
+/** Set comparator mode.
+ * @param mode New comparator mode
+ * @see ADS1115_COMP_MODE_HYSTERESIS
+ * @see ADS1115_COMP_MODE_WINDOW
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_MODE_BIT
+ */
+void ADS1115::setComparatorMode(bool mode) {
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, mode);
+}
+/** Get comparator polarity setting.
+ * @return Current comparator polarity setting
+ * @see ADS1115_COMP_POL_ACTIVE_LOW
+ * @see ADS1115_COMP_POL_ACTIVE_HIGH
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_POL_BIT
+ */
+bool ADS1115::getComparatorPolarity() {
+ I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, buffer);
+ return buffer[0];
+}
+/** Set comparator polarity setting.
+ * @param polarity New comparator polarity setting
+ * @see ADS1115_COMP_POL_ACTIVE_LOW
+ * @see ADS1115_COMP_POL_ACTIVE_HIGH
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_POL_BIT
+ */
+void ADS1115::setComparatorPolarity(bool polarity) {
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, polarity);
+}
+/** Get comparator latch enabled value.
+ * @return Current comparator latch enabled value
+ * @see ADS1115_COMP_LAT_NON_LATCHING
+ * @see ADS1115_COMP_LAT_LATCHING
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_LAT_BIT
+ */
+bool ADS1115::getComparatorLatchEnabled() {
+ I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, buffer);
+ return buffer[0];
+}
+/** Set comparator latch enabled value.
+ * @param enabled New comparator latch enabled value
+ * @see ADS1115_COMP_LAT_NON_LATCHING
+ * @see ADS1115_COMP_LAT_LATCHING
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_LAT_BIT
+ */
+void ADS1115::setComparatorLatchEnabled(bool enabled) {
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, enabled);
+}
+/** Get comparator queue mode.
+ * @return Current comparator queue mode
+ * @see ADS1115_COMP_QUE_ASSERT1
+ * @see ADS1115_COMP_QUE_ASSERT2
+ * @see ADS1115_COMP_QUE_ASSERT4
+ * @see ADS1115_COMP_QUE_DISABLE
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_QUE_BIT
+ * @see ADS1115_CFG_COMP_QUE_LENGTH
+ */
+uint8_t ADS1115::getComparatorQueueMode() {
+ I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, buffer);
+ return (uint8_t)buffer[0];
+}
+/** Set comparator queue mode.
+ * @param mode New comparator queue mode
+ * @see ADS1115_COMP_QUE_ASSERT1
+ * @see ADS1115_COMP_QUE_ASSERT2
+ * @see ADS1115_COMP_QUE_ASSERT4
+ * @see ADS1115_COMP_QUE_DISABLE
+ * @see ADS1115_RA_CONFIG
+ * @see ADS1115_CFG_COMP_QUE_BIT
+ * @see ADS1115_CFG_COMP_QUE_LENGTH
+ */
+void ADS1115::setComparatorQueueMode(uint8_t mode) {
+ I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, mode);
+}
+
+// *_THRESH registers
+
+/** Get low threshold value.
+ * @return Current low threshold value
+ * @see ADS1115_RA_LO_THRESH
+ */
+int16_t ADS1115::getLowThreshold() {
+ I2Cdev::readWord(devAddr, ADS1115_RA_LO_THRESH, buffer);
+ return buffer[0];
+}
+/** Set low threshold value.
+ * @param threshold New low threshold value
+ * @see ADS1115_RA_LO_THRESH
+ */
+void ADS1115::setLowThreshold(int16_t threshold) {
+ I2Cdev::writeWord(devAddr, ADS1115_RA_LO_THRESH, threshold);
+}
+/** Get high threshold value.
+ * @return Current high threshold value
+ * @see ADS1115_RA_HI_THRESH
+ */
+int16_t ADS1115::getHighThreshold() {
+ I2Cdev::readWord(devAddr, ADS1115_RA_HI_THRESH, buffer);
+ return buffer[0];
+}
+/** Set high threshold value.
+ * @param threshold New high threshold value
+ * @see ADS1115_RA_HI_THRESH
+ */
+void ADS1115::setHighThreshold(int16_t threshold) {
+ I2Cdev::writeWord(devAddr, ADS1115_RA_HI_THRESH, threshold);
+}
+
+/** Configures ALERT/RDY pin as a conversion ready pin.
+ * It does this by setting the MSB of the high threshold register to '1' and the MSB
+ * of the low threshold register to '0'. COMP_POL and COMP_QUE bits will be set to '0'.
+ * Note: ALERT/RDY pin requires a pull up resistor.
+ */
+void ADS1115::setConversionReadyPinMode() {
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_HI_THRESH, 15, 1);
+ I2Cdev::writeBitW(devAddr, ADS1115_RA_LO_THRESH, 15, 0);
+ setComparatorPolarity(0);
+ setComparatorQueueMode(0);
+}
+
+// Create a mask between two bits
+unsigned createMask(unsigned a, unsigned b) {
+ unsigned mask = 0;
+ for (unsigned i=a; i<=b; i++)
+ mask |= 1 << i;
+ return mask;
+}
+
+uint16_t shiftDown(uint16_t extractFrom, int places) {
+ return (extractFrom >> places);
+}
+
+
+uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) {
+ int low= high-length +1;
+ uint16_t mask = createMask(low ,high);
+ return shiftDown(extractFrom & mask, low);
+}
+
+/** Show all the config register settings
+ */
+void ADS1115::showConfigRegister() {
+ I2Cdev::readWord(devAddr, ADS1115_RA_CONFIG, buffer);
+ uint16_t configRegister =buffer[0];
+
+
+ #ifdef ADS1115_SERIAL_DEBUG
+ Serial.print("Register is:");
+ Serial.println(configRegister,BIN);
+
+ Serial.print("OS:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_OS_BIT,1), BIN);
+ Serial.print("MUX:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_MUX_BIT,ADS1115_CFG_MUX_LENGTH), BIN);
+
+ Serial.print("PGA:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_PGA_BIT,ADS1115_CFG_PGA_LENGTH), BIN);
+
+ Serial.print("MODE:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_MODE_BIT,1), BIN);
+
+ Serial.print("DR:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_DR_BIT,ADS1115_CFG_DR_LENGTH), BIN);
+
+ Serial.print("CMP_MODE:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_COMP_MODE_BIT,1), BIN);
+
+ Serial.print("CMP_POL:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_COMP_POL_BIT,1), BIN);
+
+ Serial.print("CMP_LAT:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_COMP_LAT_BIT,1), BIN);
+
+ Serial.print("CMP_QUE:\t");
+ Serial.println(getValueFromBits(configRegister,
+ ADS1115_CFG_COMP_QUE_BIT,ADS1115_CFG_COMP_QUE_LENGTH), BIN);
+ #endif
+};
+
diff --git a/lib/I2Cdevlib-ADS1115/ADS1115.h b/lib/I2Cdevlib-ADS1115/ADS1115.h
new file mode 100644
index 000000000..2ac68eea7
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/ADS1115.h
@@ -0,0 +1,200 @@
+// I2Cdev library collection - ADS1115 I2C device class header file
+// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009)
+// Note that the ADS1115 uses 16-bit registers, not 8-bit registers.
+// 8/2/2011 by Jeff Rowberg
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+// 2013-05-05 - Add debug information. Clean up Single Shot implementation
+// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan
+// 2011-08-02 - initial release
+
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _ADS1115_H_
+#define _ADS1115_H_
+
+#include "I2Cdev.h"
+
+// -----------------------------------------------------------------------------
+// Arduino-style "Serial.print" debug constant (uncomment to enable)
+// -----------------------------------------------------------------------------
+//#define ADS1115_SERIAL_DEBUG
+
+#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND)
+#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC)
+#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin
+#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin
+#define ADS1115_DEFAULT_ADDRESS ADS1115_ADDRESS_ADDR_GND
+
+#define ADS1115_RA_CONVERSION 0x00
+#define ADS1115_RA_CONFIG 0x01
+#define ADS1115_RA_LO_THRESH 0x02
+#define ADS1115_RA_HI_THRESH 0x03
+
+#define ADS1115_CFG_OS_BIT 15
+#define ADS1115_CFG_MUX_BIT 14
+#define ADS1115_CFG_MUX_LENGTH 3
+#define ADS1115_CFG_PGA_BIT 11
+#define ADS1115_CFG_PGA_LENGTH 3
+#define ADS1115_CFG_MODE_BIT 8
+#define ADS1115_CFG_DR_BIT 7
+#define ADS1115_CFG_DR_LENGTH 3
+#define ADS1115_CFG_COMP_MODE_BIT 4
+#define ADS1115_CFG_COMP_POL_BIT 3
+#define ADS1115_CFG_COMP_LAT_BIT 2
+#define ADS1115_CFG_COMP_QUE_BIT 1
+#define ADS1115_CFG_COMP_QUE_LENGTH 2
+
+
+#define ADS1115_MUX_P0_N1 0x00 // default
+#define ADS1115_MUX_P0_N3 0x01
+#define ADS1115_MUX_P1_N3 0x02
+#define ADS1115_MUX_P2_N3 0x03
+#define ADS1115_MUX_P0_NG 0x04
+#define ADS1115_MUX_P1_NG 0x05
+#define ADS1115_MUX_P2_NG 0x06
+#define ADS1115_MUX_P3_NG 0x07
+
+#define ADS1115_PGA_6P144 0x00
+#define ADS1115_PGA_4P096 0x01
+#define ADS1115_PGA_2P048 0x02 // default
+#define ADS1115_PGA_1P024 0x03
+#define ADS1115_PGA_0P512 0x04
+#define ADS1115_PGA_0P256 0x05
+#define ADS1115_PGA_0P256B 0x06
+#define ADS1115_PGA_0P256C 0x07
+
+#define ADS1115_MV_6P144 0.187500
+#define ADS1115_MV_4P096 0.125000
+#define ADS1115_MV_2P048 0.062500 // default
+#define ADS1115_MV_1P024 0.031250
+#define ADS1115_MV_0P512 0.015625
+#define ADS1115_MV_0P256 0.007813
+#define ADS1115_MV_0P256B 0.007813
+#define ADS1115_MV_0P256C 0.007813
+
+#define ADS1115_MODE_CONTINUOUS 0x00
+#define ADS1115_MODE_SINGLESHOT 0x01 // default
+
+#define ADS1115_RATE_8 0x00
+#define ADS1115_RATE_16 0x01
+#define ADS1115_RATE_32 0x02
+#define ADS1115_RATE_64 0x03
+#define ADS1115_RATE_128 0x04 // default
+#define ADS1115_RATE_250 0x05
+#define ADS1115_RATE_475 0x06
+#define ADS1115_RATE_860 0x07
+
+#define ADS1115_COMP_MODE_HYSTERESIS 0x00 // default
+#define ADS1115_COMP_MODE_WINDOW 0x01
+
+#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 // default
+#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01
+
+#define ADS1115_COMP_LAT_NON_LATCHING 0x00 // default
+#define ADS1115_COMP_LAT_LATCHING 0x01
+
+#define ADS1115_COMP_QUE_ASSERT1 0x00
+#define ADS1115_COMP_QUE_ASSERT2 0x01
+#define ADS1115_COMP_QUE_ASSERT4 0x02
+#define ADS1115_COMP_QUE_DISABLE 0x03 // default
+
+// -----------------------------------------------------------------------------
+// Arduino-style "Serial.print" debug constant (uncomment to enable)
+// -----------------------------------------------------------------------------
+//#define ADS1115_SERIAL_DEBUG
+
+
+class ADS1115 {
+ public:
+ ADS1115();
+ ADS1115(uint8_t address);
+
+ void initialize();
+ bool testConnection();
+
+ // SINGLE SHOT utilities
+ bool pollConversion(uint16_t max_retries);
+ void triggerConversion();
+
+ // Read the current CONVERSION register
+ int16_t getConversion(bool triggerAndPoll=true);
+
+ // Differential
+ int16_t getConversionP0N1();
+ int16_t getConversionP0N3();
+ int16_t getConversionP1N3();
+ int16_t getConversionP2N3();
+
+ // Single-ended
+ int16_t getConversionP0GND();
+ int16_t getConversionP1GND();
+ int16_t getConversionP2GND();
+ int16_t getConversionP3GND();
+
+ // Utility
+ float getMilliVolts(bool triggerAndPoll=true);
+ float getMvPerCount();
+
+ // CONFIG register
+ bool isConversionReady();
+ uint8_t getMultiplexer();
+ void setMultiplexer(uint8_t mux);
+ uint8_t getGain();
+ void setGain(uint8_t gain);
+ bool getMode();
+ void setMode(bool mode);
+ uint8_t getRate();
+ void setRate(uint8_t rate);
+ bool getComparatorMode();
+ void setComparatorMode(bool mode);
+ bool getComparatorPolarity();
+ void setComparatorPolarity(bool polarity);
+ bool getComparatorLatchEnabled();
+ void setComparatorLatchEnabled(bool enabled);
+ uint8_t getComparatorQueueMode();
+ void setComparatorQueueMode(uint8_t mode);
+ void setConversionReadyPinMode();
+
+ // *_THRESH registers
+ int16_t getLowThreshold();
+ void setLowThreshold(int16_t threshold);
+ int16_t getHighThreshold();
+ void setHighThreshold(int16_t threshold);
+
+ // DEBUG
+ void showConfigRegister();
+
+ private:
+ uint8_t devAddr;
+ uint16_t buffer[2];
+ bool devMode;
+ uint8_t muxMode;
+ uint8_t pgaMode;
+};
+
+#endif /* _ADS1115_H_ */
diff --git a/lib/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino b/lib/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino
new file mode 100644
index 000000000..a67b77bf0
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino
@@ -0,0 +1,91 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class
+// Example of reading two differential inputs of the ADS1115 and showing the value in mV
+// 06 May 2013 by Frederick Farzanegan (frederick1@farzanegan.org)
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+// 2013-05-13 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+#include "ADS1115.h"
+
+ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);
+
+void setup() {
+ Wire.begin(); // join I2C bus
+ Serial.begin(19200); // initialize serial communication
+ Serial.println("Initializing I2C devices...");
+ adc0.initialize(); // initialize ADS1115 16 bit A/D chip
+
+ Serial.println("Testing device connections...");
+ Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
+
+ // To get output from this method, you'll need to turn on the
+ //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file
+ adc0.showConfigRegister();
+
+ // We're going to do continuous sampling
+ adc0.setMode(ADS1115_MODE_CONTINUOUS);
+}
+
+void loop() {
+
+ // Sensor is on P0/N1 (pins 4/5)
+ Serial.println("Sensor 1 ************************");
+ // Set the gain (PGA) +/- 1.024v
+ adc0.setGain(ADS1115_PGA_1P024);
+
+ // Get the number of counts of the accumulator
+ Serial.print("Counts for sensor 1 is:");
+
+ // The below method sets the mux and gets a reading.
+ int sensorOneCounts=adc0.getConversionP0N1(); // counts up to 16-bits
+ Serial.println(sensorOneCounts);
+
+ // To turn the counts into a voltage, we can use
+ Serial.print("Voltage for sensor 1 is:");
+ Serial.println(sensorOneCounts*adc0.getMvPerCount());
+
+ Serial.println();
+
+
+ // 2nd sensor is on P2/N3 (pins 6/7)
+ Serial.println("Sensor 2 ************************");
+ // Set the gain (PGA) +/- 0.256v
+ adc0.setGain(ADS1115_PGA_0P256);
+
+ // Manually set the MUX // could have used the getConversionP* above
+ adc0.setMultiplexer(ADS1115_MUX_P2_N3);
+ Serial.print("Counts for sensor 2 is:");
+ Serial.println(adc0.getConversion());
+
+ Serial.print("mVoltage sensor 2 is:");
+ Serial.println(adc0.getMilliVolts()); // Convenience method to calculate voltage
+
+ Serial.println();
+
+ delay(500);
+}
+
diff --git a/lib/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino b/lib/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino
new file mode 100644
index 000000000..4059ac1eb
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino
@@ -0,0 +1,110 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class
+// Example of reading two differential inputs of the ADS1115 and showing the value in mV
+// 2016-03-22 by Eadf (https://github.com/eadf)
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+// 2016-03-22 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "ADS1115.h"
+
+ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);
+
+// Wire ADS1115 ALERT/RDY pin to Arduino pin 2
+const int alertReadyPin = 2;
+
+void setup() {
+ //I2Cdev::begin(); // join I2C bus
+ Wire.begin();
+ Serial.begin(115200); // initialize serial communication
+
+ Serial.println("Testing device connections...");
+ Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
+
+ adc0.initialize(); // initialize ADS1115 16 bit A/D chip
+
+ // We're going to do single shot sampling
+ adc0.setMode(ADS1115_MODE_SINGLESHOT);
+
+ // Slow things down so that we can see that the "poll for conversion" code works
+ adc0.setRate(ADS1115_RATE_8);
+
+ // Set the gain (PGA) +/- 6.144V
+ // Note that any analog input must be higher than –0.3V and less than VDD +0.3
+ adc0.setGain(ADS1115_PGA_6P144);
+ // ALERT/RDY pin will indicate when conversion is ready
+
+ pinMode(alertReadyPin,INPUT_PULLUP);
+ adc0.setConversionReadyPinMode();
+
+ // To get output from this method, you'll need to turn on the
+ //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file
+ #ifdef ADS1115_SERIAL_DEBUG
+ adc0.showConfigRegister();
+ Serial.print("HighThreshold="); Serial.println(adc0.getHighThreshold(),BIN);
+ Serial.print("LowThreshold="); Serial.println(adc0.getLowThreshold(),BIN);
+ #endif
+}
+
+/** Poll the assigned pin for conversion status
+ */
+void pollAlertReadyPin() {
+ for (uint32_t i = 0; i<100000; i++)
+ if (!digitalRead(alertReadyPin)) return;
+ Serial.println("Failed to wait for AlertReadyPin, it's stuck high!");
+}
+
+void loop() {
+
+ // The below method sets the mux and gets a reading.
+ adc0.setMultiplexer(ADS1115_MUX_P0_NG);
+ adc0.triggerConversion();
+ pollAlertReadyPin();
+ Serial.print("A0: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
+
+ adc0.setMultiplexer(ADS1115_MUX_P1_NG);
+ adc0.triggerConversion();
+ pollAlertReadyPin();
+ Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
+
+ adc0.setMultiplexer(ADS1115_MUX_P2_NG);
+ adc0.triggerConversion();
+ pollAlertReadyPin();
+ Serial.print("A2: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
+
+ adc0.setMultiplexer(ADS1115_MUX_P3_NG);
+ // Do conversion polling via I2C on this last reading:
+ Serial.print("A3: "); Serial.print(adc0.getMilliVolts(true)); Serial.print("mV");
+
+ Serial.println(digitalRead(alertReadyPin));
+ delay(500);
+}
+
+
+
+
+
diff --git a/lib/I2Cdevlib-ADS1115/library.json b/lib/I2Cdevlib-ADS1115/library.json
new file mode 100644
index 000000000..e3e65531b
--- /dev/null
+++ b/lib/I2Cdevlib-ADS1115/library.json
@@ -0,0 +1,18 @@
+{
+ "name": "I2Cdevlib-ADS1115",
+ "keywords": "MUX, PGA, comparator, oscillator, reference, i2cdevlib, i2c",
+ "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference",
+ "include": "Arduino/ADS1115",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/jrowberg/i2cdevlib.git"
+ },
+ "dependencies":
+ {
+ "name": "I2Cdevlib-Core",
+ "frameworks": "arduino"
+ },
+ "frameworks": "arduino",
+ "platforms": "atmelavr"
+}
diff --git a/lib/I2Cdevlib-Core/.library.json b/lib/I2Cdevlib-Core/.library.json
new file mode 100644
index 000000000..258acc176
--- /dev/null
+++ b/lib/I2Cdevlib-Core/.library.json
@@ -0,0 +1,31 @@
+{
+ "name": "I2Cdevlib-Core",
+ "repository": {
+ "url": "https://github.com/jrowberg/i2cdevlib.git",
+ "type": "git"
+ },
+ "platforms": [
+ "atmelavr"
+ ],
+ "frameworks": [
+ "arduino"
+ ],
+ "version": "6744ce0ac4",
+ "export": {
+ "include": "Arduino/I2Cdev"
+ },
+ "authors": [
+ {
+ "maintainer": false,
+ "name": "Jeff Rowberg",
+ "url": "https://github.com/jrowberg",
+ "email": "jeff@rowberg.net"
+ }
+ ],
+ "keywords": [
+ "i2cdevlib",
+ "i2c"
+ ],
+ "id": 11,
+ "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices."
+}
\ No newline at end of file
diff --git a/lib/I2Cdevlib-Core/I2Cdev.cpp b/lib/I2Cdevlib-Core/I2Cdev.cpp
new file mode 100644
index 000000000..db173b55a
--- /dev/null
+++ b/lib/I2Cdevlib-Core/I2Cdev.cpp
@@ -0,0 +1,1457 @@
+// I2Cdev library collection - Main I2C device class
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 2013-06-05 by Jeff Rowberg
+//
+// Changelog:
+// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications
+// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan)
+// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire
+// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation
+// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums)
+// 2011-10-03 - added automatic Arduino version detection for ease of use
+// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications
+// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x)
+// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default
+// 2011-08-02 - added support for 16-bit registers
+// - fixed incorrect Doxygen comments on some methods
+// - added timeout value for read operations (thanks mem @ Arduino forums)
+// 2011-07-30 - changed read/write function structures to return success or byte counts
+// - made all methods static for multi-device memory savings
+// 2011-07-28 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "I2Cdev.h"
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+
+ #ifdef I2CDEV_IMPLEMENTATION_WARNINGS
+ #if ARDUINO < 100
+ #warning Using outdated Arduino IDE with Wire library is functionally limiting.
+ #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended.
+ #warning This I2Cdev implementation does not support:
+ #warning - Repeated starts conditions
+ #warning - Timeout detection (some Wire requests block forever)
+ #elif ARDUINO == 100
+ #warning Using outdated Arduino IDE with Wire library is functionally limiting.
+ #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended.
+ #warning This I2Cdev implementation does not support:
+ #warning - Repeated starts conditions
+ #warning - Timeout detection (some Wire requests block forever)
+ #elif ARDUINO > 100
+ /*#warning Using current Arduino IDE with Wire library is functionally limiting.
+ #warning Arduino IDE v1.6.5+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended.
+ #warning This I2Cdev implementation does not support:
+ #warning - Timeout detection (some Wire requests block forever)*/
+ #endif
+ #endif
+
+#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+
+ //#error The I2CDEV_BUILTIN_FASTWIRE implementation is known to be broken right now. Patience, Iago!
+
+#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
+
+ #ifdef I2CDEV_IMPLEMENTATION_WARNINGS
+ #warning Using I2CDEV_BUILTIN_NBWIRE implementation may adversely affect interrupt detection.
+ #warning This I2Cdev implementation does not support:
+ #warning - Repeated starts conditions
+ #endif
+
+ // NBWire implementation based heavily on code by Gene Knight
+ // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html
+ // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html
+ TwoWire Wire;
+
+#endif
+
+/** Default constructor.
+ */
+I2Cdev::I2Cdev() {
+}
+
+/** Read a single bit from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitNum Bit position to read (0-7)
+ * @param data Container for single bit value
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) {
+ uint8_t b;
+ uint8_t count = readByte(devAddr, regAddr, &b, timeout);
+ *data = b & (1 << bitNum);
+ return count;
+}
+
+/** Read a single bit from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitNum Bit position to read (0-15)
+ * @param data Container for single bit value
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) {
+ uint16_t b;
+ uint8_t count = readWord(devAddr, regAddr, &b, timeout);
+ *data = b & (1 << bitNum);
+ return count;
+}
+
+/** Read multiple bits from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-7)
+ * @param length Number of bits to read (not more than 8)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) {
+ // 01101001 read byte
+ // 76543210 bit numbers
+ // xxx args: bitStart=4, length=3
+ // 010 masked
+ // -> 010 shifted
+ uint8_t count, b;
+ if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) {
+ uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+ b &= mask;
+ b >>= (bitStart - length + 1);
+ *data = b;
+ }
+ return count;
+}
+
+/** Read multiple bits from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-15)
+ * @param length Number of bits to read (not more than 16)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (1 = success, 0 = failure, -1 = timeout)
+ */
+int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) {
+ // 1101011001101001 read byte
+ // fedcba9876543210 bit numbers
+ // xxx args: bitStart=12, length=3
+ // 010 masked
+ // -> 010 shifted
+ uint8_t count;
+ uint16_t w;
+ if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) {
+ uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+ w &= mask;
+ w >>= (bitStart - length + 1);
+ *data = w;
+ }
+ return count;
+}
+
+/** Read single byte from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param data Container for byte value read from device
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) {
+ return readBytes(devAddr, regAddr, 1, data, timeout);
+}
+
+/** Read single word from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param data Container for word value read from device
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) {
+ return readWords(devAddr, regAddr, 1, data, timeout);
+}
+
+/** Read multiple bytes from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register regAddr to read from
+ * @param length Number of bytes to read
+ * @param data Buffer to store read data in
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Number of bytes read (-1 indicates failure)
+ */
+int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print("I2C (0x");
+ Serial.print(devAddr, HEX);
+ Serial.print(") reading ");
+ Serial.print(length, DEC);
+ Serial.print(" bytes from 0x");
+ Serial.print(regAddr, HEX);
+ Serial.print("...");
+ #endif
+
+ int8_t count = 0;
+ uint32_t t1 = millis();
+
+ #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE)
+
+ #if (ARDUINO < 100)
+ // Arduino v00xx (before v1.0), Wire library
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.send(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH));
+
+ for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) {
+ data[count] = Wire.receive();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ }
+
+ Wire.endTransmission();
+ }
+ #elif (ARDUINO == 100)
+ // Arduino v1.0.0, Wire library
+ // Adds standardized write() and read() stream methods instead of send() and receive()
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.write(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH));
+
+ for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) {
+ data[count] = Wire.read();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ }
+
+ Wire.endTransmission();
+ }
+ #elif (ARDUINO > 100)
+ // Arduino v1.0.1+, Wire library
+ // Adds official support for repeated start condition, yay!
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.write(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH));
+
+ for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) {
+ data[count] = Wire.read();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ }
+ }
+ #endif
+
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+
+ // Fastwire library
+ // no loop required for fastwire
+ uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, data, length);
+ if (status == 0) {
+ count = length; // success
+ } else {
+ count = -1; // error
+ }
+
+ #endif
+
+ // check for timeout
+ if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout
+
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(". Done (");
+ Serial.print(count, DEC);
+ Serial.println(" read).");
+ #endif
+
+ return count;
+}
+
+/** Read multiple words from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register regAddr to read from
+ * @param length Number of words to read
+ * @param data Buffer to store read data in
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Number of words read (-1 indicates failure)
+ */
+int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print("I2C (0x");
+ Serial.print(devAddr, HEX);
+ Serial.print(") reading ");
+ Serial.print(length, DEC);
+ Serial.print(" words from 0x");
+ Serial.print(regAddr, HEX);
+ Serial.print("...");
+ #endif
+
+ int8_t count = 0;
+ uint32_t t1 = millis();
+
+ #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE)
+
+ #if (ARDUINO < 100)
+ // Arduino v00xx (before v1.0), Wire library
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.send(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes
+
+ bool msb = true; // starts with MSB, then LSB
+ for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) {
+ if (msb) {
+ // first byte is bits 15-8 (MSb=15)
+ data[count] = Wire.receive() << 8;
+ } else {
+ // second byte is bits 7-0 (LSb=0)
+ data[count] |= Wire.receive();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ count++;
+ }
+ msb = !msb;
+ }
+
+ Wire.endTransmission();
+ }
+ #elif (ARDUINO == 100)
+ // Arduino v1.0.0, Wire library
+ // Adds standardized write() and read() stream methods instead of send() and receive()
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.write(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes
+
+ bool msb = true; // starts with MSB, then LSB
+ for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) {
+ if (msb) {
+ // first byte is bits 15-8 (MSb=15)
+ data[count] = Wire.read() << 8;
+ } else {
+ // second byte is bits 7-0 (LSb=0)
+ data[count] |= Wire.read();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ count++;
+ }
+ msb = !msb;
+ }
+
+ Wire.endTransmission();
+ }
+ #elif (ARDUINO > 100)
+ // Arduino v1.0.1+, Wire library
+ // Adds official support for repeated start condition, yay!
+
+ // I2C/TWI subsystem uses internal buffer that breaks with large data requests
+ // so if user requests more than BUFFER_LENGTH bytes, we have to do it in
+ // smaller chunks instead of all at once
+ for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) {
+ Wire.beginTransmission(devAddr);
+ Wire.write(regAddr);
+ Wire.endTransmission();
+ Wire.beginTransmission(devAddr);
+ Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes
+
+ bool msb = true; // starts with MSB, then LSB
+ for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) {
+ if (msb) {
+ // first byte is bits 15-8 (MSb=15)
+ data[count] = Wire.read() << 8;
+ } else {
+ // second byte is bits 7-0 (LSb=0)
+ data[count] |= Wire.read();
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[count], HEX);
+ if (count + 1 < length) Serial.print(" ");
+ #endif
+ count++;
+ }
+ msb = !msb;
+ }
+
+ Wire.endTransmission();
+ }
+ #endif
+
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+
+ // Fastwire library
+ // no loop required for fastwire
+ uint16_t intermediate[(uint8_t)length];
+ uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, (uint8_t *)intermediate, (uint8_t)(length * 2));
+ if (status == 0) {
+ count = length; // success
+ for (uint8_t i = 0; i < length; i++) {
+ data[i] = (intermediate[2*i] << 8) | intermediate[2*i + 1];
+ }
+ } else {
+ count = -1; // error
+ }
+
+ #endif
+
+ if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout
+
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(". Done (");
+ Serial.print(count, DEC);
+ Serial.println(" read).");
+ #endif
+
+ return count;
+}
+
+/** write a single bit in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitNum Bit position to write (0-7)
+ * @param value New bit value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) {
+ uint8_t b;
+ readByte(devAddr, regAddr, &b);
+ b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
+ return writeByte(devAddr, regAddr, b);
+}
+
+/** write a single bit in a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitNum Bit position to write (0-15)
+ * @param value New bit value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) {
+ uint16_t w;
+ readWord(devAddr, regAddr, &w);
+ w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum));
+ return writeWord(devAddr, regAddr, w);
+}
+
+/** Write multiple bits in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitStart First bit position to write (0-7)
+ * @param length Number of bits to write (not more than 8)
+ * @param data Right-aligned value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
+ // 010 value to write
+ // 76543210 bit numbers
+ // xxx args: bitStart=4, length=3
+ // 00011100 mask byte
+ // 10101111 original value (sample)
+ // 10100011 original & ~mask
+ // 10101011 masked | value
+ uint8_t b;
+ if (readByte(devAddr, regAddr, &b) != 0) {
+ uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+ data <<= (bitStart - length + 1); // shift data into correct position
+ data &= mask; // zero all non-important bits in data
+ b &= ~(mask); // zero all important bits in existing byte
+ b |= data; // combine data with existing byte
+ return writeByte(devAddr, regAddr, b);
+ } else {
+ return false;
+ }
+}
+
+/** Write multiple bits in a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitStart First bit position to write (0-15)
+ * @param length Number of bits to write (not more than 16)
+ * @param data Right-aligned value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) {
+ // 010 value to write
+ // fedcba9876543210 bit numbers
+ // xxx args: bitStart=12, length=3
+ // 0001110000000000 mask word
+ // 1010111110010110 original value (sample)
+ // 1010001110010110 original & ~mask
+ // 1010101110010110 masked | value
+ uint16_t w;
+ if (readWord(devAddr, regAddr, &w) != 0) {
+ uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+ data <<= (bitStart - length + 1); // shift data into correct position
+ data &= mask; // zero all non-important bits in data
+ w &= ~(mask); // zero all important bits in existing word
+ w |= data; // combine data with existing word
+ return writeWord(devAddr, regAddr, w);
+ } else {
+ return false;
+ }
+}
+
+/** Write single byte to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New byte value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
+ return writeBytes(devAddr, regAddr, 1, &data);
+}
+
+/** Write single word to a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New word value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) {
+ return writeWords(devAddr, regAddr, 1, &data);
+}
+
+/** Write multiple bytes to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register address to write to
+ * @param length Number of bytes to write
+ * @param data Buffer to copy new data from
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print("I2C (0x");
+ Serial.print(devAddr, HEX);
+ Serial.print(") writing ");
+ Serial.print(length, DEC);
+ Serial.print(" bytes to 0x");
+ Serial.print(regAddr, HEX);
+ Serial.print("...");
+ #endif
+ uint8_t status = 0;
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.beginTransmission(devAddr);
+ Wire.send((uint8_t) regAddr); // send address
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ Wire.beginTransmission(devAddr);
+ Wire.write((uint8_t) regAddr); // send address
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::beginTransmission(devAddr);
+ Fastwire::write(regAddr);
+ #endif
+ for (uint8_t i = 0; i < length; i++) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[i], HEX);
+ if (i + 1 < length) Serial.print(" ");
+ #endif
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.send((uint8_t) data[i]);
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ Wire.write((uint8_t) data[i]);
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::write((uint8_t) data[i]);
+ #endif
+ }
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.endTransmission();
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ status = Wire.endTransmission();
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::stop();
+ //status = Fastwire::endTransmission();
+ #endif
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.println(". Done.");
+ #endif
+ return status == 0;
+}
+
+/** Write multiple words to a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register address to write to
+ * @param length Number of words to write
+ * @param data Buffer to copy new data from
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print("I2C (0x");
+ Serial.print(devAddr, HEX);
+ Serial.print(") writing ");
+ Serial.print(length, DEC);
+ Serial.print(" words to 0x");
+ Serial.print(regAddr, HEX);
+ Serial.print("...");
+ #endif
+ uint8_t status = 0;
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.beginTransmission(devAddr);
+ Wire.send(regAddr); // send address
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ Wire.beginTransmission(devAddr);
+ Wire.write(regAddr); // send address
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::beginTransmission(devAddr);
+ Fastwire::write(regAddr);
+ #endif
+ for (uint8_t i = 0; i < length * 2; i++) {
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.print(data[i], HEX);
+ if (i + 1 < length) Serial.print(" ");
+ #endif
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.send((uint8_t)(data[i] >> 8)); // send MSB
+ Wire.send((uint8_t)data[i++]); // send LSB
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ Wire.write((uint8_t)(data[i] >> 8)); // send MSB
+ Wire.write((uint8_t)data[i++]); // send LSB
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB
+ status = Fastwire::write((uint8_t)data[i++]); // send LSB
+ if (status != 0) break;
+ #endif
+ }
+ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE)
+ Wire.endTransmission();
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100)
+ status = Wire.endTransmission();
+ #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE)
+ Fastwire::stop();
+ //status = Fastwire::endTransmission();
+ #endif
+ #ifdef I2CDEV_SERIAL_DEBUG
+ Serial.println(". Done.");
+ #endif
+ return status == 0;
+}
+
+/** Default timeout value for read operations.
+ * Set this to 0 to disable timeout detection.
+ */
+uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT;
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+ // I2C library
+ //////////////////////
+ // Copyright(C) 2012
+ // Francesco Ferrara
+ // ferrara[at]libero[point]it
+ //////////////////////
+
+ /*
+ FastWire
+ - 0.24 added stop
+ - 0.23 added reset
+
+ This is a library to help faster programs to read I2C devices.
+ Copyright(C) 2012 Francesco Ferrara
+ occhiobello at gmail dot com
+ [used by Jeff Rowberg for I2Cdevlib with permission]
+ */
+
+ boolean Fastwire::waitInt() {
+ int l = 250;
+ while (!(TWCR & (1 << TWINT)) && l-- > 0);
+ return l > 0;
+ }
+
+ void Fastwire::setup(int khz, boolean pullup) {
+ TWCR = 0;
+ #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
+ // activate internal pull-ups for twi (PORTC bits 4 & 5)
+ // as per note from atmega8 manual pg167
+ if (pullup) PORTC |= ((1 << 4) | (1 << 5));
+ else PORTC &= ~((1 << 4) | (1 << 5));
+ #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
+ // activate internal pull-ups for twi (PORTC bits 0 & 1)
+ if (pullup) PORTC |= ((1 << 0) | (1 << 1));
+ else PORTC &= ~((1 << 0) | (1 << 1));
+ #else
+ // activate internal pull-ups for twi (PORTD bits 0 & 1)
+ // as per note from atmega128 manual pg204
+ if (pullup) PORTD |= ((1 << 0) | (1 << 1));
+ else PORTD &= ~((1 << 0) | (1 << 1));
+ #endif
+
+ TWSR = 0; // no prescaler => prescaler = 1
+ TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate
+ TWCR = 1 << TWEN; // enable twi module, no interrupt
+ }
+
+ // added by Jeff Rowberg 2013-05-07:
+ // Arduino Wire-style "beginTransmission" function
+ // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1)
+ byte Fastwire::beginTransmission(byte device) {
+ byte twst, retry;
+ retry = 2;
+ do {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA);
+ if (!waitInt()) return 1;
+ twst = TWSR & 0xF8;
+ if (twst != TW_START && twst != TW_REP_START) return 2;
+
+ //Serial.print(device, HEX);
+ //Serial.print(" ");
+ TWDR = device << 1; // send device address without read bit (1)
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 3;
+ twst = TWSR & 0xF8;
+ } while (twst == TW_MT_SLA_NACK && retry-- > 0);
+ if (twst != TW_MT_SLA_ACK) return 4;
+ return 0;
+ }
+
+ byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) {
+ byte twst, retry;
+
+ retry = 2;
+ do {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA);
+ if (!waitInt()) return 1;
+ twst = TWSR & 0xF8;
+ if (twst != TW_START && twst != TW_REP_START) return 2;
+
+ //Serial.print(device, HEX);
+ //Serial.print(" ");
+ TWDR = device & 0xFE; // send device address without read bit (1)
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 3;
+ twst = TWSR & 0xF8;
+ } while (twst == TW_MT_SLA_NACK && retry-- > 0);
+ if (twst != TW_MT_SLA_ACK) return 4;
+
+ //Serial.print(address, HEX);
+ //Serial.print(" ");
+ TWDR = address; // send data to the previously addressed device
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 5;
+ twst = TWSR & 0xF8;
+ if (twst != TW_MT_DATA_ACK) return 6;
+
+ for (byte i = 0; i < num; i++) {
+ //Serial.print(data[i], HEX);
+ //Serial.print(" ");
+ TWDR = data[i]; // send data to the previously addressed device
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 7;
+ twst = TWSR & 0xF8;
+ if (twst != TW_MT_DATA_ACK) return 8;
+ }
+ //Serial.print("\n");
+
+ return 0;
+ }
+
+ byte Fastwire::write(byte value) {
+ byte twst;
+ //Serial.println(value, HEX);
+ TWDR = value; // send data
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 1;
+ twst = TWSR & 0xF8;
+ if (twst != TW_MT_DATA_ACK) return 2;
+ return 0;
+ }
+
+ byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) {
+ byte twst, retry;
+
+ retry = 2;
+ do {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA);
+ if (!waitInt()) return 16;
+ twst = TWSR & 0xF8;
+ if (twst != TW_START && twst != TW_REP_START) return 17;
+
+ //Serial.print(device, HEX);
+ //Serial.print(" ");
+ TWDR = device & 0xfe; // send device address to write
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 18;
+ twst = TWSR & 0xF8;
+ } while (twst == TW_MT_SLA_NACK && retry-- > 0);
+ if (twst != TW_MT_SLA_ACK) return 19;
+
+ //Serial.print(address, HEX);
+ //Serial.print(" ");
+ TWDR = address; // send data to the previously addressed device
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 20;
+ twst = TWSR & 0xF8;
+ if (twst != TW_MT_DATA_ACK) return 21;
+
+ /***/
+
+ retry = 2;
+ do {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA);
+ if (!waitInt()) return 22;
+ twst = TWSR & 0xF8;
+ if (twst != TW_START && twst != TW_REP_START) return 23;
+
+ //Serial.print(device, HEX);
+ //Serial.print(" ");
+ TWDR = device | 0x01; // send device address with the read bit (1)
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ if (!waitInt()) return 24;
+ twst = TWSR & 0xF8;
+ } while (twst == TW_MR_SLA_NACK && retry-- > 0);
+ if (twst != TW_MR_SLA_ACK) return 25;
+
+ for (uint8_t i = 0; i < num; i++) {
+ if (i == num - 1)
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ else
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
+ if (!waitInt()) return 26;
+ twst = TWSR & 0xF8;
+ if (twst != TW_MR_DATA_ACK && twst != TW_MR_DATA_NACK) return twst;
+ data[i] = TWDR;
+ //Serial.print(data[i], HEX);
+ //Serial.print(" ");
+ }
+ //Serial.print("\n");
+ stop();
+
+ return 0;
+ }
+
+ void Fastwire::reset() {
+ TWCR = 0;
+ }
+
+ byte Fastwire::stop() {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
+ if (!waitInt()) return 1;
+ return 0;
+ }
+#endif
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
+ // NBWire implementation based heavily on code by Gene Knight
+ // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html
+ // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html
+
+ /*
+ call this version 1.0
+
+ Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer
+ length and index are set *before* the data is actually read. The problem is that these
+ are variables local to the TwoWire object, and by the time we actually have read the
+ data, and know what the length actually is, we have no simple access to the object's
+ variables. The actual bytes read *is* given to the callback function, though.
+
+ The ISR code for a slave receiver is commented out. I don't have that setup, and can't
+ verify it at this time. Save it for 2.0!
+
+ The handling of the read and write processes here is much like in the demo sketch code:
+ the process is broken down into sequential functions, where each registers the next as a
+ callback, essentially.
+
+ For example, for the Read process, twi_read00 just returns if TWI is not yet in a
+ ready state. When there's another interrupt, and the interface *is* ready, then it
+ sets up the read, starts it, and registers twi_read01 as the function to call after
+ the *next* interrupt. twi_read01, then, just returns if the interface is still in a
+ "reading" state. When the reading is done, it copies the information to the buffer,
+ cleans up, and calls the user-requested callback function with the actual number of
+ bytes read.
+
+ The writing is similar.
+
+ Questions, comments and problems can go to Gene@Telobot.com.
+
+ Thumbs Up!
+ Gene Knight
+
+ */
+
+ uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH];
+ uint8_t TwoWire::rxBufferIndex = 0;
+ uint8_t TwoWire::rxBufferLength = 0;
+
+ uint8_t TwoWire::txAddress = 0;
+ uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH];
+ uint8_t TwoWire::txBufferIndex = 0;
+ uint8_t TwoWire::txBufferLength = 0;
+
+ //uint8_t TwoWire::transmitting = 0;
+ void (*TwoWire::user_onRequest)(void);
+ void (*TwoWire::user_onReceive)(int);
+
+ static volatile uint8_t twi_transmitting;
+ static volatile uint8_t twi_state;
+ static uint8_t twi_slarw;
+ static volatile uint8_t twi_error;
+ static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
+ static volatile uint8_t twi_masterBufferIndex;
+ static uint8_t twi_masterBufferLength;
+ static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
+ static volatile uint8_t twi_rxBufferIndex;
+ //static volatile uint8_t twi_Interrupt_Continue_Command;
+ static volatile uint8_t twi_Return_Value;
+ static volatile uint8_t twi_Done;
+ void (*twi_cbendTransmissionDone)(int);
+ void (*twi_cbreadFromDone)(int);
+
+ void twi_init() {
+ // initialize state
+ twi_state = TWI_READY;
+
+ // activate internal pull-ups for twi
+ // as per note from atmega8 manual pg167
+ sbi(PORTC, 4);
+ sbi(PORTC, 5);
+
+ // initialize twi prescaler and bit rate
+ cbi(TWSR, TWPS0); // TWI Status Register - Prescaler bits
+ cbi(TWSR, TWPS1);
+
+ /* twi bit rate formula from atmega128 manual pg 204
+ SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
+ note: TWBR should be 10 or higher for master mode
+ It is 72 for a 16mhz Wiring board with 100kHz TWI */
+
+ TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register
+ // enable twi module, acks, and twi interrupt
+
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
+
+ /* TWEN - TWI Enable Bit
+ TWIE - TWI Interrupt Enable
+ TWEA - TWI Enable Acknowledge Bit
+ TWINT - TWI Interrupt Flag
+ TWSTA - TWI Start Condition
+ */
+ }
+
+ typedef struct {
+ uint8_t address;
+ uint8_t* data;
+ uint8_t length;
+ uint8_t wait;
+ uint8_t i;
+ } twi_Write_Vars;
+
+ twi_Write_Vars *ptwv = 0;
+ static void (*fNextInterruptFunction)(void) = 0;
+
+ void twi_Finish(byte bRetVal) {
+ if (ptwv) {
+ free(ptwv);
+ ptwv = 0;
+ }
+ twi_Done = 0xFF;
+ twi_Return_Value = bRetVal;
+ fNextInterruptFunction = 0;
+ }
+
+ uint8_t twii_WaitForDone(uint16_t timeout) {
+ uint32_t endMillis = millis() + timeout;
+ while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue;
+ return twi_Return_Value;
+ }
+
+ void twii_SetState(uint8_t ucState) {
+ twi_state = ucState;
+ }
+
+ void twii_SetError(uint8_t ucError) {
+ twi_error = ucError ;
+ }
+
+ void twii_InitBuffer(uint8_t ucPos, uint8_t ucLength) {
+ twi_masterBufferIndex = 0;
+ twi_masterBufferLength = ucLength;
+ }
+
+ void twii_CopyToBuf(uint8_t* pData, uint8_t ucLength) {
+ uint8_t i;
+ for (i = 0; i < ucLength; ++i) {
+ twi_masterBuffer[i] = pData[i];
+ }
+ }
+
+ void twii_CopyFromBuf(uint8_t *pData, uint8_t ucLength) {
+ uint8_t i;
+ for (i = 0; i < ucLength; ++i) {
+ pData[i] = twi_masterBuffer[i];
+ }
+ }
+
+ void twii_SetSlaRW(uint8_t ucSlaRW) {
+ twi_slarw = ucSlaRW;
+ }
+
+ void twii_SetStart() {
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
+ }
+
+ void twi_write01() {
+ if (TWI_MTX == twi_state) return; // blocking test
+ twi_transmitting = 0 ;
+ if (twi_error == 0xFF)
+ twi_Finish (0); // success
+ else if (twi_error == TW_MT_SLA_NACK)
+ twi_Finish (2); // error: address send, nack received
+ else if (twi_error == TW_MT_DATA_NACK)
+ twi_Finish (3); // error: data send, nack received
+ else
+ twi_Finish (4); // other twi error
+ if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value);
+ return;
+ }
+
+
+ void twi_write00() {
+ if (TWI_READY != twi_state) return; // blocking test
+ if (TWI_BUFFER_LENGTH < ptwv -> length) {
+ twi_Finish(1); // end write with error 1
+ return;
+ }
+ twi_Done = 0x00; // show as working
+ twii_SetState(TWI_MTX); // to transmitting
+ twii_SetError(0xFF); // to No Error
+ twii_InitBuffer(0, ptwv -> length); // pointer and length
+ twii_CopyToBuf(ptwv -> data, ptwv -> length); // get the data
+ twii_SetSlaRW((ptwv -> address << 1) | TW_WRITE); // write command
+ twii_SetStart(); // start the cycle
+ fNextInterruptFunction = twi_write01; // next routine
+ return twi_write01();
+ }
+
+ void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) {
+ uint8_t i;
+ ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars));
+ ptwv -> address = address;
+ ptwv -> data = data;
+ ptwv -> length = length;
+ ptwv -> wait = wait;
+ fNextInterruptFunction = twi_write00;
+ return twi_write00();
+ }
+
+ void twi_read01() {
+ if (TWI_MRX == twi_state) return; // blocking test
+ if (twi_masterBufferIndex < ptwv -> length) ptwv -> length = twi_masterBufferIndex;
+ twii_CopyFromBuf(ptwv -> data, ptwv -> length);
+ twi_Finish(ptwv -> length);
+ if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value);
+ return;
+ }
+
+ void twi_read00() {
+ if (TWI_READY != twi_state) return; // blocking test
+ if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return
+ twi_Done = 0x00; // show as working
+ twii_SetState(TWI_MRX); // reading
+ twii_SetError(0xFF); // reset error
+ twii_InitBuffer(0, ptwv -> length - 1); // init to one less than length
+ twii_SetSlaRW((ptwv -> address << 1) | TW_READ); // read command
+ twii_SetStart(); // start cycle
+ fNextInterruptFunction = twi_read01;
+ return twi_read01();
+ }
+
+ void twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) {
+ uint8_t i;
+
+ ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars));
+ ptwv -> address = address;
+ ptwv -> data = data;
+ ptwv -> length = length;
+ fNextInterruptFunction = twi_read00;
+ return twi_read00();
+ }
+
+ void twi_reply(uint8_t ack) {
+ // transmit master read ready signal, with or without ack
+ if (ack){
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
+ } else {
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
+ }
+ }
+
+ void twi_stop(void) {
+ // send stop condition
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
+
+ // wait for stop condition to be exectued on bus
+ // TWINT is not set after a stop condition!
+ while (TWCR & _BV(TWSTO)) {
+ continue;
+ }
+
+ // update twi state
+ twi_state = TWI_READY;
+ }
+
+ void twi_releaseBus(void) {
+ // release bus
+ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
+
+ // update twi state
+ twi_state = TWI_READY;
+ }
+
+ SIGNAL(TWI_vect) {
+ switch (TW_STATUS) {
+ // All Master
+ case TW_START: // sent start condition
+ case TW_REP_START: // sent repeated start condition
+ // copy device address and r/w bit to output register and ack
+ TWDR = twi_slarw;
+ twi_reply(1);
+ break;
+
+ // Master Transmitter
+ case TW_MT_SLA_ACK: // slave receiver acked address
+ case TW_MT_DATA_ACK: // slave receiver acked data
+ // if there is data to send, send it, otherwise stop
+ if (twi_masterBufferIndex < twi_masterBufferLength) {
+ // copy data to output register and ack
+ TWDR = twi_masterBuffer[twi_masterBufferIndex++];
+ twi_reply(1);
+ } else {
+ twi_stop();
+ }
+ break;
+
+ case TW_MT_SLA_NACK: // address sent, nack received
+ twi_error = TW_MT_SLA_NACK;
+ twi_stop();
+ break;
+
+ case TW_MT_DATA_NACK: // data sent, nack received
+ twi_error = TW_MT_DATA_NACK;
+ twi_stop();
+ break;
+
+ case TW_MT_ARB_LOST: // lost bus arbitration
+ twi_error = TW_MT_ARB_LOST;
+ twi_releaseBus();
+ break;
+
+ // Master Receiver
+ case TW_MR_DATA_ACK: // data received, ack sent
+ // put byte into buffer
+ twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
+
+ case TW_MR_SLA_ACK: // address sent, ack received
+ // ack if more bytes are expected, otherwise nack
+ if (twi_masterBufferIndex < twi_masterBufferLength) {
+ twi_reply(1);
+ } else {
+ twi_reply(0);
+ }
+ break;
+
+ case TW_MR_DATA_NACK: // data received, nack sent
+ // put final byte into buffer
+ twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
+
+ case TW_MR_SLA_NACK: // address sent, nack received
+ twi_stop();
+ break;
+
+ // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case
+
+ // Slave Receiver (NOT IMPLEMENTED YET)
+ /*
+ case TW_SR_SLA_ACK: // addressed, returned ack
+ case TW_SR_GCALL_ACK: // addressed generally, returned ack
+ case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
+ case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
+ // enter slave receiver mode
+ twi_state = TWI_SRX;
+
+ // indicate that rx buffer can be overwritten and ack
+ twi_rxBufferIndex = 0;
+ twi_reply(1);
+ break;
+
+ case TW_SR_DATA_ACK: // data received, returned ack
+ case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
+ // if there is still room in the rx buffer
+ if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) {
+ // put byte in buffer and ack
+ twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
+ twi_reply(1);
+ } else {
+ // otherwise nack
+ twi_reply(0);
+ }
+ break;
+
+ case TW_SR_STOP: // stop or repeated start condition received
+ // put a null char after data if there's room
+ if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) {
+ twi_rxBuffer[twi_rxBufferIndex] = 0;
+ }
+
+ // sends ack and stops interface for clock stretching
+ twi_stop();
+
+ // callback to user defined callback
+ twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
+
+ // since we submit rx buffer to "wire" library, we can reset it
+ twi_rxBufferIndex = 0;
+
+ // ack future responses and leave slave receiver state
+ twi_releaseBus();
+ break;
+
+ case TW_SR_DATA_NACK: // data received, returned nack
+ case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
+ // nack back at master
+ twi_reply(0);
+ break;
+
+ // Slave Transmitter
+ case TW_ST_SLA_ACK: // addressed, returned ack
+ case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
+ // enter slave transmitter mode
+ twi_state = TWI_STX;
+
+ // ready the tx buffer index for iteration
+ twi_txBufferIndex = 0;
+
+ // set tx buffer length to be zero, to verify if user changes it
+ twi_txBufferLength = 0;
+
+ // request for txBuffer to be filled and length to be set
+ // note: user must call twi_transmit(bytes, length) to do this
+ twi_onSlaveTransmit();
+
+ // if they didn't change buffer & length, initialize it
+ if (0 == twi_txBufferLength) {
+ twi_txBufferLength = 1;
+ twi_txBuffer[0] = 0x00;
+ }
+
+ // transmit first byte from buffer, fall through
+
+ case TW_ST_DATA_ACK: // byte sent, ack returned
+ // copy data to output register
+ TWDR = twi_txBuffer[twi_txBufferIndex++];
+
+ // if there is more to send, ack, otherwise nack
+ if (twi_txBufferIndex < twi_txBufferLength) {
+ twi_reply(1);
+ } else {
+ twi_reply(0);
+ }
+ break;
+
+ case TW_ST_DATA_NACK: // received nack, we are done
+ case TW_ST_LAST_DATA: // received ack, but we are done already!
+ // ack future responses
+ twi_reply(1);
+ // leave slave receiver state
+ twi_state = TWI_READY;
+ break;
+ */
+
+ // all
+ case TW_NO_INFO: // no state information
+ break;
+
+ case TW_BUS_ERROR: // bus error, illegal stop/start
+ twi_error = TW_BUS_ERROR;
+ twi_stop();
+ break;
+ }
+
+ if (fNextInterruptFunction) return fNextInterruptFunction();
+ }
+
+ TwoWire::TwoWire() { }
+
+ void TwoWire::begin(void) {
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ twi_init();
+ }
+
+ void TwoWire::beginTransmission(uint8_t address) {
+ //beginTransmission((uint8_t)address);
+
+ // indicate that we are transmitting
+ twi_transmitting = 1;
+
+ // set address of targeted slave
+ txAddress = address;
+
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ }
+
+ uint8_t TwoWire::endTransmission(uint16_t timeout) {
+ // transmit buffer (blocking)
+ //int8_t ret =
+ twi_cbendTransmissionDone = NULL;
+ twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
+ int8_t ret = twii_WaitForDone(timeout);
+
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ // indicate that we are done transmitting
+ // twi_transmitting = 0;
+ return ret;
+ }
+
+ void TwoWire::nbendTransmission(void (*function)(int)) {
+ twi_cbendTransmissionDone = function;
+ twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
+ return;
+ }
+
+ void TwoWire::send(uint8_t data) {
+ if (twi_transmitting) {
+ // in master transmitter mode
+ // don't bother if buffer is full
+ if (txBufferLength >= NBWIRE_BUFFER_LENGTH) {
+ return;
+ }
+
+ // put byte in tx buffer
+ txBuffer[txBufferIndex] = data;
+ ++txBufferIndex;
+
+ // update amount in buffer
+ txBufferLength = txBufferIndex;
+ } else {
+ // in slave send mode
+ // reply to master
+ //twi_transmit(&data, 1);
+ }
+ }
+
+ uint8_t TwoWire::receive(void) {
+ // default to returning null char
+ // for people using with char strings
+ uint8_t value = 0;
+
+ // get each successive byte on each call
+ if (rxBufferIndex < rxBufferLength) {
+ value = rxBuffer[rxBufferIndex];
+ ++rxBufferIndex;
+ }
+
+ return value;
+ }
+
+ uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) {
+ // clamp to buffer length
+ if (quantity > NBWIRE_BUFFER_LENGTH) {
+ quantity = NBWIRE_BUFFER_LENGTH;
+ }
+
+ // perform blocking read into buffer
+ twi_cbreadFromDone = NULL;
+ twi_readFrom(address, rxBuffer, quantity);
+ uint8_t read = twii_WaitForDone(timeout);
+
+ // set rx buffer iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = read;
+
+ return read;
+ }
+
+ void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) {
+ // clamp to buffer length
+ if (quantity > NBWIRE_BUFFER_LENGTH) {
+ quantity = NBWIRE_BUFFER_LENGTH;
+ }
+
+ // perform blocking read into buffer
+ twi_cbreadFromDone = function;
+ twi_readFrom(address, rxBuffer, quantity);
+ //uint8_t read = twii_WaitForDone();
+
+ // set rx buffer iterator vars
+ //rxBufferIndex = 0;
+ //rxBufferLength = read;
+
+ rxBufferIndex = 0;
+ rxBufferLength = quantity; // this is a hack
+
+ return; //read;
+ }
+
+ uint8_t TwoWire::available(void) {
+ return rxBufferLength - rxBufferIndex;
+ }
+
+#endif
diff --git a/lib/I2Cdevlib-Core/I2Cdev.h b/lib/I2Cdevlib-Core/I2Cdev.h
new file mode 100644
index 000000000..4c0a2e7a2
--- /dev/null
+++ b/lib/I2Cdevlib-Core/I2Cdev.h
@@ -0,0 +1,278 @@
+// I2Cdev library collection - Main I2C device class header file
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 2013-06-05 by Jeff Rowberg
+//
+// Changelog:
+// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1
+// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications
+// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan)
+// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire
+// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation
+// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums)
+// 2011-10-03 - added automatic Arduino version detection for ease of use
+// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications
+// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x)
+// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default
+// 2011-08-02 - added support for 16-bit registers
+// - fixed incorrect Doxygen comments on some methods
+// - added timeout value for read operations (thanks mem @ Arduino forums)
+// 2011-07-30 - changed read/write function structures to return success or byte counts
+// - made all methods static for multi-device memory savings
+// 2011-07-28 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _I2CDEV_H_
+#define _I2CDEV_H_
+
+// -----------------------------------------------------------------------------
+// I2C interface implementation setting
+// -----------------------------------------------------------------------------
+#ifndef I2CDEV_IMPLEMENTATION
+#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE
+//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE
+#endif // I2CDEV_IMPLEMENTATION
+
+// comment this out if you are using a non-optimal IDE/implementation setting
+// but want the compiler to shut up about it
+#define I2CDEV_IMPLEMENTATION_WARNINGS
+
+// -----------------------------------------------------------------------------
+// I2C interface implementation options
+// -----------------------------------------------------------------------------
+#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino
+#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project
+ // ^^^ NBWire implementation is still buggy w/some interrupts!
+#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project
+#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library
+
+// -----------------------------------------------------------------------------
+// Arduino-style "Serial.print" debug constant (uncomment to enable)
+// -----------------------------------------------------------------------------
+//#define I2CDEV_SERIAL_DEBUG
+
+#ifdef ARDUINO
+ #if ARDUINO < 100
+ #include "WProgram.h"
+ #else
+ #include "Arduino.h"
+ #endif
+ #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+ #include
+ #endif
+ #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY
+ #include
+ #endif
+#endif
+
+#ifdef SPARK
+ #include
+ #define ARDUINO 101
+#endif
+
+
+// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];")
+#define I2CDEV_DEFAULT_READ_TIMEOUT 1000
+
+class I2Cdev {
+ public:
+ I2Cdev();
+
+ static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+ static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+
+ static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
+ static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
+ static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
+ static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
+ static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
+ static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
+ static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+ static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+ static uint16_t readTimeout;
+};
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+ //////////////////////
+ // FastWire 0.24
+ // This is a library to help faster programs to read I2C devices.
+ // Copyright(C) 2012
+ // Francesco Ferrara
+ //////////////////////
+
+ /* Master */
+ #define TW_START 0x08
+ #define TW_REP_START 0x10
+
+ /* Master Transmitter */
+ #define TW_MT_SLA_ACK 0x18
+ #define TW_MT_SLA_NACK 0x20
+ #define TW_MT_DATA_ACK 0x28
+ #define TW_MT_DATA_NACK 0x30
+ #define TW_MT_ARB_LOST 0x38
+
+ /* Master Receiver */
+ #define TW_MR_ARB_LOST 0x38
+ #define TW_MR_SLA_ACK 0x40
+ #define TW_MR_SLA_NACK 0x48
+ #define TW_MR_DATA_ACK 0x50
+ #define TW_MR_DATA_NACK 0x58
+
+ #define TW_OK 0
+ #define TW_ERROR 1
+
+ class Fastwire {
+ private:
+ static boolean waitInt();
+
+ public:
+ static void setup(int khz, boolean pullup);
+ static byte beginTransmission(byte device);
+ static byte write(byte value);
+ static byte writeBuf(byte device, byte address, byte *data, byte num);
+ static byte readBuf(byte device, byte address, byte *data, byte num);
+ static void reset();
+ static byte stop();
+ };
+#endif
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
+ // NBWire implementation based heavily on code by Gene Knight
+ // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html
+ // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html
+
+ #define NBWIRE_BUFFER_LENGTH 32
+
+ class TwoWire {
+ private:
+ static uint8_t rxBuffer[];
+ static uint8_t rxBufferIndex;
+ static uint8_t rxBufferLength;
+
+ static uint8_t txAddress;
+ static uint8_t txBuffer[];
+ static uint8_t txBufferIndex;
+ static uint8_t txBufferLength;
+
+ // static uint8_t transmitting;
+ static void (*user_onRequest)(void);
+ static void (*user_onReceive)(int);
+ static void onRequestService(void);
+ static void onReceiveService(uint8_t*, int);
+
+ public:
+ TwoWire();
+ void begin();
+ void begin(uint8_t);
+ void begin(int);
+ void beginTransmission(uint8_t);
+ //void beginTransmission(int);
+ uint8_t endTransmission(uint16_t timeout=0);
+ void nbendTransmission(void (*function)(int)) ;
+ uint8_t requestFrom(uint8_t, int, uint16_t timeout=0);
+ //uint8_t requestFrom(int, int);
+ void nbrequestFrom(uint8_t, int, void (*function)(int));
+ void send(uint8_t);
+ void send(uint8_t*, uint8_t);
+ //void send(int);
+ void send(char*);
+ uint8_t available(void);
+ uint8_t receive(void);
+ void onReceive(void (*)(int));
+ void onRequest(void (*)(void));
+ };
+
+ #define TWI_READY 0
+ #define TWI_MRX 1
+ #define TWI_MTX 2
+ #define TWI_SRX 3
+ #define TWI_STX 4
+
+ #define TW_WRITE 0
+ #define TW_READ 1
+
+ #define TW_MT_SLA_NACK 0x20
+ #define TW_MT_DATA_NACK 0x30
+
+ #define CPU_FREQ 16000000L
+ #define TWI_FREQ 100000L
+ #define TWI_BUFFER_LENGTH 32
+
+ /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */
+
+ #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
+ #define TW_STATUS (TWSR & TW_STATUS_MASK)
+ #define TW_START 0x08
+ #define TW_REP_START 0x10
+ #define TW_MT_SLA_ACK 0x18
+ #define TW_MT_SLA_NACK 0x20
+ #define TW_MT_DATA_ACK 0x28
+ #define TW_MT_DATA_NACK 0x30
+ #define TW_MT_ARB_LOST 0x38
+ #define TW_MR_ARB_LOST 0x38
+ #define TW_MR_SLA_ACK 0x40
+ #define TW_MR_SLA_NACK 0x48
+ #define TW_MR_DATA_ACK 0x50
+ #define TW_MR_DATA_NACK 0x58
+ #define TW_ST_SLA_ACK 0xA8
+ #define TW_ST_ARB_LOST_SLA_ACK 0xB0
+ #define TW_ST_DATA_ACK 0xB8
+ #define TW_ST_DATA_NACK 0xC0
+ #define TW_ST_LAST_DATA 0xC8
+ #define TW_SR_SLA_ACK 0x60
+ #define TW_SR_ARB_LOST_SLA_ACK 0x68
+ #define TW_SR_GCALL_ACK 0x70
+ #define TW_SR_ARB_LOST_GCALL_ACK 0x78
+ #define TW_SR_DATA_ACK 0x80
+ #define TW_SR_DATA_NACK 0x88
+ #define TW_SR_GCALL_DATA_ACK 0x90
+ #define TW_SR_GCALL_DATA_NACK 0x98
+ #define TW_SR_STOP 0xA0
+ #define TW_NO_INFO 0xF8
+ #define TW_BUS_ERROR 0x00
+
+ //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
+ //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
+
+ #ifndef sbi // set bit
+ #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+ #endif // sbi
+
+ #ifndef cbi // clear bit
+ #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+ #endif // cbi
+
+ extern TwoWire Wire;
+
+#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
+
+#endif /* _I2CDEV_H_ */
diff --git a/lib/I2Cdevlib-Core/keywords.txt b/lib/I2Cdevlib-Core/keywords.txt
new file mode 100644
index 000000000..4132a06c3
--- /dev/null
+++ b/lib/I2Cdevlib-Core/keywords.txt
@@ -0,0 +1,38 @@
+#######################################
+# Syntax Coloring Map For I2Cdev
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+I2Cdev KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+readBit KEYWORD2
+readBitW KEYWORD2
+readBits KEYWORD2
+readBitsW KEYWORD2
+readByte KEYWORD2
+readBytes KEYWORD2
+readWord KEYWORD2
+readWords KEYWORD2
+writeBit KEYWORD2
+writeBitW KEYWORD2
+writeBits KEYWORD2
+writeBitsW KEYWORD2
+writeByte KEYWORD2
+writeBytes KEYWORD2
+writeWord KEYWORD2
+writeWords KEYWORD2
+
+#######################################
+# Instances (KEYWORD2)
+#######################################
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
diff --git a/lib/I2Cdevlib-Core/library.json b/lib/I2Cdevlib-Core/library.json
new file mode 100644
index 000000000..d45609604
--- /dev/null
+++ b/lib/I2Cdevlib-Core/library.json
@@ -0,0 +1,13 @@
+{
+ "name": "I2Cdevlib-Core",
+ "keywords": "i2cdevlib, i2c",
+ "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.",
+ "include": "Arduino/I2Cdev",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/jrowberg/i2cdevlib.git"
+ },
+ "frameworks": "arduino",
+ "platforms": "atmelavr"
+}
diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino
index 49f545291..10f090796 100644
--- a/sonoff/_releasenotes.ino
+++ b/sonoff/_releasenotes.ino
@@ -1,4 +1,9 @@
-/* 5.9.0a
+/* 5.9.0b
+ * Add support for ADS1115 to be enabled in user_config.h and needs libraries i2cdevlib-Core and i2cdevlib-ADS1115 (#338, #660)
+ * Fix Exception 26 and empty console screen after usage of command WakeupDuration (#1133)
+ * Fix some changed iTead web links in README.md (#1137)
+ *
+ * 5.9.0a
* Add external sensor function pointer interface to enable easy sensor addition
* Fix Backup Configuration file download failure by defining proper file size (#1115)
*
diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index 3269b3b40..ff4cdc0e1 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -77,8 +77,9 @@ const char S_JSON_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"%s%d\":%d}";
const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}";
const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}";
-const char JSON_SNS_TEMPHUM[] PROGMEM =
- "%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}";
+const char JSON_SNS_TEMPHUM[] PROGMEM = "%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}";
+
+const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
const char S_LOG_HTTP[] PROGMEM = D_LOG_HTTP;
const char S_LOG_WIFI[] PROGMEM = D_LOG_WIFI;
@@ -113,6 +114,13 @@ const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = {
static const char kMonthNames[] = D_MONTH3LIST;
// webserver.ino
+#ifdef USE_WEBSERVER
+const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = | , {e} = |
+
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE;
@@ -128,5 +136,6 @@ const char S_FIRMWARE_UPGRADE[] PROGMEM = D_FIRMWARE_UPGRADE;
const char S_CONSOLE[] PROGMEM = D_CONSOLE;
const char S_INFORMATION[] PROGMEM = D_INFORMATION;
const char S_RESTART[] PROGMEM = D_RESTART;
+#endif // USE_WEBSERVER
#endif // _I18N_H_
\ No newline at end of file
diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
index 0574ab2e5..2dffab394 100644
--- a/sonoff/language/de-DE.h
+++ b/sonoff/language/de-DE.h
@@ -216,7 +216,7 @@
#define D_SET_BAUDRATE_TO "Baudrate eingestell auf"
#define D_RECEIVED_TOPIC "erhaltenes topic"
#define D_DATA_SIZE "Datengröße"
-#define D_ANALOG_INPUT0 "Analog0"
+#define D_ANALOG_INPUT "Analog"
#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..."
#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an"
diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h
index a621ae753..695ac4301 100644
--- a/sonoff/language/en-GB.h
+++ b/sonoff/language/en-GB.h
@@ -216,7 +216,7 @@
#define D_SET_BAUDRATE_TO "Set Baudrate to"
#define D_RECEIVED_TOPIC "Received Topic"
#define D_DATA_SIZE "Data Size"
-#define D_ANALOG_INPUT0 "Analog0"
+#define D_ANALOG_INPUT "Analog"
#define D_FINGERPRINT "Verify TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to"
diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h
index 38a28f543..03e925839 100644
--- a/sonoff/language/nl-NL.h
+++ b/sonoff/language/nl-NL.h
@@ -216,7 +216,7 @@
#define D_SET_BAUDRATE_TO "Zet baudrate op"
#define D_RECEIVED_TOPIC "Ontvangen topic"
#define D_DATA_SIZE "Data lengte"
-#define D_ANALOG_INPUT0 "Analoog0"
+#define D_ANALOG_INPUT "Analoog"
#define D_FINGERPRINT "Controleer TLS vingerafdruk..."
#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar"
diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h
index 46f0d08f8..f37ccfaa7 100644
--- a/sonoff/language/pl-PL.h
+++ b/sonoff/language/pl-PL.h
@@ -216,7 +216,7 @@
#define D_SET_BAUDRATE_TO "Ustaw szybkosc transmisji na"
#define D_RECEIVED_TOPIC "Otrzymany temat"
#define D_DATA_SIZE "Wielkosc danych"
-#define D_ANALOG_INPUT0 "Wej_analogowe"
+#define D_ANALOG_INPUT "Wej_analogowe"
#define D_FINGERPRINT "Weryfikuj odcisk TLS..."
#define D_TLS_CONNECT_FAILED_TO "Nieudane polaczenie TLS do"
diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h
index 158339dbf..dc3882854 100644
--- a/sonoff/sonoff.h
+++ b/sonoff/sonoff.h
@@ -112,7 +112,7 @@ enum Ws2812Color {WS_RED, WS_GREEN, WS_BLUE};
enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC};
enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC};
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
-enum XsnsFunctions {FUNC_XSNS_INIT, FUNC_XSNS_PREP, FUNC_XSNS_JSON, FUNC_XSNS_WEB};
+enum XsnsFunctions {FUNC_XSNS_INIT, FUNC_XSNS_PREP, FUNC_XSNS_JSON_APPEND, FUNC_XSNS_MQTT_SHOW, FUNC_XSNS_WEB};
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 3bcee078e..92be64043 100644
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
-#define VERSION 0x05090001 // 5.9.0a
+#define VERSION 0x05090002 // 5.9.0b
// Location specific includes
#include "sonoff.h" // Enumaration used in user_config.h
@@ -1800,7 +1800,7 @@ boolean MqttShowSensor()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i]));
}
}
- XsnsCall(FUNC_XSNS_JSON);
+ XsnsCall(FUNC_XSNS_JSON_APPEND);
boolean json_data_available = (strlen(mqtt_data) - json_data_start);
if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit());
@@ -1873,9 +1873,7 @@ void PerformEverySecond()
MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
}
- if (hlw_flg) {
- MqttShowHlw8012(1);
- }
+ XsnsCall(FUNC_XSNS_MQTT_SHOW);
}
}
diff --git a/sonoff/support.ino b/sonoff/support.ino
index 30a4683aa..aab885334 100644
--- a/sonoff/support.ino
+++ b/sonoff/support.ino
@@ -757,6 +757,17 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg)
return I2cRead(addr, reg, 3);
}
+void I2cWrite8v(uint8_t addr, uint8_t val)
+{
+ byte x = I2C_RETRY_COUNTER;
+
+ do {
+ Wire.beginTransmission((uint8_t)addr); // start transmission to device
+ Wire.write(val); // write data
+ x--;
+ } while (Wire.endTransmission(true) != 0 && x != 0); // end transmission
+}
+
void I2cWrite8(uint8_t addr, uint8_t reg, uint8_t val)
{
byte x = I2C_RETRY_COUNTER;
@@ -1238,10 +1249,10 @@ void AdcShow(boolean json)
analog >>= 5;
if (json) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, analog);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT "0\":%d"), mqtt_data, analog);
#ifdef USE_WEBSERVER
} else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}" D_ANALOG_INPUT0 "{m}%d{e}"), mqtt_data, analog);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "", 0, analog);
#endif // USE_WEBSERVER
}
}
@@ -1262,7 +1273,7 @@ boolean Xsns02(byte function)
// break;
// case FUNC_XSNS_PREP:
// break;
- case FUNC_XSNS_JSON:
+ case FUNC_XSNS_JSON_APPEND:
AdcShow(1);
break;
#ifdef USE_WEBSERVER
diff --git a/sonoff/user_config.h b/sonoff/user_config.h
index 671b07cea..ad8faf8f0 100644
--- a/sonoff/user_config.h
+++ b/sonoff/user_config.h
@@ -163,14 +163,15 @@
// -- Sensor code selection -----------------------
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
-//#define USE_DS18x20 // Optional using OneWire library for multiple DS18B20 and/or DS18S20 (+2k code)
+//#define USE_DS18x20 // Optional for multiple DS18B20 and/or DS18S20 sensors using library OneWire (+2k code)
#define USE_I2C // I2C using library wire (+10k code, 0.2k mem) - Disable by //
+ #define USE_SHT // Add I2C emulating code for SHT1X sensor
+ #define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor
+ #define USE_BMP // Add I2C code for BMP/BME280 sensor
#define USE_BH1750 // Add I2C code for BH1750 sensor
// #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0.5k code)
- #define USE_BMP // Add I2C code for BMP/BME280 sensor
- #define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor
- #define USE_SHT // Add I2C emulating code for SHT1X sensor
+// #define USE_ADS1115 // Add I2C code for ADS1x15 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+3k code, 0.3k mem)
// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code)
diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino
index 4e8394c7f..6764a9cde 100644
--- a/sonoff/webserver.ino
+++ b/sonoff/webserver.ino
@@ -280,11 +280,6 @@ const char HTTP_END[] PROGMEM =
"