From 601ee769f5ceeab7c71e61806804e4788f279c59 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Sat, 5 May 2018 17:13:59 +0200 Subject: Rename class pin to io_pin, add general gpio class, add uart echo --- hal/pin.hpp | 28 +++++++++++++++++------ hal/pin.tpp | 29 +++++++++++------------ hal/uart.hpp | 41 +++++++++++++++++++++++---------- hal/uart.tpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 126 insertions(+), 47 deletions(-) diff --git a/hal/pin.hpp b/hal/pin.hpp index ff131ef..bbb80dc 100644 --- a/hal/pin.hpp +++ b/hal/pin.hpp @@ -12,9 +12,23 @@ extern "C" { #include } +class gpio +{ +public: + virtual ~gpio() {} + + // digital functions + virtual void set_mode(unsigned m) = 0; + virtual void set(unsigned s) = 0; + virtual unsigned read() const = 0; + virtual void toggle() = 0; + +protected: + gpio() {} +}; template -class pin { +class io_pin : public gpio { public: enum class mode : unsigned { INPUT = 1, OUTPUT = 0 }; @@ -22,25 +36,25 @@ public: enum class state : unsigned { ON = 1, OFF = 0 }; - pin() = delete; + io_pin() = delete; template - pin(latch_T *latch, tris_T *tris, port_T *port); + io_pin(latch_T *latch, tris_T *tris, port_T *port); - virtual ~pin(); + virtual ~io_pin(); void set_mode(unsigned m); void set_mode(mode m); - state read() const; + unsigned read() const; void set(unsigned s); void set(state s); void toggle(); - bool operator==(const pin &other) const; - bool operator!=(const pin &other) const; + bool operator==(const io_pin &other) const; + bool operator!=(const io_pin &other) const; private: volatile uint8_t *_latch; diff --git a/hal/pin.tpp b/hal/pin.tpp index 3954945..42d03de 100644 --- a/hal/pin.tpp +++ b/hal/pin.tpp @@ -12,26 +12,26 @@ template template -pin::pin(latch_T *latch, tris_T *tris, port_T *port) : +io_pin::io_pin(latch_T *latch, tris_T *tris, port_T *port) : _latch(reinterpret_cast(latch)), _tris(reinterpret_cast(tris)), _port(reinterpret_cast(port)) { // default settings - set_mode(pin::mode::OUTPUT); - set(pin::state::OFF); + set_mode(io_pin::mode::OUTPUT); + set(io_pin::state::OFF); } template -pin::~pin() +io_pin::~io_pin() { } template -void pin::set_mode(unsigned m) +void io_pin::set_mode(unsigned m) { if (m) *_tris |= 1<::set_mode(unsigned m) } template -void pin::set_mode(pin::mode m) +void io_pin::set_mode(io_pin::mode m) { set_mode(static_cast(m)); } template -typename pin::state pin::read() const +unsigned io_pin::read() const { - if (*_port & (1< -void pin::set(unsigned s) +void io_pin::set(unsigned s) { if (s > 0) *_latch |= 1<::set(unsigned s) } template -void pin::set(pin::state s) +void io_pin::set(io_pin::state s) { set(static_cast(s)); } template -void pin::toggle() +void io_pin::toggle() { *_latch ^= 1< -bool pin::operator==(const pin &other) const +bool io_pin::operator==(const io_pin &other) const { return (_latch == other._latch && _tris == other._tris @@ -84,7 +81,7 @@ bool pin::operator==(const pin &other) const } template -bool pin::operator!=(const pin &other) const +bool io_pin::operator!=(const io_pin &other) const { return !(*this == other); } diff --git a/hal/uart.hpp b/hal/uart.hpp index 60dd5bb..b1dce29 100644 --- a/hal/uart.hpp +++ b/hal/uart.hpp @@ -3,6 +3,8 @@ * Author: naopross * * Created on May 2, 2018, 7:04 PM + * + * Note: Non working or untested features are commented out with #if 0 .. #endif */ #ifndef UART_HPP @@ -23,6 +25,7 @@ namespace uart { const unsigned devices_count = 4; +#if 0 enum class status : unsigned int { rx_data_available = 1<<0, @@ -42,16 +45,37 @@ namespace uart tx_full = 1<<3, tx_empty = 1<<4, }; +#endif + bool _echo[devices_count]; std::queue _rx_buffer[devices_count]; std::queue _tx_buffer[devices_count]; + // the following functions have been inlined + + // template + // std::queue& rx_buffer(); + + // template + // std::queue& tx_buffer(); + template void initialize(); + // the following functions have been inlined + + // template + // void echo(bool enabled); + + // template + // bool echo_enabled(); + template uint8_t read(); + template + uint8_t read_wait(); + #if 0 template std::string read(const unsigned len); @@ -73,22 +97,15 @@ namespace uart unsigned write(const uint8_t *buffer, const unsigned numbytes); template - status status(); - - template - transfer_status tranfer_status(); - - template - unsigned rx_buffer_size(); - - template - unsigned tx_buffer_size(); + void print(const std::string &str); +#if 0 template - bool rx_buffer_empty(); + status status(); template - bool tx_buffer_full(); + transfer_status tranfer_status(); +#endif } #endif /* UART_HPP */ diff --git a/hal/uart.tpp b/hal/uart.tpp index 148ff7d..0ecd615 100644 --- a/hal/uart.tpp +++ b/hal/uart.tpp @@ -4,8 +4,8 @@ * * Created on May 2, 2018, 7:05 PM * - * Note: Templated functions cannot be created outside of a namespace definition - * because of a g++ bug in version 4.8.0 on which xc++ is based. + * Note: Templated functions inside a namespace cannot be created outside of a + * namespace because of a g++ bug in version 4.8.0 on which xc++ is based. * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 */ @@ -40,6 +40,19 @@ namespace uart return uart::_tx_buffer[dev -1]; } + template + inline bool echo(bool enabled) + { + static_assert(dev <= devices_count, "invalid device number"); + _echo[dev -1] = enabled; + } + + template + inline bool echo_enabled() + { + static_assert(dev <= devices_count, "invalid device number"); + return _echo[dev -1]; + } // read from serial device template @@ -51,6 +64,17 @@ namespace uart return byte; } + template + uint8_t read_wait() + { + while (rx_buffer().empty()); + + uint8_t byte = rx_buffer().front(); + rx_buffer().pop(); + + return byte; + } + #if 0 template std::string read(const unsigned len) @@ -121,11 +145,21 @@ namespace uart template void write(const std::string &str) { - // TODO: if size of str is reasonale, push to queue AND THEN send + // TODO: if size of str is reasonale, push to queue AND THEN send, // right now on each call the interrupt is enabled and disabled - for (const char &c : str) { - write(c); + // for (const char &c : str) { + // write(c); + // } + + // disable send data flag + IEC1bits.U1TXIE = 0; + + for (int i = 0; i < str.size(); i++) { + tx_buffer<1>().push(static_cast(str[i])); } + + // enable send data flag + IEC1bits.U1TXIE = 1; } template @@ -138,6 +172,13 @@ namespace uart write(*(bptr++)); } } + + template + void print(const std::string &str) + { + write(str); + write("\n\r"); + } } @@ -145,8 +186,8 @@ namespace uart #ifdef DEBUG #include "pin.tpp" -pin<2> led_blue(&LATBbits, &TRISBbits, &PORTBbits); -pin<3> led_green(&LATBbits, &TRISBbits, &PORTBbits); +io_pin<2> led_blue(&LATBbits, &TRISBbits, &PORTBbits); +io_pin<3> led_green(&LATBbits, &TRISBbits, &PORTBbits); #endif void __ISR(_UART_1_VECTOR, IPL1AUTO) usart_1_isr() @@ -159,23 +200,33 @@ void __ISR(_UART_1_VECTOR, IPL1AUTO) usart_1_isr() while (!U1STAbits.URXDA); uart::rx_buffer<1>().push(static_cast(U1RXREG)); + // echo + if (uart::echo_enabled<1>()) { + // uart::write<1>(uart::rx_buffer<1>().front()); + IEC1bits.U1TXIE = 0; + uart::tx_buffer<1>().push(uart::rx_buffer<1>().front()); + IEC1bits.U1TXIE = 1; + } + IFS1bits.U1RXIF = 0; } // on each interrupt call, send one character else if (IFS1bits.U1TXIF) { - // if empty, disable send data flag - if (uart::tx_buffer<1>().empty()) { - IEC1bits.U1TXIE = 0; - return; - } + // disable TX interrupt flag + IEC1bits.U1TXIE = 0; led_green.toggle(); // write data U1TXREG = static_cast(uart::tx_buffer<1>().front()); uart::tx_buffer<1>().pop(); + // if not empty, enable tx flag + if (!uart::tx_buffer<1>().empty()) { + IEC1bits.U1TXIE = 1; + } + IFS1bits.U1TXIF = 0; } else { -- cgit v1.2.1