-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
277 lines (263 loc) · 12.4 KB
/
main.c
File metadata and controls
277 lines (263 loc) · 12.4 KB
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
#include <stdio.h>
#include "supportFiles/leds.h"
#include "supportFiles/globalTimer.h"
#include "supportFiles/interrupts.h"
#include "supportFiles/intervalTimer.h"
#include "supportFiles/utils.h"
#include <stdbool.h>
#include "queue.h"
#include "xparameters.h"
#include "filter.h"
#include "histogram.h"
#include "detector.h"
#include "transmitter.h"
#include <stdlib.h>
#include "supportFiles/buttons.h"
#include "supportFiles/switches.h"
#include "isr.h"
#include "supportFiles/mio.h"
#include <string.h>
#include "supportFiles/display.h"
#include "trigger.h"
#include "lockoutTimer.h"
#include "hitLedTimer.h"
#define HISTOGRAM_BAR_COUNT 10
#define TOTAL_RUNTIME_TIMER 1
//#define ISR_CUMULATIVE_TIMER INTERRUPT_CUMULATIVE_ISR_INTERVAL_TIMER_NUMBER
#define ISR_CUMULATIVE_TIMER 0 // Not currently defined in the student's version of the code.
#define MAIN_CUMULATIVE_TIMER 2
#define SYSTEM_TICKS_PER_HISTOGRAM_UPDATE 50000 // Effectively 2 times per second.
static uint32_t countInterruptsViaInterruptsIsrFlag = 0;
// Prints out various run-time statistics on the TFT display.
// Assumes the following:
// main is keeping track of detected interrupts with countInterruptsViaInterruptsIsrFlag,
// interval_timer(0) is the cumulative run-time of the ISR,
// interval_timer(1) is the total run-time,
// interval_timer(2) is the time spent in main running the filters, updating the display, and so forth.
// No comments in the code, the print statements are self-explanatory.
void printRunTimeStatistics()
{
display_setTextSize(1);
display_setTextColor(DISPLAY_WHITE);
display_setCursor(0, 0);
display_fillScreen(DISPLAY_BLACK);
display_print("Elements remaining in ADC queue:");
display_print(isr_adcBufferElementCount());
display_println();
display_println();
double runningSeconds, isrRunningSeconds, mainLoopRunningSeconds;
intervalTimer_getTotalDurationInSeconds(TOTAL_RUNTIME_TIMER,
&runningSeconds);
display_print("Measured run time in seconds: ");
display_print(runningSeconds);
display_println();
display_println();
intervalTimer_getTotalDurationInSeconds(ISR_CUMULATIVE_TIMER,
&isrRunningSeconds);
display_print("Cumulative run time in timerIsr: ");
display_print(isrRunningSeconds);
display_print(" (");
display_print(isrRunningSeconds / runningSeconds * 100);
display_println("%)");
display_println();
intervalTimer_getTotalDurationInSeconds(MAIN_CUMULATIVE_TIMER,
&mainLoopRunningSeconds);
display_print("Cumulative run-time in main loop: ");
display_print(mainLoopRunningSeconds);
display_print(" (");
display_print((mainLoopRunningSeconds / runningSeconds) * 100);
display_println("%)");
display_println();
uint32_t interruptCount = interrupts_isrInvocationCount();
display_print("Total interrupts: ");
display_println(interruptCount);
display_println();
display_print("Interrupts detected in main: ");
display_println(countInterruptsViaInterruptsIsrFlag);
display_println();
display_print("Detected interrupts in main: ");
display_print(
((double) countInterruptsViaInterruptsIsrFlag
/ (double) interruptCount) * 100);
display_print("%");
}
// This mode runs continously until btn3 is pressed.
// When btn3 is pressed, it exits and prints performance information to the TFT.
// During operation, it continously displays that received power on each channel, on the TFT.
void continuousPowerMode()
{
printf("Continuous mode\r\n");
// Lots of init's.
buttons_init();
switches_init();
mio_init(false);
display_init();
intervalTimer_initAll();
histogram_init(HISTOGRAM_BAR_COUNT);
leds_init(true);
transmitter_init();
detector_init();
filter_init();
isr_init();
// Init all interrupts (but does not enable the interrupts at the devices).
// Prints an error message if an internal failure occurs because the argument = true.
interrupts_initAll(true);
interrupts_enableTimerGlobalInts(); // Allows the timer to generate interrupts.
interrupts_startArmPrivateTimer(); // Start the private ARM timer running.
uint16_t histogramSystemTicks = 0;// Only update the histogram display every so many ticks.
double normalizedPowerValues[FILTER_IIR_FILTER_COUNT];// Use this to store normalized power values for the histogram.
uint16_t indexOfMaxValue; // Keep track of the index of the maximum value.
intervalTimer_reset(ISR_CUMULATIVE_TIMER);// Used to measure ISR execution time.
intervalTimer_reset(TOTAL_RUNTIME_TIMER);// Used to measure total program execution time.
intervalTimer_reset(MAIN_CUMULATIVE_TIMER); // Used to measure main-loop execution time.
intervalTimer_start(TOTAL_RUNTIME_TIMER);// Start measuring total execution time.
interrupts_enableArmInts(); // The ARM will start seeing interrupts after this.
transmitter_setContinuousMode(true); // Run the transmitter continuously.
transmitter_run();
while (!(buttons_read() & BUTTONS_BTN3_MASK)) // Run until you detect btn3 pressed.
{
if (interrupts_isrFlagGlobal) // Only do something if an interrupt has occurred.
{
//transmitter_run(); // Run the transmitter continuously, stops after one period if you don't constantly invoke this.
intervalTimer_start(MAIN_CUMULATIVE_TIMER); // Measure run-time when you are doing something.
histogramSystemTicks++; // Keep track of ticks so you know when to update the histogram.
countInterruptsViaInterruptsIsrFlag++;// Keep track of the interrupt-count based on the global flag.
interrupts_isrFlagGlobal = 0; // Reset the global flag.
detector(); // Run filters, compute power, etc.
filter_getNormalizedPowerValues(normalizedPowerValues, &indexOfMaxValue);// This normalizes power between 1 and 0.
if (histogramSystemTicks >= SYSTEM_TICKS_PER_HISTOGRAM_UPDATE)
{ // If enough ticks have transpired, update the histogram.
for (int i = 0; i < FILTER_IIR_FILTER_COUNT; i++)
{ // Update across all filters.
// The height of the histogram bar depends upon the normalized value.
histogram_data_t histogramBarValue = ((double) (HISTOGRAM_MAX_BAR_DATA_IN_PIXELS)) * normalizedPowerValues[i];
// You can have a dynamic label at the top of the bar.
char label[HISTOGRAM_BAR_TOP_MAX_LABEL_WIDTH_IN_CHARS]; // Get a buffer for the label.
// Create the label, based upon the actual power value.
if (snprintf(label, HISTOGRAM_BAR_TOP_MAX_LABEL_WIDTH_IN_CHARS, "%0.0e", filter_getCurrentPowerValue(i)) == -1)
printf("Error: snprintf encountered an error during conversion.\n\r");
// Pull out the 'e' from the exponent to make better use of your characters.
trimLabel(label);
// Have the bar value and the label, send the data to the histogram.
if (!histogram_setBarData(i, histogramBarValue, label))
{
// If returns false, histogram_setBarData() is not happy. Print out some information.
printf("Error:histogram_setBarData() histogramBarValue(%d) out of range.\n\r", histogramBarValue);
printf("Provided normalizedPowerValue[%d]:%lf\n\r", i, normalizedPowerValues[i]);
printf("Dumping current and normalized power values.\n\r");
for (int tmp_i = 0; tmp_i < FILTER_IIR_FILTER_COUNT; tmp_i++)
{
printf("currentPowerValue[%d]:%lf\n\r", tmp_i, filter_getCurrentPowerValue(tmp_i));
printf("normalizedPowerValue[%d]:%lf\n\r", tmp_i, normalizedPowerValues[tmp_i]);
}
}
}
histogram_updateDisplay();// Finally, render the histogram on the TFT.
histogramSystemTicks = 0;// Reset the tick count and wait for the next update time.
uint16_t switchValue = switches_read(); // Read the switches and switch frequency as required.
// Note that Brian sends the coefficients with the min. frequency at 0, max. frequency at 9. Transmitter does likewise.
transmitter_setFrequencyNumber(switchValue);
}
intervalTimer_stop(2);
}
}
interrupts_disableArmInts();
printRunTimeStatistics();
}
void computeNormalizedHitValues(double normalizedHitValues[],
uint16_t hitArray[])
{
// First, find the indicies of the min. and max. value in the currentPowerValue array.
uint16_t maxIndex = 0;
for (int i = 0; i < FILTER_IIR_FILTER_COUNT; i++)
{
if (hitArray[i] > hitArray[maxIndex])
maxIndex = i;
}
double maxHitValue = (double) hitArray[maxIndex];
// Normalize everything between 0.0 and 1.0.
for (int i = 0; i < FILTER_IIR_FILTER_COUNT; i++)
normalizedHitValues[i] = (double) hitArray[i] / maxHitValue;
}
// Game-playing mode. Each shot is registered on the histogram on the TFT.
void shooterMode()
{
// Lots of init's.
buttons_init();
switches_init();
mio_init(false);
display_init();
intervalTimer_initAll();
histogram_init(HISTOGRAM_BAR_COUNT);
leds_init(true);
transmitter_init();
detector_init();
filter_init();
isr_init();
hitLedTimer_init();
trigger_init();
trigger_enable();// Makes the trigger state machine responsive to the trigger.
// Init all interrupts (but does not enable the interrupts at the devices).
// Prints an error message if an internal failure occurs because the argument = true.
interrupts_initAll(true);
interrupts_enableTimerGlobalInts(); // Allows the timer to generate interrupts.
interrupts_startArmPrivateTimer(); // Start the private ARM timer running.
interrupts_enableSysMonGlobalInts();// Enable global interrupt of System Monitor.
uint16_t histogramSystemTicks = 0;// Only update the histogram display every so many ticks.
double normalizedPowerValues[FILTER_IIR_FILTER_COUNT];// Use this to store normalized power values for the histogram.
uint16_t indexOfMaxValue; // Keep track of the index of the maximum value.
intervalTimer_reset(0); // Used to measure ISR execution time.
intervalTimer_reset(1); // Used to measure total program execution time.
intervalTimer_reset(2); // Used to measure main-loop execution time.
intervalTimer_start(1); // Start measuring total execution time.
interrupts_enableArmInts(); // The ARM will start seeing interrupts after this.
lockoutTimer_start();// Ignore erroneous hits at startup (when all power values are essentially 0).
while (!(buttons_read() & BUTTONS_BTN3_MASK))
{ // Run until you detect btn3 pressed.
if (interrupts_isrFlagGlobal)
{ // Only do something if an interrupt has occurred.
intervalTimer_start(2); // Measure run-time when you are doing something.
histogramSystemTicks++; // Keep track of ticks so you know when to update the histogram.
countInterruptsViaInterruptsIsrFlag++;// Keep track of the interrupt-count based on the global flag.
interrupts_isrFlagGlobal = 0; // Reset the global flag.
detector(); // Power across all channels is computed, hit-detection, etc.
if (detector_hitDetected())
{ // Hit detected?
detector_clearHit(); // Clear the hit.
detector_hitCount_t hitCounts[DETECTOR_HIT_ARRAY_SIZE]; // Store the hit-counts here.
detector_getHitCounts(hitCounts);// Get the current hit counts.
filter_getNormalizedPowerValues(normalizedPowerValues,
&indexOfMaxValue);// This normalizes power between 1 and 0.
// Have the bar value and the label, send the data to the histogram.
double normalizedHitValues[FILTER_IIR_FILTER_COUNT];// Store normalized values here for the histogram.
computeNormalizedHitValues(normalizedHitValues, hitCounts); // Get the normalized hit values.
for (int i = 0; i < FILTER_IIR_FILTER_COUNT; i++) // Iterate through the results for each channel.
{
char label[HISTOGRAM_BAR_TOP_MAX_LABEL_WIDTH_IN_CHARS]; // Get a buffer for the label.
// Create the label, based upon the actual power value.
if (snprintf(label, HISTOGRAM_BAR_TOP_MAX_LABEL_WIDTH_IN_CHARS, "%d", hitCounts[i]) == -1)
printf("Error: snprintf encountered an error during conversion.\n\r");
histogram_setBarData(i, normalizedHitValues[i] * HISTOGRAM_MAX_BAR_DATA_IN_PIXELS, label);
histogram_updateDisplay(); // Redraw the histogram.
}
}
uint16_t switchValue = switches_read(); // Read the switches and switch frequency as required.
// Note that Brian sends the coefficients with the min. frequency at 0, max. frequency at 9. Transmitter does likewise.
transmitter_setFrequencyNumber(switchValue);
}
intervalTimer_stop(2); // All done with actual processing.
}
interrupts_disableArmInts(); // Done with loop, disable the interrupts.
printRunTimeStatistics(); // Print the statistics to the TFT.
}
// Default is continuous-power mode. Hold btn2 during reset/power-up to come up in shooter mode.
int main()
{
buttons_init();
if (buttons_read() & BUTTONS_BTN1_MASK)
filter_runTest();
else if (buttons_read() & BUTTONS_BTN2_MASK)
continuousPowerMode();
else
shooterMode();
}