-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.c
294 lines (265 loc) · 8.93 KB
/
Main.c
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// Main.c
// Runs on LM4F120/TM4C123
// You may use, edit, run or distribute this file
// You are free to change the syntax/organization of this file
// Jonathan W. Valvano 2/20/17, [email protected]
// Modified by Sile Shu 10/4/17, [email protected]
// Modified by Mustafa Hotaki 7/29/18, [email protected]
#include <stdint.h>
#include "OS.h"
#include "tm4c123gh6pm.h"
#include "LCD.h"
#include <string.h>
#include "UART.h"
#include "FIFO.h"
#include "joystick.h"
#include "PORTE.h"
// Constants
#define BGCOLOR LCD_BLACK
#define CROSSSIZE 5
#define PERIOD 4000000 // DAS 20Hz sampling period in system time units
#define PSEUDOPERIOD 8000000
#define LIFETIME 1000
#define RUNLENGTH 600 // 30 seconds run length
extern Sema4Type LCDFree;
uint16_t origin[2]; // The original ADC value of x,y if the joystick is not touched, used as reference
int16_t x = 63; // horizontal position of the crosshair, initially 63
int16_t y = 63; // vertical position of the crosshair, initially 63
int16_t prevx, prevy; // Previous x and y values of the crosshair
uint8_t select; // joystick push
uint8_t area[2];
uint32_t PseudoCount;
unsigned long NumCreated; // Number of foreground threads created
unsigned long NumSamples; // Incremented every ADC sample, in Producer
unsigned long UpdateWork; // Incremented every update on position values
unsigned long Calculation; // Incremented every cube number calculation
//---------------------User debugging-----------------------
unsigned long DataLost; // data sent by Producer, but not received by Consumer
long MaxJitter; // largest time jitter between interrupts in usec
#define JITTERSIZE 64
unsigned long const JitterSize=JITTERSIZE;
unsigned long JitterHistogram[JITTERSIZE]={0,};
unsigned long TotalWithI1;
unsigned short MaxWithI1;
void Device_Init(void){
UART_Init();
BSP_LCD_OutputInit();
BSP_Joystick_Init();
}
//------------------Task 1--------------------------------
// background thread executed at 20 Hz
//******** Producer ***************
int UpdatePosition(uint16_t rawx, uint16_t rawy, jsDataType* data){
if (rawx > origin[0]){
x = x + ((rawx - origin[0]) >> 9);
}
else{
x = x - ((origin[0] - rawx) >> 9);
}
if (rawy < origin[1]){
y = y + ((origin[1] - rawy) >> 9);
}
else{
y = y - ((rawy - origin[1]) >> 9);
}
if (x > 127){
x = 127;}
if (x < 0){
x = 0;}
if (y > 120 - CROSSSIZE){
y = 120 - CROSSSIZE;}
if (y < 0){
y = 0;}
data->x = x; data->y = y;
return 1;
}
void Producer(void){
uint16_t rawX,rawY; // raw adc value
uint8_t select;
jsDataType data;
unsigned static long LastTime; // time at previous ADC sample
unsigned long thisTime; // time at current ADC sample
long jitter; // time between measured and expected, in us
if (NumSamples < RUNLENGTH){
BSP_Joystick_Input(&rawX,&rawY,&select);
thisTime = OS_Time(); // current time, 12.5 ns
UpdateWork += UpdatePosition(rawX,rawY,&data); // calculation work
NumSamples++; // number of samples
if(JsFifo_Put(data) == 0){ // send to consumer
DataLost++;
}
//calculate jitter
if(UpdateWork > 1){ // ignore timing of first interrupt
unsigned long diff = OS_TimeDifference(LastTime,thisTime);
if(diff > PERIOD){
jitter = (diff-PERIOD+4)/8; // in 0.1 usec
}
else{
jitter = (PERIOD-diff+4)/8; // in 0.1 usec
}
if(jitter > MaxJitter){
MaxJitter = jitter; // in usec
} // jitter should be 0
if(jitter >= JitterSize){
jitter = JITTERSIZE-1;
}
JitterHistogram[jitter]++;
}
LastTime = thisTime;
}
}
//--------------end of Task 1-----------------------------
//------------------Task 2--------------------------------
// background thread executes with SW1 button
// one foreground task created with button push
// foreground treads run for 1 sec and die
// ***********ButtonWork*************
void ButtonWork(void){
uint32_t StartTime,CurrentTime,ElapsedTime;
StartTime = OS_MsTime();
ElapsedTime = 0;
OS_bWait(&LCDFree);
BSP_LCD_FillScreen(BGCOLOR);
while (ElapsedTime < LIFETIME){
CurrentTime = OS_MsTime();
ElapsedTime = CurrentTime - StartTime;
BSP_LCD_Message(0,5,0,"Life Time:",LIFETIME);
BSP_LCD_Message(1,0,0,"Horizontal Area:",area[0]);
BSP_LCD_Message(1,1,0,"Vertical Area:",area[1]);
BSP_LCD_Message(1,2,0,"Elapsed Time:",ElapsedTime);
OS_Sleep(50);
}
BSP_LCD_FillScreen(BGCOLOR);
OS_bSignal(&LCDFree);
OS_Kill(); // done, OS does not return from a Kill
}
//************SW1Push*************
// Called when SW1 Button pushed
// Adds another foreground task
// background threads execute once and return
void SW1Push(void){
if(OS_MsTime() > 20 ){ // debounce
if(OS_AddThread(&ButtonWork,128,4)){
NumCreated++;
}
OS_ClearMsTime(); // at least 20ms between touches
}
}
//--------------end of Task 2-----------------------------
//------------------Task 3--------------------------------
//******** Consumer ***************
// foreground thread, accepts data from producer
// Display crosshair and its positions
// inputs: none
// outputs: none
void Consumer(void){
while(NumSamples < RUNLENGTH){
jsDataType data;
JsFifo_Get(&data);
OS_bWait(&LCDFree);
BSP_LCD_DrawCrosshair(prevx, prevy, LCD_BLACK); // Draw a black crosshair
BSP_LCD_DrawCrosshair(data.x, data.y, LCD_RED); // Draw a red crosshair
BSP_LCD_Message(1, 5, 3, "X: ", x);
BSP_LCD_Message(1, 5, 12, "Y: ", y);
OS_bSignal(&LCDFree);
prevx = data.x;
prevy = data.y;
}
OS_Kill(); // done
}
//--------------end of Task 3-----------------------------
//------------------Task 4--------------------------------
// foreground thread that runs without waiting or sleeping
// it executes some calculation related to the position of crosshair
//******** CubeNumCalc ***************
// foreground thread, calculates the virtual cube number for the crosshair
// never blocks, never sleeps, never dies
// inputs: none
// outputs: none
void CubeNumCalc(void){
uint16_t CurrentX,CurrentY;
while(1) {
if(NumSamples < RUNLENGTH){
CurrentX = x; CurrentY = y;
area[0] = CurrentX / 22;
area[1] = CurrentY / 20;
Calculation++;
}
}
}
//--------------end of Task 4-----------------------------
//------------------Task 5--------------------------------
// UART background ISR performs serial input/output
// Two software fifos are used to pass I/O data to foreground
// Interpreter is a foreground thread, accepts input from serial port, outputs to serial port
// inputs: none
// outputs: none
// there are following commands
// print performance measures
// time-jitter, number of data points lost, number of calculations performed
// i.e., NumSamples, NumCreated, MaxJitter, DataLost, UpdateWork, Calculations
void Interpreter(void){
char command[80];
while(1){
OutCRLF(); UART_OutString(">>");
UART_InString(command,79);
OutCRLF();
if (!(strcmp(command,"NumSamples"))){
UART_OutString("NumSamples: ");
UART_OutUDec(NumSamples);
}
else if (!(strcmp(command,"NumCreated"))){
UART_OutString("NumCreated: ");
UART_OutUDec(NumCreated);
}
else if (!(strcmp(command,"MaxJitter"))){
UART_OutString("MaxJitter: ");
UART_OutUDec(MaxJitter);
}
else if (!(strcmp(command,"DataLost"))){
UART_OutString("DataLost: ");
UART_OutUDec(DataLost);
}
else if (!(strcmp(command,"UpdateWork"))){
UART_OutString("UpdateWork: ");
UART_OutUDec(UpdateWork);
}
else if (!(strcmp(command,"Calculations"))){
UART_OutString("Calculations: ");
UART_OutUDec(Calculation);
}
else if (!(strcmp(command,"FifoSize"))){
UART_OutString("JSFifoSize: ");
UART_OutUDec(JSFIFOSIZE);
}
else{
UART_OutString("Command incorrect!");
}
}
}
//--------------end of Task 5-----------------------------
void CrossHair_Init(void){
BSP_LCD_FillScreen(BGCOLOR);
BSP_Joystick_Input(&origin[0],&origin[1],&select);
}
//******************* Main Function**********
int main(void){
OS_Init(); // initialize, disable interrupts
Device_Init();
CrossHair_Init();
DataLost = 0; // lost data between producer and consumer
NumSamples = 0;
MaxJitter = 0; // in 1us units
//********initialize communication channels
JsFifo_Init();
//*******attach background tasks***********
OS_AddSW1Task(&SW1Push,2);
OS_AddPeriodicThread(&Producer,PERIOD,1); // 2 kHz real time sampling of PD3
NumCreated = 0 ;
// create initial foreground threads
NumCreated += OS_AddThread(&Interpreter,128,2);
NumCreated += OS_AddThread(&Consumer,128,1);
NumCreated += OS_AddThread(&CubeNumCalc,128,1);
OS_Launch(TIME_2MS); // doesn't return, interrupts enabled in here
return 0; // this never executes
}