From dd20f710336da749fef45d7013c5bd0324f3bf01 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 12 Jul 2019 09:46:43 +0200 Subject: [PATCH] Added support for BME280 and MCP23008 arduino libraries. --- Sming/Libraries/BME280/.gitignore | 33 ++ Sming/Libraries/BME280/BME280.cpp | 312 +++++++++++++ Sming/Libraries/BME280/BME280.h | 142 ++++++ .../BME280/BME280_Example/BME280_Example.ino | 75 +++ Sming/Libraries/BME280/README.md | 2 + Sming/Libraries/MCP23008/MCP23008.cpp | 437 ++++++++++++++++++ Sming/Libraries/MCP23008/MCP23008.h | 60 +++ Sming/Libraries/MCP23008/MCP23008.txt | 17 + 8 files changed, 1078 insertions(+) create mode 100644 Sming/Libraries/BME280/.gitignore create mode 100644 Sming/Libraries/BME280/BME280.cpp create mode 100644 Sming/Libraries/BME280/BME280.h create mode 100644 Sming/Libraries/BME280/BME280_Example/BME280_Example.ino create mode 100644 Sming/Libraries/BME280/README.md create mode 100644 Sming/Libraries/MCP23008/MCP23008.cpp create mode 100644 Sming/Libraries/MCP23008/MCP23008.h create mode 100644 Sming/Libraries/MCP23008/MCP23008.txt diff --git a/Sming/Libraries/BME280/.gitignore b/Sming/Libraries/BME280/.gitignore new file mode 100644 index 0000000000..f805e810e5 --- /dev/null +++ b/Sming/Libraries/BME280/.gitignore @@ -0,0 +1,33 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su diff --git a/Sming/Libraries/BME280/BME280.cpp b/Sming/Libraries/BME280/BME280.cpp new file mode 100644 index 0000000000..8ec18b85b8 --- /dev/null +++ b/Sming/Libraries/BME280/BME280.cpp @@ -0,0 +1,312 @@ +/* +BME280.h - Header file for the BME280 Barometric Pressure Sensor Arduino Library. +Copyright (C) 2012 Love Electronics Ltd (loveelectronics.com) + +This program is free software: you can redistribute it and/or modify +it under the terms of the version 3 GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + Datasheet for BME280: + http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf + +*/ + +#include "BME280.h" +#include "Arduino.h" +//#include + + + uint8_t osrs_t = 1; //Temperature oversampling x 1 + uint8_t osrs_p = 1; //Pressure oversampling x 1 + uint8_t osrs_h = 1; //Humidity oversampling x 1 + + uint8_t t_sb = 4; //Tstandby, 5=1000ms, 4=500ms + uint8_t filter = 0; //Filter off + uint8_t spi3w_en = 0; //3-wire SPI Disable + uint8_t BME280_OperationMode = BME280_MODE_NORMAL; + +BME280::BME280() +{ + ConversionWaitTimeMs = 5; + OversamplingSetting = 0; + Oversample = false; + + LastTemperatureTime = -1000; + LastTemperatureData = 0; + + AcceptableTemperatureLatencyForPressure = 1000; + + // SetResolution(BME280_Mode_Standard, false); +} + +uint8_t BME280::EnsureConnected() +{ + Read2(Reg_ChipId, 1, buffer); + + if(buffer[0] == ChipIdData) + IsConnected = 1; + else + IsConnected = 0; + + return buffer[0];//IsConnected; +} + +void BME280::Initialize() +{ + uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | BME280_OperationMode; + uint8_t ctrl_hum_reg = osrs_h; + + uint8_t config_reg = (t_sb << 5) | (filter << 2) | spi3w_en; + + Write(ControlHumidity, ctrl_hum_reg); + Write(Reg_Control, ctrl_meas_reg); + Write(Reg_Config, config_reg); + + + Read2(Reg_CalibrationTStart, Reg_CalibrationTEnd - Reg_CalibrationTStart + 1, buffer); + // This data is in Big Endian format from the BME280. + BME280_REGISTER_DIG_T1 = (buffer[1] << 8) | buffer[0]; + BME280_REGISTER_DIG_T2 = (buffer[3] << 8) | buffer[2]; + BME280_REGISTER_DIG_T3 = (buffer[5] << 8) | buffer[4]; + + Read2(Reg_CalibrationPStart, Reg_CalibrationPEnd - Reg_CalibrationPStart + 1, buffer); + + BME280_REGISTER_DIG_P1 = (buffer[1] << 8) | buffer[0]; + BME280_REGISTER_DIG_P2 = (buffer[3] << 8) | buffer[2]; + BME280_REGISTER_DIG_P3 = (buffer[5] << 8) | buffer[4]; + BME280_REGISTER_DIG_P4 = (buffer[7] << 8) | buffer[6]; + BME280_REGISTER_DIG_P5 = (buffer[9] << 8) | buffer[8]; + BME280_REGISTER_DIG_P6 = (buffer[11] << 8) | buffer[10]; + BME280_REGISTER_DIG_P7 = (buffer[13] << 8) | buffer[12]; + BME280_REGISTER_DIG_P8 = (buffer[15] << 8) | buffer[14]; + BME280_REGISTER_DIG_P9 = (buffer[17] << 8) | buffer[16]; + + Read2(BME280_REG_DIG_H1, 1, buffer); + BME280_REGISTER_DIG_H1 = buffer[0]; + Read2(BME280_REG_DIG_H2, 2, buffer); + BME280_REGISTER_DIG_H2 = (buffer[1] << 8) | buffer[0]; + Read2(BME280_REG_DIG_H3, 1, buffer); + BME280_REGISTER_DIG_H3 = buffer[0]; + Read2(BME280_REG_DIG_H4, 4, buffer); + BME280_REGISTER_DIG_H4 = (buffer[0] << 4) | (buffer[1]&0x0F); + + BME280_REGISTER_DIG_H5 = (buffer[2]<<4) | ((buffer[1] & 0xF0)>>4); + + BME280_REGISTER_DIG_H6 = buffer[3]; +} + +void BME280::PrintCalibrationData() +{ + Serial.print("T1:\t"); Serial.println(BME280_REGISTER_DIG_T1); + Serial.print("T2:\t"); Serial.println(BME280_REGISTER_DIG_T2); + Serial.print("T3:\t"); Serial.println(BME280_REGISTER_DIG_T3); + + Serial.print("P1:\t"); Serial.println(BME280_REGISTER_DIG_P1); + Serial.print("P2:\t"); Serial.println(BME280_REGISTER_DIG_P2); + Serial.print("P3:\t"); Serial.println(BME280_REGISTER_DIG_P3); + Serial.print("P4:\t"); Serial.println(BME280_REGISTER_DIG_P4); + Serial.print("P5:\t"); Serial.println(BME280_REGISTER_DIG_P5); + Serial.print("P6:\t"); Serial.println(BME280_REGISTER_DIG_P6); + Serial.print("P7:\t"); Serial.println(BME280_REGISTER_DIG_P7); + Serial.print("P8:\t"); Serial.println(BME280_REGISTER_DIG_P8); + Serial.print("P9:\t"); Serial.println(BME280_REGISTER_DIG_P9); + + Serial.print("H1:\t"); Serial.println(BME280_REGISTER_DIG_H1); + Serial.print("H2:\t"); Serial.println(BME280_REGISTER_DIG_H2); + Serial.print("H3:\t"); Serial.println(BME280_REGISTER_DIG_H3); + Serial.print("H4:\t"); Serial.println(BME280_REGISTER_DIG_H4); + Serial.print("H5:\t"); Serial.println(BME280_REGISTER_DIG_H5); + Serial.print("H6:\t"); Serial.println(BME280_REGISTER_DIG_H6); + +} + +int32_t BME280::GetUncompensatedTemperature() +{ + + Read2(MeasureTemperature, 3, buffer); + int32_t value = ((buffer[0] <<12) | (buffer[1] <<4) | (buffer[2] >>4)); + + return value; +} + +int32_t BME280::GetUncompensatedPressure() +{ + + Read2(MeasurePressure, 3, buffer); + + int32_t value = ((buffer[0] <<12) | (buffer[1] <<4) | (buffer[2] >>4)); + + return value ; +} + +int32_t BME280::GetUncompensatedHumidity() +{ + + Read2(MeasureHumidity, 2, buffer); + + int32_t value = ((buffer[0] <<8) | buffer[1]); + + return value ; +} + + +float BME280::CompensateTemperature(int32_t uncompensatedTemperature) +{ + + //long temperature; + int32_t var1,var2; + var1 = ((((uncompensatedTemperature>>3) - ((int32_t)BME280_REGISTER_DIG_T1<<1))) * ((int32_t)BME280_REGISTER_DIG_T2)) >> 11; + var2 = (((((uncompensatedTemperature>>4) - ((int32_t)BME280_REGISTER_DIG_T1)) * ((uncompensatedTemperature>>4) - ((int32_t)BME280_REGISTER_DIG_T1))) >> 12) * ((int32_t)BME280_REGISTER_DIG_T3)) >> 14; + t_fine = var1 + var2; + float temperature = (t_fine * 5 + 128) >> 8; /* temperature in 0.01 deg C*/ + + return temperature/100; + + +} +// +float BME280::CompensatePressure(int32_t uncompensatedPressure) { + + GetTemperature(); + int64_t var1, var2, p; + + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)BME280_REGISTER_DIG_P6; + var2 = var2 + ((var1*(int64_t)BME280_REGISTER_DIG_P5)<<17); + var2 = var2 + (((int64_t)BME280_REGISTER_DIG_P4)<<35); + var1 = ((var1 * var1 * (int64_t)BME280_REGISTER_DIG_P3)>>8) + ((var1 * (int64_t)BME280_REGISTER_DIG_P2)<<12); + var1 = (((((int64_t)1)<<47)+var1))*((int64_t)BME280_REGISTER_DIG_P1)>>33; + + if (var1 == 0) { + return 0; // avoid exception caused by division by zero + } + p = 1048576 - uncompensatedPressure; + p = (((p<<31) - var2)*3125) / var1; + var1 = (((int64_t)BME280_REGISTER_DIG_P9) * (p>>13) * (p>>13)) >> 25; + var2 = (((int64_t)BME280_REGISTER_DIG_P8) * p) >> 19; + + p = ((p + var1 + var2) >> 8) + (((int64_t)BME280_REGISTER_DIG_P7)<<4); + return (float)p/256; + +} + +float BME280::CompensateHumidity(int32_t uncompensatedPressure) { + + GetTemperature(); + + + int32_t v_x1_u32r; + + v_x1_u32r = (t_fine - ((int32_t)76800)); + + v_x1_u32r = (((((uncompensatedPressure << 14) - (((int32_t)BME280_REGISTER_DIG_H4) << 20) - + (((int32_t)BME280_REGISTER_DIG_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * + (((((((v_x1_u32r * ((int32_t)BME280_REGISTER_DIG_H6)) >> 10) * + (((v_x1_u32r * ((int32_t)BME280_REGISTER_DIG_H3)) >> 11) + ((int32_t)32768))) >> 10) + + ((int32_t)2097152)) * ((int32_t)BME280_REGISTER_DIG_H2) + 8192) >> 14)); + + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * + ((int32_t)BME280_REGISTER_DIG_H1)) >> 4)); + + v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; + v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; + float h = (v_x1_u32r>>12); + return h / 1024.0; + +} + +void BME280::SoftReset() +{ + Write(Reg_SoftReset, SoftResetInstruction); + delay(100); +} + +float BME280::GetTemperature() +{ + return CompensateTemperature(GetUncompensatedTemperature()); +} + +float BME280::GetPressure() +{ + return CompensatePressure(GetUncompensatedPressure()); +} + +float BME280::GetHumidity() +{ + return CompensateHumidity(GetUncompensatedHumidity()); +} + +/*float BME280::GetAltitude(float currentSeaLevelPressureInPa) +{ + // Get pressure in Pascals (Pa). + float pressure = GetPressure(); + // Calculate altitude from sea level. + float altitude = 44330.0 * (1.0 - powf(pressure / currentSeaLevelPressureInPa, (float)0.1902949571836346)); + return altitude; +}*/ + +//uint8_t BME280::SetResolution(uint8_t sampleResolution, bool oversample) +//{ +// OversamplingSetting = sampleResolution; +// Oversample = oversample; +// switch (sampleResolution) +// { +// case 0: +// ConversionWaitTimeMs = 5; +// break; +// case 1: +// ConversionWaitTimeMs = 8; +// break; +// case 2: +// ConversionWaitTimeMs = 14; +// break; +// case 3: +// ConversionWaitTimeMs = 26; +// break; +// default: +// return ErrorCode_1_Num; +// } +//} + +void BME280::Write(int address, int data) +{ + Wire.beginTransmission(BME280_Address); + Wire.write(address); + Wire.write(data); + Wire.endTransmission(); +} + +void BME280::Read2(int address, int length, uint8_t buffer[]) +{ + Wire.beginTransmission(BME280_Address); + Wire.write(address); + Wire.endTransmission(); + + Wire.beginTransmission(BME280_Address); + Wire.requestFrom(BME280_Address, length); + + while(Wire.available()) + { + for(uint8_t i = 0; i < length; i++) + { + buffer[i] = Wire.read(); + } + } + Wire.endTransmission(); +} + +const char* BME280::GetErrorText(int errorCode) +{ + if(ErrorCode_1_Num == 1) + return (const char*)ErrorCode_1; + + return (const char*)"Error not defined."; +} diff --git a/Sming/Libraries/BME280/BME280.h b/Sming/Libraries/BME280/BME280.h new file mode 100644 index 0000000000..23331d33f2 --- /dev/null +++ b/Sming/Libraries/BME280/BME280.h @@ -0,0 +1,142 @@ +/* +BME280.h - Header file for the BME280 Barometric Pressure Sensor Arduino Library. +Copyright (C) 2012 Love Electronics Ltd (loveelectronics.com) + +This program is free software: you can redistribute it and/or modify +it under the terms of the version 3 GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + Datasheet for BME280: + http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf + +*/ + +#ifndef BME280_h +#define BME280_h + +#include + +#include + +#define BME280_Address 0x76 + +#define ChipIdData 0x60 + +#define MeasureTemperature 0xFA + +#define MeasurePressure 0xF7 + +#define MeasureHumidity 0xFD +#define ControlHumidity 0xF2 + + + +#define Reg_ChipId 0xD0 +#define Reg_Version 0xD1 +#define Reg_CAL26 0xE1 // R calibration stored in 0xE1-0xF0 +#define Reg_Control 0xF4 +#define Reg_Config 0xF5 + +#define Reg_CalibrationTStart 0x88 +#define Reg_CalibrationTEnd 0x8D + +#define Reg_CalibrationPStart 0x8E +#define Reg_CalibrationPEnd 0x9F + + enum + { + BME280_REG_DIG_H1 = 0xA1, + BME280_REG_DIG_H2 = 0xE1, + BME280_REG_DIG_H3 = 0xE3, + BME280_REG_DIG_H4 = 0xE4, + BME280_REG_DIG_H5 = 0xE5, + BME280_REG_DIG_H6 = 0xE7, + }; +#define Reg_AnalogConverterOutMSB 0xF6 +#define Reg_SoftReset 0xE0 +#define SoftResetInstruction 0xB6 + +#define ErrorCode_1 "Entered sample resolution was invalid. See datasheet for details." +#define ErrorCode_1_Num 1 + + +#define BME280_MODE_NORMAL 0x03 //reads sensors at set interval +#define BME280_MODE_FORCED 0x01 //reads sensors once when you write this register + +class BME280 +{ + public: + BME280(); + + void Initialize(void); + + int32_t GetUncompensatedTemperature(); + float CompensateTemperature(int32_t uncompensatedTemperature); + + int32_t GetUncompensatedPressure(); + float CompensatePressure(int32_t uncompensatedPressure); + + int32_t GetUncompensatedHumidity(); + float CompensateHumidity(int32_t uncompensatedHumidity); + + float GetTemperature(); + float GetPressure(); + float GetHumidity(); + + //float GetAltitude(float currentSeaLevelPressureInPa); + + void SoftReset(); + uint8_t SetResolution(uint8_t sampleResolution, bool oversample); + + void PrintCalibrationData(); + + uint8_t EnsureConnected(); + uint8_t IsConnected; + const char* GetErrorText(int errorCode); + protected: + void Write(int address, int byte); + uint8_t* Read(int address, int length); + void Read2(int address, int length, uint8_t buffer[]); + private: + uint8_t OversamplingSetting; + bool Oversample; + int16_t ConversionWaitTimeMs; + int16_t LastTemperatureData; + int16_t LastTemperatureTime; + int16_t AcceptableTemperatureLatencyForPressure; + + + uint16_t BME280_REGISTER_DIG_T1; + int16_t BME280_REGISTER_DIG_T2; + int16_t BME280_REGISTER_DIG_T3; + + uint16_t BME280_REGISTER_DIG_P1; + int16_t BME280_REGISTER_DIG_P2; + int16_t BME280_REGISTER_DIG_P3; + int16_t BME280_REGISTER_DIG_P4; + int16_t BME280_REGISTER_DIG_P5; + int16_t BME280_REGISTER_DIG_P6; + int16_t BME280_REGISTER_DIG_P7; + int16_t BME280_REGISTER_DIG_P8; + int16_t BME280_REGISTER_DIG_P9; + + uint8_t BME280_REGISTER_DIG_H1; + int16_t BME280_REGISTER_DIG_H2; + int8_t BME280_REGISTER_DIG_H3; + int16_t BME280_REGISTER_DIG_H4; + int16_t BME280_REGISTER_DIG_H5; + int8_t BME280_REGISTER_DIG_H6; + + uint8_t buffer[64]; + int32_t t_fine; +}; +#endif + diff --git a/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino b/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino new file mode 100644 index 0000000000..8b84c5f440 --- /dev/null +++ b/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino @@ -0,0 +1,75 @@ + +// Include the Wire library for I2C access. +#include +// Include the Love Electronics BMP180 library. +#include + +// Store an instance of the BMP180 sensor. +BMP180 barometer; +// We are going to use the on board LED for an indicator. +int indicatorLed = 13; + +// Store the current sea level pressure at your location in Pascals. +float seaLevelPressure = 101325; + +void setup() +{ + // We start the serial library to output our messages. + Serial.begin(9600); + // We start the I2C on the Arduino for communication with the BMP180 sensor. + Wire.begin(); + // Set up the Indicator LED. + pinMode(indicatorLed, OUTPUT); + // We create an instance of our BMP180 sensor. + barometer = BMP180(); + // We check to see if we can connect to the sensor. + if(barometer.EnsureConnected()) + { + Serial.println("Connected to BMP180."); // Output we are connected to the computer. + digitalWrite(indicatorLed, HIGH); // Set our LED. + + // When we have connected, we reset the device to ensure a clean start. + barometer.SoftReset(); + // Now we initialize the sensor and pull the calibration data. + barometer.Initialize(); + } + else + { + Serial.println("Could not connect to BMP180."); + digitalWrite(indicatorLed, LOW); // Set our LED. + } +} + +void loop() +{ + if(barometer.IsConnected) + { + // Retrive the current pressure in Pascals. + long currentPressure = barometer.GetPressure(); + + // Print out the Pressure. + Serial.print("Pressure: "); + Serial.print(currentPressure); + Serial.print(" Pa"); + + // Retrive the current altitude (in meters). Current Sea Level Pressure is required for this. + float altitude = barometer.GetAltitude(seaLevelPressure); + + // Print out the Altitude. + Serial.print("\tAltitude: "); + Serial.print(altitude); + Serial.print(" m"); + + // Retrive the current temperature in degrees celcius. + float currentTemperature = barometer.GetTemperature(); + + // Print out the Temperature + Serial.print("\tTemperature: "); + Serial.print(currentTemperature); + Serial.write(176); + Serial.print("C"); + + Serial.println(); // Start a new line. + delay(1000); // Show new results every second. + } +} diff --git a/Sming/Libraries/BME280/README.md b/Sming/Libraries/BME280/README.md new file mode 100644 index 0000000000..98cd786742 --- /dev/null +++ b/Sming/Libraries/BME280/README.md @@ -0,0 +1,2 @@ +# BME280 +BME280 Driver for ESP8266 and Sming diff --git a/Sming/Libraries/MCP23008/MCP23008.cpp b/Sming/Libraries/MCP23008/MCP23008.cpp new file mode 100644 index 0000000000..fdd8c9728f --- /dev/null +++ b/Sming/Libraries/MCP23008/MCP23008.cpp @@ -0,0 +1,437 @@ +// MCP23008.cpp +//------------------------------------------------------------------------------ +// Library for communicating with MCP23008 8-bit port expander. +// Created by Garrett Blanton January, 24, 2013. +// Released into the public domain. +// +// Functions +//------------------------------------------------------------------------------ +// MCP23008(uint8_t addr); // Class constructor +// void writeIODIR(uint8_t cIODIR); // Write IODIR register +// void writeIPOL(uint8_t cIPOL); // Write IPOL register +// void writeGPINTEN(uint8_t cGPINTEN); // Write GPINTEN register +// void writeDEFVAL(uint8_t cDEFVAL); // Write DEFVAL register +// void writeGPPU(uint8_t cGPPU); // Write GPPU register +// void writeGPIO(uint8_t cGPIO); // Write GPIO register +// void writeOLAT(uint8_t cOLAT); // Write OLAT register +// uint8_t readIODIR(); // Read IODIR register +// uint8_t readIPOL(); // Read IPOL register +// uint8_t readGPINTEN(); // Read GPINTEN register +// uint8_t readDEFVAL(); // Read DEFVAL register +// uint8_t readGPPU(); // Read GPPU register +// uint8_t readINTF(); // Read INTF register +// uint8_t readINTCAP(); // Read INTCAP register +// uint8_t readGPIO(); // Read GPIO register +// uint8_t readOLAT(); // Read OLAT register +// +// void writebyte(uint8_t Address, uint8_t Register, uint8_t Value); +// uint8_t readbyte(uint8_t Address, uint8_t Register); + + +#include "Arduino.h" +#include "Wire.h" +#include "MCP23008.h" + +MCP23008::MCP23008(byte addr) +{ + _ADDR = addr >> 1; +} + +// writebyte +//------------------------------------------------------------------------------ +// Writes a single byte of data to the specified MCP23008 register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// Address MCP23008 Address +// Register MCP23008 Register to write +// Value Value to write to register +// +// Registers +//------------------------------------------------------------------------------ +// regIODIR 0x00 IO Direction Register +// regIPOL 0x01 Input Polarity Register +// regGPINTEN 0x02 Interrupt-On-Change Register +// regDEFVAL 0x03 Default Value Register +// regINTCON 0x04 Interrupt Control Register +// regIOCON 0x05 Configuration Register +// regGPPU 0x06 Pull-up Register +// regINTF 0x07 Interrupt Flag Register +// regINTCAP 0x08 Interrupt Captured Value Register +// regGPIO 0x09 General Purpose IO Register +// regOLAT 0x0A Output Latch Register + +void MCP23008::writebyte(uint8_t Address, uint8_t Register, uint8_t Value) +{ + Wire.beginTransmission(Address); + Wire.write(Register); + Wire.write(Value); + Wire.endTransmission(); +} + +// readbyte +//------------------------------------------------------------------------------ +// Reads a single byte of data from the specified MCP23008 register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// Address MCP23008 Address +// Register MCP23008 Register to write +// return Value read from register +// +// Registers +//------------------------------------------------------------------------------ +// regIODIR 0x00 IO Direction Register +// regIPOL 0x01 Input Polarity Register +// regGPINTEN 0x02 Interrupt-On-Change Register +// regDEFVAL 0x03 Default Value Register +// regINTCON 0x04 Interrupt Control Register +// regIOCON 0x05 Configuration Register +// regGPPU 0x06 Pull-up Register +// regINTF 0x07 Interrupt Flag Register +// regINTCAP 0x08 Interrupt Captured Value Register +// regGPIO 0x09 General Purpose IO Register +// regOLAT 0x0A Output Latch Register + +uint8_t MCP23008::readbyte(uint8_t Address, uint8_t Register) +{ + Wire.beginTransmission(Address); + Wire.write(Register); + Wire.endTransmission(); + Wire.requestFrom((char)Address,1); + Wire.available(); + return Wire.read(); +} + +// writeIODIR +//------------------------------------------------------------------------------ +// Writes to the MCP23008 IODIR register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cIODIR Data direction value (0=output; 1=input) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// IO7 |IO6 |IO5 |IO4 |IO3 |IO2 |IO1 |IO0 + + +void MCP23008::writeIODIR(uint8_t cIODIR) +{ + writebyte(_ADDR, regIODIR, cIODIR); +} + +// writeIPOL +//------------------------------------------------------------------------------ +// Writes to the MCP23008 IPOL register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cIPOL Input Polarity Register (0=Direct; 1=Opposite) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// IP7 |IP6 |IP5 |IP4 |IP3 |IP2 |IP1 |IP0 + +void MCP23008::writeIPOL(uint8_t cIPOL) +{ + writebyte(_ADDR, regIPOL, cIPOL); +} + +// writeGPINTEN +//------------------------------------------------------------------------------ +// Writes to the MCP23008 GPINTEN register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPINTEN Interrupt-On-Change Control Register (0=Disable; 1=Enable) +// +// BIT7 |BIT6 |BIT5 |BIT4 |BIT3 |BIT2 |BIT1 |BIT0 +// GPINT7|GPINT6|GPINT5|GPINT4|GPINT3|GPINT2|GPINT1|GPINT0 + +void MCP23008::writeGPINTEN(uint8_t cGPINTEN) +{ + writebyte(_ADDR, regGPINTEN, cGPINTEN); +} + +// writeDEFVAL +//------------------------------------------------------------------------------ +// Writes to the MCP23008 DEFVAL register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cDEFVAL Default Compare Register For Interrupt-On-Change (GPINT!=DEF) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// DEF7|DEF6|DEF5|DEF4|DEF3|DEF2|DEF1|DEF0 + +void MCP23008::writeDEFVAL(uint8_t cDEFVAL) +{ + writebyte(_ADDR, regDEFVAL, cDEFVAL); +} + +// writeINTCON +//------------------------------------------------------------------------------ +// Writes to the MCP23008 INTCON register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cINTCON Interrupt Control Register (0=Compare Previous Pin; 1=DEFVAL) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// IOC7|IOC6|IOC5|IOC4|IOC3|IOC2|IOC1|IOC0 + +void MCP23008::writeINTCON(uint8_t cINTCON) +{ + writebyte(_ADDR, regINTCON, cINTCON); +} + +// writeIOCON +//------------------------------------------------------------------------------ +// Writes to the MCP23008 IOCON register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cIOCON Configuration Register +// +// Bit5 0=Sequential Operation Enabled; +// 1=Sequential Operation Disabled +// Bit4 0=Slew rate enabled +// 1=Slew rate disabled +// Bit2 0=Open-drain output +// 1=Active driver output +// Bit1 0=INT output active low +// 1=INT output active high + +void MCP23008::writeIOCON(uint8_t cIOCON) +{ + writebyte(_ADDR, regIOCON, cIOCON); +} + +// writeGPPU +//------------------------------------------------------------------------------ +// Writes to the MCP23008 GPPU register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPPU Pull-up resister configuration (0=Disabled; 1=Enabled) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// PU7 |PU6 |PU5 |PU4 |PU3 |PU2 |PU1 |PU0 + +void MCP23008::writeGPPU(uint8_t cGPPU) +{ + writebyte(_ADDR, regGPPU, cGPPU); +} + +// writeGPIO +//------------------------------------------------------------------------------ +// Writes to the MCP23008 GPIO register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPIO Port Register (0=Logic Low; 1=Logic High) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0 + +void MCP23008::writeGPIO(uint8_t cGPIO) +{ + writebyte(_ADDR, regGPIO, cGPIO); +} + +// writeOLAT +//------------------------------------------------------------------------------ +// Writes to the MCP23008 OLAT register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPIO Output Latch Register (0=Logic Low; 1=Logic High) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// OL7 |OL6 |OL5 |OL4 |OL3 |OL2 |OL1 |OL0 + +void MCP23008::writeOLAT(uint8_t cOLAT) +{ + writebyte(_ADDR, regOLAT, cOLAT); +} + +// readIODIR +//------------------------------------------------------------------------------ +// Reads from the MCP23008 IODIR register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Data direction value (0=output; 1=input) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0 + +uint8_t MCP23008::readIODIR() +{ + return readbyte(_ADDR, regIODIR); +} + +// readIPOL +//------------------------------------------------------------------------------ +// Reads from the MCP23008 IPOL register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Input Polarity Register (0=Direct; 1=Opposite) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// IP7 |IP6 |IP5 |IP4 |IP3 |IP2 |IP1 |IP0 + +uint8_t MCP23008::readIPOL() +{ + return readbyte(_ADDR, regIPOL); +} + +// readGPINTEN +//------------------------------------------------------------------------------ +// Reads from the MCP23008 GPINTEN register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Interrupt-On-Change Control Register (0=Disable; 1=Enable) +// +// BIT7 |BIT6 |BIT5 |BIT4 |BIT3 |BIT2 |BIT1 |BIT0 +// GPINT7|GPINT6|GPINT5|GPINT4|GPINT3|GPINT2|GPINT1|GPINT0 + +uint8_t MCP23008::readGPINTEN() +{ + return readbyte(_ADDR, regGPINTEN); +} + +// readDEFVAL +//------------------------------------------------------------------------------ +// Reads from the MCP23008 DEFVAL register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Default Compare Register For Interrupt-On-Change (GPINT!=DEF) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// DEF7|DEF6|DEF5|DEF4|DEF3|DEF2|DEF1|DEF0 + +uint8_t MCP23008::readDEFVAL() +{ + return readbyte(_ADDR, regDEFVAL); +} + +// readINTCON +//------------------------------------------------------------------------------ +// Reads from the MCP23008 INTCON register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Interrupt Control Register (0=Compare Previous Pin; 1=DEFVAL) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// IOC7|IOC6|IOC5|IOC4|IOC3|IOC2|IOC1|IOC0 + +uint8_t MCP23008::readINTCON() +{ + return readbyte(_ADDR, regINTCON); +} + +// readIOCON +//------------------------------------------------------------------------------ +// Reads from the MCP23008 IOCON register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Configuration Register +// +// Bit5 0=Sequential Operation Enabled; +// 1=Sequential Operation Disabled +// Bit4 0=Slew rate enabled +// 1=Slew rate disabled +// Bit2 0=Open-drain output +// 1=Active driver output +// Bit1 0=INT output active low +// 1=INT output active high + +uint8_t MCP23008::readIOCON() +{ + return readbyte(_ADDR, regIOCON); +} + +// readGPPU +//------------------------------------------------------------------------------ +// Reads from the MCP23008 GPPU register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Pull-up resister configuration (0=Disabled; 1=Enabled) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// PU7 |PU6 |PU5 |PU4 |PU3 |PU2 |PU1 |PU0 + +uint8_t MCP23008::readGPPU() +{ + return readbyte(_ADDR, regGPPU); +} + +// readINTF +//------------------------------------------------------------------------------ +// Reads from the MCP23008 INTF register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Interrupt Flag Register (0=No Interrupt; 1=Caused Interrupt) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// INT7|INT6|INT5|INT4|INT3|INT2|INT1|INT0 + +uint8_t MCP23008::readINTF() +{ + return readbyte(_ADDR, regINTF); +} + +// readINTCAP +//------------------------------------------------------------------------------ +// Reads from the MCP23008 INTCAP register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// return Interrupt Capture Register (0=Logic Low; 1=Logic High) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// INT7|INT6|INT5|INT4|INT3|INT2|INT1|INT0 + +uint8_t MCP23008::readINTCAP() +{ + return readbyte(_ADDR, regINTCAP); +} + +// readGPIO +//------------------------------------------------------------------------------ +// Reads from the MCP23008 GPIO register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPIO Port Register (0=Logic Low; 1=Logic High) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0 + +uint8_t MCP23008::readGPIO() +{ + return readbyte(_ADDR, regGPIO); +} + +// readOLAT +//------------------------------------------------------------------------------ +// Reads from the MCP23008 OLAT register. +// +// Parameter Description +//------------------------------------------------------------------------------ +// cGPIO Output Latch Register (0=Logic Low; 1=Logic High) +// +// BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0 +// OL7 |OL6 |OL5 |OL4 |OL3 |OL2 |OL1 |OL0 + +uint8_t MCP23008::readOLAT() +{ + return readbyte(_ADDR, regOLAT); +} diff --git a/Sming/Libraries/MCP23008/MCP23008.h b/Sming/Libraries/MCP23008/MCP23008.h new file mode 100644 index 0000000000..81702890ef --- /dev/null +++ b/Sming/Libraries/MCP23008/MCP23008.h @@ -0,0 +1,60 @@ +// MCP23008.h +//------------------------------------------------------------------------------ +// Library for communicating with MCP23008 8-bit port expander. +// Created by Garrett Blanton January, 24, 2014. +// Released into the public domain. + +#ifndef MCP23008_h +#define MCP23008_h + +#include "Arduino.h" + +#define regIODIR 0x00 // IO Direction Register +#define regIPOL 0x01 // Input Polarity Register +#define regGPINTEN 0x02 // Interrupt-On-Change Register +#define regDEFVAL 0x03 // Default Value Register +#define regINTCON 0x04 // Interrupt Control Register +#define regIOCON 0x05 // Configuration Register +#define regGPPU 0x06 // Pull-up Register +#define regINTF 0x07 // Interrupt Flag Register +#define regINTCAP 0x08 // Interrupt Captured Value Register +#define regGPIO 0x09 // General Purpose IO Register +#define regOLAT 0x0A // Output Latch Register + +class MCP23008 +{ + public: + + MCP23008(uint8_t addr); // Class constructor + + void writeIODIR(uint8_t cIODIR); // Write IODIR register + void writeIPOL(uint8_t cIPOL); // Write IPOL register + void writeGPINTEN(uint8_t cOLINTEN); // Write GPINTEN register + void writeDEFVAL(uint8_t cDEFVAL); // Write DEFVAL register + void writeINTCON(uint8_t cINTCON); // Write INTCON register + void writeIOCON(uint8_t cIOCON); // Write IOCON register + void writeGPPU(uint8_t cOLPU); // Write GPPU register + void writeGPIO(uint8_t cOLIO); // Write GPIO register + void writeOLAT(uint8_t cOLAT); // Write OLAT register + + uint8_t readIODIR(); // Read IODIR register + uint8_t readIPOL(); // Read IPOL register + uint8_t readGPINTEN(); // Read GPINTEN register + uint8_t readDEFVAL(); // Read DEFVAL register + uint8_t readGPPU(); // Read GPPU register + uint8_t readINTCON(); // Read INTCON register + uint8_t readIOCON(); // Read IOCON register + uint8_t readINTF(); // Read INTF register + uint8_t readINTCAP(); // Read INTCAP register + uint8_t readGPIO(); // Read GPIO register + uint8_t readOLAT(); // Read OLAT register + + private: + + void writebyte(uint8_t Address, uint8_t Register, uint8_t Value); // Writes byte to MCP23008 + uint8_t readbyte(uint8_t Address, uint8_t Register); // Reads byte from MCP23008 + + uint8_t _ADDR; // MCP23008 Address : 0b0100xxx0 +}; + +#endif \ No newline at end of file diff --git a/Sming/Libraries/MCP23008/MCP23008.txt b/Sming/Libraries/MCP23008/MCP23008.txt new file mode 100644 index 0000000000..510da0164b --- /dev/null +++ b/Sming/Libraries/MCP23008/MCP23008.txt @@ -0,0 +1,17 @@ +MCP23008 KEYWORD1 +writeIODIR KEYWORD2 +writeIPOL KEYWORD2 +writeOLINTEN KEYWORD2 +writeDEFVAL KEYWORD2 +writeOLPU KEYWORD2 +writeOLIO KEYWORD2 +writeOLAT KEYWORD2 +readIODIR KEYWORD2 +readIPOL KEYWORD2 +readOLINTEN KEYWORD2 +readDEFVAL KEYWORD2 +readOLPU KEYWORD2 +readINTF KEYWORD2 +readINTCAP KEYWORD2 +readOLIO KEYWORD2 +readOLAT KEYWORD2 \ No newline at end of file