forked from grblHAL/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stream.h
380 lines (295 loc) · 14.4 KB
/
stream.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/*
stream.h - high level (serial) stream handling
Part of grblHAL
Copyright (c) 2019-2023 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file
Stream I/O functions structure for the HAL.
Helper functions for saving away and restoring a stream input buffer. _Not referenced by the core._
*/
#ifndef _STREAM_H_
#define _STREAM_H_
#define ASCII_SOH 0x01
#define ASCII_STX 0x02
#define ASCII_ETX 0x03
#define ASCII_EOT 0x04
#define ASCII_ENQ 0x05
#define ASCII_ACK 0x06
#define ASCII_BS 0x08
#define ASCII_TAB 0x09
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
#define ASCII_NAK 0x15
#define ASCII_EOF 0x1A
#define ASCII_CAN 0x18
#define ASCII_EM 0x19
#define ASCII_ESC 0x1B
#define ASCII_DEL 0x7F
#define ASCII_EOL "\r\n"
#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 1024 // must be a power of 2
#endif
#ifndef TX_BUFFER_SIZE
#define TX_BUFFER_SIZE 512 // must be a power of 2
#endif
#ifndef BLOCK_TX_BUFFER_SIZE
#define BLOCK_TX_BUFFER_SIZE 256
#endif
// Serial baud rate
#ifndef BAUD_RATE
#define BAUD_RATE 115200
#endif
// Value to be returned from input stream when no data is available
#ifndef SERIAL_NO_DATA
#define SERIAL_NO_DATA -1
#endif
#define BUFNEXT(ptr, buffer) ((ptr + 1) & (sizeof(buffer.data) - 1))
#define BUFCOUNT(head, tail, size) ((head >= tail) ? (head - tail) : (size - tail + head))
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "vfs.h"
typedef enum {
StreamType_Serial = 0,
StreamType_MPG,
StreamType_Bluetooth,
StreamType_Telnet,
StreamType_WebSocket,
StreamType_SDCard, // deprecated, use StreamType_File instead
StreamType_File = StreamType_SDCard,
StreamType_Redirected,
StreamType_Null
} stream_type_t;
/*! \brief Pointer to function for getting stream connected status.
\returns \a true connected, \a false otherwise.
*/
typedef bool (*stream_is_connected_ptr)(void);
/*! \brief Pointer to function for getting number of characters available or free in a stream buffer.
\returns number of characters available or free.
*/
typedef uint16_t (*get_stream_buffer_count_ptr)(void);
/*! \brief Pointer to function for reading a single character from a input stream.
\returns character or -1 if none available.
*/
typedef int16_t (*stream_read_ptr)(void);
/*! \brief Pointer to function for writing a null terminated string to the output stream.
\param s pointer to null terminated string.
__NOTE:__ output might be buffered until an #ASCII_LF is output, this is usually done by USB or network driver code to improve throughput.
*/
typedef void (*stream_write_ptr)(const char *s);
/*! \brief Pointer to function for writing a \a n character long string to the output stream.
\param s pointer to string.
\param len number of characters to write.
*/
typedef void (*stream_write_n_ptr)(const char *s, uint16_t len);
/*! \brief Pointer to function for writing a single character to the output stream.
\param c the character to write.
*/
typedef bool (*stream_write_char_ptr)(const char c);
/*! \brief Pointer to function for extracting real-time commands from the input stream and enqueue them for processing.
This should be called by driver code prior to inserting a character into the input buffer.
\param c character to check.
\returns true if extracted, driver code should not insert the character into the input buffer if so.
*/
typedef bool (*enqueue_realtime_command_ptr)(char c);
/*! \brief Optional, but recommended, pointer to function for enqueueing realtime command characters.
\param c character to enqueue.
\returns \a true if successfully enqueued, \a false otherwise.
__NOTE:__ Stream implementations should pass the character over the current handler registered by the set_enqueue_rt_handler().
User or plugin code should __not__ enqueue realtime command characters via this handler, it should call \a grbl.enqueue_realtime_command() instead.
*/
typedef bool (*enqueue_realtime_command2_ptr)(char c);
/*! \brief Pointer to function for setting the enqueue realtime commands handler.
\param handler a \a enqueue_realtime_command_ptr pointer to the new handler function.
\returns \a enqueue_realtime_command_ptr pointer to the replaced function.
__NOTE:__ Stream implementations should hold a pointer to the handler in a local variable and typically
set it to protocol_enqueue_realtime_command() on initialization.
*/
typedef enqueue_realtime_command_ptr (*set_enqueue_rt_handler_ptr)(enqueue_realtime_command_ptr handler);
/*! \brief Pointer to function for setting the stream baud rate.
\param baud_rate
\returns true if successful.
*/
typedef bool (*set_baud_rate_ptr)(uint32_t baud_rate);
/*! \brief Pointer to function for flushing a stream buffer. */
typedef void (*flush_stream_buffer_ptr)(void);
/*! \brief Pointer to function for flushing the input buffer and inserting an #ASCII_CAN character.
This function is typically called by the _enqueue_realtime_command_ handler when CMD_STOP or CMD_JOG_CANCEL character is processed.
The #ASCII_CAN character might be checked for and used by upstream code to flush any buffers it may have.
*/
typedef void (*cancel_read_buffer_ptr)(void);
/*! \brief Pointer to function for blocking reads from and restoring a input buffer.
This function is called with the _await_ parameter true on executing a tool change command (M6),
this shall block further reading from the input buffer.
The core function stream_rx_suspend() can be called with the _await_ parameter to do this,
it will replace the _hal.stream.read_ handler with a pointer to the dummy function stream_get_null().
Reading from the input is blocked until a tool change acknowledge character #CMD_TOOL_ACK is received,
when the driver receives this the input buffer is to be saved away and reading from the input resumed by
restoring the _hal.stream.read_ handler with its own read character function.
Driver code can do this by calling the core function stream_rx_backup().
When the tool change is complete or a soft reset is executed the core will call this function with the _await_ parameter false,
if the driver code called stream_rx_suspend() to block input it shall then call it again with the _await_ parameter as input to restore it.
\param await bool
\returns \a true if there is data in the buffer, \a false otherwise.
*/
typedef bool (*suspend_read_ptr)(bool await);
/*! \brief Pointer to function for disabling/enabling stream input.
Typically used to disable receive interrupts so that real-time command processing for the stream is blocked.
Usually it is desirable to block processing when another stream provides the input, but sometimes not.
E.g. when input is from a SD card real-time commands from the stream that initiated SD card streaming is needed
for handing feed-holds, overrides, soft resets etc.
\param disable \a true to disable stream, \a false to enable,
*/
typedef bool (*disable_rx_stream_ptr)(bool disable);
typedef union {
uint8_t value;
struct {
uint8_t connected :1, //!< deprecated
claimable :1,
claimed :1,
can_set_baud :1,
rx_only :1,
modbus_ready :1,
rts_handshake :1,
unused :1;
};
} io_stream_flags_t;
typedef union {
uint8_t value;
struct {
uint8_t connected :1,
webui_connected :1,
is_usb :1,
unused :5;
};
} io_stream_state_t;
//! Properties and handlers for stream I/O
typedef struct {
stream_type_t type; //!< Type of stream.
uint8_t instance; //!< Instance of stream type, starts from 0.
io_stream_state_t state; //!< Optional status flags such as connected status.
stream_is_connected_ptr is_connected; //!< Handler for getting stream connected status.
get_stream_buffer_count_ptr get_rx_buffer_free; //!< Handler for getting number of free characters in the input buffer.
stream_write_ptr write; //!< Handler for writing string to current output stream only.
stream_write_ptr write_all; //!< Handler for writing string to all active output streams.
stream_write_char_ptr write_char; //!< Handler for writing a single character to current stream only.
enqueue_realtime_command2_ptr enqueue_rt_command; //!< (Optional) handler for enqueueing a realtime command character.
stream_read_ptr read; //!< Handler for reading a single character from the input stream.
flush_stream_buffer_ptr reset_read_buffer; //!< Handler for flushing the input buffer.
cancel_read_buffer_ptr cancel_read_buffer; //!< Handler for flushing the input buffer and inserting an #ASCII_CAN character.
set_enqueue_rt_handler_ptr set_enqueue_rt_handler; //!< Handler for setting the enqueue realtime command character handler.
suspend_read_ptr suspend_read; //!< Optional handler for saving away and restoring the current input buffer.
stream_write_n_ptr write_n; //!< Optional handler for writing n characters to current output stream only. Required for Modbus support.
disable_rx_stream_ptr disable_rx; //!< Optional handler for disabling/enabling a stream. Recommended?
get_stream_buffer_count_ptr get_rx_buffer_count; //!< Optional handler for getting number of characters in the input buffer.
get_stream_buffer_count_ptr get_tx_buffer_count; //!< Optional handler for getting number of characters in the output buffer(s). Count shall include any unsent characters in any transmit FIFO and/or transmit register. Required for Modbus support.
flush_stream_buffer_ptr reset_write_buffer; //!< Optional handler for flushing the output buffer. Any transmit FIFO shall be flushed as well. Required for Modbus support.
set_baud_rate_ptr set_baud_rate; //!< Optional handler for setting the stream baud rate. Required for Modbus support, recommended for Bluetooth support.
vfs_file_t *file; //!< File handle, non-null if streaming from a file.
} io_stream_t;
typedef const io_stream_t *(*stream_claim_ptr)(uint32_t baud_rate);
typedef struct {
stream_type_t type; //!< Type of stream.
uint8_t instance; //!< Instance of stream type, starts from 0.
io_stream_flags_t flags;
stream_claim_ptr claim;
} io_stream_properties_t;
typedef bool (*stream_enumerate_callback_ptr)(io_stream_properties_t const *properties);
typedef struct io_stream_details {
uint8_t n_streams;
io_stream_properties_t *streams;
struct io_stream_details *next;
} io_stream_details_t;
// The following structures and functions are not referenced in the core code, may be used by drivers
typedef struct {
volatile uint_fast16_t head;
volatile uint_fast16_t tail;
volatile bool rts_state;
bool overflow;
bool backup;
char data[RX_BUFFER_SIZE];
} stream_rx_buffer_t;
typedef struct {
volatile uint_fast16_t head;
volatile uint_fast16_t tail;
char data[TX_BUFFER_SIZE];
} stream_tx_buffer_t;
typedef struct {
uint_fast16_t length;
uint_fast16_t max_length;
char *s;
char data[BLOCK_TX_BUFFER_SIZE];
} stream_block_tx_buffer_t;
// double buffered tx stream
typedef struct {
uint_fast16_t length;
uint_fast16_t max_length;
char *s;
bool use_tx2data;
char data[BLOCK_TX_BUFFER_SIZE];
char data2[BLOCK_TX_BUFFER_SIZE];
} stream_block_tx_buffer2_t;
#ifdef __cplusplus
extern "C" {
#endif
/*! \brief Dummy function for reading data from a virtual empty input buffer.
\returns always -1 as there is no data available.
*/
int16_t stream_get_null (void);
/*! \brief Function for blocking reads from or restoring an input buffer.
\param rxbuffer pointer to a stream_rx_buffer_t.
\param suspend when true _hal.stream.read_ is changed to stream_get_null(), if false it is restored if already saved.
\returns true if there is data in the buffer, false otherwise.
*/
bool stream_rx_suspend (stream_rx_buffer_t *rxbuffer, bool suspend);
bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_char_ptr write_char);
/*! \brief Function for enabling/disabling input from a secondary input stream.
\param on \a true if switching input to mpg stream, \a false when restoring original input.
\returns \a true when succsessful, \a false otherwise.
*/
bool stream_mpg_enable (bool on);
void stream_mpg_set_mode (void *data);
bool stream_mpg_check_enable (char c);
bool stream_buffer_all (char c);
bool stream_tx_blocking (void);
bool stream_enqueue_realtime_command (char c);
void stream_register_streams (io_stream_details_t *details);
bool stream_enumerate_streams (stream_enumerate_callback_ptr callback);
bool stream_connect (const io_stream_t *stream);
bool stream_connect_instance (uint8_t instance, uint32_t baud_rate);
void stream_disconnect (const io_stream_t *stream);
bool stream_connected (void);
const io_stream_t *stream_get_base (void);
io_stream_flags_t stream_get_flags (io_stream_t stream);
const io_stream_t *stream_null_init (uint32_t baud_rate);
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler, const char *description);
bool stream_set_description (const io_stream_t *stream, const char *description);
void debug_printf(const char *fmt, ...);
#if defined(DEBUG) || defined(DEBUGOUT)
#define DEBUG_PRINT 1
#ifdef DEBUGOUT
void debug_write (const char *s);
void debug_writeln (const char *s);
bool debug_stream_init (void);
#endif
#else
#define DEBUG_PRINT 0
#endif
#define debug_print(fmt, ...) \
do { if(DEBUG_PRINT) debug_printf(fmt, __VA_ARGS__); } while(0)
#ifdef __cplusplus
}
#endif
#endif