uC chip interface arduino  0.9.0
A interface for async and neuromrphic IC testing
Loading...
Searching...
No Matches
interface_spi.py
Go to the documentation of this file.
2# This file is part of the Firmware project to interface with small Async or Neuromorphic chips
3# Copyright (C) 2023 Ole Richter - University of Groningen
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18
19from .header import ConfigMainHeader, Data32bitHeader, ConfigSubHeader
20from .packet import ConfigPacket, Data32bitPacket
21import logging
22
24 """ The interface SPI creates and object though which the interface can be accessed
25
26 the pins on the uC are fixed and depend on the specific uC model, please consult the pin out diagram of you uC
27
28 to read out the state use the object funtions to get the state returned, this is done so an state ubdate can be triggered before returning the values
29 """
30 def __init__(self, api_object, interface_id):
31 """__init__ creates a not activate interface object
32
33 :param api_object: the parent manageing the conection to the uC
34 :type api_object: uC_api
35 :param interface_id: the identifier of the interface, so the interface number in the hardware it is usulay depiced after the port name like 0 -> SCK, COPI, CIPO; 1-> SCK1, COPI1, CIPO1 and so on;
36 :type interface_id: int
37 """
38
39 self.__status = 0
40 self.__status_timestamp = 0
41 self.__mode = "NONE"
42 self.__mode_timestamp = 0
43 self.__speed = 0
44 self.__speed_timestamp = 0
45 self.__order = "NONE"
46 self.__order_timestamp = 0
47 self.__number_of_bytes = 0
49 self.__data_from_chip = []
51 self.__data_to_chip = []
52 self.__data_to_chip_times = []
53 self.__api = api_object
54 self.__errors = []
55 if interface_id == 0:
56 self.__header = [ConfigMainHeader.IN_CONF_SPI0, Data32bitHeader.IN_SPI0, Data32bitHeader.OUT_SPI0]
57 elif interface_id == 1:
58 self.__header = [ConfigMainHeader.IN_CONF_SPI1, Data32bitHeader.IN_SPI1, Data32bitHeader.OUT_SPI1]
59 elif interface_id == 2:
60 self.__header = [ConfigMainHeader.IN_CONF_SPI2, Data32bitHeader.IN_SPI2, Data32bitHeader.OUT_SPI2]
61 else:
62 logging.error("SPI only up to 3 interfaces are supported at the moment")
63
64 def header(self):
65 """header returns the packet headers associated whith this interface
66
67 :return: packet headers of this interface
68 :rtype: Header (IntEnum)
69 """
70 return self.__header
71
72 def status(self):
73 """status returns the state of this interface,
74
75 it can be:
76 - active - everything is working fine
77 - activation pending - the uC has not acknolaged the activation yet after the request to activate the interface
78 - not active - the interface has not been configured and activate
79 - error - there was an error during activation or during use, please consult the errors using the errors function
80
81 :return: the state of the interface and the timestamp in us
82 :rtype: (string, int)
83 """
84 self.update()
85 state_str = ("active" if self.__status == 2 else ("activation pending" if self.__status == 1 else ("not active" if self.__status == 0 else "error" )))
86 return (state_str,self.__status_timestamp)
87
88 def interface_mode(self):
89 """interface_mode the currently active mode, consult spi arduino docs for more information
90
91 spi has 4 modes which are numbered SPI_MODE0 ...
92
93 :return: the mode and the timestamp in us as touple
94 :rtype: (string, int)
95 """
96 self.update()
97 return (self.__mode,self.__mode_timestamp)
98
99 def speed(self):
100 """speed the speed class result of the current
101
102 :return: the frequency and the timestamp in us
103 :rtype: (int, int)
104 """
105 self.update()
106 return (self.__speed,self.__speed_timestamp)
107
108 def bit_order(self):
109 """bit_order the bit order in which the word is send
110
111 :return: the active bitorder and the timestamp in us
112 :rtype: (string, int)
113 """
114 self.update()
115 return (self.__order,self.__order_timestamp)
116
118 """number_of_bytes the width of each send word, it can be 1,2,3 or 4 bytes
119
120 :return: the wisth of each word and the timestamp in us
121 :rtype: (int, int)
122 """
123 self.update()
125
126 def data_from_chip(self):
127 """data_from_chip will retun the data recoded by the uC send from the device under test (DUT)
128
129 will retun 2 lists: one with the word recoded and one with the time when it was recorded, linked by index
130
131 :return: the words from the DUT and the times of those words
132 :rtype: ([int],[int])
133 """
134 self.update()
135 return (self.__data_from_chip, data_from_chip_times)
136
137 def data_to_chip(self):
138 """data_to_chip will retun the data send by the uC to the device under test (DUT)
139
140 will retun 2 lists: one with the word send and one with the exact time when it was send, linked by index
141
142 the time might differ slightly from the time you sheduled the send word,
143 as it is the time when it was send out and the uC can only send one word at a time
144
145 :return: the words send to the DUT and the times of those words
146 :rtype: ([int],[int])
147 """
148 self.update()
149 return (self.__data_to_chip, self.__data_to_chip_times)
150
152 self.update()
153 data = self.__data_from_chip
154 time = self.__data_from_chip_times
155 self.__data_from_chip = []
156 self.__data_from_chip_times = []
157 return (data, time)
158
160 self.update()
161 data = self.__data_to_chip
162 time = self.__data_to_chip_times
163 self.__data_to_chip = []
164 self.__data_to_chip_times = []
165 return (data, time)
166
167 def errors(self):
168 """errors all errors corresponding to this interface
169
170 :return: list of all errors
171 :rtype: [string]
172 """
173 self.update()
174 return self.__errors
175
176 def __str__(self):
177 """__str__ will return the current state, properies and data as a string
178
179 :return: the current state, properies and data
180 :rtype: string
181 """
182 self.update()
183 state_str = ("active" if self.__status == 2 else ("activation pending" if self.__status == 1 else ("not active" if self.__status == 0 else "error" )))
184 return "SPI"+ \
185 "\nHeader: " + str(self.__header) + \
186 "\nStatus: " + state_str + " at " + str(self.__status_timestamp) + "us" + \
187 "\nMode "+ str(self.__mode) +" at " + str(self.__mode_timestamp) + "us" + \
188 "\nSpeed "+ str(self.__speed) +" at " + str(self.__speed_timestamp) + "us" + \
189 "\nOrder "+ str(self.__order) +" at " + str(self.__order_timestamp) + "us" + \
190 "\nBytes per word "+ str(self.__number_of_bytes) +" at " + str(self.__number_of_bytes_timestamp) + "us" + \
191 "\nSend: "+ str(self.__data_to_chip) +" at " + str(self.__data_to_chip_times) + "us" + \
192 "\nRecived: "+ str(self.__data_from_chip) +" at " + str(self.__data_from_chip_times) + "us" + \
193 "\nERRORS: "+str(self.__errors) + "\n"
194
195 def process_packet(self, packet):
196 """process_packet this function accepts packages fro this interface from the api and updates its internal state
197
198 :param packet: the packet to be processed
199 :type packet: Packet, or any sub class
200 """
201 if packet.header() in self.__header:
202 if packet.header() == self.__header[0]:
203 if packet.config_header() == ConfigSubHeader.CONF_ACTIVE:
204 self.__status = 2
205 self.__status_timestamp = packet.time()
206 return
207 elif packet.config_header() == ConfigSubHeader.CONF_BYTE_ORDER:
208 self.__order = ("MSBFIRST" if (packet.value()==1) else "LSBFIRST")
209 self.__order_timestamp = packet.time()
210 return
211 elif packet.config_header() == ConfigSubHeader.CONF_SPEED_CLASS:
212 self.__speed = packet.value()
213 self.__speed_timestamp = packet.time()
214 return
215 elif packet.config_header() == ConfigSubHeader.CONF_TYPE:
216 self.__mode = packet.value()
217 self.__mode_timestamp = packet.time()
218 return
219 elif packet.config_header() == ConfigSubHeader.CONF_WIDTH:
220 self.__number_of_bytes = packet.value()
221 self.__number_of_bytes_timestamp = packet.time()
222 return
223 elif packet.header() == self.__header[1] :
224 self.__data_to_chip.append(packet.value())
225 self.__data_to_chip_times.append(packet.time())
226 return
227 elif packet.header() == self.__header[2]:
228 self.__data_from_chip.append(packet.value())
229 self.__data_from_chip_times.append(packet.time())
230 return
231 self.__errors.append(str(packet))
232 self.__status = -1
233
234 def activate(self, mode="SPI_MODE0", speed_class=0, order="LSBFIRST",number_of_bytes=1,time=0):
235 """activate activates and configures the interface,
236 if the interface is not availible on the UC it will put its state in en error state and prevent further use
237
238 :param mode: choose between "SPI_MODE0" "SPI_MODE1" "SPI_MODE2" or "SPI_MODE3" see arduino SPI docs, defaults to "SPI_MODE0"
239 :type mode: str, optional
240 :param speed_class: 0-8 0:10kHz 1:50kHz 2:100kHz 3:500kHz 4:1MHz 5:2MHz 6:4MHz 7:8MHz 8:12MHz, defaults to 0
241 :type speed_class: int, optional
242 :param order: Choose between "MSBFIRST" or "LSBFIRST" for order in which the word is transmitted, defaults to "LSBFIRST"
243 :type order: str, optional
244 :param number_of_bytes: 1-4 number of bytes contained in a word or better the length of a word, defaults to 1
245 :type number_of_bytes: int, optional
246 :param time: the time in us after start_experiment when this function should be executed, defaults to 0 (execute instantly)
247 :type time: int, optional
248 """
249 if self.__status >= 1:
250 logging.warning("SPI interface "+str(self.__header[0])+" is already activated or waiting activation, doing nothing")
251 else:
252 self.__api.send_packet(ConfigPacket(header = self.__header[0], config_header = ConfigSubHeader.CONF_TYPE, \
253 value=( 0 if mode == "SPI_MODE0" else (1 if mode == "SPI_MODE1" else (2 if mode == "SPI_MODE2" else 3))),time = time))
254 self.__api.send_packet(ConfigPacket(header = self.__header[0], config_header = ConfigSubHeader.CONF_SPEED_CLASS,value=speed_class,time = time))
255 self.__api.send_packet(ConfigPacket(header = self.__header[0], config_header = ConfigSubHeader.CONF_BYTE_ORDER, \
256 value=(1 if order == "MSBFIRST" else 0),time = time))
257 self.__api.send_packet(ConfigPacket(header = self.__header[0], config_header = ConfigSubHeader.CONF_WIDTH,value=number_of_bytes,time = time))
258 self.__api.send_packet(ConfigPacket(header = self.__header[0], config_header = ConfigSubHeader.CONF_ACTIVE,time = time))
259 self.__status = 1
260
261 def send(self, word, time = 0):
262 """send send a word via this interface
263
264 :param word: the word to send
265 :type word: int
266 :param time: the time in us after start_experiment when this word should be send, defaults to 0 (execute instantly)
267 :type time: int, optional
268 """
269 # we dont check the status here anymore as the uC will report the error anyway
270 self.__api.send_packet(Data32bitPacket(header = self.__header[1], value = word, time = time))
271
272
273 def update(self):
274 """update updates the internal state form the uC
275 """
276 self.__api.update_state()
The interface SPI creates and object though which the interface can be accessed.
def bit_order(self)
bit_order the bit order in which the word is send
def status(self)
status returns the state of this interface,
def process_packet(self, packet)
process_packet this function accepts packages fro this interface from the api and updates its interna...
def __str__(self)
str will return the current state, properies and data as a string
def interface_mode(self)
interface_mode the currently active mode, consult spi arduino docs for more information
def number_of_bytes()
number_of_bytes the width of each send word, it can be 1,2,3 or 4 bytes
def update(self)
update updates the internal state form the uC
def send(self, word, time=0)
send send a word via this interface
def __init__(self, api_object, interface_id)
init creates a not activate interface object
def speed(self)
speed the speed class result of the current
def errors(self)
errors all errors corresponding to this interface
def activate(self, mode="SPI_MODE0", speed_class=0, order="LSBFIRST", number_of_bytes=1, time=0)
activate activates and configures the interface, if the interface is not availible on the UC it will ...
def data_from_chip(self)
data_from_chip will retun the data recoded by the uC send from the device under test (DUT)
def data_to_chip(self)
data_to_chip will retun the data send by the uC to the device under test (DUT)
The ConfigPacket is used to cumunicate configuration instructions with the uC all availible instructi...
Definition: packet.py:375
The Data32bitPacket is used to send 32bit data instructions to the uC all availible instructions are ...
Definition: packet.py:125