uC chip interface arduino  0.9.0
A interface for async and neuromrphic IC testing
Loading...
Searching...
No Matches
interface_i2c.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) 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#include <Arduino.h>
19#include "interface_i2c.h"
20#include <Wire.h>
21
22
23// reserve and clear the memory of the static global variables.
24// see header for description
29
31
32// handles incomming configuraion packets
33void Interface_i2c::configure(uint8_t id, uint8_t config, uint8_t data){
34 // check if the ID is valid otherwise throw error
35 if (id >= I2C_NUMBER_OF_INTERFACES) {
37 return;
38 }
39 uint8_t interface;
40 switch(id){
41 case 0: interface = IN_CONF_I2C0; break;
42 case 1: interface = IN_CONF_I2C1; break;
43 case 2: interface = IN_CONF_I2C2; break;
44 default:interface = IN_CONF_I2C0; break; // should never happen
45 }
46 // handle the different config sub headers
47 switch (config){
48 // activate the interface and reserve the pins
49 case CONF_ACTIVE:
51 if (Interface_i2c::active[id]){
52 // send confirmation
53 send_config(interface,config,Interface_i2c::active[id]);
54 }
55 return;
56 case CONF_WIDTH:
57 // throw error if interface is to wide
58 if (data > 2 || data < 1) {
61 // send confirmation
62 send_config(interface,config,1);
63 return;
64 }
65 else Interface_i2c::width[id] = data;
66 break;
67 case CONF_BYTE_ORDER:
68 Interface_i2c::byte_order[id] = (data > 0);
69 send_config(interface,config,(data > 0));
70 break;
72 switch (data){
73 default:
74 case 0:
75 Interface_i2c::frequency[id] = 100000;
76 send_config(interface,config,0);
77 break;
78 case 1:
79 Interface_i2c::frequency[id] = 400000;
80 send_config(interface,config,data);
81 break;
82 case 2:
83 Interface_i2c::frequency[id] = 1000000;
84 send_config(interface,config,data);
85 break;
86 case 3:
87 Interface_i2c::frequency[id] = 3400000;
88 send_config(interface,config,data);
89 break;
90 case 4:
91 Interface_i2c::frequency[id] = 10000;
92 send_config(interface,config,data);
93 break;
94 }
95
96 break;
97
98 default:
100 return;
101
102 }
103 //send confirmation
104 send_config(interface,config,data);
105}
106
107
108void Interface_i2c::process_packet(uint8_t id,uint8_t device_address_8, uint8_t register_address, uint8_t data_ms, uint8_t data_ls){
109 bool read = device_address_8 & 254;
110 uint8_t device_address = device_address_8 >> 1;
111
112 if (id >= I2C_NUMBER_OF_INTERFACES) {
114 return;
115 }
116 else if (!Interface_i2c::active[id]){
117 switch (id){
118 default:
122 }
123 }
124 else{
125 if (read) Interface_i2c::inst[id]->read(device_address,register_address,data_ls);
126 else Interface_i2c::inst[id]->write(device_address,register_address,data_ls,data_ms);
127 }
128}
129
130
131//---------------------------------------------------------------------------------------------------------------------------------------
132// Interface_i2c constructor
133//---------------------------------------------------------------------------------------------------------------------------------------
134
135Interface_i2c::Interface_i2c(uint8_t id, uint32_t frequency) {
136 _id = id;
137 if (frequency == 0) _frequency = 100000;
138 else _frequency = frequency;
139 if (id >= I2C_NUMBER_OF_INTERFACES) {
141 }
142 else {
143 switch(_id){
144 case 0:
146 _i2c = &Wire;
147 _i2c->setClock(_frequency);
148 _i2c->setTimeout(1000);
149 _i2c->begin();
150 Interface_i2c::active[id] = true;
151 }
152 break;
153 #if (I2C_NUMBER_OF_INTERFACES > 1)
154 case 1:
155 if(reserve_output_pin(I2C_SCL1_PORT, IN_CONF_I2C1) && reserve_input_pin(I2C_SDA1_PORT, IN_CONF_I2C1)){
156 _i2c = &Wire1;
157 _i2c->setClock(_frequency);
158 _i2c->setTimeout(1000);
159 _i2c->begin();
160 Interface_i2c::active[id] = true;
161 }
162 break;
163 #endif
164 #if (I2C_NUMBER_OF_INTERFACES > 2)
165 case 2:
166 if(reserve_output_pin(I2C_SCL2_PORT, IN_CONF_I2C2) && reserve_input_pin(I2C_SDA2_PORT, IN_CONF_I2C2)){
167 _i2c = &Wire2;
168 _i2c->setClock(_frequency);
169 _i2c->setTimeout(1000);
170 _i2c->begin();
171 Interface_i2c::active[id] = true;
172 }
173 break;
174 #endif
175 default:
177 }
178 }
179}
180
181void Interface_i2c::write(uint8_t device_address, uint8_t register_address, uint8_t data_ls, uint8_t data_ms) volatile {
182 uint8_t result = 0;
183 if (_i2c != NULL){
184 noInterrupts();
185 _i2c->beginTransmission(device_address);
186 if (Interface_i2c::width[_id] != 0) _i2c->write(register_address);
187 if (Interface_i2c::width[_id] == 2 && Interface_i2c::byte_order[_id]) _i2c->write(data_ms);
188 _i2c->write(data_ls);
189 if (Interface_i2c::width[_id] == 2 && !Interface_i2c::byte_order[_id]) _i2c->write(data_ms);
190 result = _i2c->endTransmission(true);
191 interrupts();
192 if(result>0){
193 switch (_id){
197 }
198 }
199 switch (_id){
200 case 0: send_data_i2c(IN_I2C0,device_address<<1,register_address,data_ls,data_ms); break;
201 case 1: send_data_i2c(IN_I2C1,device_address<<1,register_address,data_ls,data_ms); break;
202 case 2: send_data_i2c(IN_I2C2,device_address<<1,register_address,data_ls,data_ms); break;
203 }
204
205 }
206 else{
207 //this makes no sense here
209 }
210}
211
212void Interface_i2c::read(uint8_t device_address, uint8_t register_address, uint8_t number_of_bytes) volatile{
213 uint8_t result = 0;
214 if (number_of_bytes > 32) {
215 switch (_id){
216 default:
220 }
221 return;
222 }
223 if (_i2c != NULL){
224 noInterrupts();
225 uint8_t byte_mulitply = Interface_i2c::width[_id];
226 if (byte_mulitply != 0) {
227 _i2c->beginTransmission(device_address);
228 _i2c->write(register_address);
229 result = _i2c->endTransmission(false);
230 if(result>0){
231 switch (_id){
235 }
236 }
237 }
238 else byte_mulitply = 1;
239 result = _i2c->requestFrom(device_address,number_of_bytes*byte_mulitply,true);
240 interrupts();
241 if(result!=byte_mulitply){
242 switch (_id){
246 }
247 }
248 if (_i2c->available() == number_of_bytes*byte_mulitply) {
249 uint8_t position = 0;
250 for (position = 0; position < number_of_bytes; position++){
251 uint8_t data_ls = 0;
252 uint8_t data_ms = 0;
253 if (byte_mulitply == 2 && !Interface_i2c::byte_order[_id]){
254 data_ls = _i2c->read();
255 data_ms = _i2c->read();
256 }
257 else if (byte_mulitply == 2 && Interface_i2c::byte_order[_id]){
258 data_ms = _i2c->read();
259 data_ls = _i2c->read();
260 }
261 else {
262 data_ls = _i2c->read();
263 }
264 switch (_id){
265 case 0: send_data_i2c(IN_I2C0,(device_address<<1)+1,register_address,data_ls,data_ms); break;
266 case 1: send_data_i2c(IN_I2C1,(device_address<<1)+1,register_address,data_ls,data_ms); break;
267 case 2: send_data_i2c(IN_I2C2,(device_address<<1)+1,register_address,data_ls,data_ms); break;
268 }
269 }
270 }
271
272 else{
273 // this does not make sense here
275 }
276 }
277}
278
279uint16_t Interface_i2c::read_return(uint8_t device_address, uint8_t register_address) volatile{
280 uint16_t data = 0;
281 uint8_t result = 0;
282 if (_i2c != NULL){
283 noInterrupts();
284 uint8_t byte_mulitply = Interface_i2c::width[_id];
285 if (byte_mulitply != 0) {
286 _i2c->beginTransmission(device_address);
287 _i2c->write(register_address);
288 result = _i2c->endTransmission();
289 if(result>0){
290 switch (_id){
294 }
295 }
296 }
297 else byte_mulitply = 1;
298 result = _i2c->requestFrom(device_address,byte_mulitply,true);
299 interrupts();
300 if(result!=byte_mulitply){
301 switch (_id){
305 }
306 }
307 if (_i2c->available() == byte_mulitply) {
308 if (byte_mulitply == 2 && !Interface_i2c::byte_order[_id]){
309 data = _i2c->read();
310 data |= (_i2c->read()<<8);
311 }
312 else if (byte_mulitply == 2 && Interface_i2c::byte_order[_id]){
313 data = (_i2c->read()<<8);
314 data |= _i2c->read();
315 }
316 else {
317 data = _i2c->read();
318 }
319 return data;
320 }
321 else{
322 // this does not make sense here
324 }
325 }
326}
uint32_t _frequency
Definition: interface_i2c.h:82
Interface_i2c(uint8_t id, uint32_t freqency=100000U)
arduino::TwoWire * _i2c
Definition: interface_i2c.h:86
static volatile uint8_t width[I2C_NUMBER_OF_INTERFACES]
Definition: interface_i2c.h:50
void read(uint8_t device_address, uint8_t register_address, uint8_t number_of_bytes) volatile
uint16_t read_return(uint8_t device_address, uint8_t register_address) volatile
static volatile bool active[I2C_NUMBER_OF_INTERFACES]
Definition: interface_i2c.h:52
static volatile uint8_t byte_order[I2C_NUMBER_OF_INTERFACES]
Definition: interface_i2c.h:51
static void configure(uint8_t id, uint8_t config, uint8_t data)
static volatile Interface_i2c * inst[I2C_NUMBER_OF_INTERFACES]
Definition: interface_i2c.h:57
void write(uint8_t device_address, uint8_t register_address, uint8_t data_ms, uint8_t data_ls) volatile
static void process_packet(uint8_t id, uint8_t device_address, uint8_t register_address, uint8_t data_ms, uint8_t data_ls)
static volatile uint32_t frequency[I2C_NUMBER_OF_INTERFACES]
Definition: interface_i2c.h:53
void error_message(uint8_t error_header, uint8_t source_header, uint32_t value, uint8_t sub_source_header)
void send_data_i2c(uint8_t header, uint8_t device_address_8, uint8_t register_address, uint8_t value_ms, uint8_t value_ls, bool is_confirmation)
void send_config(uint8_t header, uint8_t config_header, uint8_t value)
@ IN_I2C0
Definition: datatypes.h:119
@ IN_CONF_I2C2
Definition: datatypes.h:235
@ IN_CONF_I2C0
Definition: datatypes.h:221
@ IN_CONF_I2C1
Definition: datatypes.h:228
@ IN_I2C1
Definition: datatypes.h:128
@ IN_I2C2
Definition: datatypes.h:137
@ CONF_SPEED_CLASS
Definition: datatypes.h:664
@ CONF_INPUT
Definition: datatypes.h:631
@ CONF_ACTIVE
Definition: datatypes.h:618
@ CONF_WIDTH
Definition: datatypes.h:649
@ CONF_BYTE_ORDER
Definition: datatypes.h:660
@ OUT_ERROR_INTERFACE_NOT_ACTIVE
Definition: datatypes.h:557
@ OUT_ERROR_UNKNOWN_CONFIGURATION
Definition: datatypes.h:562
@ OUT_ERROR_PERIPHERAL_INTERFACE_NOT_READY
Definition: datatypes.h:573
@ OUT_ERROR_CONFIGURATION_OUT_OF_BOUNDS
Definition: datatypes.h:579
bool reserve_output_pin(uint8_t id, uint8_t from_instruction)
bool reserve_input_pin(uint8_t id, uint8_t from_instruction)
#define I2C_NUMBER_OF_INTERFACES
Definition: uc_boards.h:112
@ I2C_SDA_PORT
Definition: uc_boards.h:115
@ I2C_SCL_PORT
Definition: uc_boards.h:114