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