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