#!/usr/bin/python

import serial
import usbtmc
import os.path
import sys
import time
import Adafruit_GPIO as GPIO

# open serial port
ser = serial.Serial(
		port='/dev/serial0',
		baudrate = 4800,
		parity=serial.PARITY_NONE,
		stopbits=serial.STOPBITS_ONE,
		bytesize=serial.EIGHTBITS,
		timeout=1
)

def command(cmd):
  ser.write(cmd + '\r')
  time.sleep(1)
  bytesToRead = ser.inWaiting()
  result = ser.read(bytesToRead)
  withoutControlCharacters = filter(lambda x: ord(x)>=32, result)
  return withoutControlCharacters
  
# test device identification
identification = command('I?')
print('identification: ' + identification)
if 'HM8012' not in identification:
  print('no HM8012 device found')
  ser.close()
  sys.exit(1)


pinA0 = 23
pinA1 = 24

gpio = GPIO.get_platform_gpio()
gpio.setup(pinA0, GPIO.OUT)
gpio.setup(pinA1, GPIO.OUT)

gpio.output(pinA0, 0)
gpio.output(pinA1, 0)

LogFile = '/pub/logs/batteroo.csv'

siglent =  usbtmc.Instrument("USB::0x0483::0x7540::INSTR")

delay = 0.02
shunt = 1.0419

def siglentCmd(cmd):
  siglent.write(cmd)
  time.sleep(delay)

def measureVolt(adr):
  gpio.output(pinA0, adr & 1)
  gpio.output(pinA1, adr >> 1)
  time.sleep(2)
  return float(command("S?").split()[0])

def measureUCurrent():
  return measureVolt(0)

def measureBatterooIn():
  return measureVolt(1)

def measureBatterooOut():
  return measureVolt(2)

def measureShunt():
  return measureVolt(3) / shunt

def setLoad(current):
  # binary search the required voltage, measuring the shunt voltage
  volt = 0
  step = 0.64
  while True:
    siglentCmd("CH1:VOLT " + str(volt))
    shunt = measureShunt()
    #print("set: " + str(volt) + ", shunt: " + str(shunt))
    if shunt < current:
      volt += step
    else:
      volt -= step
      step /= 2
      volt += step
    if step < 0.01:
      break
    if volt > 4:
      # safety test: don't go higher than 4 V
      siglentCmd("CH1:VOLT 0")
      break

def setInputVoltage(volt):
  # start with the specified input voltage, then increment until batteroo in voltage is reached
  adjusted = volt
  while True:
    siglentCmd("CH2:VOLT " + str(adjusted))
    batterooIn = measureBatterooIn()
    #print("volt: " + str(adjusted) + ", batterooIn: " + str(batterooIn))
    if batterooIn < volt:
      adjusted += 0.01
    else:
      break
    if adjusted > 1.7:
      # safety test: don't go higher than 1.7 V
      siglentCmd("CH2:VOLT 0")
      break
  
def measureAll():
  print("uCurrent: " + str(measureUCurrent()))
  print("batteroo in: " + str(measureBatterooIn()))
  print("batteroo out: " + str(measureBatterooOut()))
  print("shunt: " + str(measureShunt()))

def createGraph(log, inputVoltage):
  line = "input voltage: " + str(inputVoltage)
  print(line)
  log.write(line + '\n')
  # print("input " + str(inputVoltage)+ " V")
  for i in range(1,11):
    # set load
    load = float(i) / 100
    # print("load " + str(load)+ " A")
    setLoad(load)
    
    # now adjust input voltage because of the voltage drop
    setInputVoltage(inputVoltage)
    line = str(measureUCurrent()) + "," + str(measureBatterooIn()) + "," + str(measureBatterooOut()) + "," + str(measureShunt())
    print(line)
    log.write(line + '\n')


with open('/pub/logs/batteroo.csv', 'w') as log:
  log.write('input current,input voltage,output voltage,output current\n')
  createGraph(log, 0.6)
  createGraph(log, 0.8)
  createGraph(log, 1.0)
  createGraph(log, 1.2)
  createGraph(log, 1.4)
  createGraph(log, 1.6)
