diff options
Diffstat (limited to 'cores/arduino')
-rwxr-xr-x | cores/arduino/HardwareSerial.cpp | 124 | ||||
-rwxr-xr-x | cores/arduino/HardwareSerial.h | 4 | ||||
-rwxr-xr-x | cores/arduino/wiring.h | 4 | ||||
-rwxr-xr-x | cores/arduino/wiring_analog.c | 2 |
4 files changed, 81 insertions, 53 deletions
diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index f8a959a..1af6a66 100755 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -49,41 +49,41 @@ ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; inline void store_char(unsigned char c, ring_buffer *rx_buffer) { - int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; - } + int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer->tail) { + rx_buffer->buffer[rx_buffer->head] = c; + rx_buffer->head = i; + } } #if defined(__AVR_ATmega1280__) SIGNAL(SIG_USART0_RECV) { - unsigned char c = UDR0; + unsigned char c = UDR0; store_char(c, &rx_buffer); } SIGNAL(SIG_USART1_RECV) { - unsigned char c = UDR1; + unsigned char c = UDR1; store_char(c, &rx_buffer1); } SIGNAL(SIG_USART2_RECV) { - unsigned char c = UDR2; + unsigned char c = UDR2; store_char(c, &rx_buffer2); } SIGNAL(SIG_USART3_RECV) { - unsigned char c = UDR3; + unsigned char c = UDR3; store_char(c, &rx_buffer3); } @@ -96,9 +96,9 @@ SIGNAL(USART_RX_vect) #endif { #if defined(__AVR_ATmega8__) - unsigned char c = UDR; + unsigned char c = UDR; #else - unsigned char c = UDR0; + unsigned char c = UDR0; #endif store_char(c, &rx_buffer); } @@ -111,7 +111,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre) + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) { _rx_buffer = rx_buffer; _ubrrh = ubrrh; @@ -123,14 +123,43 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, _txen = txen; _rxcie = rxcie; _udre = udre; + _u2x = u2x; } // Public Methods ////////////////////////////////////////////////////////////// -void HardwareSerial::begin(long speed) +void HardwareSerial::begin(long baud) { - *_ubrrh = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8; - *_ubrrl = ((F_CPU / 16 + speed / 2) / speed - 1); + uint16_t baud_setting; + bool use_u2x; + + // U2X mode is needed for baud rates higher than (CPU Hz / 16) + if (baud > F_CPU / 16) { + use_u2x = true; + } else { + // figure out if U2X mode would allow for a better connection + + // calculate the percent difference between the baud-rate specified and + // the real baud rate for both U2X and non-U2X mode (0-255 error percent) + uint8_t nonu2x_baud_error = abs((int)(255-((F_CPU/(16*(((F_CPU/8/baud-1)/2)+1))*255)/baud))); + uint8_t u2x_baud_error = abs((int)(255-((F_CPU/(8*(((F_CPU/4/baud-1)/2)+1))*255)/baud))); + + // prefer non-U2X mode because it handles clock skew better + use_u2x = (nonu2x_baud_error > u2x_baud_error); + } + + if (use_u2x) { + *_ucsra = 1 << _u2x; + baud_setting = (F_CPU / 4 / baud - 1) / 2; + } else { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + sbi(*_ucsrb, _rxen); sbi(*_ucsrb, _txen); sbi(*_ucsrb, _rxcie); @@ -138,54 +167,53 @@ void HardwareSerial::begin(long speed) uint8_t HardwareSerial::available(void) { - return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; + return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; } int HardwareSerial::read(void) { - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { - return -1; - } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE; - return c; - } + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + return c; + } } void HardwareSerial::flush() { - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + _rx_buffer->head = _rx_buffer->tail; } void HardwareSerial::write(uint8_t c) { - while (!((*_ucsra) & (1 << _udre))) - ; + while (!((*_ucsra) & (1 << _udre))) + ; - *_udr = c; + *_udr = c; } // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(__AVR_ATmega8__) -HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE); +HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); #else -HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0); +HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); #endif #if defined(__AVR_ATmega1280__) -HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1); -HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2); -HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3); +HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); +HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); +HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); #endif - diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 8610f5a..f975ccd 100755 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -39,12 +39,13 @@ class HardwareSerial : public Print uint8_t _txen; uint8_t _rxcie; uint8_t _udre; + uint8_t _u2x; public: HardwareSerial(ring_buffer *rx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre); + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); void begin(long); uint8_t available(void); int read(void); @@ -62,4 +63,3 @@ extern HardwareSerial Serial3; #endif #endif - diff --git a/cores/arduino/wiring.h b/cores/arduino/wiring.h index 619e695..f0ba04c 100755 --- a/cores/arduino/wiring.h +++ b/cores/arduino/wiring.h @@ -86,8 +86,8 @@ extern "C"{ #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) -#define lowByte(w) ((w) & 0xff) -#define highByte(w) ((w) >> 8) +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) #define bitRead(value, bit) (((value) >> (bit)) & 0x01) #define bitSet(value, bit) ((value) |= (1UL << (bit))) diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index 529ad52..782a0bd 100755 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -42,7 +42,7 @@ int analogRead(uint8_t pin) // set the analog reference (high two bits of ADMUX) and select the // channel (low 4 bits). this also sets ADLAR (left-adjust result) // to 0 (the default). - ADMUX = (analog_reference << 6) | (pin & 0x07); + ADMUX = (analog_reference << 6) | (pin & 0x0f); #if defined(__AVR_ATmega1280__) // the MUX5 bit of ADCSRB selects whether we're reading from channels |