Prusa MINI Firmware overview
twibus.h
Go to the documentation of this file.
1 /**
2  * Marlin 3D Printer Firmware
3  * Copyright (c) 2019 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 #pragma once
23 
24 #include "../core/macros.h"
25 
26 #include <Wire.h>
27 
28 // Print debug messages with M111 S2 (Uses 236 bytes of PROGMEM)
29 //#define DEBUG_TWIBUS
30 
31 typedef void (*twiReceiveFunc_t)(int bytes);
32 typedef void (*twiRequestFunc_t)();
33 
34 #define TWIBUS_BUFFER_SIZE 32
35 
36 /**
37  * TWIBUS class
38  *
39  * This class implements a wrapper around the two wire (I2C) bus, allowing
40  * Marlin to send and request data from any slave device on the bus.
41  *
42  * The two main consumers of this class are M260 and M261. M260 provides a way
43  * to send an I2C packet to a device (no repeated starts) by caching up to 32
44  * bytes in a buffer and then sending the buffer.
45  * M261 requests data from a device. The received data is relayed to serial out
46  * for the host to interpret.
47  *
48  * For more information see
49  * - http://marlinfw.org/docs/gcode/M260.html
50  * - http://marlinfw.org/docs/gcode/M261.html
51  *
52  */
53 class TWIBus {
54  private:
55  /**
56  * @brief Number of bytes on buffer
57  * @description Number of bytes in the buffer waiting to be flushed to the bus
58  */
59  uint8_t buffer_s = 0;
60 
61  /**
62  * @brief Internal buffer
63  * @details A fixed buffer. TWI commands can be no longer than this.
64  */
65  char buffer[TWIBUS_BUFFER_SIZE];
66 
67 
68  public:
69  /**
70  * @brief Target device address
71  * @description The target device address. Persists until changed.
72  */
74 
75  /**
76  * @brief Class constructor
77  * @details Initialize the TWI bus and clear the buffer
78  */
79  TWIBus();
80 
81  /**
82  * @brief Reset the buffer
83  * @details Set the buffer to a known-empty state
84  */
85  void reset();
86 
87  /**
88  * @brief Send the buffer data to the bus
89  * @details Flush the buffer to the target address
90  */
91  void send();
92 
93  /**
94  * @brief Add one byte to the buffer
95  * @details Add a byte to the end of the buffer.
96  * Silently fails if the buffer is full.
97  *
98  * @param c a data byte
99  */
100  void addbyte(const char c);
101 
102  /**
103  * @brief Add some bytes to the buffer
104  * @details Add bytes to the end of the buffer.
105  * Concatenates at the buffer size.
106  *
107  * @param src source data address
108  * @param bytes the number of bytes to add
109  */
110  void addbytes(char src[], uint8_t bytes);
111 
112  /**
113  * @brief Add a null-terminated string to the buffer
114  * @details Add bytes to the end of the buffer up to a nul.
115  * Concatenates at the buffer size.
116  *
117  * @param str source string address
118  */
119  void addstring(char str[]);
120 
121  /**
122  * @brief Set the target slave address
123  * @details The target slave address for sending the full packet
124  *
125  * @param adr 7-bit integer address
126  */
127  void address(const uint8_t adr);
128 
129  /**
130  * @brief Prefix for echo to serial
131  * @details Echo a label, length, address, and "data:"
132  *
133  * @param bytes the number of bytes to request
134  */
135  static void echoprefix(uint8_t bytes, const char prefix[], uint8_t adr);
136 
137  /**
138  * @brief Echo data on the bus to serial
139  * @details Echo some number of bytes from the bus
140  * to serial in a parser-friendly format.
141  *
142  * @param bytes the number of bytes to request
143  */
144  static void echodata(uint8_t bytes, const char prefix[], uint8_t adr);
145 
146  /**
147  * @brief Echo data in the buffer to serial
148  * @details Echo the entire buffer to serial
149  * to serial in a parser-friendly format.
150  *
151  * @param bytes the number of bytes to request
152  */
153  void echobuffer(const char prefix[], uint8_t adr);
154 
155  /**
156  * @brief Request data from the slave device and wait.
157  * @details Request a number of bytes from a slave device.
158  * Wait for the data to arrive, and return true
159  * on success.
160  *
161  * @param bytes the number of bytes to request
162  * @return status of the request: true=success, false=fail
163  */
164  bool request(const uint8_t bytes);
165 
166  /**
167  * @brief Capture data from the bus into the buffer.
168  * @details Capture data after a request has succeeded.
169  *
170  * @param bytes the number of bytes to request
171  * @return the number of bytes captured to the buffer
172  */
173  uint8_t capture(char *dst, const uint8_t bytes);
174 
175  /**
176  * @brief Flush the i2c bus.
177  * @details Get all bytes on the bus and throw them away.
178  */
179  static void flush();
180 
181  /**
182  * @brief Request data from the slave device, echo to serial.
183  * @details Request a number of bytes from a slave device and output
184  * the returned data to serial in a parser-friendly format.
185  *
186  * @param bytes the number of bytes to request
187  */
188  void relay(const uint8_t bytes);
189 
190  #if I2C_SLAVE_ADDRESS > 0
191 
192  /**
193  * @brief Register a slave receive handler
194  * @details Set a handler to receive data addressed to us
195  *
196  * @param handler A function to handle receiving bytes
197  */
198  inline void onReceive(const twiReceiveFunc_t handler) { Wire.onReceive(handler); }
199 
200  /**
201  * @brief Register a slave request handler
202  * @details Set a handler to send data requested from us
203  *
204  * @param handler A function to handle receiving bytes
205  */
206  inline void onRequest(const twiRequestFunc_t handler) { Wire.onRequest(handler); }
207 
208  /**
209  * @brief Default handler to receive
210  * @details Receive bytes sent to our slave address
211  * and simply echo them to serial.
212  */
213  void receive(uint8_t bytes);
214 
215  /**
216  * @brief Send a reply to the bus
217  * @details Send the buffer and clear it.
218  * If a string is passed, write it into the buffer first.
219  */
220  void reply(char str[]=nullptr);
221  inline void reply(const char str[]) { reply((char*)str); }
222 
223  #endif
224 
225  #if ENABLED(DEBUG_TWIBUS)
226 
227  /**
228  * @brief Prints a debug message
229  * @details Prints a simple debug message "TWIBus::function: value"
230  */
231  static void prefix(const char func[]);
232  static void debug(const char func[], uint32_t adr);
233  static void debug(const char func[], char c);
234  static void debug(const char func[], char adr[]);
235  static inline void debug(const char func[], uint8_t v) { debug(func, (uint32_t)v); }
236 
237  #endif
238 };
I2C_SLAVE_ADDRESS
#define I2C_SLAVE_ADDRESS
Definition: Configuration_A3ides_2209_MINI_adv.h:1883
WITHIN
#define WITHIN(N, L, H)
Definition: macros.h:195
SERIAL_CHAR
#define SERIAL_CHAR(x)
Definition: serial.h:69
twiRequestFunc_t
void(* twiRequestFunc_t)()
Definition: twibus.h:32
TWIBus::address
void address(const uint8_t adr)
Set the target slave address.
TWIBus::addr
uint8_t addr
Target device address @description The target device address. Persists until changed.
Definition: twibus.h:73
TWIBus::reset
void reset()
Reset the buffer.
TwoWire::beginTransmission
void beginTransmission(uint8_t)
Definition: Wire.cpp:16
I2C_ADDRESS
#define I2C_ADDRESS(A)
Definition: macros.h:292
TWIBus::addbyte
void addbyte(const char c)
Add one byte to the buffer.
SERIAL_ECHOPAIR
#define SERIAL_ECHOPAIR(V...)
Definition: serial.h:114
TwoWire::requestFrom
uint8_t requestFrom(uint8_t, uint8_t)
Definition: Wire.cpp:24
i
uint8_t i
Definition: screen_test_graph.c:72
SERIAL_ECHO_START
#define SERIAL_ECHO_START()
Definition: serial.h:179
SERIAL_ECHOLN
#define SERIAL_ECHOLN(x)
Definition: serial.h:72
Wire.h
twiReceiveFunc_t
void(* twiReceiveFunc_t)(int bytes)
Definition: twibus.h:31
SERIAL_ECHO_MSG
#define SERIAL_ECHO_MSG(S)
Definition: serial.h:183
PSTR
#define PSTR(str)
Definition: pgmspace.h:31
TwoWire::write
virtual size_t write(uint8_t)
Definition: Wire.cpp:32
TWIBus::capture
uint8_t capture(char *dst, const uint8_t bytes)
Capture data from the bus into the buffer.
Wire
TwoWire Wire
Definition: Wire.cpp:60
COUNT
#define COUNT(a)
Definition: macros.h:200
TwoWire::read
virtual int read(void)
Definition: Wire.cpp:49
TwoWire::begin
void begin(void)
Definition: Wire.cpp:13
void
void
Definition: png.h:1083
SERIAL_ECHOPGM
#define SERIAL_ECHOPGM(S)
Definition: serial.h:173
TWIBus
Definition: twibus.h:53
TWIBus::echodata
static void echodata(uint8_t bytes, const char prefix[], uint8_t adr)
Echo data on the bus to serial.
uint8_t
const uint8_t[]
Definition: 404_html.c:3
TWIBus::addbytes
void addbytes(char src[], uint8_t bytes)
Add some bytes to the buffer.
TWIBus::flush
static void flush()
Flush the i2c bus.
TWIBus::request
bool request(const uint8_t bytes)
Request data from the slave device and wait.
TWIBus::echobuffer
void echobuffer(const char prefix[], uint8_t adr)
Echo data in the buffer to serial.
DEBUGGING
#define DEBUGGING(F)
Definition: serial.h:47
TWIBus::addstring
void addstring(char str[])
Add a null-terminated string to the buffer.
SERIAL_EOL
#define SERIAL_EOL()
Definition: serial.h:181
TWIBUS_BUFFER_SIZE
#define TWIBUS_BUFFER_SIZE
Definition: twibus.h:34
TwoWire::endTransmission
uint8_t endTransmission(void)
Definition: Wire.cpp:20
TwoWire::available
virtual int available(void)
Definition: Wire.cpp:45
TWIBus::relay
void relay(const uint8_t bytes)
Request data from the slave device, echo to serial.
TWIBus::TWIBus
TWIBus()
Class constructor.
serialprintPGM
void serialprintPGM(PGM_P str)
Definition: serial.cpp:35
TWIBus::send
void send()
Send the buffer data to the bus.
twibus.h
TWIBus::echoprefix
static void echoprefix(uint8_t bytes, const char prefix[], uint8_t adr)
Prefix for echo to serial.