
# sampleRate = .02

import time
import smbus
import threading
from homealone import *

# ADS1x15 analog digital converter

class ADS1x15Interface(Interface):
    def __init__(self, name, interface=None, addr=0x48, gain=4096, sps=250, icType=0x00, event=None):
        Interface.__init__(self, name, interface)
        # self.addr = addr
        self.gain = gain
        self.sps = sps
        self.icType = icType
        self.adc = ADS1x15(i2c=self.interface, addr=addr, icType=self.icType)
        self.lock = threading.Lock()
        self.event = event

    def read(self, addr):
        debug('debugAds', self.name, "read", addr, "gain", self.gain)
        try:
            with self.lock:
                # time.sleep(sampleRate)
                value = self.adc.readADCSingleEnded(addr, self.gain, self.sps)
                debug('debugAds', self.name, "value", value)
            return float(value / 1000)
        except Exception as ex:
            log("ADS1x15Interface exception", type(ex).__name__, str(ex))
            return 0

class ADS1x15DiffInterface(ADS1x15Interface):
    def __init__(self, name, interface=None, addr=0x48, gain=4096, sps=250, icType=0x00, event=None):
        ADS1x15Interface.__init__(self, name, interface, addr, gain, sps, icType)

    def read(self, addr):
        debug('debugAds', self.name, "read", addr, "gain", self.gain)
        try:
            with self.lock:
                # time.sleep(sampleRate)
                value = self.adc.readADCDifferential(addr, addr+1, self.gain, self.sps)
                debug('debugAds', self.name, "value", value)
            return float(value / 1000)
        except Exception as ex:
            log("ADS1x15DiffInterface exception", type(ex).__name__, str(ex))
            raise
            return 0

# ===========================================================================
# ADS1x15 Class
#
# Originally written by K. Townsend, Adafruit (https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/tree/master/Adafruit_ADS1x15)
# Updates and new functions implementation by Pedro Villanueva, 03/2013.
# The only error in the original code was in line 57:
#              __ADS1015_REG_CONFIG_DR_920SPS    = 0x0050
# should be
#              __ADS1015_REG_CONFIG_DR_920SPS    = 0x0060
#
# NOT IMPLEMENTED: Conversion ready pin, page 15 datasheet.
# ===========================================================================

class ADS1x15:
  i2c = None

  # icType Identifiers
  __IC_ADS1015                      = 0x00
  __IC_ADS1115                      = 0x01

  # Pointer Register
  __ADS1015_REG_POINTER_MASK        = 0x03
  __ADS1015_REG_POINTER_CONVERT     = 0x00
  __ADS1015_REG_POINTER_CONFIG      = 0x01
  __ADS1015_REG_POINTER_LOWTHRESH   = 0x02
  __ADS1015_REG_POINTER_HITHRESH    = 0x03

  # Config Register
  __ADS1015_REG_CONFIG_OS_MASK      = 0x8000
  __ADS1015_REG_CONFIG_OS_SINGLE    = 0x8000  # Write: Set to start a single-conversion
  __ADS1015_REG_CONFIG_OS_BUSY      = 0x0000  # Read: Bit = 0 when conversion is in progress
  __ADS1015_REG_CONFIG_OS_NOTBUSY   = 0x8000  # Read: Bit = 1 when device is not performing a conversion

  __ADS1015_REG_CONFIG_MUX_MASK     = 0x7000
  __ADS1015_REG_CONFIG_MUX_DIFF_0_1 = 0x0000  # Differential P = AIN0, N = AIN1 (default)
  __ADS1015_REG_CONFIG_MUX_DIFF_0_3 = 0x1000  # Differential P = AIN0, N = AIN3
  __ADS1015_REG_CONFIG_MUX_DIFF_1_3 = 0x2000  # Differential P = AIN1, N = AIN3
  __ADS1015_REG_CONFIG_MUX_DIFF_2_3 = 0x3000  # Differential P = AIN2, N = AIN3
  __ADS1015_REG_CONFIG_MUX_SINGLE_0 = 0x4000  # Single-ended AIN0
  __ADS1015_REG_CONFIG_MUX_SINGLE_1 = 0x5000  # Single-ended AIN1
  __ADS1015_REG_CONFIG_MUX_SINGLE_2 = 0x6000  # Single-ended AIN2
  __ADS1015_REG_CONFIG_MUX_SINGLE_3 = 0x7000  # Single-ended AIN3

  __ADS1015_REG_CONFIG_PGA_MASK     = 0x0E00
  __ADS1015_REG_CONFIG_PGA_6_144V   = 0x0000  # +/-6.144V range
  __ADS1015_REG_CONFIG_PGA_4_096V   = 0x0200  # +/-4.096V range
  __ADS1015_REG_CONFIG_PGA_2_048V   = 0x0400  # +/-2.048V range (default)
  __ADS1015_REG_CONFIG_PGA_1_024V   = 0x0600  # +/-1.024V range
  __ADS1015_REG_CONFIG_PGA_0_512V   = 0x0800  # +/-0.512V range
  __ADS1015_REG_CONFIG_PGA_0_256V   = 0x0A00  # +/-0.256V range

  __ADS1015_REG_CONFIG_MODE_MASK    = 0x0100
  __ADS1015_REG_CONFIG_MODE_CONTIN  = 0x0000  # Continuous conversion mode
  __ADS1015_REG_CONFIG_MODE_SINGLE  = 0x0100  # Power-down single-shot mode (default)

  __ADS1015_REG_CONFIG_DR_MASK      = 0x00E0
  __ADS1015_REG_CONFIG_DR_128SPS    = 0x0000  # 128 samples per second
  __ADS1015_REG_CONFIG_DR_250SPS    = 0x0020  # 250 samples per second
  __ADS1015_REG_CONFIG_DR_490SPS    = 0x0040  # 490 samples per second
  __ADS1015_REG_CONFIG_DR_920SPS    = 0x0060  # 920 samples per second
  __ADS1015_REG_CONFIG_DR_1600SPS   = 0x0080  # 1600 samples per second (default)
  __ADS1015_REG_CONFIG_DR_2400SPS   = 0x00A0  # 2400 samples per second
  __ADS1015_REG_CONFIG_DR_3300SPS   = 0x00C0  # 3300 samples per second (also 0x00E0)

  __ADS1115_REG_CONFIG_DR_8SPS      = 0x0000  # 8 samples per second
  __ADS1115_REG_CONFIG_DR_16SPS     = 0x0020  # 16 samples per second
  __ADS1115_REG_CONFIG_DR_32SPS     = 0x0040  # 32 samples per second
  __ADS1115_REG_CONFIG_DR_64SPS     = 0x0060  # 64 samples per second
  __ADS1115_REG_CONFIG_DR_128SPS    = 0x0080  # 128 samples per second
  __ADS1115_REG_CONFIG_DR_250SPS    = 0x00A0  # 250 samples per second (default)
  __ADS1115_REG_CONFIG_DR_475SPS    = 0x00C0  # 475 samples per second
  __ADS1115_REG_CONFIG_DR_860SPS    = 0x00E0  # 860 samples per second

  __ADS1015_REG_CONFIG_CMODE_MASK   = 0x0010
  __ADS1015_REG_CONFIG_CMODE_TRAD   = 0x0000  # Traditional comparator with hysteresis (default)
  __ADS1015_REG_CONFIG_CMODE_WINDOW = 0x0010  # Window comparator

  __ADS1015_REG_CONFIG_CPOL_MASK    = 0x0008
  __ADS1015_REG_CONFIG_CPOL_ACTVLOW = 0x0000  # ALERT/RDY pin is low when active (default)
  __ADS1015_REG_CONFIG_CPOL_ACTVHI  = 0x0008  # ALERT/RDY pin is high when active

  __ADS1015_REG_CONFIG_CLAT_MASK    = 0x0004  # Determines if ALERT/RDY pin latches once asserted
  __ADS1015_REG_CONFIG_CLAT_NONLAT  = 0x0000  # Non-latching comparator (default)
  __ADS1015_REG_CONFIG_CLAT_LATCH   = 0x0004  # Latching comparator

  __ADS1015_REG_CONFIG_CQUE_MASK    = 0x0003
  __ADS1015_REG_CONFIG_CQUE_1CONV   = 0x0000  # Assert ALERT/RDY after one conversions
  __ADS1015_REG_CONFIG_CQUE_2CONV   = 0x0001  # Assert ALERT/RDY after two conversions
  __ADS1015_REG_CONFIG_CQUE_4CONV   = 0x0002  # Assert ALERT/RDY after four conversions
  __ADS1015_REG_CONFIG_CQUE_NONE    = 0x0003  # Disable the comparator and put ALERT/RDY in high state (default)


  # Dictionaries with the sampling speed values
  # These simplify and clean the code (avoid the abuse of if/elif/else clauses)
  spsADS1115 = {
    8:__ADS1115_REG_CONFIG_DR_8SPS,
    16:__ADS1115_REG_CONFIG_DR_16SPS,
    32:__ADS1115_REG_CONFIG_DR_32SPS,
    64:__ADS1115_REG_CONFIG_DR_64SPS,
    128:__ADS1115_REG_CONFIG_DR_128SPS,
    250:__ADS1115_REG_CONFIG_DR_250SPS,
    475:__ADS1115_REG_CONFIG_DR_475SPS,
    860:__ADS1115_REG_CONFIG_DR_860SPS
  }
  spsADS1015 = {
    128:__ADS1015_REG_CONFIG_DR_128SPS,
    250:__ADS1015_REG_CONFIG_DR_250SPS,
    490:__ADS1015_REG_CONFIG_DR_490SPS,
    920:__ADS1015_REG_CONFIG_DR_920SPS,
    1600:__ADS1015_REG_CONFIG_DR_1600SPS,
    2400:__ADS1015_REG_CONFIG_DR_2400SPS,
    3300:__ADS1015_REG_CONFIG_DR_3300SPS
  }
  # Dictionariy with the programable gains
  pgaADS1x15 = {
    6144:__ADS1015_REG_CONFIG_PGA_6_144V,
    4096:__ADS1015_REG_CONFIG_PGA_4_096V,
    2048:__ADS1015_REG_CONFIG_PGA_2_048V,
    1024:__ADS1015_REG_CONFIG_PGA_1_024V,
    512:__ADS1015_REG_CONFIG_PGA_0_512V,
    256:__ADS1015_REG_CONFIG_PGA_0_256V
  }

  # Constructor
  def __init__(self, i2c, addr=0x48, icType=__IC_ADS1015, debug=False):
    # Depending on if you have an old or a new Raspberry Pi, you
    # may need to change the I2C bus.  Older Pis use SMBus 0,
    # whereas new Pis use SMBus 1.  If you see an error like:
    # 'Error accessing 0x48: Check your I2C address '
    # change the SMBus number in the initializer below!
    self.i2c = i2c
    self.addr = addr
    self.icType = icType
    self.debug = debug

    # Make sure the icType specified is valid
    if ((icType < self.__IC_ADS1015) | (icType > self.__IC_ADS1115)):
      if (self.debug):
        print("ADS1x15: Invalid icType specfied: %h" % icType)
      return -1
    else:
      self.icType = icType

    # Set pga value, so that getLastConversionResult() can use it,
    # any function that accepts a pga value must update this.
    self.pga = 6144


  def readADCSingleEnded(self, channel=0, pga=6144, sps=250):
    "Gets a single-ended ADC reading from the specified channel in mV. \
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see datasheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."

    # With invalid channel return -1
    if (channel > 3):
      if (self.debug):
        print("ADS1x15: Invalid channel specified: %d" % channel)
      return -1

    # Disable comparator, Non-latching, Alert/Rdy active low
    # traditional comparator, single-shot mode
    config = self.__ADS1015_REG_CONFIG_CQUE_NONE    | \
             self.__ADS1015_REG_CONFIG_CLAT_NONLAT  | \
             self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \
             self.__ADS1015_REG_CONFIG_CMODE_TRAD   | \
             self.__ADS1015_REG_CONFIG_MODE_SINGLE

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set the channel to be converted
    if channel == 3:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3
    elif channel == 2:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2
    elif channel == 1:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1
    else:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0

    # Set 'start single-conversion' bit
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write config register to the ADC
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)

    # Wait for the ADC conversion to complete
    # The minimum delay depends on the sps: delay >= 1/sps
    # We add 0.1ms to be sure
    delay = 1.0/sps+0.0001
    time.sleep(delay)

    # Read the conversion results
    result = self.i2c.readBlock(self.addr, self.__ADS1015_REG_POINTER_CONVERT, 2)
    if (self.icType == self.__IC_ADS1015):
        # Shift right 4 bits for the 12-bit ADS1015 and convert to mV
        return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0
    else:
      # Return a mV value for the ADS1115
      # (Take signed values into account as well)
      val = (result[0] << 8) | (result[1])
      if val > 0x7FFF:
        return (val - 0xFFFF)*pga/32768.0
      else:
        return ( (result[0] << 8) | (result[1]) )*pga/32768.0


  def readADCDifferential(self, chP=0, chN=1, pga=6144, sps=250):
    "Gets a differential ADC reading from channels chP and chN in mV. \
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see data sheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."

    # Disable comparator, Non-latching, Alert/Rdy active low
    # traditional comparator, single-shot mode
    config = self.__ADS1015_REG_CONFIG_CQUE_NONE    | \
             self.__ADS1015_REG_CONFIG_CLAT_NONLAT  | \
             self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \
             self.__ADS1015_REG_CONFIG_CMODE_TRAD   | \
             self.__ADS1015_REG_CONFIG_MODE_SINGLE

    # Set channels
    if ( (chP == 0) & (chN == 1) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1
    elif ( (chP == 0) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3
    elif ( (chP == 2) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3
    elif ( (chP == 1) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3
    else:
      if (self.debug):
        print("ADS1x15: Invalid channels specified: %d, %d" % (chP, chN))
        return -1

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init()) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set 'start single-conversion' bit
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write config register to the ADC
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)

    # Wait for the ADC conversion to complete
    # The minimum delay depends on the sps: delay >= 1/sps
    # We add 0.1ms to be sure
    delay = 1.0/sps+0.0001
    time.sleep(delay)

    # Read the conversion results
    result = self.i2c.readBlock(self.addr, self.__ADS1015_REG_POINTER_CONVERT, 2)
    if (self.icType == self.__IC_ADS1015):
        # Shift right 4 bits for the 12-bit ADS1015 and convert to mV
        return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0
    else:
      # Return a mV value for the ADS1115
      # (Take signed values into account as well)
      val = (result[0] << 8) | (result[1])
      if val > 0x7FFF:
        return (val - 0xFFFF)*pga/32768.0
      else:
        return ( (result[0] << 8) | (result[1]) )*pga/32768.0


  def readADCDifferential01(self, pga=6144, sps=250):
    "Gets a differential ADC reading from channels 0 and 1 in mV\
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see data sheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."
    return self.readADCDifferential(0, 1, pga, sps)


  def readADCDifferential03(self, pga=6144, sps=250):
    "Gets a differential ADC reading from channels 0 and 3 in mV \
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see data sheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."
    return self.readADCDifferential(0, 3, pga, sps)


  def readADCDifferential13(self, pga=6144, sps=250):
    "Gets a differential ADC reading from channels 1 and 3 in mV \
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see data sheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."
    return self.__readADCDifferential(1, 3, pga, sps)


  def readADCDifferential23(self, pga=6144, sps=250):
    "Gets a differential ADC reading from channels 2 and 3 in mV \
    The sample rate for this mode (single-shot) can be used to lower the noise \
    (low sps) or to lower the power consumption (high sps) by duty cycling, \
    see data sheet page 14 for more info. \
    The pga must be given in mV, see page 13 for the supported values."
    return self.readADCDifferential(2, 3, pga, sps)


  def startContinuousConversion(self, channel=0, pga=6144, sps=250):
    "Starts the continuous conversion mode and returns the first ADC reading \
    in mV from the specified channel. \
    The sps controls the sample rate. \
    The pga must be given in mV, see datasheet page 13 for the supported values. \
    Use getLastConversionResults() to read the next values and \
    stopContinuousConversion() to stop converting."

    # Default to channel 0 with invalid channel, or return -1?
    if (channel > 3):
      if (self.debug):
        print("ADS1x15: Invalid channel specified: %d" % channel)
      return -1

    # Disable comparator, Non-latching, Alert/Rdy active low
    # traditional comparator, continuous mode
    # The last flag is the only change we need, page 11 datasheet
    config = self.__ADS1015_REG_CONFIG_CQUE_NONE    | \
             self.__ADS1015_REG_CONFIG_CLAT_NONLAT  | \
             self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \
             self.__ADS1015_REG_CONFIG_CMODE_TRAD   | \
             self.__ADS1015_REG_CONFIG_MODE_CONTIN

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init()) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set the channel to be converted
    if channel == 3:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3
    elif channel == 2:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2
    elif channel == 1:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1
    else:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0

    # Set 'start single-conversion' bit to begin conversions
    # No need to change this for continuous mode!
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write config register to the ADC
    # Once we write the ADC will convert continously
    # we can read the next values using getLastConversionResult
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)

    # Wait for the ADC conversion to complete
    # The minimum delay depends on the sps: delay >= 1/sps
    # We add 0.5ms to be sure
    delay = 1.0/sps+0.0005
    time.sleep(delay)

    # Read the conversion results
    result = self.i2c.readBlock(self.addr, self.__ADS1015_REG_POINTER_CONVERT, 2)
    if (self.icType == self.__IC_ADS1015):
        # Shift right 4 bits for the 12-bit ADS1015 and convert to mV
        return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0
    else:
      # Return a mV value for the ADS1115
      # (Take signed values into account as well)
      val = (result[0] << 8) | (result[1])
      if val > 0x7FFF:
        return (val - 0xFFFF)*pga/32768.0
      else:
        return ( (result[0] << 8) | (result[1]) )*pga/32768.0

  def startContinuousDifferentialConversion(self, chP=0, chN=1, pga=6144, sps=250):
    "Starts the continuous differential conversion mode and returns the first ADC reading \
    in mV as the difference from the specified channels. \
    The sps controls the sample rate. \
    The pga must be given in mV, see datasheet page 13 for the supported values. \
    Use getLastConversionResults() to read the next values and \
    stopContinuousConversion() to stop converting."

    # Disable comparator, Non-latching, Alert/Rdy active low
    # traditional comparator, continuous mode
    # The last flag is the only change we need, page 11 datasheet
    config = self.__ADS1015_REG_CONFIG_CQUE_NONE    | \
             self.__ADS1015_REG_CONFIG_CLAT_NONLAT  | \
             self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \
             self.__ADS1015_REG_CONFIG_CMODE_TRAD   | \
             self.__ADS1015_REG_CONFIG_MODE_CONTIN

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init()) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % sps)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set channels
    if ( (chP == 0) & (chN == 1) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1
    elif ( (chP == 0) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3
    elif ( (chP == 2) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3
    elif ( (chP == 1) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3
    else:
      if (self.debug):
        print("ADS1x15: Invalid channels specified: %d, %d" % (chP, chN))
    return -1

    # Set 'start single-conversion' bit to begin conversions
    # No need to change this for continuous mode!
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write config register to the ADC
    # Once we write the ADC will convert continously
    # we can read the next values using getLastConversionResult
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)

    # Wait for the ADC conversion to complete
    # The minimum delay depends on the sps: delay >= 1/sps
    # We add 0.5ms to be sure
    delay = 1.0/sps+0.0005
    time.sleep(delay)

    # Read the conversion results
    result = self.i2c.readBlock(self.addr, self.__ADS1015_REG_POINTER_CONVERT, 2)
    if (self.icType == self.__IC_ADS1015):
      # Shift right 4 bits for the 12-bit ADS1015 and convert to mV
      return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0
    else:
      # Return a mV value for the ADS1115
      # (Take signed values into account as well)
      val = (result[0] << 8) | (result[1])
      if val > 0x7FFF:
        return (val - 0xFFFF)*pga/32768.0
      else:
        return ( (result[0] << 8) | (result[1]) )*pga/32768.0


  def stopContinuousConversion(self):
    "Stops the ADC's conversions when in continuous mode \
    and resets the configuration to its default value."
    # Write the default config register to the ADC
    # Once we write, the ADC will do a single conversion and
    # enter power-off mode.
    config = 0x8583 # Page 18 datasheet.
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)
    return True

  def getLastConversionResults(self):
    "Returns the last ADC conversion result in mV"
    # Read the conversion results
    result = self.i2c.readBlock(self.addr, self.__ADS1015_REG_POINTER_CONVERT, 2)
    if (self.icType == self.__IC_ADS1015):
        # Shift right 4 bits for the 12-bit ADS1015 and convert to mV
        return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*self.pga/2048.0
    else:
      # Return a mV value for the ADS1115
      # (Take signed values into account as well)
      val = (result[0] << 8) | (result[1])
      if val > 0x7FFF:
        return (val - 0xFFFF)*self.pga/32768.0
      else:
        return ( (result[0] << 8) | (result[1]) )*self.pga/32768.0


  def startSingleEndedComparator(self, channel, thresholdHigh, thresholdLow, \
                                 pga=6144, sps=250, \
                                 activeLow=True, traditionalMode=True, latching=False, \
                                 numReadings=1):
    "Starts the comparator mode on the specified channel, see datasheet pg. 15. \
    In traditional mode it alerts (ALERT pin will go low)  when voltage exceeds  \
    thresholdHigh until it falls below thresholdLow (both given in mV). \
    In window mode (traditionalMode=False) it alerts when voltage doesn't lie\
    between both thresholds.\
    In latching mode the alert will continue until the conversion value is read. \
    numReadings controls how many readings are necessary to trigger an alert: 1, 2 or 4.\
    Use getLastConversionResults() to read the current value  (which may differ \
    from the one that triggered the alert) and clear the alert pin in latching mode. \
    This function starts the continuous conversion mode.  The sps controls \
    the sample rate and the pga the gain, see datasheet page 13. "

    # With invalid channel return -1
    if (channel > 3):
      if (self.debug):
        print("ADS1x15: Invalid channel specified: %d" % channel)
      return -1

    # Continuous mode
    config = self.__ADS1015_REG_CONFIG_MODE_CONTIN

    if (activeLow==False):
      config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVHI
    else:
      config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW

    if (traditionalMode==False):
      config |= self.__ADS1015_REG_CONFIG_CMODE_WINDOW
    else:
      config |= self.__ADS1015_REG_CONFIG_CMODE_TRAD

    if (latching==True):
      config |= self.__ADS1015_REG_CONFIG_CLAT_LATCH
    else:
      config |= self.__ADS1015_REG_CONFIG_CLAT_NONLAT

    if (numReadings==4):
      config |= self.__ADS1015_REG_CONFIG_CQUE_4CONV
    elif (numReadings==2):
      config |= self.__ADS1015_REG_CONFIG_CQUE_2CONV
    else:
      config |= self.__ADS1015_REG_CONFIG_CQUE_1CONV

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init()) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      if ( (sps not in self.spsADS1015) & self.debug):
        print("ADS1x15: Invalid sps specified: %d, using 1600sps" % sps)
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid sps specified: %d, using 250sps" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % pga)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set the channel to be converted
    if channel == 3:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3
    elif channel == 2:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2
    elif channel == 1:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1
    else:
      config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0

    # Set 'start single-conversion' bit to begin conversions
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write threshold high and low registers to the ADC
    # V_digital = (2^(n-1)-1)/pga*V_analog
    if (self.icType == self.__IC_ADS1015):
      thresholdHighWORD = int(thresholdHigh*(2048.0/pga))
    else:
      thresholdHighWORD = int(thresholdHigh*(32767.0/pga))
    bytes = [(thresholdHighWORD >> 8) & 0xFF, thresholdHighWORD & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_HITHRESH, bytes)

    if (self.icType == self.__IC_ADS1015):
      thresholdLowWORD = int(thresholdLow*(2048.0/pga))
    else:
      thresholdLowWORD = int(thresholdLow*(32767.0/pga))
    bytes = [(thresholdLowWORD >> 8) & 0xFF, thresholdLowWORD & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_LOWTHRESH, bytes)

    # Write config register to the ADC
    # Once we write the ADC will convert continously and alert when things happen,
    # we can read the converted values using getLastConversionResult
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)


  def startDifferentialComparator(self, chP, chN, thresholdHigh, thresholdLow, \
                                 pga=6144, sps=250, \
                                 activeLow=True, traditionalMode=True, latching=False, \
                                 numReadings=1):
    "Starts the comparator mode on the specified channel, see datasheet pg. 15. \
    In traditional mode it alerts (ALERT pin will go low)  when voltage exceeds  \
    thresholdHigh until it falls below thresholdLow (both given in mV). \
    In window mode (traditionalMode=False) it alerts when voltage doesn't lie\
    between both thresholds.\
    In latching mode the alert will continue until the conversion value is read. \
    numReadings controls how many readings are necessary to trigger an alert: 1, 2 or 4.\
    Use getLastConversionResults() to read the current value  (which may differ \
    from the one that triggered the alert) and clear the alert pin in latching mode. \
    This function starts the continuous conversion mode.  The sps controls \
    the sample rate and the pga the gain, see datasheet page 13. "

    # Continuous mode
    config = self.__ADS1015_REG_CONFIG_MODE_CONTIN

    if (activeLow==False):
      config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVHI
    else:
      config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW

    if (traditionalMode==False):
      config |= self.__ADS1015_REG_CONFIG_CMODE_WINDOW
    else:
      config |= self.__ADS1015_REG_CONFIG_CMODE_TRAD

    if (latching==True):
      config |= self.__ADS1015_REG_CONFIG_CLAT_LATCH
    else:
      config |= self.__ADS1015_REG_CONFIG_CLAT_NONLAT

    if (numReadings==4):
      config |= self.__ADS1015_REG_CONFIG_CQUE_4CONV
    elif (numReadings==2):
      config |= self.__ADS1015_REG_CONFIG_CQUE_2CONV
    else:
      config |= self.__ADS1015_REG_CONFIG_CQUE_1CONV

    # Set sample per seconds, defaults to 250sps
    # If sps is in the dictionary (defined in init()) it returns the value of the constant
    # othewise it returns the value for 250sps. This saves a lot of if/elif/else code!
    if (self.icType == self.__IC_ADS1015):
      if ( (sps not in self.spsADS1015) & self.debug):
        print("ADS1x15: Invalid sps specified: %d, using 1600sps" % sps)
      config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS)
    else:
      if ( (sps not in self.spsADS1115) & self.debug):
        print("ADS1x15: Invalid sps specified: %d, using 250sps" % sps)
      config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS)

    # Set PGA/voltage range, defaults to +-6.144V
    if ( (pga not in self.pgaADS1x15) & self.debug):
      print("ADS1x15: Invalid pga specified: %d, using 6144mV" % pga)
    config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V)
    self.pga = pga

    # Set channels
    if ( (chP == 0) & (chN == 1) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1
    elif ( (chP == 0) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3
    elif ( (chP == 2) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3
    elif ( (chP == 1) & (chN == 3) ):
      config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3
    else:
      if (self.debug):
        print("ADS1x15: Invalid channels specified: %d, %d" % (chP, chN))
    return -1

    # Set 'start single-conversion' bit to begin conversions
    config |= self.__ADS1015_REG_CONFIG_OS_SINGLE

    # Write threshold high and low registers to the ADC
    # V_digital = (2^(n-1)-1)/pga*V_analog
    if (self.icType == self.__IC_ADS1015):
      thresholdHighWORD = int(thresholdHigh*(2048.0/pga))
    else:
      thresholdHighWORD = int(thresholdHigh*(32767.0/pga))
    bytes = [(thresholdHighWORD >> 8) & 0xFF, thresholdHighWORD & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_HITHRESH, bytes)

    if (self.icType == self.__IC_ADS1015):
      thresholdLowWORD = int(thresholdLow*(2048.0/pga))
    else:
      thresholdLowWORD = int(thresholdLow*(32767.0/pga))
    bytes = [(thresholdLowWORD >> 8) & 0xFF, thresholdLowWORD & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_LOWTHRESH, bytes)

    # Write config register to the ADC
    # Once we write the ADC will convert continously and alert when things happen,
    # we can read the converted values using getLastConversionResult
    bytes = [(config >> 8) & 0xFF, config & 0xFF]
    self.i2c.writeBlock(self.addr, self.__ADS1015_REG_POINTER_CONFIG, bytes)
