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

Subversion Repositories openrisc

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

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 861 stekern
#include <unistd.h>
38 500 julius
#endif
39
 
40 462 julius
SC_HAS_PROCESS(UartSC);
41 42 julius
 
42 6 julius
//! Constructor for the Uart system C model
43
 
44
//! @param[in] name  Name of this module, passed to the parent constructor.
45
// Todo: Probably some sort of scaler parameter
46
 
47 500 julius
UartSC::UartSC(sc_core::sc_module_name uart):
48
        sc_module(uart)
49 6 julius
{
50 500 julius
#ifdef UART_SC_STDIN_ENABLE
51
        SC_THREAD(driveRx);
52
#endif
53
        SC_THREAD(checkTx);
54 462 julius
        dont_initialize();
55 500 julius
        sensitive << uarttx;
56 6 julius
 
57 462 julius
}                               // UartSC ()
58
 
59
void
60 500 julius
UartSC::initUart(int uart_baud)
61 6 julius
{
62 500 julius
        // Calculate number of ns per UART bit
63
        ns_per_bit = (int) ((long long)1000000000/(long long)uart_baud);
64 462 julius
        bits_received = 0;
65 500 julius
 
66
        // Init state of RX
67
        rx_state = 0;
68
 
69
        // Set input, ORPSoC's RX, line to high
70
        uartrx.write(true);
71
 
72
 
73 42 julius
#ifdef UART_SC_DEBUG
74 462 julius
        printf
75 500 julius
                ("UartSC Initialised: Baud: %d, ns per bit: %d\n",
76
                 uart_baud, ns_per_bit);
77 42 julius
#endif
78 462 julius
}
79 6 julius
 
80 500 julius
// Some C from 
81
// http://cc.byexamples.com/2007/04/08/non-blocking-user-input-in-loop-without-ncurses/
82
//
83
int UartSC::kbhit()
84 462 julius
{
85 500 julius
#ifdef UART_SC_STDIN_ENABLE
86
    struct timeval tv;
87
    fd_set fds;
88
    tv.tv_sec = 0;
89
    tv.tv_usec = 0;
90
    FD_ZERO(&fds);
91
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
92
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
93
    return FD_ISSET(STDIN_FILENO, &fds);
94
#else
95
    return 0;
96
#endif
97
}
98 6 julius
 
99 500 julius
#define NB_ENABLE 1
100
#define NB_DISABLE 0
101
 
102
// The following is apparently VERY Linux-centric. Maybe a ncurses version could
103
// be handy if this gets used on various platforms.
104
void UartSC::nonblock(int state)
105
{
106
#ifdef UART_SC_STDIN_ENABLE
107
        struct termios ttystate;
108
 
109
        //get the terminal state
110
        tcgetattr(STDIN_FILENO, &ttystate);
111
 
112
        if (state==NB_ENABLE)
113
        {
114
                //turn off canonical mode
115
                ttystate.c_lflag &= ~ICANON;
116
                //minimum of number input read.
117
                ttystate.c_cc[VMIN] = 1;
118
        }
119
        else if (state==NB_DISABLE)
120
        {
121
                //turn on canonical mode
122
                ttystate.c_lflag |= ICANON;
123
        }
124
        //set the terminal attributes.
125
        tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
126
#endif  
127
}
128
 
129
 
130
 
131
void UartSC::driveRx()
132
{
133
        static char c;
134
 
135
        UartSC::nonblock(NB_ENABLE);
136
 
137
        while(1)
138
        {
139
                if (rx_state == 0) // Waiting for a character input from user
140
                {
141
 
142
                        // Do we have a character on input?
143
                        //c=cin.peek();
144
 
145
 
146
                        if (kbhit())
147
                        {
148
 
149
                                c = fgetc(stdin);
150 42 julius
#ifdef UART_SC_DEBUG
151 500 julius
                                cout << "UartSC::driveRX got " << c << endl;
152 42 julius
#endif
153 500 julius
                                rx_state++;
154
                        }
155 462 julius
 
156 500 julius
                        wait(1000000, SC_NS);
157
 
158
                }
159
                else if (rx_state == 1)
160
                {
161 42 julius
#ifdef UART_SC_DEBUG
162 500 julius
                        cout << "UartSC::driveRX start-bit " << c << endl;
163 42 julius
#endif
164 500 julius
                        // Start bit - low
165
                        uartrx.write(false);
166
                        rx_state++;
167
                        // Wait a bit
168
                        wait(ns_per_bit, SC_NS);
169 462 julius
                }
170 500 julius
                else if (rx_state > 1 && rx_state < 10)
171
                {
172
#ifdef UART_SC_DEBUG
173
                        cout << "UartSC::driveRX bit " << rx_state-2 << " " <<
174
                             (c & (1 << rx_state-2)) << endl;
175
#endif
176 6 julius
 
177 500 julius
                        if (c & (1 << rx_state-2))
178
                                uartrx.write(true);
179
                        else
180
                                uartrx.write(false);
181
 
182
                        rx_state++;
183
 
184
                        // Wait a bit
185
                        wait(ns_per_bit, SC_NS);
186
                }
187
                else if (rx_state == 10)
188
                {
189
#ifdef UART_SC_DEBUG
190
                        cout << "UartSC::driveRX stop bit" << endl;
191
#endif
192
                        rx_state = 0;
193
                        // Stop bit
194
                        uartrx.write(true);
195
                        // Wait a bit
196
                        wait(ns_per_bit + (ns_per_bit/2), SC_NS);
197
 
198
                }
199
        }
200
}
201
 
202
 
203
// Maybe do this with threads instead?!
204
void UartSC::checkTx()
205
{
206
        while(1){
207
 
208
                // Check the number of bits received
209
                if (bits_received == 0) {
210
                        // Check if tx is low
211
                        if ((uarttx.read() & 1) == 0) {
212
 
213
                                // Line pulled low, begin receive of new char
214
                                current_char = 0;
215
 
216
                                //counter = 1;                  
217
 
218
                                bits_received++;        // We got the start bit
219
 
220
                                // Now wait until next bit
221
                                wait(ns_per_bit, SC_NS);
222
#ifdef UART_SC_DEBUG
223
                                cout << "UartSC checkTx: got start bit at time "
224
                                     << sc_time_stamp() << endl;
225
#endif
226
                        }
227
                        else
228
                                // Nothing yet - keep waiting
229
                                wait(ns_per_bit/2, SC_NS);
230
 
231
                } else if (bits_received > 0 && bits_received < 9) {
232
 
233
                        current_char |= ((uarttx.read() & 1) <<
234
                                         (bits_received - 1));
235
 
236 462 julius
                        // Increment bit number
237
                        bits_received++;
238 500 julius
 
239
                        // Wait for next bit
240
                        wait(ns_per_bit, SC_NS);
241
 
242
 
243
                } else if (bits_received == 9) {
244
 
245
                        // Now check for stop bit 1
246 462 julius
                        if ((uarttx.read() & 1) != 1) {
247
                                printf("UART TX framing error at time\n");
248
                                cout << sc_time_stamp() << endl;
249 500 julius
 
250
                                // Perhaps do something else here to deal with 
251
                                // this.
252 462 julius
                                bits_received = 0;
253 500 julius
                        }
254
                        else
255
                        {
256 462 julius
                                // Print the char
257 42 julius
#ifdef UART_SC_DEBUG
258 462 julius
                                printf("Char received: 0x%2x time: ",
259
                                       current_char);
260
                                cout << sc_time_stamp() << endl;
261 42 julius
#endif
262 500 julius
                                // cout'ing the char didn't work for some 
263
                                // systems.
264 462 julius
                                //cout << current_char;
265
                                printf("%c", current_char);
266 500 julius
 
267 462 julius
                                bits_received = 0;
268
                        }
269 500 julius
                }
270 6 julius
        }
271
}

powered by: WebSVN 2.1.0

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