@@ -18,6 +18,65 @@ uint8_t next_uart_num = 1;
18
18
#endif
19
19
20
20
#ifdef ARDUINO_ARCH_ESP32
21
+
22
+ #define UART_PARITY_EVEN 0 << 0
23
+ #define UART_PARITY_ODD 1 << 0
24
+ #define UART_PARITY_EN 1 << 1
25
+ #define UART_NB_BIT_5 0 << 2
26
+ #define UART_NB_BIT_6 1 << 2
27
+ #define UART_NB_BIT_7 2 << 2
28
+ #define UART_NB_BIT_8 3 << 2
29
+ #define UART_NB_STOP_BIT_1 1 << 4
30
+ #define UART_NB_STOP_BIT_2 3 << 4
31
+ #define UART_TICK_APB_CLOCK 1 << 27
32
+
33
+ uint32_t UARTComponent::get_config () {
34
+ uint32_t config = 0 ;
35
+
36
+ /*
37
+ * All bits numbers below come from
38
+ * framework-arduinoespressif32/cores/esp32/esp32-hal-uart.h
39
+ * And more specifically conf0 union in uart_dev_t.
40
+ *
41
+ * Below is bit used from conf0 union.
42
+ * <name>:<bits position> <values>
43
+ * parity:0 0:even 1:odd
44
+ * parity_en:1 Set this bit to enable uart parity check.
45
+ * bit_num:2-4 0:5bits 1:6bits 2:7bits 3:8bits
46
+ * stop_bit_num:4-6 stop bit. 1:1bit 2:1.5bits 3:2bits
47
+ * tick_ref_always_on:27 select the clock.1:apb clock:ref_tick
48
+ */
49
+
50
+ if (this ->parity_ == " even" )
51
+ config |= UART_PARITY_EVEN | UART_PARITY_EN;
52
+ else if (this ->parity_ == " odd" )
53
+ config |= UART_PARITY_ODD | UART_PARITY_EN;
54
+
55
+ switch (this ->nr_bits_ ) {
56
+ case 5 :
57
+ config |= UART_NB_BIT_5;
58
+ break ;
59
+ case 6 :
60
+ config |= UART_NB_BIT_6;
61
+ break ;
62
+ case 7 :
63
+ config |= UART_NB_BIT_7;
64
+ break ;
65
+ case 8 :
66
+ config |= UART_NB_BIT_8;
67
+ break ;
68
+ }
69
+
70
+ if (this ->stop_bits_ == 1 )
71
+ config |= UART_NB_STOP_BIT_1;
72
+ else
73
+ config |= UART_NB_STOP_BIT_2;
74
+
75
+ config |= UART_TICK_APB_CLOCK;
76
+
77
+ return config;
78
+ }
79
+
21
80
void UARTComponent::setup () {
22
81
ESP_LOGCONFIG (TAG, " Setting up UART..." );
23
82
// Use Arduino HardwareSerial UARTs if all used pins match the ones
@@ -30,10 +89,7 @@ void UARTComponent::setup() {
30
89
}
31
90
int8_t tx = this ->tx_pin_ .has_value () ? *this ->tx_pin_ : -1 ;
32
91
int8_t rx = this ->rx_pin_ .has_value () ? *this ->rx_pin_ : -1 ;
33
- uint32_t config = SERIAL_8N1;
34
- if (this ->stop_bits_ == 2 )
35
- config = SERIAL_8N2;
36
- this ->hw_serial_ ->begin (this ->baud_rate_ , config, rx, tx);
92
+ this ->hw_serial_ ->begin (this ->baud_rate_ , get_config (), rx, tx);
37
93
}
38
94
39
95
void UARTComponent::dump_config () {
@@ -45,6 +101,8 @@ void UARTComponent::dump_config() {
45
101
ESP_LOGCONFIG (TAG, " RX Pin: GPIO%d" , *this ->rx_pin_ );
46
102
}
47
103
ESP_LOGCONFIG (TAG, " Baud Rate: %u baud" , this ->baud_rate_ );
104
+ ESP_LOGCONFIG (TAG, " Bits: %u" , this ->nr_bits_ );
105
+ ESP_LOGCONFIG (TAG, " Parity: %s" , this ->parity_ .c_str ());
48
106
ESP_LOGCONFIG (TAG, " Stop bits: %u" , this ->stop_bits_ );
49
107
this ->check_logger_conflict_ ();
50
108
}
@@ -107,17 +165,46 @@ void UARTComponent::flush() {
107
165
#endif // ESP32
108
166
109
167
#ifdef ARDUINO_ARCH_ESP8266
168
+ uint32_t UARTComponent::get_config () {
169
+ uint32_t config = 0 ;
170
+
171
+ if (this ->parity_ == " none" )
172
+ config |= UART_PARITY_NONE;
173
+ else if (this ->parity_ == " even" )
174
+ config |= UART_PARITY_EVEN;
175
+ else if (this ->parity_ == " odd" )
176
+ config |= UART_PARITY_ODD;
177
+
178
+ switch (this ->nr_bits_ ) {
179
+ case 5 :
180
+ config |= UART_NB_BIT_5;
181
+ break ;
182
+ case 6 :
183
+ config |= UART_NB_BIT_6;
184
+ break ;
185
+ case 7 :
186
+ config |= UART_NB_BIT_7;
187
+ break ;
188
+ case 8 :
189
+ config |= UART_NB_BIT_8;
190
+ break ;
191
+ }
192
+
193
+ if (this ->stop_bits_ == 1 )
194
+ config |= UART_NB_STOP_BIT_1;
195
+ else
196
+ config |= UART_NB_STOP_BIT_2;
197
+
198
+ return config;
199
+ }
200
+
110
201
void UARTComponent::setup () {
111
202
ESP_LOGCONFIG (TAG, " Setting up UART bus..." );
112
203
// Use Arduino HardwareSerial UARTs if all used pins match the ones
113
204
// preconfigured by the platform. For example if RX disabled but TX pin
114
205
// is 1 we still want to use Serial.
115
- uint32_t mode = UART_NB_BIT_8 | UART_PARITY_NONE;
116
- if (this ->stop_bits_ == 1 )
117
- mode |= UART_NB_STOP_BIT_1;
118
- else
119
- mode |= UART_NB_STOP_BIT_2;
120
- SerialConfig config = static_cast <SerialConfig>(mode);
206
+ SerialConfig config = static_cast <SerialConfig>(get_config ());
207
+
121
208
if (this ->tx_pin_ .value_or (1 ) == 1 && this ->rx_pin_ .value_or (3 ) == 3 ) {
122
209
this ->hw_serial_ = &Serial;
123
210
this ->hw_serial_ ->begin (this ->baud_rate_ , config);
@@ -132,7 +219,7 @@ void UARTComponent::setup() {
132
219
this ->sw_serial_ = new ESP8266SoftwareSerial ();
133
220
int8_t tx = this ->tx_pin_ .has_value () ? *this ->tx_pin_ : -1 ;
134
221
int8_t rx = this ->rx_pin_ .has_value () ? *this ->rx_pin_ : -1 ;
135
- this ->sw_serial_ ->setup (tx, rx, this ->baud_rate_ , this ->stop_bits_ );
222
+ this ->sw_serial_ ->setup (tx, rx, this ->baud_rate_ , this ->stop_bits_ , this -> nr_bits_ , this -> parity_ );
136
223
}
137
224
}
138
225
@@ -145,6 +232,8 @@ void UARTComponent::dump_config() {
145
232
ESP_LOGCONFIG (TAG, " RX Pin: GPIO%d" , *this ->rx_pin_ );
146
233
}
147
234
ESP_LOGCONFIG (TAG, " Baud Rate: %u baud" , this ->baud_rate_ );
235
+ ESP_LOGCONFIG (TAG, " Bits: %u" , this ->nr_bits_ );
236
+ ESP_LOGCONFIG (TAG, " Parity: %s" , this ->parity_ .c_str ());
148
237
ESP_LOGCONFIG (TAG, " Stop bits: %u" , this ->stop_bits_ );
149
238
if (this ->hw_serial_ != nullptr ) {
150
239
ESP_LOGCONFIG (TAG, " Using hardware serial interface." );
@@ -249,8 +338,12 @@ void UARTComponent::flush() {
249
338
}
250
339
}
251
340
252
- void ESP8266SoftwareSerial::setup (int8_t tx_pin, int8_t rx_pin, uint32_t baud_rate, uint8_t stop_bits) {
341
+ void ESP8266SoftwareSerial::setup (int8_t tx_pin, int8_t rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t nr_bits,
342
+ std::string &parity) {
253
343
this ->bit_time_ = F_CPU / baud_rate;
344
+ this ->stop_bits_ = stop_bits;
345
+ this ->nr_bits_ = nr_bits;
346
+ this ->parity_ = parity;
254
347
if (tx_pin != -1 ) {
255
348
auto pin = GPIOPin (tx_pin, OUTPUT);
256
349
pin.setup ();
@@ -264,21 +357,22 @@ void ESP8266SoftwareSerial::setup(int8_t tx_pin, int8_t rx_pin, uint32_t baud_ra
264
357
this ->rx_buffer_ = new uint8_t [this ->rx_buffer_size_ ];
265
358
pin.attach_interrupt (ESP8266SoftwareSerial::gpio_intr, this , FALLING);
266
359
}
267
- this ->stop_bits_ = stop_bits;
268
360
}
269
361
void ICACHE_RAM_ATTR ESP8266SoftwareSerial::gpio_intr (ESP8266SoftwareSerial *arg) {
270
362
uint32_t wait = arg->bit_time_ + arg->bit_time_ / 3 - 500 ;
271
363
const uint32_t start = ESP.getCycleCount ();
272
364
uint8_t rec = 0 ;
273
365
// Manually unroll the loop
274
- rec |= arg->read_bit_ (&wait , start) << 0 ;
275
- rec |= arg->read_bit_ (&wait , start) << 1 ;
276
- rec |= arg->read_bit_ (&wait , start) << 2 ;
277
- rec |= arg->read_bit_ (&wait , start) << 3 ;
278
- rec |= arg->read_bit_ (&wait , start) << 4 ;
279
- rec |= arg->read_bit_ (&wait , start) << 5 ;
280
- rec |= arg->read_bit_ (&wait , start) << 6 ;
281
- rec |= arg->read_bit_ (&wait , start) << 7 ;
366
+ for (int i = 0 ; i < arg->nr_bits_ ; i++)
367
+ rec |= arg->read_bit_ (&wait , start) << i;
368
+
369
+ /* If parity is enabled, just read it and ignore it. */
370
+ /* TODO: Should we check parity? Or is it too slow for nothing added..*/
371
+ if (arg->parity_ == " even" )
372
+ arg->read_bit_ (&wait , start);
373
+ else if (arg->parity_ == " odd" )
374
+ arg->read_bit_ (&wait , start);
375
+
282
376
// Stop bit
283
377
arg->wait_ (&wait , start);
284
378
if (arg->stop_bits_ == 2 )
@@ -294,21 +388,29 @@ void ICACHE_RAM_ATTR HOT ESP8266SoftwareSerial::write_byte(uint8_t data) {
294
388
ESP_LOGE (TAG, " UART doesn't have TX pins set!" );
295
389
return ;
296
390
}
391
+ bool parity_bit = false ;
392
+ bool need_parity_bit = true ;
393
+ if (this ->parity_ == " even" )
394
+ parity_bit = true ;
395
+ else if (this ->parity_ == " odd" )
396
+ parity_bit = false ;
397
+ else
398
+ need_parity_bit = false ;
297
399
298
400
{
299
401
InterruptLock lock;
300
402
uint32_t wait = this ->bit_time_ ;
301
403
const uint32_t start = ESP.getCycleCount ();
302
404
// Start bit
303
405
this ->write_bit_ (false , &wait , start);
304
- this -> write_bit_ (data & ( 1 << 0 ), & wait , start);
305
- this -> write_bit_ ( data & (1 << 1 ), & wait , start );
306
- this ->write_bit_ (data & ( 1 << 2 ) , &wait , start);
307
- this -> write_bit_ (data & ( 1 << 3 ), & wait , start);
308
- this -> write_bit_ (data & ( 1 << 4 ), & wait , start) ;
309
- this -> write_bit_ (data & ( 1 << 5 ), & wait , start);
310
- this -> write_bit_ (data & ( 1 << 6 ), & wait , start);
311
- this ->write_bit_ (data & ( 1 << 7 ) , &wait , start);
406
+ for ( int i = 0 ; i < this -> nr_bits_ ; i++) {
407
+ bool bit = data & (1 << i );
408
+ this ->write_bit_ (bit , &wait , start);
409
+ if (need_parity_bit)
410
+ parity_bit ^= bit ;
411
+ }
412
+ if (need_parity_bit)
413
+ this ->write_bit_ (parity_bit , &wait , start);
312
414
// Stop bit
313
415
this ->write_bit_ (true , &wait , start);
314
416
if (this ->stop_bits_ == 2 )
0 commit comments