Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9120f2e

Browse files
Bounifacchinm
authored andcommitted
Add 9bit support to HardwareSerial
Squash and rebase of arduino/Arduino#2291 Supersedes arduino/Arduino#1221
1 parent 6c861d8 commit 9120f2e

File tree

3 files changed

+149
-52
lines changed

3 files changed

+149
-52
lines changed

‎cores/arduino/HardwareSerial.cpp‎

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,25 @@ void HardwareSerial::_tx_udr_empty_irq(void)
8282
{
8383
// If interrupts are enabled, there must be more data in the output
8484
// buffer. Send the next byte
85-
unsigned char c = _tx_buffer[_tx_buffer_tail];
86-
_tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;
8785

88-
*_udr = c;
86+
if(bit_is_set(*_ucsrb, UCSZ02)) {
87+
// If Uart is configured for 9 bit mode
88+
unsigned char mb = _tx_buffer[_tx_buffer_tail];
89+
unsigned char c = _tx_buffer[_tx_buffer_tail + 1];
90+
_tx_buffer_tail = (_tx_buffer_tail + 2) % SERIAL_TX_BUFFER_SIZE;
91+
if(mb & 0x01) {
92+
sbi(*_ucsrb, TXB80);
93+
} else {
94+
cbi(*_ucsrb, TXB80);
95+
}
96+
*_udr = c;
97+
} else {
98+
// UART is configured for 5 to 8 bit modes
99+
unsigned char c = _tx_buffer[_tx_buffer_tail];
100+
_tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;
101+
102+
*_udr = c;
103+
}
89104

90105
// clear the TXC bit -- "can be cleared by writing a one to its bit
91106
// location". This makes sure flush() won't return until the bytes
@@ -100,7 +115,7 @@ void HardwareSerial::_tx_udr_empty_irq(void)
100115

101116
// Public Methods //////////////////////////////////////////////////////////////
102117

103-
void HardwareSerial::begin(unsigned long baud, byte config)
118+
void HardwareSerial::begin(unsigned long baud, uint16_t config)
104119
{
105120
// Try u2x mode first
106121
uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2;
@@ -127,8 +142,12 @@ void HardwareSerial::begin(unsigned long baud, byte config)
127142
#if defined(__AVR_ATmega8__)
128143
config |= 0x80; // select UCSRC register (shared with UBRRH)
129144
#endif
130-
*_ucsrc = config;
131-
145+
146+
if(config & 0x100) {
147+
sbi(*_ucsrb, UCSZ02);
148+
}
149+
*_ucsrc = (uint8_t) config;
150+
132151
sbi(*_ucsrb, RXEN0);
133152
sbi(*_ucsrb, TXEN0);
134153
sbi(*_ucsrb, RXCIE0);
@@ -151,15 +170,28 @@ void HardwareSerial::end()
151170

152171
int HardwareSerial::available(void)
153172
{
154-
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
173+
unsigned int a = (unsigned int) (SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_RX_BUFFER_SIZE;
174+
if(bit_is_set(*_ucsrb, UCSZ02)) {
175+
// If Uart is in 9 bit mode return only the half, because we use two bytes per 9 bit "byte".
176+
return a / 2;
177+
}
178+
else {
179+
// For 5 - 8 bit modes simply return the number
180+
return a;
181+
}
155182
}
156183

157184
int HardwareSerial::peek(void)
158185
{
159186
if (_rx_buffer_head == _rx_buffer_tail) {
160187
return -1;
161188
} else {
162-
return _rx_buffer[_rx_buffer_tail];
189+
if(bit_is_set(*_ucsrb, UCSZ02)) {
190+
// If Uart is in 9 bit mode read two bytes and merge them
191+
return (_rx_buffer[_rx_buffer_tail] << 8) | _rx_buffer[_rx_buffer_tail + 1 % SERIAL_RX_BUFFER_SIZE];
192+
} else {
193+
return _rx_buffer[_rx_buffer_tail];
194+
}
163195
}
164196
}
165197

@@ -169,9 +201,17 @@ int HardwareSerial::read(void)
169201
if (_rx_buffer_head == _rx_buffer_tail) {
170202
return -1;
171203
} else {
172-
unsigned char c = _rx_buffer[_rx_buffer_tail];
173-
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE;
174-
return c;
204+
if(bit_is_set(*_ucsrb, UCSZ02)) {
205+
// If Uart is in 9 bit mode read two bytes and merge them
206+
unsigned char mb = _rx_buffer[_rx_buffer_tail];
207+
unsigned char c = _rx_buffer[_rx_buffer_tail + 1];
208+
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 2) % SERIAL_RX_BUFFER_SIZE;
209+
return ((mb << 8) | c);
210+
} else {
211+
unsigned char c = _rx_buffer[_rx_buffer_tail];
212+
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE;
213+
return c;
214+
}
175215
}
176216
}
177217

@@ -210,20 +250,35 @@ void HardwareSerial::flush()
210250
// the hardware finished tranmission (TXC is set).
211251
}
212252

213-
size_t HardwareSerial::write(uint8_t c)
253+
size_t HardwareSerial::write(uint16_t c)
214254
{
215255
_written = true;
216256
// If the buffer and the data register is empty, just write the byte
217257
// to the data register and be done. This shortcut helps
218258
// significantly improve the effective datarate at high (>
219259
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
220260
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
221-
*_udr = c;
261+
if(bit_is_set(*_ucsrb, UCSZ02)) {
262+
// in 9 bit mode set TXB8 bit if necessary
263+
if(c & 0x100) {
264+
sbi(*_ucsrb, TXB80);
265+
} else {
266+
cbi(*_ucsrb, TXB80);
267+
}
268+
}
269+
*_udr = (uint8_t) c;
222270
sbi(*_ucsra, TXC0);
223271
return 1;
224272
}
225-
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
226-
273+
274+
tx_buffer_index_t i;
275+
276+
if(bit_is_set(*_ucsrb, UCSZ02)) {
277+
i = ((_tx_buffer_head + 2) % SERIAL_TX_BUFFER_SIZE);
278+
} else {
279+
i = ((_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE);
280+
}
281+
227282
// If the output buffer is full, there's nothing for it other than to
228283
// wait for the interrupt handler to empty it a bit
229284
while (i == _tx_buffer_tail) {
@@ -239,7 +294,13 @@ size_t HardwareSerial::write(uint8_t c)
239294
}
240295
}
241296

242-
_tx_buffer[_tx_buffer_head] = c;
297+
298+
if(bit_is_set(*_ucsrb, UCSZ02)) {
299+
_tx_buffer[_tx_buffer_head] = (uint8_t) (c >> 8) & 0x01;
300+
_tx_buffer[_tx_buffer_head + 1] = (uint8_t) c;
301+
} else {
302+
_tx_buffer[_tx_buffer_head] = (uint8_t) c;
303+
}
243304
_tx_buffer_head = i;
244305

245306
sbi(*_ucsrb, UDRIE0);

‎cores/arduino/HardwareSerial.h‎

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -65,30 +65,41 @@ typedef uint8_t rx_buffer_index_t;
6565
#endif
6666

6767
// Define config for Serial.begin(baud, config);
68-
#define SERIAL_5N1 0x00
69-
#define SERIAL_6N1 0x02
70-
#define SERIAL_7N1 0x04
71-
#define SERIAL_8N1 0x06
72-
#define SERIAL_5N2 0x08
73-
#define SERIAL_6N2 0x0A
74-
#define SERIAL_7N2 0x0C
75-
#define SERIAL_8N2 0x0E
76-
#define SERIAL_5E1 0x20
77-
#define SERIAL_6E1 0x22
78-
#define SERIAL_7E1 0x24
79-
#define SERIAL_8E1 0x26
80-
#define SERIAL_5E2 0x28
81-
#define SERIAL_6E2 0x2A
82-
#define SERIAL_7E2 0x2C
83-
#define SERIAL_8E2 0x2E
84-
#define SERIAL_5O1 0x30
85-
#define SERIAL_6O1 0x32
86-
#define SERIAL_7O1 0x34
87-
#define SERIAL_8O1 0x36
88-
#define SERIAL_5O2 0x38
89-
#define SERIAL_6O2 0x3A
90-
#define SERIAL_7O2 0x3C
91-
#define SERIAL_8O2 0x3E
68+
#define SERIAL_5N1 0x000 //0b000000000
69+
#define SERIAL_6N1 0x002 //0b000000010
70+
#define SERIAL_7N1 0x004 //0b000000100
71+
#define SERIAL_8N1 0x006 //0b000000110
72+
#define SERIAL_9N1 0x106 //0b100000110
73+
74+
#define SERIAL_5N2 0x008 //0b000001000
75+
#define SERIAL_6N2 0x00A //0b000001010
76+
#define SERIAL_7N2 0x00C //0b000001100
77+
#define SERIAL_8N2 0x00E //0b000001110
78+
#define SERIAL_9N2 0x10E //0b100001110
79+
80+
#define SERIAL_5E1 0x020 //0b000100000
81+
#define SERIAL_6E1 0x022 //0b000100010
82+
#define SERIAL_7E1 0x024 //0b000100100
83+
#define SERIAL_8E1 0x026 //0b000100110
84+
#define SERIAL_9E1 0x126 //0b100100110
85+
86+
#define SERIAL_5E2 0x028 //0b000101000
87+
#define SERIAL_6E2 0x02A //0b000101010
88+
#define SERIAL_7E2 0x02C //0b000101100
89+
#define SERIAL_8E2 0x02E //0b000101110
90+
#define SERIAL_9E2 0x12E //0b100101110
91+
92+
#define SERIAL_5O1 0x030 //0b000110000
93+
#define SERIAL_6O1 0x032 //0b000110010
94+
#define SERIAL_7O1 0x034 //0b000110100
95+
#define SERIAL_8O1 0x036 //0b000110110
96+
#define SERIAL_9O1 0x136 //0b100110110
97+
98+
#define SERIAL_5O2 0x038 //0b000111000
99+
#define SERIAL_6O2 0x03A //0b000111010
100+
#define SERIAL_7O2 0x03C //0b000111100
101+
#define SERIAL_8O2 0x03E //0b000111110
102+
#define SERIAL_9O2 0x13E //0b100111110
92103

93104
class HardwareSerial : public Stream
94105
{
@@ -119,18 +130,18 @@ class HardwareSerial : public Stream
119130
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
120131
volatile uint8_t *ucsrc, volatile uint8_t *udr);
121132
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
122-
void begin(unsigned long, uint8_t);
133+
void begin(unsigned long, uint16_t);
123134
void end();
124135
virtual int available(void);
125136
virtual int peek(void);
126137
virtual int read(void);
127138
virtual int availableForWrite(void);
128139
virtual void flush(void);
129-
virtual size_t write(uint8_t);
130-
inline size_t write(unsigned long n) { return write((uint8_t)n); }
131-
inline size_t write(long n) { return write((uint8_t)n); }
132-
inline size_t write(unsigned int n) { return write((uint8_t)n); }
133-
inline size_t write(int n) { return write((uint8_t)n); }
140+
virtual size_t write(uint16_t);
141+
inline size_t write(unsigned long n) { return write((uint16_t)n); }
142+
inline size_t write(long n) { return write((uint16_t)n); }
143+
inline size_t write(unsigned int n) { return write((uint16_t)n); }
144+
inline size_t write(int n) { return write((uint16_t)n); }
134145
using Print::write; // pull in write(str) and write(buf, size) from Print
135146
operator bool() { return true; }
136147

‎cores/arduino/HardwareSerial_private.h‎

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
#define U2X0 U2X
4949
#define UPE0 UPE
5050
#define UDRE0 UDRE
51+
#define UCSZ02 UCSZ2
52+
#define TXB80 TXB8
53+
#define RXB80 RXB8
5154
#elif defined(TXC1)
5255
// Some devices have uart1 but no uart0
5356
#define TXC0 TXC1
@@ -58,6 +61,9 @@
5861
#define U2X0 U2X1
5962
#define UPE0 UPE1
6063
#define UDRE0 UDRE1
64+
#define UCSZ02 UCSZ12
65+
#define TXB80 TXB81
66+
#define RXB80 RXB81
6167
#else
6268
#error No UART found in HardwareSerial.cpp
6369
#endif
@@ -68,17 +74,17 @@
6874
// changed for future hardware.
6975
#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \
7076
UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \
71-
UDRE1 != UDRE0)
77+
UDRE1 != UDRE0||UCSZ12!=UCSZ02||TXB81!=TXB80||RXB81!=RXB80)
7278
#error "Not all bit positions for UART1 are the same as for UART0"
7379
#endif
7480
#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \
7581
UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \
76-
UDRE2 != UDRE0)
82+
UDRE2 != UDRE0||UCSZ22!=UCSZ02||TXB82!=TXB80||RXB82!=RXB80)
7783
#error "Not all bit positions for UART2 are the same as for UART0"
7884
#endif
7985
#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \
8086
UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \
81-
UDRE3 != UDRE0)
87+
UDRE3 != UDRE0||UCSZ32!=UCSZ02||TXB83!=TXB80||TXB83!=TXB80)
8288
#error "Not all bit positions for UART3 are the same as for UART0"
8389
#endif
8490

@@ -103,15 +109,34 @@ void HardwareSerial::_rx_complete_irq(void)
103109
if (bit_is_clear(*_ucsra, UPE0)) {
104110
// No Parity error, read byte and store it in the buffer if there is
105111
// room
106-
unsigned char c = *_udr;
107-
rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
112+
rx_buffer_index_t i;
113+
unsigned char mb;
114+
unsigned char c;
115+
116+
if(bit_is_set(*_ucsrb, UCSZ02)) {
117+
// If Uart is configured for 9 bit mode
118+
i = (unsigned int)(_rx_buffer_head + 2) % SERIAL_RX_BUFFER_SIZE;
119+
mb = (*_ucsrb >> RXB80) & 0x01;
120+
c = *_udr;
121+
} else {
122+
// UART is configured for 5 to 8 bit modes
123+
i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
124+
c = *_udr;
125+
}
108126

109127
// if we should be storing the received character into the location
110128
// just before the tail (meaning that the head would advance to the
111129
// current location of the tail), we're about to overflow the buffer
112130
// and so we don't write the character or advance the head.
113131
if (i != _rx_buffer_tail) {
114-
_rx_buffer[_rx_buffer_head] = c;
132+
if(bit_is_set(*_ucsrb, UCSZ02)) {
133+
// If Uart is configured for 9 bit mode
134+
_rx_buffer[_rx_buffer_head] = mb;
135+
_rx_buffer[_rx_buffer_head + 1] = c;
136+
} else {
137+
// UART is configured for 5 to 8 bit modes
138+
_rx_buffer[_rx_buffer_head] = c;
139+
}
115140
_rx_buffer_head = i;
116141
}
117142
} else {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /