# 2.2.1b
#
# fuelGauge = MAX17048(0x36, traceDebug=True)
# fuelGauge.begin()
# fuelGauge.read_config()
# fuelGauge.read_vcell()
# fuelGauge.read_SOC()
# fuelGauge.read_CRate()
#

import ustruct
import time
from trap import * # 2.2.9b
from machine import I2C # 2.2.18

class MAX17048:
    def __init__(self, iicadr=0x36, i2c=None, sda='P22', scl='P21', traceDebug=False, sdAccess=False):  # 2.2.9b  cf  i2c, address, gain
        self.trace = traceDebug
        self.adr = iicadr
        self.sdAccess = sdAccess # 2.2.9b

        self.data = 0
        self.vcell = 0
        self.soc = 0
        self.crate = 0

        # I2C bus declaration is extenal
        # MCP are connected on I2C bus #1   SDA-P22   SCL-P21
        #                      I2C bus #2   SDA-P18   SCL-P17
        #
        if i2c is not None: # 2.2.18
            self.i2c1 = i2c
        else:
            # from machine import I2C
            self.i2c1 = I2C(0, mode=I2C.MASTER, pins=(sda, scl))


    def begin(self):
        # if self.trace == False: # for debug only 2.3.10
        #    print('fuelGauge SIMULATED')
        #    return True
        try:
            # print("\nChannel 0 voltage: {}V".format(self.get_voltage(0)))
            # print("Channel 0 ADC value: {}\n".format(self.read(0)))
            self.read_config()
            print('Detected fuelGauge - MAX17048 Adr:' + str(self.adr) )
            return True

        except Exception as e: # 2.2.9b
            scratch = 'fuelGauge - MAX17048 Adr:' + str(self.adr) + ' not found - '  # 2.2.9b  print('MAX17048 fuelGauge Adr:' + str(self.adr) + ' not found.')
            file_errLog(0, scratch + str(e), self.sdAccess)  # 2.2.9b
            # 2.2.18 print('Begin I2C1 scan ...')
            # 2.2.18 print(self.i2c1.scan())
            return False


    # def _write_register(self, register, value):
    #    data = ustruct.pack('>BH', register, value)
    #    self.i2c1.writeto(self.adr, data)


    def _read_register(self, register):
        self.data = self.i2c1.readfrom_mem(self.adr, register, 2 )
        if self.trace :
            print('_read_register (' + str(register) + "): " + str(self.data) )
        return ustruct.unpack('>H', self.data)[0]   # unsigned short    ustruct.unpack('>h', data)[0]

    def read_config(self):
        return self.i2c1.readfrom_mem(self.adr, 8, 2)

    def read_vcell(self):
        # if self.trace == False: return 4.11 # for debug only 2.3.10
        try: # 2.2.3b
            ADCount = self._read_register(2)
            self.vcell = ADCount * 0.000078125
        except:
            self.vcell = 0
        return self.vcell

    def read_SOC(self):
        # if self.trace == False: return 90.11 # for debug only 2.3.10
        try: # 2.2.3b
            ADCount = self._read_register(4)
            self.soc = ADCount / 256
        except:
            self.soc = 0
        return self.soc

    def read_CRate(self):
        # if self.trace == False: return 1.11 # for debug only 2.3.10
        try: # 2.2.3b
            self.data = self.i2c1.readfrom_mem(self.adr, 22, 2 )
            if self.trace :
                print('read_CRate (22): ' + str(self.data) )
            ADCount = ustruct.unpack('>h', self.data)[0]  # signed 16bit
            self.crate = ADCount * 0.208   # Charge/discharge rate % per hour
        except:
            self.crate = 0
        return self.crate
