]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/nova/i2c.py
5c1ecb1b4612f1f14d057f0b646e3f9e14450fd9
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / nova / i2c.py
1 """I2C Class for Binho Nova"""
2
3 from adafruit_blinka.microcontroller.nova import Connection
4
5
6 class I2C:
7     """Custom I2C Class for Binho Nova"""
8     WHR_PAYLOAD_MAX_LENGTH = 1024
9
10     def __init__(self, *, frequency=400000):
11         self._nova = Connection.getInstance()
12         self._nova.setNumericalBase(10)
13         self._nova.setOperationMode(0, "I2C")
14         self._nova.setPullUpStateI2C(0, "EN")
15         self._nova.setClockI2C(0, frequency)
16
17         self._novaCMDVer = "0"
18         if hasattr(self._nova, "getCommandVer"):
19             response = self._nova.getCommandVer().split(" ")
20             if response[0] != "-NG":
21                 self._novaCMDVer = response[1]
22
23     def __del__(self):
24         """Close Nova on delete"""
25         self._nova.close()
26
27     def scan(self):
28         """Perform an I2C Device Scan"""
29         scanResults = []
30
31         for i in range(8, 121):
32             result = self._nova.scanAddrI2C(0, i << 1)
33
34             resp = result.split(" ")
35
36             if resp[3] == "OK":
37                 scanResults.append(i)
38
39         return scanResults
40
41     def writeto(self, address, buffer, *, start=0, end=None, stop=True):
42         """Write data from the buffer to an address"""
43         end = end if end else len(buffer)
44         readBytes = 0
45         if int(self._novaCMDVer) >= 1:
46             chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
47             for i in range(chunks):
48                 chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
49                 chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
50                 self._nova.writeToReadFromI2C(0,
51                                               address<<1,
52                                               stop,
53                                               readBytes,
54                                               chunk_end-chunk_start,
55                                               buffer[chunk_start:chunk_end])
56             if rest:
57                 self._nova.writeToReadFromI2C(0,
58                                               address<<1,
59                                               stop,
60                                               readBytes,
61                                               rest,
62                                               buffer[-1*rest:])
63         else:
64             self._nova.startI2C(0, address<<1)
65
66             for i in range(start, end):
67                 self._nova.writeByteI2C(0, buffer[i])
68
69             if stop:
70                 self._nova.endI2C(0)
71             else:
72                 self._nova.endI2C(0, True)
73
74     # pylint: disable=unused-argument
75     def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
76         """Read data from an address and into the buffer"""
77         end = end if end else len(buffer)
78         result = self._nova.readBytesI2C(0, address << 1, len(buffer[start:end]))
79
80         if result != "-NG":
81             resp = result.split(" ")
82
83             for i in range(len(buffer[start:end])):
84                 buffer[start + i] = int(resp[2 + i])
85         else:
86             raise RuntimeError(
87                 "Received error response from Binho Nova, result = " + result
88             )
89
90     def writeto_then_readfrom(
91             self,
92             address,
93             buffer_out,
94             buffer_in,
95             *,
96             out_start=0,
97             out_end=None,
98             in_start=0,
99             in_end=None,
100             stop=False
101     ):
102         """Write data from buffer_out to an address and then
103         read data from an address and into buffer_in
104         """
105         out_end = out_end if out_end else len(buffer_out)
106         in_end = in_end if in_end else len(buffer_in)
107         if int(self._novaCMDVer) >= 1:
108             totalIn = in_end - in_start
109             totalOut = out_end - out_start
110             totalBytes = totalIn
111             if totalOut > totalIn:
112                 totalBytes = totalOut
113             chunks, rest = divmod(totalBytes, self.WHR_PAYLOAD_MAX_LENGTH)
114             if rest > 0:
115                 chunks += 1
116
117             for i in range(chunks):
118                 # calculate the number of bytes to be written and read
119                 numInBytes = self.WHR_PAYLOAD_MAX_LENGTH
120                 if totalIn < self.WHR_PAYLOAD_MAX_LENGTH:
121                     numInBytes = totalIn
122                 numOutBytes = self.WHR_PAYLOAD_MAX_LENGTH
123                 if totalOut < self.WHR_PAYLOAD_MAX_LENGTH:
124                     numOutBytes = totalOut
125
126                 # setup the buffer out chunk offset
127                 buffer = '0'
128                 if numOutBytes > 0:
129                     chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
130                     chunk_end = chunk_start + numOutBytes
131                     buffer = buffer_out[chunk_start:chunk_end]
132
133                 result = self._nova.writeToReadFromI2C(0,
134                                                        address<<1,
135                                                        stop,
136                                                        numInBytes,
137                                                        numOutBytes,
138                                                        buffer)
139                 totalIn -= numInBytes
140                 totalOut -= numOutBytes
141
142                 if result != "-NG":
143                     if numInBytes:
144                         resp = result.split(" ")
145                         resp = resp[2]
146
147                         for j in range(numInBytes):
148                             buffer_in[in_start+i*self.WHR_PAYLOAD_MAX_LENGTH+j] = \
149                                                                      int(resp[j*2]+resp[j*2+1], 16)
150                 else:
151                     raise RuntimeError("Received error response from Binho Nova, result = " + \
152                                        result)
153         else:
154             self._nova.startI2C(0, address<<1)
155
156             for i in range(out_start, out_end):
157                 self._nova.writeByteI2C(0, buffer_out[i])
158
159             if stop:
160                 self._nova.endI2C(0)
161             else:
162                 self._nova.endI2C(0, True)
163
164             result = self._nova.readBytesI2C(0, address<<1, len(buffer_in[in_start:in_end]))
165
166             if result != "-NG":
167                 resp = result.split(" ")
168
169                 for i in range(len(buffer_in[in_start:in_end])):
170                     buffer_in[in_start+i] = int(resp[2+i])
171             else:
172                 raise RuntimeError(
173                     "Received error response from Binho Nova, result = " + result
174                 )
175 # pylint: enable=unused-argument