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
   - opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY
205
   - opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY
206
   - build_marlin
206
   - build_marlin
207
   #
207
   #
208
-  # Enable BEZIER_CURVE_SUPPORT
208
+  # Enable BEZIER_CURVE_SUPPORT, EXPERIMENTAL_I2CBUS, and I2C_SLAVE_ADDRESS
209
   #
209
   #
210
   - restore_configs
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
   - build_marlin
213
   - build_marlin
213
   #
214
   #
214
   # Enable COREXY
215
   # Enable COREXY

+ 1
- 0
Marlin/Configuration_adv.h View File

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

+ 19
- 9
Marlin/Marlin_main.cpp View File

835
   void enableStepperDrivers() { pinMode(STEPPER_RESET_PIN, INPUT); }  // set to input, which allows it to be pulled high by pullups
835
   void enableStepperDrivers() { pinMode(STEPPER_RESET_PIN, INPUT); }  // set to input, which allows it to be pulled high by pullups
836
 #endif
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
  * Marlin entry-point: Set up before the program loop
847
  * Marlin entry-point: Set up before the program loop
840
  *  - Set up the kill pin, filament runout, power hold
848
  *  - Set up the kill pin, filament runout, power hold
981
       for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
989
       for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
982
         mixing_virtual_tool_mix[t][i] = mixing_factor[i];
990
         mixing_virtual_tool_mix[t][i] = mixing_factor[i];
983
   #endif
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
    */
5258
    */
5247
   inline void gcode_M155() {
5259
   inline void gcode_M155() {
5248
     // Set the target address
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
     // Add a new byte to the buffer
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
     // Flush the buffer to the bus
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
     // Reset and rewind the buffer
5269
     // Reset and rewind the buffer
5260
     else if (code_seen('R')) i2c.reset();
5270
     else if (code_seen('R')) i2c.reset();
5266
    * Usage: M156 A<slave device address base 10> B<number of bytes>
5276
    * Usage: M156 A<slave device address base 10> B<number of bytes>
5267
    */
5277
    */
5268
   inline void gcode_M156() {
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
       i2c.reqbytes(bytes);
5284
       i2c.reqbytes(bytes);
5275
     }
5285
     }
5276
     else {
5286
     else {

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

801
 // @section i2cbus
801
 // @section i2cbus
802
 
802
 
803
 //#define EXPERIMENTAL_I2CBUS
803
 //#define EXPERIMENTAL_I2CBUS
804
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
804
 
805
 
805
 #endif // CONFIGURATION_ADV_H
806
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

803
 // @section i2cbus
803
 // @section i2cbus
804
 
804
 
805
 //#define EXPERIMENTAL_I2CBUS
805
 //#define EXPERIMENTAL_I2CBUS
806
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
806
 
807
 
807
 #endif // CONFIGURATION_ADV_H
808
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

797
 // @section i2cbus
797
 // @section i2cbus
798
 
798
 
799
 //#define EXPERIMENTAL_I2CBUS
799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800
 
801
 
801
 #endif // CONFIGURATION_ADV_H
802
 #endif // CONFIGURATION_ADV_H

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

797
 // @section i2cbus
797
 // @section i2cbus
798
 
798
 
799
 //#define EXPERIMENTAL_I2CBUS
799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800
 
801
 
801
 #endif // CONFIGURATION_ADV_H
802
 #endif // CONFIGURATION_ADV_H

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

796
 // @section i2cbus
796
 // @section i2cbus
797
 
797
 
798
 //#define EXPERIMENTAL_I2CBUS
798
 //#define EXPERIMENTAL_I2CBUS
799
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
799
 
800
 
800
 #endif // CONFIGURATION_ADV_H
801
 #endif // CONFIGURATION_ADV_H

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

801
 // @section i2cbus
801
 // @section i2cbus
802
 
802
 
803
 //#define EXPERIMENTAL_I2CBUS
803
 //#define EXPERIMENTAL_I2CBUS
804
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
804
 
805
 
805
 #endif // CONFIGURATION_ADV_H
806
 #endif // CONFIGURATION_ADV_H

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

797
 // @section i2cbus
797
 // @section i2cbus
798
 
798
 
799
 //#define EXPERIMENTAL_I2CBUS
799
 //#define EXPERIMENTAL_I2CBUS
800
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
800
 
801
 
801
 #endif // CONFIGURATION_ADV_H
802
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

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

795
 // @section i2cbus
795
 // @section i2cbus
796
 
796
 
797
 //#define EXPERIMENTAL_I2CBUS
797
 //#define EXPERIMENTAL_I2CBUS
798
+#define I2C_SLAVE_ADDRESS  0 // Set non-zero to act as a slave
798
 
799
 
799
 #endif // CONFIGURATION_ADV_H
800
 #endif // CONFIGURATION_ADV_H

+ 20
- 21
Marlin/twibus.cpp View File

29
 #include <Wire.h>
29
 #include <Wire.h>
30
 
30
 
31
 TWIBus::TWIBus() {
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
   this->reset();
37
   this->reset();
34
 }
38
 }
35
 
39
 
36
 void TWIBus::reset() {
40
 void TWIBus::reset() {
37
-  this->addr = 0;
38
   this->buffer_s = 0;
41
   this->buffer_s = 0;
39
   this->buffer[0] = 0x00;
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
   this->addr = addr;
46
   this->addr = addr;
44
 
47
 
45
   #if ENABLED(DEBUG_TWIBUS)
48
   #if ENABLED(DEBUG_TWIBUS)
46
-    debug(PSTR("sendto"), this->addr);
49
+    debug(PSTR("address"), this->addr);
47
   #endif
50
   #endif
48
 }
51
 }
49
 
52
 
50
-void TWIBus::addbyte(char c) {
53
+void TWIBus::addbyte(const char c) {
51
   if (buffer_s >= sizeof(this->buffer)) return;
54
   if (buffer_s >= sizeof(this->buffer)) return;
52
   this->buffer[this->buffer_s++] = c;
55
   this->buffer[this->buffer_s++] = c;
53
 
56
 
67
   Wire.write(this->buffer, this->buffer_s);
70
   Wire.write(this->buffer, this->buffer_s);
68
   Wire.endTransmission();
71
   Wire.endTransmission();
69
 
72
 
70
-    // Reset the buffer after sending the data
73
+  // Reset the buffer after sending the data
71
   this->reset();
74
   this->reset();
72
 }
75
 }
73
 
76
 
74
-void TWIBus::reqbytes(uint8_t bytes) {
77
+void TWIBus::reqbytes(const uint8_t bytes) {
75
   if (!this->addr) return;
78
   if (!this->addr) return;
76
 
79
 
77
   #if ENABLED(DEBUG_TWIBUS)
80
   #if ENABLED(DEBUG_TWIBUS)
78
     debug(PSTR("reqbytes"), bytes);
81
     debug(PSTR("reqbytes"), bytes);
79
   #endif
82
   #endif
80
 
83
 
84
+  // requestFrom() is a blocking function
81
   millis_t t = millis() + this->timeout;
85
   millis_t t = millis() + this->timeout;
82
   Wire.requestFrom(this->addr, bytes);
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
   SERIAL_ECHO_START;
96
   SERIAL_ECHO_START;
91
   SERIAL_ECHOPAIR("i2c-reply: from:", this->addr);
97
   SERIAL_ECHOPAIR("i2c-reply: from:", this->addr);
92
-  SERIAL_ECHOPAIR(" bytes:", Wire.available());
98
+  SERIAL_ECHOPAIR(" bytes:", bytes);
93
   SERIAL_ECHOPGM (" data:");
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
   SERIAL_EOL;
101
   SERIAL_EOL;
100
-
101
-  // Reset the buffer after sending the data
102
-  this->reset();
103
 }
102
 }
104
 
103
 
105
 #if ENABLED(DEBUG_TWIBUS)
104
 #if ENABLED(DEBUG_TWIBUS)

+ 59
- 29
Marlin/twibus.h View File

25
 
25
 
26
 #include "macros.h"
26
 #include "macros.h"
27
 
27
 
28
+#include <Wire.h>
29
+
28
 // Print debug messages with M111 S2 (Uses 236 bytes of PROGMEM)
30
 // Print debug messages with M111 S2 (Uses 236 bytes of PROGMEM)
29
 //#define DEBUG_TWIBUS
31
 //#define DEBUG_TWIBUS
30
 
32
 
33
+typedef void (*twiSlaveFunc_t)(int bytes);
34
+
31
 /**
35
 /**
32
  * TWIBUS class
36
  * TWIBUS class
33
  *
37
  *
49
   private:
53
   private:
50
     /**
54
     /**
51
      * @brief Timeout value in milliseconds
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
     const int timeout = 5;
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
      * @brief Number of bytes on buffer
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
     uint8_t buffer_s = 0;
66
     uint8_t buffer_s = 0;
71
 
67
 
72
     /**
68
     /**
73
      * @brief Internal buffer
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
   public:
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
      * @brief Class constructor
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
     TWIBus();
86
     TWIBus();
85
 
87
 
86
     /**
88
     /**
87
      * @brief Reset the buffer
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
     void reset();
92
     void reset();
91
 
93
 
92
     /**
94
     /**
93
      * @brief Send the buffer data to the bus
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
     void send();
98
     void send();
98
 
99
 
99
     /**
100
     /**
100
      * @brief Add one byte to the buffer
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
      * @param c a data byte
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
      * @param addr 7-bit integer address
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
      * @param bytes the number of bytes to request
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
     #if ENABLED(DEBUG_TWIBUS)
156
     #if ENABLED(DEBUG_TWIBUS)
127
 
157
 

Loading…
Cancel
Save