]> defiant.homedns.org Git - pyshared.git/blob - bus_pirate.py
Bootloader: Allow to set i2c addr
[pyshared.git] / bus_pirate.py
1 #!/usr/bin/env python
2 # -*- coding: iso-8859-15 -*-
3
4 import serial
5 import struct
6 import threading
7
8 dPinToBit = {
9                 "POWER": 6,
10                 "PULLUP": 5,
11                 "AUX": 4,
12                 "MOSI": 3,
13                 "CLK": 2,
14                 "MISO": 1,
15                 "CS": 0
16 }
17
18 # http://dangerousprototypes.com/docs/Bitbang
19 # http://dangerousprototypes.com/docs/SPI_(binary)
20 class BP:
21         def __init__(self, sDevice):
22                 self.lock = threading.Lock()
23                 self.pSerial = serial.Serial(sDevice, baudrate=115200, timeout=0.1)
24                 self.mode_bit_bang()
25                 self.io_state = 0
26                 self.io_dir = 0
27
28         def command(self, cmd, num_read):
29                 with self.lock:
30                         self.pSerial.write(cmd)
31                         return self.pSerial.read(num_read)
32
33         def mode_bit_bang(self):
34                 for i in range(20):
35                         if self.command(chr(0x0), 5) == "BBIO1":
36                                 return
37                 raise Exception("Failed to enter bit bang mode")
38
39         def mode_spi(self, mode, speed):
40                 if self.command(chr(0x1), 4) != "SPI1":
41                         raise Exception()
42                 self.spi_set_mode(mode)
43                 self.spi_set_speed(speed)
44
45         def spi_set_mode(self, mode):
46                 if mode not in range(0, 4):
47                         raise Exception("Unknown mode")
48                 if mode == 0:
49                         self.spi_command(chr(0b10001000))
50                 elif mode == 1:
51                         self.spi_command(chr(0b10001010))
52                 elif mode == 2:
53                         self.spi_command(chr(0b10001100))
54                 elif mode == 3:
55                         self.spi_command(chr(0b10001110))
56
57         def spi_set_speed(self, speed):
58                 lSpeeds = ["30kHz", "125kHz", "250kHz", "1MHz", "2MHz", "2.6MHz", "4MHz", "8MHz"]
59                 val = lSpeeds.index(speed)
60                 self.spi_command(chr(0b01100000 | val))
61
62         def power_enable(self):
63                 self.set_io("POWER", True)
64         
65         def get_adc(self):
66                 s = self.command(chr(0x14), 2)
67                 v = struct.unpack(">h", s)
68                 return v[0]/1024.0*6.6
69
70         # http://codepad.org/qtYpZmIF
71         def pwm(self, freq, duty_cycle_percent):
72                 lPrescaler = {0:1, 1:8 , 2:64, 3:256}
73                 Fosc = 32e6
74                 Tcy = 2.0 / Fosc
75                 period = 1.0 / freq
76                 prescaler = 1
77
78                 # find needed prescaler
79                 for i in range(4):
80                         prescaler = lPrescaler[i]
81                         PRy = period * 1.0 / (Tcy * prescaler)
82                         PRy = int(PRy - 1)
83                         OCR = int(PRy * duty_cycle_percent)
84
85                         if PRy < (2 ** 16 - 1):
86                                 break # valid value for PRy, keep values
87
88                 cmd = struct.pack(">BBHH", 0b00010010, i, OCR, PRy)
89                 ret = self.command(cmd, 1)
90                 if ord(ret) != 0x1:
91                         raise Exception()
92
93         def spi_command(self, cmd):
94                 ret = self.command(cmd, 1)
95                 if ord(ret) != 0x1:
96                         raise Exception()
97         
98         def spi_write(self, data, num_read=0):
99                 if len(data) > 4096:
100                         raise Exception("SPI Data String too long")
101                 return self.spi_command(struct.pack(">Bhh%ds" % len(data), 0x04, len(data), num_read, data))
102
103         def set_io_output(self, pin):
104                 if pin not in dPinToBit.keys():
105                         raise Exception("Bad output pin")
106                 self.io_dir &= ~(1 << dPinToBit[pin])
107                 state = 0b01000000 | self.io_dir
108                 self.command(chr(state), 1)
109
110         def set_io_input(self, pin):
111                 if pin not in dPinToBit.keys():
112                         raise Exception("Bad input pin")
113                 self.io_dir |= (1 << dPinToBit[pin])
114                 state = 0b01000000 | self.io_dir
115                 self.command(chr(state), 1)
116
117         def set_io(self, pin, val):
118                 if pin not in dPinToBit.keys():
119                         raise Exception("Bad output pin")
120                 if val:
121                         self.io_state |=  (1 << dPinToBit[pin])
122                 else:
123                         self.io_state &= ~(1 << dPinToBit[pin])
124                 state = self.update_io()
125
126         def update_io(self):
127                 state = self.command(chr(0b10000000 | self.io_state), 1)
128                 return ord(state)
129
130         def get_io(self, pin):
131                 if pin not in dPinToBit.keys():
132                         raise Exception("Bad I/O pin")
133                 state = self.update_io()
134                 return state & (1 << dPinToBit[pin])
135
136         def mode_i2c(self, bEnablePower=False, bEnablePullup=False, iSpeedkHz=100):
137                 if self.command(chr(0x2), 4) != "I2C1":
138                         raise Exception()
139
140                 dSpeeds = {
141                         5: 0x0,
142                         50: 0x1,
143                         100: 0x2,
144                         400: 0x3,
145                 }
146                 if iSpeedkHz not in dSpeeds.keys():
147                         raise Exception("Invalid I2C speed")
148                 ret = self.command(chr(0b01100000 | dSpeeds[iSpeedkHz]), 1)
149                 if ord(ret) != 0x1:
150                         raise Exception()
151
152                 periphals = 0b01000000
153                 if bEnablePower:
154                         periphals |= (1<<3)
155                 if bEnablePullup:
156                         periphals |= (1<<2)
157                 ret = self.command(chr(periphals), 1)
158                 if ord(ret) != 0x1:
159                         raise Exception()
160
161         def i2c_ping(self, addr):
162                 # 1. Write
163                 # command (1) | number of write bytes (2) | number of read bytes (2) | bytes to write (0..)
164                 msg = struct.pack(">BHHB", 0x08, 1, 0, addr)
165                 ret = self.command(msg, 1)
166
167                 if ord(ret[0]) != 0x1:
168                         raise Exception("I2C ping failed")
169
170         def i2c_write(self, addr, reg, s):
171                 # 1. Write
172                 # command (1) | number of write bytes (2) | number of read bytes (2) | bytes to write (0..)
173                 msg = struct.pack(">BHHBB%ds" % len(s), 0x08, 2+len(s), 0, addr, reg, s)
174                 ret = self.command(msg, 1)
175
176                 if ord(ret[0]) != 0x1:
177                         raise Exception("I2C write error")
178
179         def i2c_read(self, addr, reg, num_read):
180                 # set reg
181                 if reg != None:
182                         self.i2c_write(addr, reg, "")
183
184                 # command (1) | number of write bytes (2) | number of read bytes (2) | bytes to write (0..)
185                 msg = struct.pack(">BHHB", 0x08, 1, num_read, addr | 0x1)
186                 ret = self.command(msg, 1 + num_read)
187
188                 if ord(ret[0]) != 0x1:
189                         raise Exception("I2C read error")
190
191                 return ret[1:]
192
193         def i2c_search(self):
194                 for i in range(128):
195                         msg = struct.pack(">BHHB", 0x08, 1, 1, i)
196                         ret = self.command(msg, 1)
197                         if ord(ret) == 0x1:
198                                 print "Found I2C Addr: 0x%x" % (i & ~0x1)