#!   /usr/bin/env   python
#    coding: utf8

# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org

import sys
import rr
import time
import os
import re
from ctypes import *

from ptsexcept import *

from cp210x_eeprom import usb, valuefile, cp210x
from cp210x_eeprom.eeprom import EEPROM


"""
test21: Store calibration data to calibraton box CP2103 EEPROM

"""


# Calibration box vendor and device IDs
BOX_USB_VID = "10C4" # Cygnal Integrated Products, Inc.
BOX_USB_PID = "EA60" # CP210x Composite Device

CALIBR_RANGES = ['10V', '1V', '100mV']


def find_device(vid,pid):
    usb_patterns = []
    vid = int(vid, 16)
    pid = int(pid, 16)
    usb_patterns.append(dict(idVendor=vid, idProduct=pid))
    for dev in cp210x.Cp210xProgrammer.list_devices(usb_patterns):
        return dev


def get_calibr_data(dev):
    dev.open()
    try:
        eeprom = EEPROM(dev)
    finally:
        dev.close()
    eeprom_value = eeprom.get_values()
    product_string = eeprom_value['product_string']
    print "Product string: \"%s\"" % product_string
    calibr_string_list = product_string.split(' ')
    if len(calibr_string_list) != 3:
        raise Exception('Product string has the wrong format.')

    calibr_data = {}
    for i in range(len(calibr_string_list)):
        pattern = r'\b[0-9]\.[0-9]{8}\b'
        if re.search(pattern, calibr_string_list[i]):
            calibr_data[CALIBR_RANGES[i]] = calibr_string_list[i]
        else:
            raise Exception('Product string has the wrong format.')

    return calibr_data


def set_calibr_data(dev, data):
    dev.open()
    product_string = data[CALIBR_RANGES[0]] + ' ' + data[CALIBR_RANGES[1]] + ' ' + data[CALIBR_RANGES[2]]
    print "New product string value: \"%s\"" % product_string
    try:
        dev.set_product_string(product_string)
        print "Calibration data written to cp210x EEPROM."
    finally:
        dev.close()


def input_calibr_data(range_str):
    while(True):
        calibr_string = raw_input("Enter calibration voltage for "+range_str+" range (in volts, max 10 char): ")
        pattern = r'\b[0-9]\.[0-9]{8}\b'
        if re.search(pattern, calibr_string):
            return calibr_string
        else:
            print "[ERROR] Calibration string format is wrong, MUST be '\\b[0-9]\.[0-9]{8}\\b' (e.g 0.00000000).\n"
            continue


def main ():
    usb.init()
    dev = find_device(BOX_USB_VID, BOX_USB_PID)

    # Ask user to input calibration data
    calibr_data = {}
    for range_str in CALIBR_RANGES:
        calibr_data[range_str] = input_calibr_data(range_str)

    # Write calibration data to cp210x EEPROM
    set_calibr_data(dev, calibr_data)

    print "Readback calibration data from cp210x EEPROM."
    calibr_data = get_calibr_data(dev)
    for range_str, value in calibr_data.iteritems():
        print "%5s range calibration voltage is: %s V" % (range_str, value)


if __name__ == '__main__' :
    main()
