Subversion Repositories MK-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
#ifndef TWIBUS_H
24
#define TWIBUS_H
25
 
26
#include "macros.h"
27
 
28
#include <Wire.h>
29
 
30
// Print debug messages with M111 S2 (Uses 236 bytes of PROGMEM)
31
//#define DEBUG_TWIBUS
32
 
33
typedef void (*twiReceiveFunc_t)(int bytes);
34
typedef void (*twiRequestFunc_t)();
35
 
36
#if ENABLED(MECHADUINO_I2C_COMMANDS)
37
  typedef union {
38
    float fval;
39
    byte bval[sizeof(float)];
40
  } i2cFloat;
41
#endif
42
 
43
#define TWIBUS_BUFFER_SIZE 32
44
 
45
/**
46
 * TWIBUS class
47
 *
48
 * This class implements a wrapper around the two wire (I2C) bus, allowing
49
 * Marlin to send and request data from any slave device on the bus.
50
 *
51
 * The two main consumers of this class are M260 and M261. M260 provides a way
52
 * to send an I2C packet to a device (no repeated starts) by caching up to 32
53
 * bytes in a buffer and then sending the buffer.
54
 * M261 requests data from a device. The received data is relayed to serial out
55
 * for the host to interpret.
56
 *
57
 *  For more information see
58
 *    - http://marlinfw.org/docs/gcode/M260.html
59
 *    - http://marlinfw.org/docs/gcode/M261.html
60
 *
61
 */
62
class TWIBus {
63
  private:
64
    /**
65
     * @brief Number of bytes on buffer
66
     * @description Number of bytes in the buffer waiting to be flushed to the bus
67
     */
68
    uint8_t buffer_s = 0;
69
 
70
    /**
71
     * @brief Internal buffer
72
     * @details A fixed buffer. TWI commands can be no longer than this.
73
     */
74
    char buffer[TWIBUS_BUFFER_SIZE];
75
 
76
 
77
  public:
78
    /**
79
     * @brief Target device address
80
     * @description The target device address. Persists until changed.
81
     */
82
    uint8_t addr = 0;
83
 
84
    /**
85
     * @brief Class constructor
86
     * @details Initialize the TWI bus and clear the buffer
87
     */
88
    TWIBus();
89
 
90
    /**
91
     * @brief Reset the buffer
92
     * @details Set the buffer to a known-empty state
93
     */
94
    void reset();
95
 
96
    /**
97
     * @brief Send the buffer data to the bus
98
     * @details Flush the buffer to the target address
99
     */
100
    void send();
101
 
102
    /**
103
     * @brief Add one byte to the buffer
104
     * @details Add a byte to the end of the buffer.
105
     *          Silently fails if the buffer is full.
106
     *
107
     * @param c a data byte
108
     */
109
    void addbyte(const byte c);
110
 
111
    /**
112
     * @brief Add some bytes to the buffer
113
     * @details Add bytes to the end of the buffer.
114
     *          Concatenates at the buffer size.
115
     *
116
     * @param src source data address
117
     * @param bytes the number of bytes to add
118
     */
119
    void addbytes(byte src[], uint8_t bytes);
120
 
121
    /**
122
     * @brief Add a null-terminated string to the buffer
123
     * @details Add bytes to the end of the buffer up to a nul.
124
     *          Concatenates at the buffer size.
125
     *
126
     * @param str source string address
127
     */
128
    void addstring(char str[]);
129
 
130
    /**
131
     * @brief Set the target slave address
132
     * @details The target slave address for sending the full packet
133
     *
134
     * @param adr 7-bit integer address
135
     */
136
    void address(const uint8_t adr);
137
 
138
    /**
139
     * @brief Prefix for echo to serial
140
     * @details Echo a label, length, address, and "data:"
141
     *
142
     * @param bytes the number of bytes to request
143
     */
144
    static void echoprefix(uint8_t bytes, const char prefix[], uint8_t adr);
145
 
146
    /**
147
     * @brief Echo data on the bus to serial
148
     * @details Echo some number of bytes from the bus
149
     *          to serial in a parser-friendly format.
150
     *
151
     * @param bytes the number of bytes to request
152
     */
153
    static void echodata(uint8_t bytes, const char prefix[], uint8_t adr);
154
 
155
    /**
156
     * @brief Echo data in the buffer to serial
157
     * @details Echo the entire buffer to serial
158
     *          to serial in a parser-friendly format.
159
     *
160
     * @param bytes the number of bytes to request
161
     */
162
    void echobuffer(const char prefix[], uint8_t adr);
163
 
164
    /**
165
     * @brief Request data from the slave device and wait.
166
     * @details Request a number of bytes from a slave device.
167
     *          Wait for the data to arrive, and return true
168
     *          on success.
169
     *
170
     * @param bytes the number of bytes to request
171
     * @return status of the request: true=success, false=fail
172
     */
173
    bool request(const uint8_t bytes);
174
 
175
    /**
176
     * @brief Capture data from the bus into the buffer.
177
     * @details Capture data after a request has succeeded.
178
     *
179
     * @param bytes the number of bytes to request
180
     * @return the number of bytes captured to the buffer
181
     */
182
    uint8_t capture(byte *dst, const uint8_t bytes);
183
 
184
    /**
185
     * @brief Flush the i2c bus.
186
     * @details Get all bytes on the bus and throw them away.
187
     */
188
    static void flush();
189
 
190
    /**
191
     * @brief Request data from the slave device, echo to serial.
192
     * @details Request a number of bytes from a slave device and output
193
     *          the returned data to serial in a parser-friendly format.
194
     *
195
     * @param bytes the number of bytes to request
196
     */
197
    void relay(const uint8_t bytes);
198
 
199
    #if I2C_SLAVE_ADDRESS > 0
200
 
201
      /**
202
       * @brief Register a slave receive handler
203
       * @details Set a handler to receive data addressed to us
204
       *
205
       * @param handler A function to handle receiving bytes
206
       */
207
      inline void onReceive(const twiReceiveFunc_t handler) { Wire.onReceive(handler); }
208
 
209
      /**
210
       * @brief Register a slave request handler
211
       * @details Set a handler to send data requested from us
212
       *
213
       * @param handler A function to handle receiving bytes
214
       */
215
      inline void onRequest(const twiRequestFunc_t handler) { Wire.onRequest(handler); }
216
 
217
      /**
218
       * @brief Default handler to receive
219
       * @details Receive bytes sent to our slave address
220
       *          and simply echo them to serial.
221
       */
222
      void receive(uint8_t bytes);
223
 
224
      /**
225
       * @brief Send a reply to the bus
226
       * @details Send the buffer and clear it.
227
       *          If a string is passed, write it into the buffer first.
228
       */
229
      void reply(char str[]=NULL);
230
      inline void reply(const char str[]) { this->reply((char*)str); }
231
 
232
    #endif
233
 
234
    #if ENABLED(DEBUG_TWIBUS)
235
 
236
      /**
237
       * @brief Prints a debug message
238
       * @details Prints a simple debug message "TWIBus::function: value"
239
       */
240
      static void prefix(const char func[]);
241
      static void debug(const char func[], uint32_t adr);
242
      static void debug(const char func[], char c);
243
      static void debug(const char func[], char adr[]);
244
      static inline void debug(const char func[], uint8_t v) { debug(func, (uint32_t)v); }
245
 
246
    #endif
247
};
248
 
249
#endif // TWIBUS_H