@@ -69,6 +69,8 @@ void SerialDispatcher::begin(unsigned long baudrate, uint16_t config)
69
69
ThreadCustomerData data;
70
70
data.thread_id = current_thread_id;
71
71
data.block_tx_buffer = false ;
72
+ data.prefix_func = nullptr ;
73
+ data.suffix_func = nullptr ;
72
74
_thread_customer_list.push_back (data);
73
75
}
74
76
}
@@ -99,19 +101,37 @@ void SerialDispatcher::end()
99
101
int SerialDispatcher::available ()
100
102
{
101
103
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
102
- return _serial.available ();
104
+ auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
105
+ if (iter == std::end (_thread_customer_list)) return 0 ;
106
+
107
+ prepareSerialReader (iter);
108
+ handleSerialReader ();
109
+
110
+ return iter->rx_buffer ->available ();
103
111
}
104
112
105
113
int SerialDispatcher::peek ()
106
114
{
107
115
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
108
- return _serial.peek ();
116
+ auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
117
+ if (iter == std::end (_thread_customer_list)) return 0 ;
118
+
119
+ prepareSerialReader (iter);
120
+ handleSerialReader ();
121
+
122
+ return iter->rx_buffer ->peek ();
109
123
}
110
124
111
125
int SerialDispatcher::read ()
112
126
{
113
127
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
114
- return _serial.read ();
128
+ auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
129
+ if (iter == std::end (_thread_customer_list)) return 0 ;
130
+
131
+ prepareSerialReader (iter);
132
+ handleSerialReader ();
133
+
134
+ return iter->rx_buffer ->read_char ();
115
135
}
116
136
117
137
void SerialDispatcher::flush ()
@@ -166,6 +186,22 @@ void SerialDispatcher::unblock()
166
186
_cond.notify_one ();
167
187
}
168
188
189
+ void SerialDispatcher::prefix (PrefixInjectorCallbackFunc func)
190
+ {
191
+ mbed::ScopedLock<rtos::Mutex> lock (_mutex);
192
+ auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
193
+ if (iter == std::end (_thread_customer_list)) return ;
194
+ iter->prefix_func = func;
195
+ }
196
+
197
+ void SerialDispatcher::suffix (SuffixInjectorCallbackFunc func)
198
+ {
199
+ mbed::ScopedLock<rtos::Mutex> lock (_mutex);
200
+ auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
201
+ if (iter == std::end (_thread_customer_list)) return ;
202
+ iter->suffix_func = func;
203
+ }
204
+
169
205
/* *************************************************************************************
170
206
* PRIVATE MEMBER FUNCTIONS
171
207
**************************************************************************************/
@@ -190,10 +226,46 @@ void SerialDispatcher::threadFunc()
190
226
if (d.block_tx_buffer )
191
227
return ;
192
228
229
+ /* Return if there's no data to be written to the
230
+ * serial interface. This statement is necessary
231
+ * because otherwise the prefix/suffix functions
232
+ * will be invoked and will be printing something,
233
+ * even though no data is actually to be printed for
234
+ * most threads.
235
+ */
236
+ if (!d.tx_buffer .available ())
237
+ return ;
238
+
239
+ /* The prefix callback function allows the
240
+ * user to insert a custom message before
241
+ * a new message is written to the serial
242
+ * driver. This is useful e.g. for wrapping
243
+ * protocol (e.g. the 'AT' protocol) or providing
244
+ * a timestamp, a log level, ...
245
+ */
246
+ if (d.prefix_func )
247
+ {
248
+ String const prefix_str = d.prefix_func ();
249
+ _serial.write (prefix_str.c_str ());
250
+ }
251
+
252
+ /* Now it's time to actually write the message
253
+ * conveyed by the user via Serial.print/println.
254
+ */
193
255
while (d.tx_buffer .available ())
194
256
{
195
257
_serial.write (d.tx_buffer .read_char ());
196
258
}
259
+
260
+ /* Similar to the prefix function this callback
261
+ * allows the user to specify a specific message
262
+ * to be appended to each message, e.g. '\r\n'.
263
+ */
264
+ if (d.suffix_func )
265
+ {
266
+ String const suffix_str = d.suffix_func ();
267
+ _serial.write (suffix_str.c_str ());
268
+ }
197
269
});
198
270
}
199
271
}
@@ -203,4 +275,31 @@ std::list<SerialDispatcher::ThreadCustomerData>::iterator SerialDispatcher::find
203
275
return std::find_if (std::begin (_thread_customer_list),
204
276
std::end (_thread_customer_list),
205
277
[thread_id](ThreadCustomerData const d) -> bool { return (d.thread_id == thread_id); });
206
- }
278
+ }
279
+
280
+ void SerialDispatcher::prepareSerialReader (std::list<ThreadCustomerData>::iterator & iter)
281
+ {
282
+ if (!iter->rx_buffer )
283
+ iter->rx_buffer .reset (new arduino::RingBuffer ());
284
+ }
285
+
286
+ void SerialDispatcher::handleSerialReader ()
287
+ {
288
+ while (_serial.available ())
289
+ {
290
+ int const c = _serial.read ();
291
+
292
+ std::for_each (std::begin (_thread_customer_list),
293
+ std::end (_thread_customer_list),
294
+ [c](ThreadCustomerData & d)
295
+ {
296
+ if (!d.rx_buffer )
297
+ return ;
298
+
299
+ if (!d.rx_buffer ->availableForStore ())
300
+ return ;
301
+
302
+ d.rx_buffer ->store_char (c);
303
+ });
304
+ }
305
+ }
0 commit comments