valuefile.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2007 Johannes Hölzl <johannes.hoelzl@gmx.de>
  3. #
  4. # This library is covered by the GNU LGPL, read LICENSE for details.
  5. # For documentation of the baudrate table see:
  6. #
  7. # [AN205] Silicon Labs Application Note 205 Rev. 0.3
  8. # http://www.silabs.com/public/documents/tpub_doc/anote/Microcontrollers/Interface/en/an205.pdf
  9. import re
  10. from ConfigParser import ConfigParser
  11. import cp210x
  12. from cp210x import VALUES, SIZE_BAUDRATES
  13. __all__ = ['read_file', 'write_file', 'update_values', 'PrescalerIsZero',
  14. 'ValuesFileError']
  15. class ValuesError(StandardError):
  16. pass
  17. class PrescalerIsZero(ValuesError):
  18. pass
  19. class ValuesFileError(ValuesError):
  20. pass
  21. version_pattern = re.compile(r'^\s*(\d\d?)\.(\d\d?)\s*$')
  22. def read_version(s):
  23. match = version_pattern.match(s)
  24. if match is None:
  25. raise ValueError("Version does not match 'xx.yy'")
  26. return (int(match.group(1)), int(match.group(2)))
  27. def write_version(v):
  28. return "%d.%02d" % v
  29. def read_hex(s):
  30. return int(s.strip(), 16)
  31. def write_hex(num):
  32. return "%04X" % num
  33. def write_bool(b):
  34. if b:
  35. return 'yes'
  36. else:
  37. return 'no'
  38. def read_bool(s):
  39. s = s.strip().lower()
  40. if s not in ['true', 'yes', 'false', 'no']:
  41. raise ValueError("Boolean must be either 'true', 'yes', 'false' or 'no'.")
  42. return s in ['true', 'yes']
  43. def read_baudrate_info(s):
  44. values = s.split(',')
  45. if len(values) != 3:
  46. raise ValueError("Baudrate info must be three comma-separated items")
  47. try:
  48. baudgen = read_hex(values[0])
  49. except ValueError:
  50. raise ValueError("The first baudrate info must be a hex-value")
  51. try:
  52. timer0 = read_hex(values[1])
  53. except ValueError:
  54. raise ValueError("The second baudrate info must be a hex-value")
  55. try:
  56. prescale = int(values[2])
  57. except ValueError:
  58. raise ValueError("The thirdbaudrate info must be a number")
  59. return (baudgen, timer0, prescale)
  60. TYPES = {
  61. 'boolean': (read_bool, write_bool),
  62. 'int': (int, str),
  63. 'id': (read_hex, write_hex),
  64. 'string': (str, str),
  65. 'version': (read_version, write_version),
  66. }
  67. def read_file(fp):
  68. cp = ConfigParser()
  69. if isinstance(fp, str):
  70. cp.read([fp])
  71. else:
  72. cp.readfp(fp)
  73. values = {}
  74. for name, type in VALUES:
  75. if name is 'baudrate_table':
  76. continue
  77. reader, _ = TYPES[type]
  78. if cp.has_option('usb device', name):
  79. try:
  80. values[name] = reader(cp.get('usb device', name))
  81. except ValueError, err:
  82. raise ValuesFileError("Key '%s': %s" % (name, str(err)))
  83. if cp.has_section('baudrate table'):
  84. baudrate_table = []
  85. for name, value in cp.items('baudrate table'):
  86. try:
  87. baudrate = int(name)
  88. except ValueError:
  89. raise ValuesFileError("Key names in 'baudrate table' must be"
  90. " baudrate numbers.")
  91. try:
  92. baudrate_table.append(read_baudrate_info(value) + (baudrate, ))
  93. except ValueError, err:
  94. raise ValuesFileError("Wrong baudrate info %i: %s"
  95. % (baudrate, str(err)))
  96. baudrate_table.sort(key=(lambda i: i[3]), reverse=True)
  97. values['baudrate_table'] = baudrate_table
  98. return values
  99. def write_file(fp, values):
  100. fp.write("[usb device]\n")
  101. for name, type in VALUES:
  102. if name == 'baudrate_table':
  103. continue
  104. _, writer = TYPES[type]
  105. if name in values:
  106. fp.write("%s = %s\n" % (name, writer(values[name])))
  107. if 'baudrate_table' in values:
  108. fp.write("\n")
  109. fp.write("[baudrate table]\n")
  110. for (baudgen, timegen, prescaler,
  111. baudrate) in sorted(values['baudrate_table'], key=(lambda i: i[3]),
  112. reverse=True):
  113. fp.write("%7d = %04X, %04X, %d # %s\n"
  114. % (baudrate, baudgen, timegen, prescaler,
  115. show_baudrate(baudgen, timegen, prescaler)))
  116. def calc_baudrate(baudgen, timegen, prescaler):
  117. # This formulas are from AN205 page 5.
  118. if prescaler == 0:
  119. raise PrescalerIsZero("Prescaler is 0")
  120. baudrate = (24000000. / prescaler) / (0x10000 - baudgen)
  121. return (baudrate, (0x10000 - timegen) * 2)
  122. def show_baudrate(baudgen, timegen, prescaler):
  123. try:
  124. baudrate, timeout = calc_baudrate(baudgen, timegen, prescaler)
  125. except PrescalerIsZero:
  126. return "Wrong data, Prescaler is 0."
  127. if timeout >= 1000:
  128. timeout = "%1.3f ms" % (float(timeout) / 1000)
  129. else:
  130. timeout = "%d us" % timeout
  131. if baudrate is None:
  132. return ", %s" % (baudrate, timeout)
  133. else:
  134. return "%7.0f Baud, %s" % (baudrate, timeout)
  135. def update_values(v, new, dev):
  136. old_baudrate_table = v.get('baudrate_table')
  137. new_baudrate_table = new.get('baudrate_table')
  138. v.update(new)
  139. # update baudrate table
  140. # it is needed, that the baudrate table has 32 entries when it is written
  141. # to the eeprom or device.
  142. if ((old_baudrate_table is not None or new_baudrate_table is not None) and
  143. (new_baudrate_table is None or
  144. len(new_baudrate_table) < SIZE_BAUDRATES)):
  145. if old_baudrate_table is not None:
  146. if len(old_baudrate_table) < SIZE_BAUDRATES:
  147. baudrate_table = old_baudrate_table
  148. else:
  149. baudrate_table = list(merge_baudrate_table(dev.baudrate_table,
  150. old_baudrate_table))
  151. else:
  152. baudrate_table = dev.baudrate_table
  153. if new_baudrate_table:
  154. baudrate_table = list(merge_baudrate_table(baudrate_table,
  155. new_baudrate_table))
  156. v['baudrate_table'] = baudrate_table
  157. def merge_baudrate_table(old, new):
  158. for (old_info, (start, stop)) in zip(old, REQUEST_BAUDRATE_RANGES):
  159. for baudgen, timer, prescaler, baudrate in new:
  160. if ((start is None or baudrate <= start) and
  161. baudrate >= stop):
  162. yield (baudgen, timer, prescaler, baudrate)
  163. break
  164. else:
  165. yield old_info
  166. REQUEST_BAUDRATE_RANGES = [
  167. # The table data is from AN205 Table 1 on page 1.
  168. # Start End Default Baudrate
  169. (None, 2457601), # Undefined
  170. (2457600, 1474561), # Undefined
  171. (1474560, 1053258), # Undefined
  172. (1053257, 670255), # 921600
  173. ( 670254, 567139), # 576000
  174. ( 567138, 491521), # 500000
  175. ( 491520, 273067), # 460800
  176. ( 273066, 254235), # 256000
  177. ( 254234, 237833), # 250000
  178. ( 237832, 156869), # 230400
  179. ( 156868, 129348), # 153600
  180. ( 129347, 117029), # 128000
  181. ( 117028, 77609), # 115200
  182. ( 77608, 64112), # 76800
  183. ( 64111, 58054), # 64000
  184. ( 58053, 56281), # 57600
  185. ( 56280, 51559), # 56000
  186. ( 51558, 38602), # 51200
  187. ( 38601, 28913), # 38400
  188. ( 28912, 19251), # 28800
  189. ( 19250, 16063), # 19200
  190. ( 16062, 14429), # 16000
  191. ( 14428, 9613), # 14400
  192. ( 9612, 7208), # 9600
  193. ( 7207, 4804), # 7200
  194. ( 4803, 4001), # 4800
  195. ( 4000, 2401), # 4000
  196. ( 2400, 1801), # 2400
  197. ( 1800, 1201), # 1800
  198. ( 1200, 601), # 1200
  199. ( 600, 301), # 600
  200. ( 300, 57), # 300
  201. ]