diff --git a/usart/usart.cpp b/usart/usart.cpp index b451df5..016ead4 100644 --- a/usart/usart.cpp +++ b/usart/usart.cpp @@ -235,6 +235,66 @@ void USART0::setMode( Mode enmMode ) setUCSRC( ui8UCSRC ); } +////////////////////////////////////////////////////////////////////////// +uint32_t USART0::getBaudRate() +{ + uint16_t ui16UBRR; + ui16UBRR = static_cast( *m_vui8pUBRRH ) << 8; + ui16UBRR |= *m_vui8pUBRRL; + + return F_CPU / ( static_cast( 16 ) * ( ui16UBRR + 1 ) ); +} + +////////////////////////////////////////////////////////////////////////// +uint8_t USART0::getDataBits() +{ + if( *m_vui8pUCSRB & ( 1 << UCSZ2_D ) ) + { + return 9; + } + + uint8_t ui8UCSRC = readUCSRC(); + + bool bZeroBit = ui8UCSRC & ( 1 << UCSZ0_D ); + bool bOneBit = ui8UCSRC & ( 1 << UCSZ1_D ); + + return 5 + ( bOneBit << 1 | bZeroBit ); +} + +////////////////////////////////////////////////////////////////////////// +USART0::Parity USART0::getParity() +{ + uint8_t ui8UCSRC = readUCSRC(); + + bool bZeroBit = ui8UCSRC & ( 1 << UPM0_D ); + bool bOneBit = ui8UCSRC & ( 1 << UPM1_D ); + + if( bOneBit && !bZeroBit ) + { + return Parity::EVEN; + } + + if( bOneBit && bZeroBit ) + { + return Parity::ODD; + } + + return Parity::DISABLED; +} + +////////////////////////////////////////////////////////////////////////// +USART0::StopBit USART0::getStopBits() +{ + uint8_t ui8UCSRC = readUCSRC(); + + if( ui8UCSRC & ( 1 << USBS_D ) ) + { + return StopBit::TWO; + } + + return StopBit::ONE; +} + ////////////////////////////////////////////////////////////////////////// USART0::~USART0() { @@ -300,7 +360,7 @@ bool USART0::receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS ) { _delay_ms( 1 ); - if( ui16DelayCounter++ >= ui16TimeoutMS ) + if( ui16DelayCounter++ > ui16TimeoutMS ) { return false; } @@ -309,6 +369,39 @@ bool USART0::receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS ) return true; } +////////////////////////////////////////////////////////////////////////// +uint8_t USART0::receiveByteBlocked() +{ + uint8_t ui8Received; + while( !receiveByte( ui8Received ) ); + return ui8Received; +} + +////////////////////////////////////////////////////////////////////////// +uint8_t USART0::receivePeek() +{ + uint8_t ui8Received; + + if( !( SREG & ( 1 << SREG_I ) && m_vsizeRXBufferHead == m_vsizeRXBufferTail ) ) + { + while( !( *m_vui8pUCSRA & ( 1 << RXC_D ) ) ); + ui8Received = *m_vui8pUDR; + + size_t sizeIndex = ( m_vsizeRXBufferHead + 1 ) % sm_sizeRXBUFFER_SIZE; + + if( sizeIndex != m_vsizeRXBufferTail ) + { + m_vui8aRXBuffer[m_vsizeRXBufferHead] = ui8Received; + m_vsizeRXBufferHead = sizeIndex; + } + + return ui8Received; + } + + while( m_vsizeRXBufferHead == m_vsizeRXBufferTail ); + return m_vui8aRXBuffer[m_vsizeRXBufferTail]; +} + ////////////////////////////////////////////////////////////////////////// bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator /* = "\r\n" */ ) { @@ -324,6 +417,41 @@ bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *s if( strstr( szBuffer, szLineTerminator ) ) { + szBuffer[sizeReceived - strlen( szLineTerminator )] = '\0'; + return true; + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, uint16_t ui16TimeoutMS, const char *szLineTerminator /* = "\r\n" */ ) +{ + size_t sizeReceived = 0; + + while( sizeReceived < sizeBufferLength - 1 ) + { + uint8_t ui8ReceiveByte; + uint16_t ui16DelayCounter = 0; + + while( !receiveByte( ui8ReceiveByte ) ) + { + _delay_ms( 1 ); + + if( ui16DelayCounter++ > ui16TimeoutMS ) + { + szBuffer[sizeReceived] = '\0'; + return false; + } + } + + szBuffer[sizeReceived++] = ui8ReceiveByte; + szBuffer[sizeReceived] = '\0'; + + if( strstr( szBuffer, szLineTerminator ) ) + { + szBuffer[sizeReceived - strlen( szLineTerminator )] = '\0'; return true; } } @@ -334,16 +462,56 @@ bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *s ////////////////////////////////////////////////////////////////////////// void USART0::flushReceive() { - uint8_t ui8Received; + uint32_t ui32BaudRate = getBaudRate(); + uint8_t ui8BitsPerSymbol = 1; - while( m_vsizeRXBufferHead != m_vsizeRXBufferTail ) + ui8BitsPerSymbol += getDataBits(); + + if( getParity() != Parity::DISABLED ) { - receiveByte( ui8Received ); + ui8BitsPerSymbol += 1; } - if( !( SREG & ( 1 << SREG_I ) ) && ( *m_vui8pUCSRA & ( 1 << RXC_D ) ) ) + if( getStopBits() == StopBit::ONE ) { - ui8Received = *m_vui8pUDR; + ui8BitsPerSymbol += 1; + } + else + { + ui8BitsPerSymbol += 2; + } + + uint16_t ui16BaudDelayMS = static_cast( ( 1000.0 * ui8BitsPerSymbol ) / ui32BaudRate ) + 1; + + uint8_t ui8Received; + + if( !( SREG & ( 1 << SREG_I ) ) ) + { + while( true ) + { + for( uint16_t i = 0; i < ui16BaudDelayMS; ++i ) + { + _delay_ms( 1 ); + } + + if( m_vsizeRXBufferHead != m_vsizeRXBufferTail ) + { + receiveByte( ui8Received ); + continue; + } + + if( ( *m_vui8pUCSRA & ( 1 << RXC_D ) ) ) + { + ui8Received = *m_vui8pUDR; + continue; + } + + break; + } + } + else + { + while( receiveByte( ui8Received, ui16BaudDelayMS ) ); } } diff --git a/usart/usart.h b/usart/usart.h index 1e0b1bb..d4a66e0 100644 --- a/usart/usart.h +++ b/usart/usart.h @@ -1,7 +1,7 @@ /* * Copyright (c) by BlackMark 2015-2016 -* Date 24/05/2016 -* Version 2.9 +* Date 26/05/2016 +* Version 3.3 */ #ifndef USART_H @@ -128,6 +128,11 @@ private: void setStopBits( StopBit enmStopBits ); void setMode( Mode enmMode ); + uint32_t getBaudRate(); + uint8_t getDataBits(); + Parity getParity(); + StopBit getStopBits(); + ~USART0(); public: @@ -139,7 +144,10 @@ public: bool receiveByte( uint8_t &ui8Data ); bool receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS ); + uint8_t receiveByteBlocked(); + uint8_t receivePeek(); bool receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator = "\r\n" ); + bool receiveLine( char *szBuffer, size_t sizeBufferLength, uint16_t ui16TimeoutMS, const char *szLineTerminator = "\r\n" ); void flushReceive(); void transmitByte( uint8_t ui8Data );