OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [UartSC.cpp] - Blame information for rev 598

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 julius
// ----------------------------------------------------------------------------
2
 
3
// SystemC Uart: implementation
4
 
5
// This file is part of the cycle accurate model of the OpenRISC 1000 based
6
// system-on-chip, ORPSoC, built using Verilator.
7
 
8
// This program is free software: you can redistribute it and/or modify it
9
// under the terms of the GNU Lesser General Public License as published by
10
// the Free Software Foundation, either version 3 of the License, or (at your
11
// option) any later version.
12
 
13
// This program is distributed in the hope that it will be useful, but WITHOUT
14
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16
// License for more details.
17
 
18
// You should have received a copy of the GNU Lesser General Public License
19
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
21
// ----------------------------------------------------------------------------
22
 
23
// $Id: $
24
 
25
#include <iostream>
26
#include <iomanip>
27
 
28
#include "UartSC.h"
29
 
30 42 julius
//#define UART_SC_DEBUG
31 6 julius
 
32 500 julius
// Keep disabled for now, to stop any portability problems cropping up.
33
//#define UART_SC_STDIN_ENABLE
34
 
35
#ifdef UART_SC_STDIN_ENABLE
36
#include <termios.h>
37
#endif
38
 
39 462 julius
SC_HAS_PROCESS(UartSC);
40 42 julius
 
41 6 julius
//! Constructor for the Uart system C model
42
 
43
//! @param[in] name  Name of this module, passed to the parent constructor.
44
// Todo: Probably some sort of scaler parameter
45
 
46 500 julius
UartSC::UartSC(sc_core::sc_module_name uart):
47
        sc_module(uart)
48 6 julius
{
49 500 julius
#ifdef UART_SC_STDIN_ENABLE
50
        SC_THREAD(driveRx);
51
#endif
52
        SC_THREAD(checkTx);
53 462 julius
        dont_initialize();
54 500 julius
        sensitive << uarttx;
55 6 julius
 
56 462 julius
}                               // UartSC ()
57
 
58
void
59 500 julius
UartSC::initUart(int uart_baud)
60 6 julius
{
61 500 julius
        // Calculate number of ns per UART bit
62
        ns_per_bit = (int) ((long long)1000000000/(long long)uart_baud);
63 462 julius
        bits_received = 0;
64 500 julius
 
65
        // Init state of RX
66
        rx_state = 0;
67
 
68
        // Set input, ORPSoC's RX, line to high
69
        uartrx.write(true);
70
 
71
 
72 42 julius
#ifdef UART_SC_DEBUG
73 462 julius
        printf
74 500 julius
                ("UartSC Initialised: Baud: %d, ns per bit: %d\n",
75
                 uart_baud, ns_per_bit);
76 42 julius
#endif
77 462 julius
}
78 6 julius
 
79 500 julius
// Some C from 
80
// http://cc.byexamples.com/2007/04/08/non-blocking-user-input-in-loop-without-ncurses/
81
//
82
int UartSC::kbhit()
83 462 julius
{
84 500 julius
#ifdef UART_SC_STDIN_ENABLE
85
    struct timeval tv;
86
    fd_set fds;
87
    tv.tv_sec = 0;
88
    tv.tv_usec = 0;
89
    FD_ZERO(&fds);
90
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
91
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
92
    return FD_ISSET(STDIN_FILENO, &fds);
93
#else
94
    return 0;
95
#endif
96
}
97 6 julius
 
98 500 julius
#define NB_ENABLE 1
99
#define NB_DISABLE 0
100
 
101
// The following is apparently VERY Linux-centric. Maybe a ncurses version could
102
// be handy if this gets used on various platforms.
103
void UartSC::nonblock(int state)
104
{
105
#ifdef UART_SC_STDIN_ENABLE
106
        struct termios ttystate;
107
 
108
        //get the terminal state
109
        tcgetattr(STDIN_FILENO, &ttystate);
110
 
111
        if (state==NB_ENABLE)
112
        {
113
                //turn off canonical mode
114
                ttystate.c_lflag &= ~ICANON;
115
                //minimum of number input read.
116
                ttystate.c_cc[VMIN] = 1;
117
        }
118
        else if (state==NB_DISABLE)
119
        {
120
                //turn on canonical mode
121
                ttystate.c_lflag |= ICANON;
122
        }
123
        //set the terminal attributes.
124
        tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
125
#endif  
126
}
127
 
128
 
129
 
130
void UartSC::driveRx()
131
{
132
        static char c;
133
 
134
        UartSC::nonblock(NB_ENABLE);
135
 
136
        while(1)
137
        {
138
                if (rx_state == 0) // Waiting for a character input from user
139
                {
140
 
141
                        // Do we have a character on input?
142
                        //c=cin.peek();
143
 
144
 
145
                        if (kbhit())
146
                        {
147
 
148
                                c = fgetc(stdin);
149 42 julius
#ifdef UART_SC_DEBUG
150 500 julius
                                cout << "UartSC::driveRX got " << c << endl;
151 42 julius
#endif
152 500 julius
                                rx_state++;
153
                        }
154 462 julius
 
155 500 julius
                        wait(1000000, SC_NS);
156
 
157
                }
158
                else if (rx_state == 1)
159
                {
160 42 julius
#ifdef UART_SC_DEBUG
161 500 julius
                        cout << "UartSC::driveRX start-bit " << c << endl;
162 42 julius
#endif
163 500 julius
                        // Start bit - low
164
                        uartrx.write(false);
165
                        rx_state++;
166
                        // Wait a bit
167
                        wait(ns_per_bit, SC_NS);
168 462 julius
                }
169 500 julius
                else if (rx_state > 1 && rx_state < 10)
170
                {
171
#ifdef UART_SC_DEBUG
172
                        cout << "UartSC::driveRX bit " << rx_state-2 << " " <<
173
                             (c & (1 << rx_state-2)) << endl;
174
#endif
175 6 julius
 
176 500 julius
                        if (c & (1 << rx_state-2))
177
                                uartrx.write(true);
178
                        else
179
                                uartrx.write(false);
180
 
181
                        rx_state++;
182
 
183
                        // Wait a bit
184
                        wait(ns_per_bit, SC_NS);
185
                }
186
                else if (rx_state == 10)
187
                {
188
#ifdef UART_SC_DEBUG
189
                        cout << "UartSC::driveRX stop bit" << endl;
190
#endif
191
                        rx_state = 0;
192
                        // Stop bit
193
                        uartrx.write(true);
194
                        // Wait a bit
195
                        wait(ns_per_bit + (ns_per_bit/2), SC_NS);
196
 
197
                }
198
        }
199
}
200
 
201
 
202
// Maybe do this with threads instead?!
203
void UartSC::checkTx()
204
{
205
        while(1){
206
 
207
                // Check the number of bits received
208
                if (bits_received == 0) {
209
                        // Check if tx is low
210
                        if ((uarttx.read() & 1) == 0) {
211
 
212
                                // Line pulled low, begin receive of new char
213
                                current_char = 0;
214
 
215
                                //counter = 1;                  
216
 
217
                                bits_received++;        // We got the start bit
218
 
219
                                // Now wait until next bit
220
                                wait(ns_per_bit, SC_NS);
221
#ifdef UART_SC_DEBUG
222
                                cout << "UartSC checkTx: got start bit at time "
223
                                     << sc_time_stamp() << endl;
224
#endif
225
                        }
226
                        else
227
                                // Nothing yet - keep waiting
228
                                wait(ns_per_bit/2, SC_NS);
229
 
230
                } else if (bits_received > 0 && bits_received < 9) {
231
 
232
                        current_char |= ((uarttx.read() & 1) <<
233
                                         (bits_received - 1));
234
 
235 462 julius
                        // Increment bit number
236
                        bits_received++;
237 500 julius
 
238
                        // Wait for next bit
239
                        wait(ns_per_bit, SC_NS);
240
 
241
 
242
                } else if (bits_received == 9) {
243
 
244
                        // Now check for stop bit 1
245 462 julius
                        if ((uarttx.read() & 1) != 1) {
246
                                printf("UART TX framing error at time\n");
247
                                cout << sc_time_stamp() << endl;
248 500 julius
 
249
                                // Perhaps do something else here to deal with 
250
                                // this.
251 462 julius
                                bits_received = 0;
252 500 julius
                        }
253
                        else
254
                        {
255 462 julius
                                // Print the char
256 42 julius
#ifdef UART_SC_DEBUG
257 462 julius
                                printf("Char received: 0x%2x time: ",
258
                                       current_char);
259
                                cout << sc_time_stamp() << endl;
260 42 julius
#endif
261 500 julius
                                // cout'ing the char didn't work for some 
262
                                // systems.
263 462 julius
                                //cout << current_char;
264
                                printf("%c", current_char);
265 500 julius
 
266 462 julius
                                bits_received = 0;
267
                        }
268 500 julius
                }
269 6 julius
        }
270
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.