diff options
Diffstat (limited to 'contrib/cp210x-program/cp210x/valuefile.py')
-rw-r--r-- | contrib/cp210x-program/cp210x/valuefile.py | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/contrib/cp210x-program/cp210x/valuefile.py b/contrib/cp210x-program/cp210x/valuefile.py new file mode 100644 index 0000000..ae665d2 --- /dev/null +++ b/contrib/cp210x-program/cp210x/valuefile.py @@ -0,0 +1,234 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2007 Johannes Hölzl <johannes.hoelzl@gmx.de> +# +# This library is covered by the GNU LGPL, read LICENSE for details. + +# For documentation of the baudrate table see: +# +# [AN205] Silicon Labs Application Note 205 Rev. 0.3 +# http://www.silabs.com/public/documents/tpub_doc/anote/Microcontrollers/Interface/en/an205.pdf + +import re +from ConfigParser import ConfigParser + +import cp210x +from cp210x import VALUES, SIZE_BAUDRATES + +__all__ = ['read_file', 'write_file', 'update_values', 'PrescalerIsZero', + 'ValuesFileError'] + +class ValuesError(StandardError): + pass + +class PrescalerIsZero(ValuesError): + pass + +class ValuesFileError(ValuesError): + pass + +version_pattern = re.compile(r'^\s*(\d\d?)\.(\d\d?)\s*$') +def read_version(s): + match = version_pattern.match(s) + if match is None: + raise ValueError("Version does not match 'xx.yy'") + return (int(match.group(1)), int(match.group(2))) +def write_version(v): + return "%d.%02d" % v + +def read_hex(s): + return int(s.strip(), 16) + +def write_hex(num): + return "%04X" % num + +def write_bool(b): + if b: + return 'yes' + else: + return 'no' + +def read_bool(s): + s = s.strip().lower() + if s not in ['true', 'yes', 'false', 'no']: + raise ValueError("Boolean must be either 'true', 'yes', 'false' or 'no'.") + return s in ['true', 'yes'] + +def read_baudrate_info(s): + values = s.split(',') + if len(values) != 3: + raise ValueError("Baudrate info must be three comma-separated items") + try: + baudgen = read_hex(values[0]) + except ValueError: + raise ValueError("The first baudrate info must be a hex-value") + try: + timer0 = read_hex(values[1]) + except ValueError: + raise ValueError("The second baudrate info must be a hex-value") + try: + prescale = int(values[2]) + except ValueError: + raise ValueError("The thirdbaudrate info must be a number") + return (baudgen, timer0, prescale) + +TYPES = { + 'boolean': (read_bool, write_bool), + 'int': (int, str), + 'id': (read_hex, write_hex), + 'string': (str, str), + 'version': (read_version, write_version), +} + +def read_file(fp): + cp = ConfigParser() + if isinstance(fp, str): + cp.read([fp]) + else: + cp.readfp(fp) + + values = {} + + for name, type in VALUES: + if name is 'baudrate_table': + continue + reader, _ = TYPES[type] + if cp.has_option('usb device', name): + try: + values[name] = reader(cp.get('usb device', name)) + except ValueError, err: + raise ValuesFileError("Key '%s': %s" % (name, str(err))) + + if cp.has_section('baudrate table'): + baudrate_table = [] + for name, value in cp.items('baudrate table'): + try: + baudrate = int(name) + except ValueError: + raise ValuesFileError("Key names in 'baudrate table' must be" + " baudrate numbers.") + try: + baudrate_table.append(read_baudrate_info(value) + (baudrate, )) + except ValueError, err: + raise ValuesFileError("Wrong baudrate info %i: %s" + % (baudrate, str(err))) + baudrate_table.sort(key=(lambda i: i[3]), reverse=True) + + values['baudrate_table'] = baudrate_table + return values + +def write_file(fp, values): + fp.write("[usb device]\n") + + for name, type in VALUES: + if name == 'baudrate_table': + continue + _, writer = TYPES[type] + if name in values: + fp.write("%s = %s\n" % (name, writer(values[name]))) + + if 'baudrate_table' in values: + fp.write("\n") + fp.write("[baudrate table]\n") + for (baudgen, timegen, prescaler, + baudrate) in sorted(values['baudrate_table'], key=(lambda i: i[3]), + reverse=True): + fp.write("%7d = %04X, %04X, %d # %s\n" + % (baudrate, baudgen, timegen, prescaler, + show_baudrate(baudgen, timegen, prescaler))) + +def calc_baudrate(baudgen, timegen, prescaler): + # This formulas are from AN205 page 5. + if prescaler == 0: + raise PrescalerIsZero("Prescaler is 0") + baudrate = (24000000. / prescaler) / (0x10000 - baudgen) + return (baudrate, (0x10000 - timegen) * 2) + +def show_baudrate(baudgen, timegen, prescaler): + try: + baudrate, timeout = calc_baudrate(baudgen, timegen, prescaler) + except PrescalerIsZero: + return "Wrong data, Prescaler is 0." + if timeout >= 1000: + timeout = "%1.3f ms" % (float(timeout) / 1000) + else: + timeout = "%d us" % timeout + if baudrate is None: + return ", %s" % (baudrate, timeout) + else: + return "%7.0f Baud, %s" % (baudrate, timeout) + +def update_values(v, new, dev): + old_baudrate_table = v.get('baudrate_table') + new_baudrate_table = new.get('baudrate_table') + + v.update(new) + + # update baudrate table + # it is needed, that the baudrate table has 32 entries when it is written + # to the eeprom or device. + if ((old_baudrate_table is not None or new_baudrate_table is not None) and + (new_baudrate_table is None or + len(new_baudrate_table) < SIZE_BAUDRATES)): + + if old_baudrate_table is not None: + if len(old_baudrate_table) < SIZE_BAUDRATES: + baudrate_table = old_baudrate_table + else: + baudrate_table = list(merge_baudrate_table(dev.baudrate_table, + old_baudrate_table)) + else: + baudrate_table = dev.baudrate_table + + if new_baudrate_table: + baudrate_table = list(merge_baudrate_table(baudrate_table, + new_baudrate_table)) + v['baudrate_table'] = baudrate_table + + + +def merge_baudrate_table(old, new): + for (old_info, (start, stop)) in zip(old, REQUEST_BAUDRATE_RANGES): + for baudgen, timer, prescaler, baudrate in new: + if ((start is None or baudrate <= start) and + baudrate >= stop): + yield (baudgen, timer, prescaler, baudrate) + break + else: + yield old_info + +REQUEST_BAUDRATE_RANGES = [ +# The table data is from AN205 Table 1 on page 1. +# Start End Default Baudrate + (None, 2457601), # Undefined + (2457600, 1474561), # Undefined + (1474560, 1053258), # Undefined + (1053257, 670255), # 921600 + ( 670254, 567139), # 576000 + ( 567138, 491521), # 500000 + ( 491520, 273067), # 460800 + ( 273066, 254235), # 256000 + ( 254234, 237833), # 250000 + ( 237832, 156869), # 230400 + ( 156868, 129348), # 153600 + ( 129347, 117029), # 128000 + ( 117028, 77609), # 115200 + ( 77608, 64112), # 76800 + ( 64111, 58054), # 64000 + ( 58053, 56281), # 57600 + ( 56280, 51559), # 56000 + ( 51558, 38602), # 51200 + ( 38601, 28913), # 38400 + ( 28912, 19251), # 28800 + ( 19250, 16063), # 19200 + ( 16062, 14429), # 16000 + ( 14428, 9613), # 14400 + ( 9612, 7208), # 9600 + ( 7207, 4804), # 7200 + ( 4803, 4001), # 4800 + ( 4000, 2401), # 4000 + ( 2400, 1801), # 2400 + ( 1800, 1201), # 1800 + ( 1200, 601), # 1200 + ( 600, 301), # 600 + ( 300, 57), # 300 +] |