summaryrefslogtreecommitdiffstats
path: root/hal
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2018-05-05 17:13:59 +0200
committerNao Pross <naopross@thearcway.org>2018-05-05 17:13:59 +0200
commit601ee769f5ceeab7c71e61806804e4788f279c59 (patch)
treebc0479325be9e69b7039304deba663ad89422700 /hal
parentAdd top comments (diff)
downloadSAMLiquidSmoke-601ee769f5ceeab7c71e61806804e4788f279c59.tar.gz
SAMLiquidSmoke-601ee769f5ceeab7c71e61806804e4788f279c59.zip
Rename class pin to io_pin, add general gpio class, add uart echo
Diffstat (limited to 'hal')
-rw-r--r--hal/pin.hpp28
-rw-r--r--hal/pin.tpp29
-rw-r--r--hal/uart.hpp41
-rw-r--r--hal/uart.tpp75
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 {