-
Notifications
You must be signed in to change notification settings - Fork 4
/
ardubus.pde
294 lines (271 loc) · 10.7 KB
/
ardubus.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/*
ArduBus is an Arduino program that eases the task of interfacing
a new I2C device by using custom commands, so no programming is
required.
Copyright (C) 2010 Santiago Reig
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ArduBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ArduBus. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wire.h>
#define BUFFSIZ 50 //Tamaño del buffer del puerto serie lo suficientemente grande
#define BAUD 115200 //Velocidad puerto serie
#define MCU_FREQ 16000000L //Frecuencia de funcionamiento del microcontrolador
boolean error;
boolean echo = true; //Hacer echo de la entrada del puerto serie
boolean debug = false; //Activar mensajes de depuracion
char buffer[BUFFSIZ]; //Almacen de la cadena de entrada por puerto serie
char *parseptr; //Puntero para recorrer el vector
void setup()
{
Serial.begin(BAUD); //Iniciamos el puerto serie
Wire.begin(); //Iniciamos el bus I2C
Serial.println(""); //Mensaje de bienvenida
Serial.println("ArduBus v0.3");
Serial.println("KungFu Labs - http://www.kungfulabs.com");
Serial.println("ArduBus Copyright (C) 2010 Santiago Reig");
Serial.println("");
selectSpeed();
Serial.println("202 I2C READY");
Serial.println("205 I2C PULLUP ON");
}
void loop()
{
error = false; //Limpimos la bandera de error
Serial.print("I2C>"); //Escribimos el 'prompt'
readString(); //Leemos el comando escrito a traves del puerto serie
startWork(); //Ejecutamos las acciones indicadas
}
void readString() {
char c;
int buffSize = 0;
parseptr = buffer;
Serial.flush();
while (true) {
while (Serial.available() == 0); //Esperamos a que llegue otro caracter
c=Serial.read();
if (c == 127){
if (buffSize != 0){ //Si borramos un caracter, retrocedemos una posicion
buffSize--; //Evitamos crear valores negativos
if (echo){
Serial.print(c);
}
}
continue;
}
if (echo){ //Hacemos eco
if (c == '\r') Serial.println(); //Iniciamos una nueva linea
else Serial.print(c);
}
if ((buffSize == BUFFSIZ-1) || (c == '\r')) { //Leemos hasta detectar el intro
buffer[buffSize] = 0; //En la ultima posicion escribimos un 0 para definir el final de la cadena
return;
}
buffer[buffSize++] = c; //Guardamos el caracter recibido
}
}
void selectSpeed(){
byte i2cSpeed;
char option[] = "Select I2C bus speed:\r\n1. 50 kHz\r\n2. 100 kHz\r\n3. 400 kHz";
i2cSpeed = selectMenu(option,3);
switch (i2cSpeed){
case 1:
Serial.println("50 kHz selected");
TWBR = ((MCU_FREQ/50000)-16)/2;
break;
case 2:
Serial.println("100 kHz selected");
TWBR = ((MCU_FREQ/100000)-16)/2;
break;
case 3:
Serial.println("400 kHz selected");
TWBR = ((MCU_FREQ/400000)-16)/2;
break;
}
}
byte selectMenu(char* options,int len){ //Mostramos menu y devolvemos el valor escogido
Serial.println(options);
do{
Serial.print("I2C>");
readString();
if (parseptr[0] < '0' || parseptr[0] > '9' || parseptr[0]-'0' > len) Serial.println("ERROR: Option not recognized");
} while (parseptr[0] < '0' || parseptr[0] > '9' || parseptr[0]-'0' > len); //Limite de 10 opciones para seleccionar
return parseptr[0]-'0';
}
void startWork(){
byte address,data,nReads;
if (parseptr[0] == 'E'){ //Comando de ECHO
echo = !echo;
if (echo) Serial.println("Echo activado");
else Serial.println("Echo desactivado");
return;
}
else if (parseptr[0] == 'D'){ //Comando de DEBUG
debug = !debug;
if (debug) Serial.println("Debug activado");
else Serial.println("Debug desactivado");
return;
}
if (debug){
Serial.print("Procesando cadena: ");
Serial.println(buffer);
}
while (parseptr[0] == '{'){ //Mientras haya un comando nuevo...
parseptr++; //Avanzamos para analizar el siguiente caracter
Serial.println("210 I2C START CONDITION");
address = parseArgument(); //El primer argumento es la direccion
if (error){
Serial.println("ERROR: Syntax not recognized");
return;
}
if (parseptr[1] != 'r' && parseptr[2] != 'r'){ //Si el siguiente (r) o el segundo caracter (0r), contando el espacio, es una 'r', modo lectura
Wire.beginTransmission(address); //Abrimos comunicaciones con el esclavo
Serial.print("220 I2C WRITE: 0x");
Serial.println(address,HEX);
while (parseptr[0] != '}' && parseptr[0] != 0){ //Vamos escribiendo datos hasta encontrar la llave de final de comando o se acabe el vector
data = parseArgument(); //Cojemos el valor del dato analizando la cadena de texto
if (error){
Wire.endTransmission();
Serial.println("ERROR: Syntax not recognized");
return;
}
Wire.send(data); //Enviamos dato
Serial.print("220 I2C WRITE: 0x");
Serial.println(data,HEX);
}
Wire.endTransmission(); //Una vez ya escrito todo, finalizamos la conexión
Serial.println("240 I2C STOP CONDITION");
parseptr++;
}
else {
nReads = parseArgument(); //Leemos el numero de bytes que se quieren leer
if (error){
Serial.println("ERROR: Syntax not recognized");
return;
}
Wire.requestFrom(address,nReads); //Pedimos los datos al esclavo
while(Wire.available()){ //Segun los recibimos los vamos escribiendo
Serial.print("230 I2C READ: 0x"); //POSIBLE BUG: se lea mas rapido que se recibe y salga del bucle, hacer bucle for con nReads
Serial.println(Wire.receive(),HEX);
}
Serial.println("240 I2C STOP CONDITION");
}
}
}
byte parseArgument(){
byte argument;
if (parseptr[0] == ' '){ //Si detectamos un espacio lo saltamos
if (debug) Serial.println("Detectado espacio");
parseptr++;
}
if (parseptr[0] >= '1' && parseptr[0] <= '9'){ //Deteccion para decimales tipo: '15'
if (debug) Serial.print("Detectado #dec");
argument = parseDec();
}
else if (parseptr[0] == '0'){
parseptr++;
if (parseptr[0] == ' ' || parseptr[0] == '}' || parseptr[0] == 0) argument = 0; //Si hay un 0 seguido de uno de esos caracteres, es que es un 0 decimal, no 0xYY,0bYYYYY,...
else if (parseptr[0] == 'x' || parseptr[0] == 'h'){
parseptr++;
if (debug) Serial.print("Detectado #hex"); //Deteccion para hexadecimales tipo: '0x4F'
argument = parseHex();
}
else if (parseptr[0] == 'b'){
parseptr++;
if (debug) Serial.print("Detectado #bin"); //Deteccion para binarios tipo: '0b110101'
argument = parseBin();
}
else if (parseptr[0] == 'd'){
parseptr++;
if (debug) Serial.print("Detectado #dec"); //Deteccion para decimales tipo: '0d15'
argument = parseDec();
}
else if (parseptr[0] == 'r'){
parseptr++;
if (debug) Serial.print("Detectado #read");
argument = parseDec(); //Usamos parseDec ya que 0rXX es un numero decimal
}
}
else if (parseptr[0] == 'r'){ //Contabilizacion cadena de 'r' tipo: 'rrrrrrr'
if (debug) Serial.print("Detectado #read");
argument = parseRead();
}
else{
error=true;
parseptr++;
}
return argument;
}
byte parseRead(){
byte result = 0;
while (parseptr[0] == 'r'){
result++;
parseptr++;
}
if (debug){
Serial.print(" - 0r"); //Mostramos el valor convertido
Serial.println(result,HEX);
}
return result;
}
byte parseHex(){ //Convertimos de texto a numero hexadecimal
byte result = 0;
while (parseptr[0] != ' ' && parseptr[0] != '}' && parseptr[0] != 0){
if (parseptr[0] >= '0' && parseptr[0] <= '9'){
result *= 16;
result += parseptr[0]-'0';
}
else if (parseptr[0] >= 'a' && parseptr[0] <= 'f'){
result *= 16;
result += parseptr[0]-'a'+10;
}
else if (parseptr[0] >= 'A' && parseptr[0] <= 'F'){
result *= 16;
result += parseptr[0]-'A'+10;
}
else return result;
parseptr++;
}
if (debug){
Serial.print(" - 0x"); //Mostramos el valor convertido
Serial.println(result,HEX);
}
return result;
}
byte parseDec(){
byte result = 0;
while (parseptr[0] != ' ' && parseptr[0] != '}' && parseptr[0] != 0){
if ((parseptr[0] < '0') || (parseptr[0] > '9'))
return result;
result *= 10;
result += parseptr[0]-'0';
parseptr++;
}
if (debug){
Serial.print(" - 0x"); //Mostramos el valor convertido
Serial.println(result,HEX);
}
return result;
}
byte parseBin(){
byte result = 0;
while (parseptr[0] != ' ' && parseptr[0] != '}' && parseptr[0] != 0){
if ((parseptr[0] < '0') || (parseptr[0] > '1'))
return result;
result *= 2;
result += parseptr[0]-'0';
parseptr++;
}
if (debug){
Serial.print(" - 0x"); //Mostramos el valor convertido
Serial.println(result,HEX);
}
return result;
}