Browse Source

Merge pull request #4595 from thinkyhead/rc_i2c_slave

Add support for i2c slave address
Scott Lahteine 8 years ago
parent
commit
52560e257f

+ 3
- 2
.travis.yml View File

@@ -205,10 +205,11 @@ script:
205 205
   - opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY
206 206
   - build_marlin
207 207
   #
208
-  # Enable BEZIER_CURVE_SUPPORT
208
+  # Enable BEZIER_CURVE_SUPPORT, EXPERIMENTAL_I2CBUS, and I2C_SLAVE_ADDRESS
209 209
   #
210 210
   - restore_configs
211
-  - opt_enable_adv BEZIER_CURVE_SUPPORT
211
+  - opt_enable_adv BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS
212
+  - opt_set_adv I2C_SLAVE_ADDRESS 1
212 213
   - build_marlin
213 214
   #
214 215
   # Enable COREXY

+ 1
- 0
Marlin/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 19
- 9
Marlin/Marlin_main.cpp View File

@@ -835,6 +835,14 @@ void servo_init() {
835 835
   void enableStepperDrivers() { pinMode(STEPPER_RESET_PIN, INPUT); }  // set to input, which allows it to be pulled high by pullups
836 836
 #endif
837 837
 
838
+#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
839
+
840
+  void i2c_listener(int bytes) {
841
+    i2c.receive(bytes);        // just echo all bytes received to serial
842
+  }
843
+
844
+#endif
845
+
838 846
 /**
839 847
  * Marlin entry-point: Set up before the program loop
840 848
  *  - Set up the kill pin, filament runout, power hold
@@ -981,6 +989,10 @@ void setup() {
981 989
       for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
982 990
         mixing_virtual_tool_mix[t][i] = mixing_factor[i];
983 991
   #endif
992
+
993
+  #if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
994
+    i2c.onReceive(i2c_listener);
995
+  #endif
984 996
 }
985 997
 
986 998
 /**
@@ -5246,15 +5258,13 @@ inline void gcode_M121() { endstops.enable_globally(false); }
5246 5258
    */
5247 5259
   inline void gcode_M155() {
5248 5260
     // Set the target address
5249
-    if (code_seen('A'))
5250
-      i2c.address(code_value_byte());
5261
+    if (code_seen('A')) i2c.address(code_value_byte());
5251 5262
 
5252 5263
     // Add a new byte to the buffer
5253
-    else if (code_seen('B'))
5254
-      i2c.addbyte(code_value_int());
5264
+    if (code_seen('B')) i2c.addbyte(code_value_byte());
5255 5265
 
5256 5266
     // Flush the buffer to the bus
5257
-    else if (code_seen('S')) i2c.send();
5267
+    if (code_seen('S')) i2c.send();
5258 5268
 
5259 5269
     // Reset and rewind the buffer
5260 5270
     else if (code_seen('R')) i2c.reset();
@@ -5266,11 +5276,11 @@ inline void gcode_M121() { endstops.enable_globally(false); }
5266 5276
    * Usage: M156 A<slave device address base 10> B<number of bytes>
5267 5277
    */
5268 5278
   inline void gcode_M156() {
5269
-    uint8_t addr = code_seen('A') ? code_value_byte() : 0;
5270
-    int bytes    = code_seen('B') ? code_value_int() : 1;
5279
+    if (code_seen('A')) i2c.address(code_value_byte());
5280
+
5281
+    uint8_t bytes = code_seen('B') ? code_value_byte() : 1;
5271 5282
 
5272
-    if (addr && bytes > 0 && bytes <= 32) {
5273
-      i2c.address(addr);
5283
+    if (i2c.addr > 0 && bytes > 0 && bytes <= 32) {
5274 5284
       i2c.reqbytes(bytes);
5275 5285
     }
5276 5286
     else {

+ 1
- 0
Marlin/example_configurations/Cartesio/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/Felix/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/Hephestos/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/Hephestos_2/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/K8200/Configuration_adv.h View File

@@ -801,5 +801,6 @@ const unsigned int dropsegments = 2; //everything with less than this number of
801 801
 // @section i2cbus
802 802
 
803 803
 //#define EXPERIMENTAL_I2CBUS
804
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
804 805
 
805 806
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/K8400/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/RigidBot/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/SCARA/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/TAZ4/Configuration_adv.h View File

@@ -803,5 +803,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
803 803
 // @section i2cbus
804 804
 
805 805
 //#define EXPERIMENTAL_I2CBUS
806
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
806 807
 
807 808
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/WITBOX/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/delta/biv2.5/Configuration_adv.h View File

@@ -797,5 +797,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
797 797
 // @section i2cbus
798 798
 
799 799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800 801
 
801 802
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/delta/generic/Configuration_adv.h View File

@@ -797,5 +797,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
797 797
 // @section i2cbus
798 798
 
799 799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800 801
 
801 802
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h View File

@@ -796,5 +796,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
796 796
 // @section i2cbus
797 797
 
798 798
 //#define EXPERIMENTAL_I2CBUS
799
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
799 800
 
800 801
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h View File

@@ -801,5 +801,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
801 801
 // @section i2cbus
802 802
 
803 803
 //#define EXPERIMENTAL_I2CBUS
804
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
804 805
 
805 806
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h View File

@@ -797,5 +797,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
797 797
 // @section i2cbus
798 798
 
799 799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800 801
 
801 802
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/makibox/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 1
- 0
Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h View File

@@ -795,5 +795,6 @@ const unsigned int dropsegments = 5; //everything with less than this number of
795 795
 // @section i2cbus
796 796
 
797 797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798 799
 
799 800
 #endif // CONFIGURATION_ADV_H

+ 20
- 21
Marlin/twibus.cpp View File

@@ -29,25 +29,28 @@
29 29
 #include <Wire.h>
30 30
 
31 31
 TWIBus::TWIBus() {
32
-  Wire.begin(); // We use no address so we will join the BUS as the master
32
+  #if I2C_SLAVE_ADDRESS == 0
33
+    Wire.begin();                  // No address joins the BUS as the master
34
+  #else
35
+    Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave
36
+  #endif
33 37
   this->reset();
34 38
 }
35 39
 
36 40
 void TWIBus::reset() {
37
-  this->addr = 0;
38 41
   this->buffer_s = 0;
39 42
   this->buffer[0] = 0x00;
40 43
 }
41 44
 
42
-void TWIBus::address(uint8_t addr) {
45
+void TWIBus::address(const uint8_t addr) {
43 46
   this->addr = addr;
44 47
 
45 48
   #if ENABLED(DEBUG_TWIBUS)
46
-    debug(PSTR("sendto"), this->addr);
49
+    debug(PSTR("address"), this->addr);
47 50
   #endif
48 51
 }
49 52
 
50
-void TWIBus::addbyte(char c) {
53
+void TWIBus::addbyte(const char c) {
51 54
   if (buffer_s >= sizeof(this->buffer)) return;
52 55
   this->buffer[this->buffer_s++] = c;
53 56
 
@@ -67,39 +70,35 @@ void TWIBus::send() {
67 70
   Wire.write(this->buffer, this->buffer_s);
68 71
   Wire.endTransmission();
69 72
 
70
-    // Reset the buffer after sending the data
73
+  // Reset the buffer after sending the data
71 74
   this->reset();
72 75
 }
73 76
 
74
-void TWIBus::reqbytes(uint8_t bytes) {
77
+void TWIBus::reqbytes(const uint8_t bytes) {
75 78
   if (!this->addr) return;
76 79
 
77 80
   #if ENABLED(DEBUG_TWIBUS)
78 81
     debug(PSTR("reqbytes"), bytes);
79 82
   #endif
80 83
 
84
+  // requestFrom() is a blocking function
81 85
   millis_t t = millis() + this->timeout;
82 86
   Wire.requestFrom(this->addr, bytes);
87
+  while (Wire.available() < bytes && PENDING(millis(), t)) { /*nada*/ }
83 88
 
84
-    // requestFrom() is a blocking function
85
-  while (Wire.available() < bytes) {
86
-    if (ELAPSED(millis(), t)) break;
87
-    else continue;
88
-  }
89
+  this->relaydata(bytes);
89 90
 
91
+  // Reset the buffer after sending the data
92
+  this->reset();
93
+}
94
+
95
+void TWIBus::relaydata(uint8_t bytes) {
90 96
   SERIAL_ECHO_START;
91 97
   SERIAL_ECHOPAIR("i2c-reply: from:", this->addr);
92
-  SERIAL_ECHOPAIR(" bytes:", Wire.available());
98
+  SERIAL_ECHOPAIR(" bytes:", bytes);
93 99
   SERIAL_ECHOPGM (" data:");
94
-
95
-    // Protect against buffer overflows if the number of received bytes
96
-    // is less than the number of requested bytes
97
-  uint8_t wba = Wire.available();
98
-  for (int i = 0; i < wba; i++) SERIAL_CHAR(Wire.read());
100
+  while (bytes-- && Wire.available()) SERIAL_CHAR(Wire.read());
99 101
   SERIAL_EOL;
100
-
101
-  // Reset the buffer after sending the data
102
-  this->reset();
103 102
 }
104 103
 
105 104
 #if ENABLED(DEBUG_TWIBUS)

+ 59
- 29
Marlin/twibus.h View File

@@ -25,9 +25,13 @@
25 25
 
26 26
 #include "macros.h"
27 27
 
28
+#include <Wire.h>
29
+
28 30
 // Print debug messages with M111 S2 (Uses 236 bytes of PROGMEM)
29 31
 //#define DEBUG_TWIBUS
30 32
 
33
+typedef void (*twiSlaveFunc_t)(int bytes);
34
+
31 35
 /**
32 36
  * TWIBUS class
33 37
  *
@@ -49,79 +53,105 @@ class TWIBus {
49 53
   private:
50 54
     /**
51 55
      * @brief Timeout value in milliseconds
52
-     * @details For blocking operations this constant value will set the max
53
-     * amount of time Marlin will keep waiting for a reply. Useful is something
54
-     * goes wrong on the bus and the SDA/SCL lines are held up by another device.
56
+     * @details Maximum amount of time (ms) to wait for a reply.
57
+     *          Useful if something goes wrong on the bus and the
58
+     *          SDA/SCL lines are held up by another device.
55 59
      */
56 60
     const int timeout = 5;
57 61
 
58 62
     /**
59
-     * @brief Target device address
60
-     * @description This stores, until the buffer is flushed, the target device
61
-     * address, take not we do follow Arduino 7bit addressing.
62
-     */
63
-    uint8_t addr = 0;
64
-
65
-    /**
66 63
      * @brief Number of bytes on buffer
67
-     * @description This var holds the total number of bytes on our buffer
68
-     * waiting to be flushed to the bus.
64
+     * @description Number of bytes in the buffer waiting to be flushed to the bus.
69 65
      */
70 66
     uint8_t buffer_s = 0;
71 67
 
72 68
     /**
73 69
      * @brief Internal buffer
74
-     * @details This is a fixed buffer, TWI command cannot be longer than this
70
+     * @details A fixed buffer. TWI commands can be no longer than this.
75 71
      */
76
-    char buffer[30];
72
+    char buffer[32];
77 73
 
78 74
 
79 75
   public:
80 76
     /**
77
+     * @brief Target device address
78
+     * @description The target device address. Persists until changed.
79
+     */
80
+    uint8_t addr = 0;
81
+
82
+    /**
81 83
      * @brief Class constructor
82
-     * @details Initialized the TWI bus and clears the buffer
84
+     * @details Initialize the TWI bus and clear the buffer
83 85
      */
84 86
     TWIBus();
85 87
 
86 88
     /**
87 89
      * @brief Reset the buffer
88
-     * @details Brings the internal buffer to a known-empty state
90
+     * @details Set the buffer to a known-empty state
89 91
      */
90 92
     void reset();
91 93
 
92 94
     /**
93 95
      * @brief Send the buffer data to the bus
94
-     * @details Flushed the buffer into the bus targeting the cached slave device
95
-     * address.
96
+     * @details Flush the buffer to the bus at the target address.
96 97
      */
97 98
     void send();
98 99
 
99 100
     /**
100 101
      * @brief Add one byte to the buffer
101
-     * @details Adds the byte to the buffer in a sequential way, if buffer is full
102
-     * the request is silently ignored.
102
+     * @details Add a byte to the end of the buffer.
103
+     *          Silently fails if the buffer is full.
103 104
      *
104 105
      * @param c a data byte
105 106
      */
106
-    void addbyte(char c);
107
+    void addbyte(const char c);
107 108
 
108 109
     /**
109
-     * @brief Sets the target slave address
110
-     * @details The target slave address is stored so it can be later used when
111
-     * the complete packet needs to be sent over the bus.
110
+     * @brief Set the target slave address
111
+     * @details The target slave address for sending the full packet.
112 112
      *
113 113
      * @param addr 7-bit integer address
114 114
      */
115
-    void address(uint8_t addr);
115
+    void address(const uint8_t addr);
116
+
117
+    /**
118
+     * @brief Request data from the slave device
119
+     * @details Request a number of bytes from a slave device.
120
+     *          This implementation simply sends the data to serial
121
+     *          in a parser-friendly format.
122
+     *
123
+     * @param bytes the number of bytes to request
124
+     */
125
+    void reqbytes(const uint8_t bytes);
116 126
 
117 127
     /**
118
-     * @brief Request data from slave device
119
-     * @details Requests data from a slave device, when the data is received it will
120
-     * be relayed to the serial line using a parser-friendly formatting.
128
+     * @brief Relay data from the slave device to serial
129
+     * @details Relay a number of bytes from the bus to
130
+     *          serial in a parser-friendly format.
121 131
      *
122 132
      * @param bytes the number of bytes to request
123 133
      */
124
-    void reqbytes(uint8_t bytes);
134
+    void relaydata(uint8_t bytes);
135
+
136
+    #if I2C_SLAVE_ADDRESS > 0
137
+
138
+      /**
139
+       * @brief Receive bytes (passively)
140
+       * @details Receive bytes sent to our slave address.
141
+       *          and simply echo them to serial.
142
+       */
143
+      inline void receive(uint8_t bytes) { relaydata(bytes); }
144
+
145
+      /**
146
+       * @brief Register a slave handler
147
+       * @details Set a handler to receive data from the bus,
148
+       *          so we can act as a slave.
149
+       *
150
+       * @param handler A function to handle receiving bytes
151
+       */
152
+      inline void onReceive(const twiSlaveFunc_t handler) { Wire.onReceive(handler); }
153
+
154
+    #endif
125 155
 
126 156
     #if ENABLED(DEBUG_TWIBUS)
127 157
 

Loading…
Cancel
Save