@@ -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
152171int 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
157184int 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);
0 commit comments