/* Copyright (c) 2011 Arduino. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "UARTClass.h" // Constructors //////////////////////////////////////////////////////////////// UARTClass::UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) { _rx_buffer = pRx_buffer ; _pUart=pUart ; _dwIrq=dwIrq ; _dwId=dwId ; } // Public Methods ////////////////////////////////////////////////////////////// void UARTClass::begin( const uint32_t dwBaudRate ) { // Configure PMC pmc_enable_periph_clk( _dwId ) ; // Disable PDC channel _pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS ; // Reset and disable receiver and transmitter _pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS ; // Configure mode _pUart->UART_MR = UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL ; // Configure baudrate (asynchronous, no oversampling) _pUart->UART_BRGR = (SystemCoreClock / dwBaudRate) >> 4 ; // Configure interrupts _pUart->UART_IDR = 0xFFFFFFFF; _pUart->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME; // Enable UART interrupt in NVIC NVIC_EnableIRQ(_dwIrq); // Enable receiver and transmitter _pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ; } void UARTClass::end( void ) { // clear any received data _rx_buffer->_iHead = _rx_buffer->_iTail ; // Disable UART interrupt in NVIC NVIC_DisableIRQ( _dwIrq ) ; // Wait for any outstanding data to be sent flush(); pmc_disable_periph_clk( _dwId ) ; } int UARTClass::available( void ) { return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ; } int UARTClass::peek( void ) { if ( _rx_buffer->_iHead == _rx_buffer->_iTail ) return -1 ; return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ; } int UARTClass::read( void ) { // if the head isn't ahead of the tail, we don't have any characters if ( _rx_buffer->_iHead == _rx_buffer->_iTail ) return -1 ; uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ; _rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ; return uc ; } void UARTClass::flush( void ) { // Wait for transmission to complete while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) ; } size_t UARTClass::write( const uint8_t uc_data ) { // Check if the transmitter is ready while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) ; // Send character _pUart->UART_THR = uc_data; return 1; } size_t UARTClass::canWrite( void ) const //***** DC42 added { return (_pUart->UART_SR & UART_SR_TXRDY) ? 1 : 0; } void UARTClass::IrqHandler( void ) { uint32_t status = _pUart->UART_SR; // Did we receive data ? if ((status & UART_SR_RXRDY) == UART_SR_RXRDY) _rx_buffer->store_char(_pUart->UART_RHR); // Acknowledge errors if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME) { // TODO: error reporting outside ISR _pUart->UART_CR |= UART_CR_RSTSTA; } }