remove a bash-ism from a Makefile
[fx2lib.git] / utils / ihx2iic.py
blob4938ee2bc975b6995da346d5e833bbfabb19a2d5
1 #!/usr/bin/env python
3 # Copyright 2009, Ubixum, Inc
5 # This file copied and modified for fx2lib from the GnuRadio project
7 # Copyright 2004,2006 Free Software Foundation, Inc.
9 # This file is part of GNU Radio
11 # GNU Radio is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3, or (at your option)
14 # any later version.
16 # GNU Radio is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with GNU Radio; see the file COPYING. If not, write to
23 # the Free Software Foundation, Inc., 51 Franklin Street,
24 # Boston, MA 02110-1301, USA.
27 import re
28 import sys, struct
29 import os, os.path
30 from optparse import OptionParser
31 from functools import reduce
34 def hex_to_bytes (s):
35 if len (s) & 0x1:
36 raise ValueError("Length must be even")
37 r = []
38 for i in range (0, len(s), 2):
39 r.append (int (s[i:i+2], 16))
40 return r
42 def msb (x):
43 return (x >> 8) & 0xff
45 def lsb (x):
46 return x & 0xff
48 class ihx_rec (object):
49 def __init__ (self, addr, type, data):
50 self.addr = addr
51 self.type = type
52 self.data = data
54 class ihx_file (object):
55 def __init__ (self):
56 self.pat = re.compile (r':[0-9A-F]{10,}')
57 def read (self, file):
58 r = []
59 for line in file:
60 line = line.strip().upper ()
61 if not self.pat.match (line):
62 raise ValueError("Invalid hex record format")
63 bytes = hex_to_bytes (line[1:])
64 sum = reduce (lambda x, y: x + y, bytes, 0) % 256
65 if sum != 0:
66 raise ValueError("Bad hex checksum")
67 lenx = bytes[0]
68 addr = (bytes[1] << 8) + bytes[2]
69 type = bytes[3]
70 data = bytes[4:-1]
71 if lenx != len (data):
72 raise ValueError("Invalid hex record (bad length)")
73 if type != 0:
74 break;
75 r.append (ihx_rec (addr, type, data))
77 return r
80 def build_eeprom_image (filename, outfile,vid,pid,devid,cb):
81 """Build a ``C2 Load'' EEPROM image.
83 For details on this format, see section 3.4.3 of
84 the EZ-USB FX2 Technical Reference Manual
85 """
87 image = [
88 0xC2, # boot from EEPROM
89 lsb (vid),
90 msb (vid),
91 lsb (pid),
92 msb (pid),
93 lsb (devid),
94 msb (devid),
95 cb # configuration byte
98 # you could just append all the records..
99 # but that would most likely cause a lot of
100 # extra headers/addrs to be written
101 ihx = ihx_file();
102 records = ihx.read(open(filename))
104 # create image map of all values we're writing data too
105 image_map={}
106 for r in records:
107 addr=r.addr
109 l=len(r.data)
110 while c<l:
111 image_map[addr] = r.data[c]
112 addr += 1
113 c += 1
114 # now create new records based on contiguous image data
115 max_addr = max(image_map.keys())
116 records = []
117 start_addr = 0
119 while start_addr <= max_addr:
120 if start_addr not in image_map:
121 start_addr += 1
122 continue
123 end_addr = start_addr
124 # add continguous data up to 10 bits long (0x3ff)
125 # is max size, trm 3.4.3
126 size=0
127 while end_addr in image_map and size < 0x3ff:
128 end_addr += 1
129 size += 1
131 l = end_addr - start_addr
132 data = []
133 for d in range(l):
134 data.append(image_map [ start_addr + d ])
135 records.append ( ihx_rec ( start_addr, 0, data ) )
136 start_addr = end_addr
139 # 4 byte header that indicates where to load
140 # the immediately follow code bytes.
142 for r in records:
143 image.extend( [
144 msb (len (r.data)),
145 lsb (len (r.data)),
146 msb (r.addr),
147 lsb (r.addr)
149 image.extend(r.data)
152 # writes 0 to CPUCS reg (brings FX2 out of reset)
153 image.extend ( [
154 0x80,
155 0x01,
156 0xe6,
157 0x00,
158 0x00
161 buf=struct.pack ( "B"*len(image), *image )
162 print("iic Image Size" , len(buf))
163 out=open( outfile, 'wb')
164 out.write(buf)
165 out.close();
167 if __name__ == '__main__':
168 usage = "usage: %prog [options] firmware.ihx outfile"
169 parser = OptionParser (usage=usage)
170 parser.add_option ( "-v", "--vid", type="int", default=0x04b4,
171 help="Vendor ID for iic c2 image." )
172 parser.add_option ( "-p", "--pid", type="int", default=0x0082,
173 help="Product ID for iic c2 image." )
174 parser.add_option ( "-d", "--devid", type="int", default=0,
175 help="Device ID for iic c2 image." )
176 parser.add_option ( "-c", "--configbyte", type="int", default=0x04,
177 help="Configuration Byte (i2c & disconnect polarity, default 0x04)" )
178 (options, args) = parser.parse_args ()
179 if len (args) != 2:
180 parser.print_help ()
181 sys.exit (1)
183 ihx_filename = args[0]
184 iic_filename = args[1]
185 build_eeprom_image ( ihx_filename, iic_filename, options.vid, options.pid, options.devid, options.configbyte )