diff options
author | Nao Pross <naopross@thearcway.org> | 2018-05-05 17:13:59 +0200 |
---|---|---|
committer | Nao Pross <naopross@thearcway.org> | 2018-05-05 17:13:59 +0200 |
commit | 601ee769f5ceeab7c71e61806804e4788f279c59 (patch) | |
tree | bc0479325be9e69b7039304deba663ad89422700 | |
parent | Add top comments (diff) | |
download | SAMLiquidSmoke-601ee769f5ceeab7c71e61806804e4788f279c59.tar.gz SAMLiquidSmoke-601ee769f5ceeab7c71e61806804e4788f279c59.zip |
Rename class pin to io_pin, add general gpio class, add uart echo
-rw-r--r-- | hal/pin.hpp | 28 | ||||
-rw-r--r-- | hal/pin.tpp | 29 | ||||
-rw-r--r-- | hal/uart.hpp | 41 | ||||
-rw-r--r-- | 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 <xc.h> } +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<unsigned bit> -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<typename latch_T, typename tris_T, typename port_T> - 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<bit> &other) const; - bool operator!=(const pin<bit> &other) const; + bool operator==(const io_pin<bit> &other) const; + bool operator!=(const io_pin<bit> &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<unsigned bit> template<typename latch_T, typename tris_T, typename port_T> -pin<bit>::pin(latch_T *latch, tris_T *tris, port_T *port) : +io_pin<bit>::io_pin(latch_T *latch, tris_T *tris, port_T *port) : _latch(reinterpret_cast<volatile uint8_t *>(latch)), _tris(reinterpret_cast<volatile uint8_t *>(tris)), _port(reinterpret_cast<volatile uint8_t *>(port)) { // default settings - set_mode(pin<bit>::mode::OUTPUT); - set(pin<bit>::state::OFF); + set_mode(io_pin<bit>::mode::OUTPUT); + set(io_pin<bit>::state::OFF); } template<unsigned bit> -pin<bit>::~pin() +io_pin<bit>::~io_pin() { } template<unsigned bit> -void pin<bit>::set_mode(unsigned m) +void io_pin<bit>::set_mode(unsigned m) { if (m) *_tris |= 1<<bit; // input @@ -40,22 +40,19 @@ void pin<bit>::set_mode(unsigned m) } template<unsigned bit> -void pin<bit>::set_mode(pin<bit>::mode m) +void io_pin<bit>::set_mode(io_pin<bit>::mode m) { set_mode(static_cast<unsigned>(m)); } template<unsigned bit> -typename pin<bit>::state pin<bit>::read() const +unsigned io_pin<bit>::read() const { - if (*_port & (1<<bit)) - return state::ON; - else - return state::OFF; + return (*_port & (1<<bit)) ? 1 : 0; } template<unsigned bit> -void pin<bit>::set(unsigned s) +void io_pin<bit>::set(unsigned s) { if (s > 0) *_latch |= 1<<bit; // on @@ -64,19 +61,19 @@ void pin<bit>::set(unsigned s) } template<unsigned bit> -void pin<bit>::set(pin<bit>::state s) +void io_pin<bit>::set(io_pin<bit>::state s) { set(static_cast<unsigned>(s)); } template<unsigned bit> -void pin<bit>::toggle() +void io_pin<bit>::toggle() { *_latch ^= 1<<bit; } template<unsigned bit> -bool pin<bit>::operator==(const pin<bit> &other) const +bool io_pin<bit>::operator==(const io_pin<bit> &other) const { return (_latch == other._latch && _tris == other._tris @@ -84,7 +81,7 @@ bool pin<bit>::operator==(const pin<bit> &other) const } template<unsigned bit> -bool pin<bit>::operator!=(const pin<bit> &other) const +bool io_pin<bit>::operator!=(const io_pin<bit> &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<uint8_t> _rx_buffer[devices_count]; std::queue<uint8_t> _tx_buffer[devices_count]; + // the following functions have been inlined + + // template<unsigned dev> + // std::queue<uint8_t>& rx_buffer(); + + // template<unsigned dev> + // std::queue<uint8_t>& tx_buffer(); + template<unsigned dev> void initialize(); + // the following functions have been inlined + + // template<unsigned dev> + // void echo(bool enabled); + + // template<unsigned dev> + // bool echo_enabled(); + template<unsigned dev> uint8_t read(); + template<unsigned dev> + uint8_t read_wait(); + #if 0 template<unsigned dev> std::string read(const unsigned len); @@ -73,22 +97,15 @@ namespace uart unsigned write(const uint8_t *buffer, const unsigned numbytes); template<unsigned dev> - status status(); - - template<unsigned dev> - transfer_status tranfer_status(); - - template<unsigned dev> - unsigned rx_buffer_size(); - - template<unsigned dev> - unsigned tx_buffer_size(); + void print(const std::string &str); +#if 0 template<unsigned dev> - bool rx_buffer_empty(); + status status(); template<unsigned dev> - 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<unsigned dev> + inline bool echo(bool enabled) + { + static_assert(dev <= devices_count, "invalid device number"); + _echo[dev -1] = enabled; + } + + template<unsigned dev> + inline bool echo_enabled() + { + static_assert(dev <= devices_count, "invalid device number"); + return _echo[dev -1]; + } // read from serial device template<unsigned dev> @@ -51,6 +64,17 @@ namespace uart return byte; } + template<unsigned dev> + uint8_t read_wait() + { + while (rx_buffer<dev>().empty()); + + uint8_t byte = rx_buffer<dev>().front(); + rx_buffer<dev>().pop(); + + return byte; + } + #if 0 template<unsigned dev> std::string read(const unsigned len) @@ -121,11 +145,21 @@ namespace uart template<unsigned dev> 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<dev>(c); + // for (const char &c : str) { + // write<dev>(c); + // } + + // disable send data flag + IEC1bits.U1TXIE = 0; + + for (int i = 0; i < str.size(); i++) { + tx_buffer<1>().push(static_cast<uint8_t>(str[i])); } + + // enable send data flag + IEC1bits.U1TXIE = 1; } template<unsigned dev> @@ -138,6 +172,13 @@ namespace uart write<dev>(*(bptr++)); } } + + template<unsigned dev> + void print(const std::string &str) + { + write<dev>(str); + write<dev>("\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<uint8_t>(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<decltype(U1TXREG)>(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 { |