summaryrefslogtreecommitdiffstats
path: root/hal/uart.tpp
blob: 8c120ec371b35600879558a7d31645d9098fe077 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* 
 * File:   uart.tpp
 * Author: naopross
 *
 * 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.
 *       See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
 */

#ifndef UART_TPP
#define UART_TPP

#include "hwconfig.hpp"
#include "uart.hpp"

extern "C" {
// #include <proc/p32mx470f512h.h>
#include <xc.h>
#include <sys/attribs.h>
}


/* templated functions */
namespace uart
{
    template<unsigned dev>
    bool rx_buffer_empty()
    {
        return rx_buffer[dev -1].empty();
    }

    template<unsigned dev>
    bool tx_buffer_full()
    {
        return !tx_buffer[dev -1].empty();
    }

    template<unsigned dev>
    uint8_t read()
    {
        uint8_t byte = rx_buffer[dev -1].front();
        rx_buffer[dev -1].pop();

        return byte;
    }

    template<unsigned dev>
    unsigned read(uint8_t *buffer, const unsigned numbytes)
    {
        uint8_t *bptr = buffer;
        unsigned len = numbytes;
        
        while (len--) {
            *(bptr++) = read<dev>();
        }
    }

    template<unsigned dev>
    void write(const uint8_t byte)
    {

    }

    template<unsigned dev>
    void write(const std::string &str)
    {
        for (const char &c : str) {
            write<dev>(c);
        }
    }

    template<unsigned dev>
    unsigned write(const uint8_t *buffer, const unsigned numbytes)
    {

    }
}


/* specializations for UART1 */

// debug
#include "pin.tpp"
pin<2> led_blue(&LATBbits, &TRISBbits, &PORTEbits);

void __ISR(_UART_1_VECTOR, IPL1AUTO) usart_1_isr()
{
    if (IFS1bits.U1RXIF) {
        // debug
        led_blue.toggle();
        while (U1STAbits.URXDA) {
            uart::rx_buffer[0].push(static_cast<uint8_t>(U1RXREG));
        }

        IFS1bits.U1RXIF = 0;
    } else if (IFS1bits.U1TXIF) {
        IFS1bits.U1TXIF = 0;
    } else {
        if (U1STAbits.OERR == 1) {
            U1STAbits.OERR = 0;
        }

        IFS1bits.U1TXIF = 0;
    }
}

namespace uart
{
    template<>
    void initialize<1>()
    {
        // STSEL 1S;
        // IREN disabled;
        // PDSEL 8N;
        // RTSMD disabled;
        // RXINV disabled;
        // SIDL disabled;
        // WAKE disabled;
        // ABAUD disabled;
        // LPBACK disabled;
        // BRGH enabled;
        // UEN TX_RX;
        // ON enabled; 
        U1MODE = 0x8008;
        // UTXISEL TX_ONE_CHAR;
        // UTXINV disabled;
        // ADDR 0;
        // URXEN disabled;
        // OERR disabled;
        // ADM_EN disabled;
        // URXISEL RX_ONE_CHAR;
        // UTXBRK disabled;
        // UTXEN disabled;
        // ADDEN disabled; 
        U1STA = 0x0;
        // U1TXREG 0; 
        U1TXREG = 0x0;
        // BaudRate = 9600;
        // Frequency = 1000000 Hz;
        // BRG 25; 
        U1BRG = 0x19;

        IEC1bits.U1RXIE = 1;

        U1STAbits.UTXEN = 1;
        U1STAbits.URXEN = 1;

        // Enabling  UART
        U1MODEbits.ON = 1;

        // UERI: UART1 Error
        // Priority: 1
        // SubPriority: 0
        IPC7bits.U1IP = 1;
        IPC7bits.U1IS = 0;

        // map uart pins to port F
        hw::regunlock(); // unlock PPS
        CFGCONbits.IOLOCK = 0;

        U1RXRbits.U1RXR = 0x0004;   //RF1->UART1:U1RX;
        RPF0Rbits.RPF0R = 0x0003;   //RF0->UART1:U1TX;

        CFGCONbits.IOLOCK = 1; // lock   PPS
        hw::reglock();
    }
}

#endif