Add Library

This commit is contained in:
Siwat Sirichai 2019-08-09 09:01:56 +07:00
parent e365b9dbd9
commit 3c47103b39
318 changed files with 56465 additions and 0 deletions

View file

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View file

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

View file

@ -0,0 +1,283 @@
/***************************************************
This is a library for the MCP23017 i2c port expander
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#ifdef __AVR
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#endif
#include "Adafruit_MCP23017.h"
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// minihelper to keep Arduino backward compatibility
static inline void wiresend(uint8_t x) {
#if ARDUINO >= 100
Wire.write((uint8_t) x);
#else
Wire.send(x);
#endif
}
static inline uint8_t wirerecv(void) {
#if ARDUINO >= 100
return Wire.read();
#else
return Wire.receive();
#endif
}
/**
* Bit number associated to a give Pin
*/
uint8_t Adafruit_MCP23017::bitForPin(uint8_t pin){
return pin%8;
}
/**
* Register address, port dependent, for a given PIN
*/
uint8_t Adafruit_MCP23017::regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr){
return(pin<8) ?portAaddr:portBaddr;
}
/**
* Reads a given register
*/
uint8_t Adafruit_MCP23017::readRegister(uint8_t addr){
// read the current GPINTEN
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(addr);
Wire.endTransmission();
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1);
return wirerecv();
}
/**
* Writes a given register
*/
void Adafruit_MCP23017::writeRegister(uint8_t regAddr, uint8_t regValue){
// Write the register
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(regAddr);
wiresend(regValue);
Wire.endTransmission();
}
/**
* Helper to update a single bit of an A/B register.
* - Reads the current register value
* - Writes the new register value
*/
void Adafruit_MCP23017::updateRegisterBit(uint8_t pin, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr) {
uint8_t regValue;
uint8_t regAddr=regForPin(pin,portAaddr,portBaddr);
uint8_t bit=bitForPin(pin);
regValue = readRegister(regAddr);
// set the value for the particular bit
bitWrite(regValue,bit,pValue);
writeRegister(regAddr,regValue);
}
////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the MCP23017 given its HW selected address, see datasheet for Address selection.
*/
void Adafruit_MCP23017::begin(uint8_t addr) {
if (addr > 7) {
addr = 7;
}
i2caddr = addr;
Wire.begin();
// set defaults!
// all inputs on port A and B
writeRegister(MCP23017_IODIRA,0xff);
writeRegister(MCP23017_IODIRB,0xff);
}
/**
* Initializes the default MCP23017, with 000 for the configurable part of the address
*/
void Adafruit_MCP23017::begin(void) {
begin(0);
}
/**
* Sets the pin mode to either INPUT or OUTPUT
*/
void Adafruit_MCP23017::pinMode(uint8_t p, uint8_t d) {
updateRegisterBit(p,(d==INPUT),MCP23017_IODIRA,MCP23017_IODIRB);
}
/**
* Reads all 16 pins (port A and B) into a single 16 bits variable.
*/
uint16_t Adafruit_MCP23017::readGPIOAB() {
uint16_t ba = 0;
uint8_t a;
// read the current GPIO output latches
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(MCP23017_GPIOA);
Wire.endTransmission();
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2);
a = wirerecv();
ba = wirerecv();
ba <<= 8;
ba |= a;
return ba;
}
/**
* Read a single port, A or B, and return its current 8 bit value.
* Parameter b should be 0 for GPIOA, and 1 for GPIOB.
*/
uint8_t Adafruit_MCP23017::readGPIO(uint8_t b) {
// read the current GPIO output latches
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
if (b == 0)
wiresend(MCP23017_GPIOA);
else {
wiresend(MCP23017_GPIOB);
}
Wire.endTransmission();
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1);
return wirerecv();
}
/**
* Writes all the pins in one go. This method is very useful if you are implementing a multiplexed matrix and want to get a decent refresh rate.
*/
void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) {
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(MCP23017_GPIOA);
wiresend(ba & 0xFF);
wiresend(ba >> 8);
Wire.endTransmission();
}
void Adafruit_MCP23017::digitalWrite(uint8_t pin, uint8_t d) {
uint8_t gpio;
uint8_t bit=bitForPin(pin);
// read the current GPIO output latches
uint8_t regAddr=regForPin(pin,MCP23017_OLATA,MCP23017_OLATB);
gpio = readRegister(regAddr);
// set the pin and direction
bitWrite(gpio,bit,d);
// write the new GPIO
regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB);
writeRegister(regAddr,gpio);
}
void Adafruit_MCP23017::pullUp(uint8_t p, uint8_t d) {
updateRegisterBit(p,d,MCP23017_GPPUA,MCP23017_GPPUB);
}
uint8_t Adafruit_MCP23017::digitalRead(uint8_t pin) {
uint8_t bit=bitForPin(pin);
uint8_t regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB);
return (readRegister(regAddr) >> bit) & 0x1;
}
/**
* Configures the interrupt system. both port A and B are assigned the same configuration.
* Mirroring will OR both INTA and INTB pins.
* Opendrain will set the INT pin to value or open drain.
* polarity will set LOW or HIGH on interrupt.
* Default values after Power On Reset are: (false, false, LOW)
* If you are connecting the INTA/B pin to arduino 2/3, you should configure the interupt handling as FALLING with
* the default configuration.
*/
void Adafruit_MCP23017::setupInterrupts(uint8_t mirroring, uint8_t openDrain, uint8_t polarity){
// configure the port A
uint8_t ioconfValue=readRegister(MCP23017_IOCONA);
bitWrite(ioconfValue,6,mirroring);
bitWrite(ioconfValue,2,openDrain);
bitWrite(ioconfValue,1,polarity);
writeRegister(MCP23017_IOCONA,ioconfValue);
// Configure the port B
ioconfValue=readRegister(MCP23017_IOCONB);
bitWrite(ioconfValue,6,mirroring);
bitWrite(ioconfValue,2,openDrain);
bitWrite(ioconfValue,1,polarity);
writeRegister(MCP23017_IOCONB,ioconfValue);
}
/**
* Set's up a pin for interrupt. uses arduino MODEs: CHANGE, FALLING, RISING.
*
* Note that the interrupt condition finishes when you read the information about the port / value
* that caused the interrupt or you read the port itself. Check the datasheet can be confusing.
*
*/
void Adafruit_MCP23017::setupInterruptPin(uint8_t pin, uint8_t mode) {
// set the pin interrupt control (0 means change, 1 means compare against given value);
updateRegisterBit(pin,(mode!=CHANGE),MCP23017_INTCONA,MCP23017_INTCONB);
// if the mode is not CHANGE, we need to set up a default value, different value triggers interrupt
// In a RISING interrupt the default value is 0, interrupt is triggered when the pin goes to 1.
// In a FALLING interrupt the default value is 1, interrupt is triggered when pin goes to 0.
updateRegisterBit(pin,(mode==FALLING),MCP23017_DEFVALA,MCP23017_DEFVALB);
// enable the pin for interrupt
updateRegisterBit(pin,HIGH,MCP23017_GPINTENA,MCP23017_GPINTENB);
}
uint8_t Adafruit_MCP23017::getLastInterruptPin(){
uint8_t intf;
// try port A
intf=readRegister(MCP23017_INTFA);
for(int i=0;i<8;i++) if (bitRead(intf,i)) return i;
// try port B
intf=readRegister(MCP23017_INTFB);
for(int i=0;i<8;i++) if (bitRead(intf,i)) return i+8;
return MCP23017_INT_ERR;
}
uint8_t Adafruit_MCP23017::getLastInterruptPinValue(){
uint8_t intPin=getLastInterruptPin();
if(intPin!=MCP23017_INT_ERR){
uint8_t intcapreg=regForPin(intPin,MCP23017_INTCAPA,MCP23017_INTCAPB);
uint8_t bit=bitForPin(intPin);
return (readRegister(intcapreg)>>bit) & (0x01);
}
return MCP23017_INT_ERR;
}

View file

@ -0,0 +1,97 @@
/***************************************************
This is a library for the MCP23017 i2c port expander
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#ifndef _Adafruit_MCP23017_H_
#define _Adafruit_MCP23017_H_
// Don't forget the Wire library
#ifndef ARDUINO_AVR_GEMMA
//TinyWireM is now part of
// Adafruit version of Wire Library, so this
// will work with Adafruit ATtiny85's
//But Arduino Gemma doesn't use that library
// We do NOT want to include Wire if it's an arduino Gemma
#include <Wire.h>
#else
#include <TinyWireM.h>
#define Wire TinyWireM
#endif
class Adafruit_MCP23017 {
public:
void begin(uint8_t addr);
void begin(void);
void pinMode(uint8_t p, uint8_t d);
void digitalWrite(uint8_t p, uint8_t d);
void pullUp(uint8_t p, uint8_t d);
uint8_t digitalRead(uint8_t p);
void writeGPIOAB(uint16_t);
uint16_t readGPIOAB();
uint8_t readGPIO(uint8_t b);
void setupInterrupts(uint8_t mirroring, uint8_t open, uint8_t polarity);
void setupInterruptPin(uint8_t p, uint8_t mode);
uint8_t getLastInterruptPin();
uint8_t getLastInterruptPinValue();
private:
uint8_t i2caddr;
uint8_t bitForPin(uint8_t pin);
uint8_t regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr);
uint8_t readRegister(uint8_t addr);
void writeRegister(uint8_t addr, uint8_t value);
/**
* Utility private method to update a register associated with a pin (whether port A/B)
* reads its value, updates the particular bit, and writes its value.
*/
void updateRegisterBit(uint8_t p, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr);
};
#define MCP23017_ADDRESS 0x20
// registers
#define MCP23017_IODIRA 0x00
#define MCP23017_IPOLA 0x02
#define MCP23017_GPINTENA 0x04
#define MCP23017_DEFVALA 0x06
#define MCP23017_INTCONA 0x08
#define MCP23017_IOCONA 0x0A
#define MCP23017_GPPUA 0x0C
#define MCP23017_INTFA 0x0E
#define MCP23017_INTCAPA 0x10
#define MCP23017_GPIOA 0x12
#define MCP23017_OLATA 0x14
#define MCP23017_IODIRB 0x01
#define MCP23017_IPOLB 0x03
#define MCP23017_GPINTENB 0x05
#define MCP23017_DEFVALB 0x07
#define MCP23017_INTCONB 0x09
#define MCP23017_IOCONB 0x0B
#define MCP23017_GPPUB 0x0D
#define MCP23017_INTFB 0x0F
#define MCP23017_INTCAPB 0x11
#define MCP23017_GPIOB 0x13
#define MCP23017_OLATB 0x15
#define MCP23017_INT_ERR 255
#endif

View file

@ -0,0 +1,15 @@
This is a library for the MCP23017 I2c Port Expander
These chips use I2C to communicate, 2 pins required to interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_MCP23017. Check that the Adafruit_MCP23017 folder contains Adafruit_MCP23017.cpp and Adafruit_MCP23017.h
Place the Adafruit_MCP23017 library folder your <arduinosketchfolder>/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.

View file

@ -0,0 +1,32 @@
#include <Wire.h>
#include "Adafruit_MCP23017.h"
// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!
// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
// Input #0 is on pin 21 so connect a button or switch from there to ground
Adafruit_MCP23017 mcp;
void setup() {
mcp.begin(); // use default address 0
mcp.pinMode(0, INPUT);
mcp.pullUp(0, HIGH); // turn on a 100K pullup internally
pinMode(13, OUTPUT); // use the p13 LED as debugging
}
void loop() {
// The LED will 'echo' the button
digitalWrite(13, mcp.digitalRead(0));
}

View file

@ -0,0 +1,123 @@
// Install the LowPower library for optional sleeping support.
// See loop() function comments for details on usage.
//#include <LowPower.h>
#include <Wire.h>
#include <Adafruit_MCP23017.h>
Adafruit_MCP23017 mcp;
byte ledPin=13;
// Interrupts from the MCP will be handled by this PIN
byte arduinoIntPin=3;
// ... and this interrupt vector
byte arduinoInterrupt=1;
volatile boolean awakenByInterrupt = false;
// Two pins at the MCP (Ports A/B where some buttons have been setup.)
// Buttons connect the pin to grond, and pins are pulled up.
byte mcpPinA=7;
byte mcpPinB=15;
void setup(){
Serial.begin(9600);
Serial.println("MCP23007 Interrupt Test");
pinMode(arduinoIntPin,INPUT);
mcp.begin(); // use default address 0
// We mirror INTA and INTB, so that only one line is required between MCP and Arduino for int reporting
// The INTA/B will not be Floating
// INTs will be signaled with a LOW
mcp.setupInterrupts(true,false,LOW);
// configuration for a button on port A
// interrupt will triger when the pin is taken to ground by a pushbutton
mcp.pinMode(mcpPinA, INPUT);
mcp.pullUp(mcpPinA, HIGH); // turn on a 100K pullup internally
mcp.setupInterruptPin(mcpPinA,FALLING);
// similar, but on port B.
mcp.pinMode(mcpPinB, INPUT);
mcp.pullUp(mcpPinB, HIGH); // turn on a 100K pullup internall
mcp.setupInterruptPin(mcpPinB,FALLING);
// We will setup a pin for flashing from the int routine
pinMode(ledPin, OUTPUT); // use the p13 LED as debugging
}
// The int handler will just signal that the int has happen
// we will do the work from the main loop.
void intCallBack(){
awakenByInterrupt=true;
}
void handleInterrupt(){
// Get more information from the MCP from the INT
uint8_t pin=mcp.getLastInterruptPin();
uint8_t val=mcp.getLastInterruptPinValue();
// We will flash the led 1 or 2 times depending on the PIN that triggered the Interrupt
// 3 and 4 flases are supposed to be impossible conditions... just for debugging.
uint8_t flashes=4;
if(pin==mcpPinA) flashes=1;
if(pin==mcpPinB) flashes=2;
if(val!=LOW) flashes=3;
// simulate some output associated to this
for(int i=0;i<flashes;i++){
delay(100);
digitalWrite(ledPin,HIGH);
delay(100);
digitalWrite(ledPin,LOW);
}
// we have to wait for the interrupt condition to finish
// otherwise we might go to sleep with an ongoing condition and never wake up again.
// as, an action is required to clear the INT flag, and allow it to trigger again.
// see datasheet for datails.
while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) ));
// and clean queued INT signal
cleanInterrupts();
}
// handy for interrupts triggered by buttons
// normally signal a few due to bouncing issues
void cleanInterrupts(){
EIFR=0x01;
awakenByInterrupt=false;
}
/**
* main routine: sleep the arduino, and wake up on Interrups.
* the LowPower library, or similar is required for sleeping, but sleep is simulated here.
* It is actually posible to get the MCP to draw only 1uA while in standby as the datasheet claims,
* however there is no stadndby mode. Its all down to seting up each pin in a way that current does not flow.
* and you can wait for interrupts while waiting.
*/
void loop(){
// enable interrupts before going to sleep/wait
// And we setup a callback for the arduino INT handler.
attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
// Simulate a deep sleep
while(!awakenByInterrupt);
// Or sleep the arduino, this lib is great, if you have it.
//LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
// disable interrupts while handling them.
detachInterrupt(arduinoInterrupt);
if(awakenByInterrupt) handleInterrupt();
}

View file

@ -0,0 +1,35 @@
#include <Wire.h>
#include "Adafruit_MCP23017.h"
// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!
// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
// Output #0 is on pin 21 so connect an LED or whatever from that to ground
Adafruit_MCP23017 mcp;
void setup() {
mcp.begin(); // use default address 0
mcp.pinMode(0, OUTPUT);
}
// flip the pin #0 up and down
void loop() {
delay(100);
mcp.digitalWrite(0, HIGH);
delay(100);
mcp.digitalWrite(0, LOW);
}

View file

@ -0,0 +1,21 @@
#######################################
# Syntax Coloring Map for MCP23017
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MCP23017 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
pullUp KEYWORD2
writeGPIOAB KEYWORD2
readGPIOAB KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View file

@ -0,0 +1,9 @@
name=Adafruit MCP23017 Arduino Library
version=1.0.4
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Library for the MCP23017 I2C Port Expander
paragraph=Library for the MCP23017 I2C Port Expander
category=Signal Input/Output
url=https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
architectures=*

View file

@ -0,0 +1,26 @@
Software License Agreement (BSD License)
Copyright (c) 2012, Adafruit Industries
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.