11
11
12
12
/*
13
13
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
14
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
15
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
16
+ Copyright (C) 2009-2011 Jeff Hoefs. All rights reserved.
14
17
15
18
This library is free software; you can redistribute it and/or
16
19
modify it under the terms of the GNU Lesser General Public
27
30
*/
28
31
29
32
#include < Servo . h>
33
+ #include < Wire . h>
30
34
#include < Firmata . h>
31
35
36
+ // move the following defines to Firmata.h?
37
+ #define I2C_WRITE B00000000
38
+ #define I2C_READ B00001000
39
+ #define I2C_READ_CONTINUOUSLY B00010000
40
+ #define I2C_STOP_READING B00011000
41
+ #define I2C_READ_WRITE_MODE_MASK B00011000
42
+ #define I2C_10BIT_ADDRESS_MODE_MASK B00100000
43
+
44
+ #define MAX_QUERIES 8
45
+ #define MINIMUM_SAMPLING_INTERVAL 10
46
+
47
+ #define REGISTER_NOT_SPECIFIED - 1
48
+
32
49
/* ==============================================================================
33
50
* GLOBAL VARIABLES
34
51
*============================================================================*/
@@ -50,12 +67,70 @@ unsigned long currentMillis; // store the current value from millis()
50
67
unsigned long previousMillis; // for comparison with currentMillis
51
68
int samplingInterval = 19 ; // how often to run the main loop (in ms)
52
69
53
- Servo servos[MAX_SERVOS ];
70
+ /* i2c data */
71
+ struct i2c_device_info {
72
+ byte addr;
73
+ byte reg;
74
+ byte bytes;
75
+ };
54
76
77
+ /* for i2c read continuous more */
78
+ i2c_device_info query[MAX_QUERIES ];
79
+
80
+ byte i2cRxData[32 ];
81
+ boolean readingContinuously = false ;
82
+ boolean isI2CEnabled = false ;
83
+ byte queryIndex = 0 ;
84
+ unsigned int i2cReadDelayTime = 0 ; // default delay time between i2c read request and Wire.requestFrom()
85
+
86
+ Servo servos[MAX_SERVOS ];
55
87
/* ==============================================================================
56
88
* FUNCTIONS
57
89
*============================================================================*/
58
90
91
+ void readAndReportData (byte address , int theRegister , byte numBytes ) {
92
+ // allow I2C requests that don't require a register read
93
+ // for example, some devices using an interrupt pin to signify new data available
94
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
95
+ if (theRegister != REGISTER_NOT_SPECIFIED ) {
96
+ Wire . beginTransmission(address);
97
+ #if ARDUINO >= 100
98
+ Wire . write((byte )theRegister);
99
+ #else
100
+ Wire . send((byte )theRegister);
101
+ #endif
102
+ Wire . endTransmission();
103
+ delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck
104
+ } else {
105
+ theRegister = 0 ; // fill the register with a dummy value
106
+ }
107
+
108
+ Wire . requestFrom(address, numBytes); // all bytes are returned in requestFrom
109
+
110
+ // check to be sure correct number of bytes were returned by slave
111
+ if (numBytes == Wire . available()) {
112
+ i2cRxData[0 ] = address;
113
+ i2cRxData[1 ] = theRegister;
114
+ for (int i = 0 ; i < numBytes; i++ ) {
115
+ #if ARDUINO >= 100
116
+ i2cRxData[2 + i] = Wire . read();
117
+ #else
118
+ i2cRxData[2 + i] = Wire . receive();
119
+ #endif
120
+ }
121
+ }
122
+ else {
123
+ if (numBytes > Wire . available()) {
124
+ Firmata . sendString(" I2C Read Error: Too many bytes received" );
125
+ } else {
126
+ Firmata . sendString(" I2C Read Error: Too few bytes received" );
127
+ }
128
+ }
129
+
130
+ // send slave address, register and received bytes
131
+ Firmata . sendSysex(SYSEX_I2C_REPLY , numBytes + 2 , i2cRxData);
132
+ }
133
+
59
134
void outputPort(byte portNumber, byte portValue, byte forceSend)
60
135
{
61
136
// pins not configured as INPUT are cleared to zeros
@@ -99,6 +174,13 @@ void checkDigitalInputs(void)
99
174
*/
100
175
void setPinModeCallback(byte pin, int mode)
101
176
{
177
+ if (pinConfig[pin] == I2C && mode != I2C ) {
178
+ isI2CEnabled = false ;
179
+ // uncomment the following once end() method is added to Wire library
180
+ // Wire.end();
181
+ Firmata . sendString(" Once I2C is enabled, the I2C pins cannot be changed to another mode" );
182
+ return ;
183
+ }
102
184
if (IS_PIN_SERVO (pin) && mode != SERVO && servos[PIN_TO_SERVO (pin)]. attached()) {
103
185
servos[PIN_TO_SERVO (pin)]. detach();
104
186
}
@@ -155,8 +237,11 @@ void setPinModeCallback(byte pin, int mode)
155
237
}
156
238
break ;
157
239
case I2C :
158
- pinConfig[pin] = mode;
159
- Firmata . sendString(" I2C mode not yet supported" );
240
+ if (IS_PIN_I2C (pin)) {
241
+ pinConfig[pin] = I2C ;
242
+ // TODO: if not enabled call enableI2CPins()?
243
+ // or does user have to call I2C config again in order to reenable I2C?
244
+ }
160
245
break ;
161
246
default :
162
247
Firmata . sendString(" Unknown pin mode" ); // TODO: put error msgs in EEPROM
@@ -243,7 +328,87 @@ void reportDigitalCallback(byte port, int value)
243
328
244
329
void sysexCallback(byte command, byte argc, byte * argv)
245
330
{
331
+ byte mode;
332
+ byte slaveAddress;
333
+ byte slaveRegister;
334
+ byte data;
335
+ unsigned int delayTime;
336
+
246
337
switch (command) {
338
+ case I2C_REQUEST :
339
+ mode = argv[1 ] & I2C_READ_WRITE_MODE_MASK ;
340
+ if (argv[1 ] & I2C_10BIT_ADDRESS_MODE_MASK ) {
341
+ Firmata . sendString(" 10-bit addressing mode is not yet supported" );
342
+ return ;
343
+ }
344
+ else {
345
+ slaveAddress = argv[0 ];
346
+ }
347
+
348
+ switch (mode) {
349
+ case I2C_WRITE :
350
+ Wire . beginTransmission(slaveAddress);
351
+ for (byte i = 2 ; i < argc; i += 2 ) {
352
+ data = argv[i] + (argv[i + 1 ] << 7 );
353
+ #if ARDUINO >= 100
354
+ Wire . write(data);
355
+ #else
356
+ Wire . send(data);
357
+ #endif
358
+ }
359
+ Wire . endTransmission();
360
+ delayMicroseconds(70 );
361
+ break ;
362
+ case I2C_READ :
363
+ if (argc == 6 ) {
364
+ // a slave register is specified
365
+ slaveRegister = argv[2 ] + (argv[3 ] << 7 );
366
+ data = argv[4 ] + (argv[5 ] << 7 ); // bytes to read
367
+ readAndReportData(slaveAddress, (int )slaveRegister, data);
368
+ }
369
+ else {
370
+ // a slave register is NOT specified
371
+ data = argv[2 ] + (argv[3 ] << 7 ); // bytes to read
372
+ readAndReportData(slaveAddress, (int )REGISTER_NOT_SPECIFIED , data);
373
+ }
374
+ break ;
375
+ case I2C_READ_CONTINUOUSLY :
376
+ if ((queryIndex + 1 ) >= MAX_QUERIES ) {
377
+ // too many queries, just ignore
378
+ Firmata . sendString(" too many queries" );
379
+ break ;
380
+ }
381
+ query[queryIndex]. addr = slaveAddress;
382
+ query[queryIndex]. reg = argv[2 ] + (argv[3 ] << 7 );
383
+ query[queryIndex]. bytes = argv[4 ] + (argv[5 ] << 7 );
384
+ readingContinuously = true ;
385
+ queryIndex++ ;
386
+ break ;
387
+ case I2C_STOP_READING :
388
+ readingContinuously = false ;
389
+ queryIndex = 0 ;
390
+ break ;
391
+ default :
392
+ break ;
393
+ }
394
+ break ;
395
+ case I2C_CONFIG :
396
+ delayTime = (argv[4 ] + (argv[5 ] << 7 )); // MSB
397
+ delayTime = (delayTime << 8 ) + (argv[2 ] + (argv[3 ] << 7 )); // add LSB
398
+
399
+ if (delayTime > 0 ) {
400
+ i2cReadDelayTime = delayTime;
401
+ }
402
+
403
+ if (argc > 6 ) {
404
+ // If you extend I2C_Config, handle your data here
405
+ }
406
+
407
+ if (! isI2CEnabled) {
408
+ enableI2CPins();
409
+ }
410
+
411
+ break ;
247
412
case SERVO_CONFIG :
248
413
if (argc > 4 ) {
249
414
// these vars are here for clarity, they'll optimized away by the compiler
@@ -263,6 +428,9 @@ void sysexCallback(byte command, byte argc, byte *argv)
263
428
case SAMPLING_INTERVAL :
264
429
if (argc > 1 )
265
430
samplingInterval = argv[0 ] + (argv[1 ] << 7 );
431
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL ) {
432
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL ;
433
+ }
266
434
else
267
435
Firmata . sendString(" Not enough data" );
268
436
break ;
@@ -296,6 +464,10 @@ void sysexCallback(byte command, byte argc, byte *argv)
296
464
Serial . write(SERVO );
297
465
Serial . write(14 );
298
466
}
467
+ if (IS_PIN_I2C (pin)) {
468
+ Serial . write(I2C );
469
+ Serial . write(1 ); // to do: determine appropriate value
470
+ }
299
471
Serial . write(127 );
300
472
}
301
473
Serial . write(END_SYSEX );
@@ -326,6 +498,31 @@ void sysexCallback(byte command, byte argc, byte *argv)
326
498
}
327
499
}
328
500
501
+ void enableI2CPins()
502
+ {
503
+ byte i;
504
+ // is there a faster way to do this? would probaby require importing
505
+ // Arduino.h to get SCL and SDA pins
506
+ for (i= 0 ; i < TOTAL_PINS ; i++ ) {
507
+ if (IS_PIN_I2C (i)) {
508
+ // mark pins as i2c so they are ignore in non i2c data requests
509
+ setPinModeCallback(i, I2C );
510
+ }
511
+ }
512
+
513
+ isI2CEnabled = true ;
514
+
515
+ // is there enough time before the first I2C request to call this here?
516
+ Wire . begin();
517
+ }
518
+
519
+ void systemResetCallback()
520
+ {
521
+ // clear i2c read continuous data
522
+ readingContinuously = false ;
523
+ queryIndex = 0 ;
524
+ }
525
+
329
526
330
527
/* ==============================================================================
331
528
* SETUP()
@@ -342,6 +539,7 @@ void setup()
342
539
Firmata . attach(REPORT_DIGITAL , reportDigitalCallback);
343
540
Firmata . attach(SET_PIN_MODE , setPinModeCallback);
344
541
Firmata . attach(START_SYSEX , sysexCallback);
542
+ Firmata . attach(SYSTEM_RESET , systemResetCallback);
345
543
346
544
// TODO: load state from EEPROM here
347
545
@@ -365,7 +563,7 @@ void setup()
365
563
analogInputsToReport = 0 ;
366
564
367
565
Firmata . begin(57600 );
368
-
566
+
369
567
/* send digital inputs to set the initial state on the host computer,
370
568
* since once in the loop(), this firmware will only send on change */
371
569
for (i= 0 ; i < TOTAL_PORTS ; i++ ) {
@@ -405,5 +603,11 @@ void loop()
405
603
}
406
604
}
407
605
}
606
+ // report i2c data if read continuous mode is enabled
607
+ if (readingContinuously) {
608
+ for (byte i = 0 ; i < queryIndex; i++ ) {
609
+ readAndReportData(query[i]. addr, query[i]. reg, query[i]. bytes);
610
+ }
611
+ }
408
612
}
409
613
}
0 commit comments