uC chip interface arduino  0.9.0
A interface for async and neuromrphic IC testing
Loading...
Searching...
No Matches
interface_AER_from_chip.cpp
Go to the documentation of this file.
1/*
2 This file is part of the Firmware project to interface with small Async or Neuromorphic chips
3 Copyright (C) 2022 Matteo Cartiglia - University of Zurich
4 Copyright (C) 2022-2023 Ole Richter - University of Groningen
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>.
18*/
19#include <Arduino.h>
21#include "misc_functions.h"
22#include "interface_i2c.h"
23#include <Wire.h>
24
25// reserve and clear the memory of the static global variables.
26// see header for description
27volatile uint8_t AER_from_chip::data_pins[8][32] = {};
28volatile uint8_t AER_from_chip::data_width[8] = {};
29volatile uint8_t AER_from_chip::req_pin[8] = {};
30volatile uint8_t AER_from_chip::ack_pin[8] = {};
31volatile uint8_t AER_from_chip::req_delay[8] = {};
32volatile bool AER_from_chip::hs_lowactive[8] = {};
33volatile bool AER_from_chip::data_lowactive[8] = {};
34volatile bool AER_from_chip::active[8] = {};
35volatile uint8_t AER_from_chip::type[8] = {};
36volatile uint8_t AER_from_chip::port[8] = {};
37volatile AER_from_chip* AER_from_chip::inst[8] = {};
38
39// handles incomming configuraion packets
40void AER_from_chip::configure(uint8_t id, uint8_t config, uint8_t data){
41 // check if the ID is valid otherwise throw error
42 if (id >= 8) {
44 return;
45 }
46 uint8_t interface;
47 switch(id){
48 case 0: interface = IN_CONF_ASYNC_FROM_CHIP0; break;
49 case 1: interface = IN_CONF_ASYNC_FROM_CHIP1; break;
50 case 2: interface = IN_CONF_ASYNC_FROM_CHIP2; break;
51 case 3: interface = IN_CONF_ASYNC_FROM_CHIP3; break;
52 case 4: interface = IN_CONF_ASYNC_FROM_CHIP4; break;
53 case 5: interface = IN_CONF_ASYNC_FROM_CHIP5; break;
54 case 6: interface = IN_CONF_ASYNC_FROM_CHIP6; break;
55 case 7: interface = IN_CONF_ASYNC_FROM_CHIP7; break;
56 default:interface = OUT_ERROR; break;
57 }
58 // handle the different config sub headers
59 switch (config){
60 // activate the interface and reserve the pins
61 case CONF_ACTIVE:
71 if (AER_from_chip::active[id]){
72 // send confirmation
73 send_config(interface,config,AER_from_chip::active[id]);
74 }
75 return;
76 // configure the type (done via class switching for speed!)
77 case CONF_TYPE:
78 // replace by class
80 AER_from_chip::type[id] = data;
81 if (data == ASYNC_4Phase_MCP23017){
82 // if (!Interface_i2c::active[0]) {
83 // Interface_i2c::configure(0,CONF_BYTE_ORDER,0U);
84 // Interface_i2c::configure(0,CONF_WIDTH,2U);
85 // Interface_i2c::inst[0] = new Interface_i2c(0,100000U);
86 // } else {
87 // error_message(OUT_ERROR_INTERFACE_ALREADY_ACTIVE,IN_CONF_I2C0,0,interface);
88 // return;
89 // }
90 }
91 break;
92 // configure the location of the request pin
93 case CONF_REQ:
94 AER_from_chip::req_pin[id] = data;
95 break;
96 // configure the location of the ack pin
97 case CONF_ACK:
98 AER_from_chip::ack_pin[id] = data;
99 break;
100 // configure how many data channels are used in the AER interface
101 case CONF_WIDTH:
102 // throw error if interface is to wide
103 if (data > 32) {
106 // send confirmation
107 send_config(interface,config,32);
108 return;
109 }
110 else {
111 AER_from_chip::data_width[id] = data;
112 }
113 break;
114 // configure the delay on the req line
115 case CONF_REQ_DELAY:
116 AER_from_chip::req_delay[id] = data;
117 break;
118 // conf if handshake signals are active low or not
119 default:
120 if (config < 32){
121 AER_from_chip::data_pins[id][config] = data;
122 }
123 // throw and error if the config header is not implemented
124 else {
126 return;
127 }
128 }
129 //send confirmation
130 send_config(interface,config,data);
131}
132
133
134//---------------------------------------------------------------------------------------------------------------------------------------
135// AER_from_chip constructor
136//---------------------------------------------------------------------------------------------------------------------------------------
137
138AER_from_chip::AER_from_chip(uint8_t id, uint8_t reqPin, uint8_t ackPin, volatile uint8_t dataPins[], uint8_t numDataPins, uint8_t delay, bool handshakeActiveLow, bool dataActiveLow, uint8_t type) {
139 _reqPin = reqPin;
140 _ackPin = ackPin;
141 _dataPins = dataPins;
142 _numDataPins = numDataPins;
143 _delay = delay;
144 _type = type;
145 _handshakeActiveLow = handshakeActiveLow;
146 _dataActiveLow = dataActiveLow;
147 _id = id;
148
149 if (id >= 8) {
151 return;
152 }
153
154 if (setupPins()){
155 switch(_id){
156 case 0:
157 attachInterrupt(digitalPinToInterrupt(reqPin), aer0_ISR, CHANGE);
158 AER_from_chip::active[id] = true;
159 break;
160 case 1:
161 attachInterrupt(digitalPinToInterrupt(reqPin), aer1_ISR, CHANGE);
162 AER_from_chip::active[id] = true;
163 break;
164 case 2:
165 attachInterrupt(digitalPinToInterrupt(reqPin), aer2_ISR, CHANGE);
166 AER_from_chip::active[id] = true;
167 break;
168 case 3:
169 attachInterrupt(digitalPinToInterrupt(reqPin), aer3_ISR, CHANGE);
170 AER_from_chip::active[id] = true;
171 break;
172 case 4:
173 attachInterrupt(digitalPinToInterrupt(reqPin), aer4_ISR, CHANGE);
174 AER_from_chip::active[id] = true;
175 break;
176 case 5:
177 attachInterrupt(digitalPinToInterrupt(reqPin), aer5_ISR, CHANGE);
178 AER_from_chip::active[id] = true;
179 break;
180 case 6:
181 attachInterrupt(digitalPinToInterrupt(reqPin), aer6_ISR, CHANGE);
182 AER_from_chip::active[id] = true;
183 break;
184 case 7:
185 attachInterrupt(digitalPinToInterrupt(reqPin), aer7_ISR, CHANGE);
186 AER_from_chip::active[id] = true;
187 break;
188 default:
190 }
191 }
192}
193
194//---------------------------------------------------------------------------------------------------------------------------------------
195// reqRead: Reads REQ pin state
196//---------------------------------------------------------------------------------------------------------------------------------------
197
198bool AER_from_chip::reqRead() volatile {
199 #if defined(TEENSYDUINO)
200 return digitalReadFast(_reqPin)^_handshakeActiveLow;
201 #else
202 return digitalRead(_reqPin)^_handshakeActiveLow;
203 #endif
204
205}
206
207//---------------------------------------------------------------------------------------------------------------------------------------
208// ackWrite: Writes to ACK pin
209//---------------------------------------------------------------------------------------------------------------------------------------
210
211void AER_from_chip::ackWrite(bool val) volatile {
212 #if defined(TEENSYDUINO)
213 digitalWriteFast(_ackPin, val^_handshakeActiveLow);
214 #else
215 digitalWrite(_ackPin, val^_handshakeActiveLow);
216 #endif
217}
218
219
220//----------------------------------------------------------------------------------------------------------------------------------
221// recordEvent: Records output events as they occur
222//----------------------------------------------------------------------------------------------------------------------------------
224 uint8_t interface;
225 switch(_id){
226 case 0: interface = OUT_ASYNC_FROM_CHIP0; break;
227 case 1: interface = OUT_ASYNC_FROM_CHIP1; break;
228 case 2: interface = OUT_ASYNC_FROM_CHIP2; break;
229 case 3: interface = OUT_ASYNC_FROM_CHIP3; break;
230 case 4: interface = OUT_ASYNC_FROM_CHIP4; break;
231 case 5: interface = OUT_ASYNC_FROM_CHIP5; break;
232 case 6: interface = OUT_ASYNC_FROM_CHIP6; break;
233 case 7: interface = OUT_ASYNC_FROM_CHIP7; break;
234 default:interface = OUT_ERROR; break;
235 }
236 send_data32(interface, getData());
237}
238
239//----------------------------------------------------------------------------------------------------------------------------------
240// handshake: Executes REQ/ACK handshake between Teensy and ALIVE
241//----------------------------------------------------------------------------------------------------------------------------------
244 if (!reqRead()) {
245 ackWrite(0); //@TODO replace with direct pin access
246 }
247 else if (reqRead()) {
248 ackWrite(1); //@TODO replace with direct pin access
249 }
250
251 }
252
253 else if(!_handshakeActiveLow) {
254 if (!reqRead()) {
255 ackWrite(0); //@TODO replace with direct pin access
256 }
257
258 else if (reqRead()) {
259 ackWrite(1); //@TODO replace with direct pin access
260 }
261 }
262}
263
264
265//----------------------------------------------------------------------------------------------------------------------------------
266// setupPins: Sets up the relevant pins for communication
267//----------------------------------------------------------------------------------------------------------------------------------
268
270 if (reserve_input_pin(_reqPin)) pinMode(_reqPin, INPUT);
271 else return false;
272 if (reserve_output_pin(_ackPin)) pinMode(_ackPin, OUTPUT);
273 else return false;
275 Wire.begin();
276 Wire.setClock(400000);
277 return true;
278 }
279 else {
280 for(int i = 0; i < _numDataPins; i++) {
281 if (reserve_input_pin(_dataPins[i])) pinMode(_dataPins[i], INPUT);
282 else return false;
283 }
284 return true;
285 }
286}
287
288
289//---------------------------------------------------------------------------------------------------------------------------------------
290// getData: Retrieves event
291//---------------------------------------------------------------------------------------------------------------------------------------
292
293uint32_t AER_from_chip::getData() volatile{
294 uint32_t data = 0;
295 if (_delay) {
297 }
299
300 uint8_t interface;
301 switch(_id){
302 case 0: interface = OUT_ASYNC_FROM_CHIP0; break;
303 case 1: interface = OUT_ASYNC_FROM_CHIP1; break;
304 case 2: interface = OUT_ASYNC_FROM_CHIP2; break;
305 case 3: interface = OUT_ASYNC_FROM_CHIP3; break;
306 case 4: interface = OUT_ASYNC_FROM_CHIP4; break;
307 case 5: interface = OUT_ASYNC_FROM_CHIP5; break;
308 case 6: interface = OUT_ASYNC_FROM_CHIP6; break;
309 case 7: interface = OUT_ASYNC_FROM_CHIP7; break;
310 default:interface = OUT_ERROR; break;
311 }
312 uint8_t count_shift = 0;
313 uint8_t transmission_success = 0;
314 Wire.beginTransmission((uint8_t) 32U);
315 Wire.write((uint8_t) 18U);
316
317 transmission_success = Wire.endTransmission(false);
318 if(transmission_success>0){
319 error_message(OUT_ERROR_PERIPHERAL_INTERFACE_NOT_READY,interface,transmission_success,IN_I2C2);
320 return 0;
321 }
322
323 transmission_success = Wire.requestFrom((uint8_t) 32U,2,true);
324 if(transmission_success != 2){
326 return 0;
327 }
328
329 data |= Wire.read()<<8*count_shift;
330 count_shift++;
331 data |= Wire.read()<<8*count_shift;
332 count_shift++;
333
334 Wire.beginTransmission((uint8_t) 33U);
335 Wire.write((uint8_t) 18U);
336 transmission_success = Wire.endTransmission(false);
337 if(transmission_success>0){
338 error_message(OUT_ERROR_PERIPHERAL_INTERFACE_NOT_READY,interface,transmission_success,IN_I2C2);
339 return 0;
340 }
341
342 transmission_success = Wire.requestFrom((uint8_t) 33U,2,true);
343 if(transmission_success != 2){
345 return 0;
346 }
347 data |= Wire.read()<<8*count_shift;
348 count_shift++;
349 data |= Wire.read()<<8*count_shift;
350 count_shift++;
351
352
353 // data = Interface_i2c::inst[0]->read_return(32U,18U);
354 // data |= (Interface_i2c::inst[0]->read_return(33U,18U)<<16);
355 return data;
356
357 }
358
359 else{
360 for (int i = 0; i < _numDataPins; i++) {
361 #if defined(TEENSYDUINO)
362 data |= digitalReadFast(_dataPins[i]) << i; // @todo read with direct pin access
363 #else
364 data |= digitalRead(_dataPins[i]) << i;
365 #endif
366 }
367 if (_dataActiveLow) {
368 return ~data;
369 }
370 else {
371 return data;
372 }
373 }
374}
375
376
377void aer_ISR(uint8_t id) {
378 if (AER_from_chip::inst[id]->reqRead()) {
379 if ( offset_time != 0 ) {
381 }
383 }
384 else if (!AER_from_chip::inst[id]->reqRead()) {
386 }
387}
388
389void aer0_ISR() { aer_ISR(0); }
390void aer1_ISR() { aer_ISR(1); }
391void aer2_ISR() { aer_ISR(2); }
392void aer3_ISR() { aer_ISR(3); }
393void aer4_ISR() { aer_ISR(4); }
394void aer5_ISR() { aer_ISR(5); }
395void aer6_ISR() { aer_ISR(6); }
396void aer7_ISR() { aer_ISR(7); }
static volatile AER_from_chip * inst[8]
volatile uint8_t * _dataPins
void ackWrite(bool val) volatile
static volatile uint8_t port[8]
uint32_t getData() volatile
static volatile bool data_lowactive[8]
static volatile uint8_t data_width[8]
static volatile bool hs_lowactive[8]
static volatile uint8_t data_pins[8][32]
void recordEvent() volatile
static void configure(uint8_t id, uint8_t config, uint8_t data)
static volatile bool active[8]
static volatile uint8_t type[8]
static volatile uint8_t req_delay[8]
static volatile uint8_t req_pin[8]
AER_from_chip(uint8_t id, uint8_t reqPin, uint8_t ackPin, volatile uint8_t dataPins[], uint8_t numDataPins, uint8_t delay=0, bool activeLow=false, bool dataActiveLow=false, uint8_t type=ASYNC_4Phase_Chigh_Dhigh)
static volatile uint8_t ack_pin[8]
volatile unsigned long offset_time
void error_message(uint8_t error_header, uint8_t source_header, uint32_t value, uint8_t sub_source_header)
void send_data32(uint8_t header, uint32_t value, bool is_confirmation)
void send_config(uint8_t header, uint8_t config_header, uint8_t value)
@ IN_CONF_ASYNC_FROM_CHIP6
Definition: datatypes.h:340
@ IN_CONF_ASYNC_TO_CHIP0
Definition: datatypes.h:242
@ IN_CONF_ASYNC_FROM_CHIP5
Definition: datatypes.h:333
@ IN_CONF_ASYNC_FROM_CHIP2
Definition: datatypes.h:312
@ IN_CONF_ASYNC_FROM_CHIP0
Definition: datatypes.h:298
@ IN_CONF_ASYNC_FROM_CHIP3
Definition: datatypes.h:319
@ IN_CONF_ASYNC_FROM_CHIP7
Definition: datatypes.h:347
@ IN_I2C2
Definition: datatypes.h:137
@ IN_CONF_ASYNC_FROM_CHIP1
Definition: datatypes.h:305
@ IN_CONF_ASYNC_FROM_CHIP4
Definition: datatypes.h:326
@ CONF_TYPE
Definition: datatypes.h:669
@ CONF_REQ
Definition: datatypes.h:637
@ CONF_REQ_DELAY
Definition: datatypes.h:655
@ CONF_ACTIVE
Definition: datatypes.h:618
@ CONF_WIDTH
Definition: datatypes.h:649
@ CONF_ACK
Definition: datatypes.h:643
@ OUT_ASYNC_FROM_CHIP0
Definition: datatypes.h:468
@ OUT_I2C2
Definition: datatypes.h:461
@ OUT_ASYNC_FROM_CHIP1
Definition: datatypes.h:475
@ OUT_ASYNC_FROM_CHIP5
Definition: datatypes.h:503
@ OUT_ASYNC_FROM_CHIP4
Definition: datatypes.h:496
@ OUT_ASYNC_FROM_CHIP3
Definition: datatypes.h:489
@ OUT_ERROR
Definition: datatypes.h:522
@ OUT_ASYNC_FROM_CHIP2
Definition: datatypes.h:482
@ OUT_ASYNC_FROM_CHIP6
Definition: datatypes.h:510
@ OUT_ERROR_UNKNOWN_CONFIGURATION
Definition: datatypes.h:562
@ OUT_ASYNC_FROM_CHIP7
Definition: datatypes.h:517
@ OUT_ERROR_PERIPHERAL_INTERFACE_NOT_READY
Definition: datatypes.h:573
@ OUT_ERROR_CONFIGURATION_OUT_OF_BOUNDS
Definition: datatypes.h:579
void aer_ISR(uint8_t id)
void aer6_ISR()
void aer1_ISR()
void aer5_ISR()
void aer2_ISR()
void aer0_ISR()
void aer3_ISR()
void aer7_ISR()
void aer4_ISR()
void aer6_ISR()
void aer1_ISR()
void aer5_ISR()
void aer2_ISR()
void aer0_ISR()
void aer3_ISR()
void aer7_ISR()
void aer4_ISR()
@ ASYNC_4Phase_Clow_Dhigh
@ ASYNC_4Phase_MCP23017
bool reserve_output_pin(uint8_t id, uint8_t from_instruction)
bool reserve_input_pin(uint8_t id, uint8_t from_instruction)
void delay20ns(uint8_t clocks)
kinda accurate for CPU ferquencies from 400MHz-2GHz, below the resolution becomes more coarse as it m...