# cPy - RPi driver for 16 bit adc ads1115 over i2c
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2024-12-12  initial release

# Used board: RPi-4 with ads1115 connected to GPIO-2 SDA1 and GPIO-3 SCL1

from	collections		import	deque
from	smbus2			import	i2c_msg

# ================================= ads1115 ========================================

class Ads1115:

    SEL_DTA		= 0x00						# select data register
    SEL_CFG		= 0x01						# select config registert
    MUX_A0_A1 	= 0x00						# differential A0=Pos A1=Neg
    MUX_A2_A3 	= 0x30						# differential A0=Pos A1=Neg
    MUX_A0_GND 	= 0x40						# differential A0=Pos A1=Neg
    GAIN_2V   	= 0x04						# +/- 2.048V
    GAIN_1V   	= 0x06						# +/- 1.024V
    DR_8     	= 0x00						#   8 samples per second
    DR_32     	= 0x40						#  32 samples per second
    DR_128     	= 0x80						# 128 samples per second


    # ads1115 setup 0..2Volt between A0 and GND at 32 samples per second
    def __init__(self, i2c, addr=0x48, avg=8, mux=MUX_A0_GND, gain=GAIN_2V):
        self.i2c  = i2c
        self.addr = addr
        self.avg  = avg
        self.que  = None
        msg       = i2c_msg.write(addr, [self.SEL_CFG, mux | gain, self.DR_32])
        i2c.i2c_rdwr(msg)
        if avg >= 3:
            self.que  = deque([self.get()]*avg, avg)
        
    
    # read ADC value 0..32767 and update the deque, t = 1 mSec
    def get(self):
        msg  = i2c_msg.write(self.addr, [self.SEL_DTA])
        self.i2c.i2c_rdwr(msg)
        msg  = i2c_msg.read(self.addr, 2)
        self.i2c.i2c_rdwr(msg)
        data = list(msg)
        res  = data[0] * 256 + data[1]
        if self.que:
            self.que.append(res)
        return res        


    # return the average value of the que without largest and smallest values
    def getAvg(self):
        if self.que:
            data = list(self.que)
            data.sort()
            data = data[1:-1]
            return sum(data) // (self.avg-2)

# ================================ generator =============================

if __name__ == '__main__':
    
    import	time
    from	smbus2		import	SMBus			# full python implementation
    
    i2c		= SMBus(1)

    # dump average ads1115 value @ 10 Hz
    def generator():
        adc = Ads1115(i2c)
        while True:
            for _ in range(3):
                time.sleep(0.033)			# sample at 30Hz, adc internal is 32 Hz
                adc.get()
            print(adc.getAvg())				# print Avg @ 10 Hz
            
            
    generator()
    
# ================================== End =================================
