aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/test/cpp/common/uart.h
blob: 05021ca363184bec2d1d15125a79d2232842febc (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
class UartRx : public TimeProcess{
public:

	CData *rx;
	uint32_t uartTimeRate;
	UartRx(CData *rx, uint32_t uartTimeRate){
		this->rx = rx;
		this->uartTimeRate = uartTimeRate;
		schedule(uartTimeRate);
	}

	enum State {START, DATA, STOP};
	State state = START;
	char data;
	uint32_t counter;


	virtual void tick(){
		switch(state){
			case START:
				if(*rx == 0){
					state = DATA;
					counter = 0;
					data = 0;
					schedule(uartTimeRate*5/4);
				} else {
					schedule(uartTimeRate/4);
				}
			break;
			case DATA:
				data |= (*rx) << counter++;
				if(counter == 8){
					state = STOP;
				}
				schedule(uartTimeRate);
			break;
			case STOP:
				if(*rx){
					cout << data << flush;
				} else {
					cout << "UART RX FRAME ERROR at " << time << endl;
				}

				schedule(uartTimeRate/4);
				state = START;
			break;
		}
	}
};

#include<pthread.h>
#include <mutex>
#include <queue>

class UartTx : public TimeProcess{
public:

	CData *tx;
	uint32_t uartTimeRate;

	enum State {START, DATA, STOP};
	State state = START;
	char data;
	uint32_t counter;
	pthread_t inputThreadId;
	queue<uint8_t> inputsQueue;
	mutex inputsMutex;

	UartTx(CData *tx, uint32_t uartTimeRate){
		this->tx = tx;
		this->uartTimeRate = uartTimeRate;
		schedule(uartTimeRate);
		pthread_create(&inputThreadId, NULL, &inputThreadWrapper, this);
		*tx = 1;
	}

	static void* inputThreadWrapper(void *uartTx){
		((UartTx*)uartTx)->inputThread();
		return NULL;
	}

	void inputThread(){
		while(1){
			uint8_t c = getchar();
			inputsMutex.lock();
			inputsQueue.push(c);
			inputsMutex.unlock();
		}
	}

	virtual void tick(){
		switch(state){
			case START:
				inputsMutex.lock();
				if(!inputsQueue.empty()){
					data = inputsQueue.front();
					inputsQueue.pop();
					inputsMutex.unlock();
					state = DATA;
					counter = 0;
					*tx = 0;
					schedule(uartTimeRate);
				} else {
					inputsMutex.unlock();
					schedule(uartTimeRate*50);
				}
			break;
			case DATA:
				*tx = (data >> counter) & 1;
				counter++;
				if(counter == 8){
					state = STOP;
				}
				schedule(uartTimeRate);
			break;
			case STOP:
				*tx = 1;
				schedule(uartTimeRate);
				state = START;
			break;
		}
	}
};