1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
3 # SPDX-License-Identifier: MIT
4 """SPI Class for Binho Nova"""
5 from adafruit_blinka.microcontroller.nova import Connection
9 """Custom SPI Class for Binho Nova"""
12 BUFFER_PAYLOAD_MAX_LENGTH = 64
13 WHR_PAYLOAD_MAX_LENGTH = 1024
15 def __init__(self, clock):
16 self._nova = Connection.getInstance()
17 self._nova.setNumericalBase(10)
18 self._nova.setOperationMode(0, "SPI")
19 self._nova.setClockSPI(0, clock)
20 self._nova.setModeSPI(0, 0)
21 self._nova.setIOpinMode(0, "DOUT")
22 self._nova.setIOpinMode(1, "DOUT")
23 self._nova.beginSPI(0)
24 self._novaCMDVer = "0"
25 if hasattr(self._nova, "getCommandVer"):
26 response = self._nova.getCommandVer().split(" ")
27 if response[0] != "-NG":
28 self._novaCMDVer = response[1]
30 # Cpol and Cpha set by mode
38 """Close Nova on delete"""
41 # pylint: disable=too-many-arguments,unused-argument
53 """Initialize the Port"""
54 self._nova.setClockSPI(0, baudrate)
55 self._nova.setModeSPI(0, (polarity << 1) | (phase))
57 # pylint: enable=too-many-arguments,unused-argument
60 def get_received_data(lineOutput):
61 """Return any received data"""
62 return lineOutput.split("RXD ")[1]
66 """Return the current frequency"""
67 return self._nova.getClockSPI(0).split("CLK ")[1]
69 def write(self, buf, start=0, end=None):
70 """Write data from the buffer to SPI"""
71 end = end if end else len(buf)
72 payloadMaxLength = self.BUFFER_PAYLOAD_MAX_LENGTH
73 if int(self._novaCMDVer) >= 1:
74 payloadMaxLength = self.WHR_PAYLOAD_MAX_LENGTH
75 chunks, rest = divmod(end - start, payloadMaxLength)
77 for i in range(chunks):
78 chunk_start = start + i * payloadMaxLength
79 chunk_end = chunk_start + payloadMaxLength
80 if int(self._novaCMDVer) >= 1:
81 self._nova.writeToReadFromSPI(
82 0, True, False, chunk_end - chunk_start, buf[chunk_start:chunk_end]
85 self._nova.clearBuffer(0)
86 self._nova.writeToBuffer(0, 0, buf[chunk_start:chunk_end])
87 self._nova.transferBufferSPI(0, chunk_end - chunk_start + 1)
89 if int(self._novaCMDVer) >= 1:
90 self._nova.writeToReadFromSPI(0, True, False, rest, buf[-1 * rest :])
92 self._nova.clearBuffer(0)
93 self._nova.writeToBuffer(0, 0, buf[-1 * rest :])
94 self._nova.transferBufferSPI(0, rest)
96 def readinto(self, buf, start=0, end=None, write_value=0):
97 """Read data from SPI and into the buffer"""
98 end = end if end else len(buf)
99 if int(self._novaCMDVer) >= 1:
100 chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
102 for i in range(chunks):
103 chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
104 chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
105 result = self._nova.writeToReadFromSPI(
106 0, False, True, chunk_end - chunk_start, write_value
109 resp = result.split(" ")
111 # loop over half of resp len as we're reading 2 chars at a time to form a byte
112 loops = int(len(resp) / 2)
113 for j in range(loops):
114 buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
115 resp[j * 2] + resp[j * 2 + 1], 16
119 "Received error response from Binho Nova, result = " + result
122 result = self._nova.writeToReadFromSPI(
123 0, False, True, rest, write_value
126 resp = result.split(" ")
129 # loop over half of resp len as we're reading 2 chars at a time to form a byte
130 loops = int(len(resp) / 2)
131 for j in range(loops):
132 buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
133 resp[j * 2] + resp[j * 2 + 1], 16
137 "Received error response from Binho Nova, result = " + result
140 for i in range(start, end):
141 buf[start + i] = int(
142 self.get_received_data(self._nova.transferSPI(0, write_value))
145 # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
147 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
149 """Perform a half-duplex write from buffer_out and then
150 read data into buffer_in
152 out_end = out_end if out_end else len(buffer_out)
153 in_end = in_end if in_end else len(buffer_in)
154 readlen = in_end - in_start
155 writelen = out_end - out_start
156 if readlen > writelen:
157 # resize out and pad with 0's
158 tmp = bytearray(buffer_out)
159 tmp.extend([0] * (readlen - len(buffer_out)))
162 if int(self._novaCMDVer) >= 1:
163 chunks, rest = divmod(len(buffer_out), self.WHR_PAYLOAD_MAX_LENGTH)
165 for i in range(chunks):
166 chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
167 chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
168 result = self._nova.writeToReadFromSPI(
172 chunk_end - chunk_start,
173 buffer_out[chunk_start:chunk_end],
177 resp = result.split(" ")
180 # loop over half of resp len as we're reading 2 chars at a time to form a byte
181 loops = int(len(resp) / 2)
182 for j in range(loops):
183 buffer_in[(i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j] = (
184 int(resp[j * 2] + resp[j * 2 + 1], 16)
188 "Received error response from Binho Nova, result = " + result
191 result = self._nova.writeToReadFromSPI(
192 0, True, True, rest, buffer_out[-1 * rest :]
195 resp = result.split(" ")
198 # loop over half of resp len as we're reading 2 chars at a time to form a byte
199 loops = int(len(resp) / 2)
200 for j in range(loops):
201 buffer_in[(i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j] = (
202 int(resp[j * 2] + resp[j * 2 + 1], 16)
206 "Received error response from Binho Nova, result = " + result
210 for data_out in buffer_out:
212 self.get_received_data(self._nova.transferSPI(0, data_out))
215 buffer_in[in_start + i] = data_in
218 # pylint: enable=too-many-arguments,too-many-locals,too-many-branches