-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomp_debug.h
More file actions
196 lines (169 loc) · 8.05 KB
/
comp_debug.h
File metadata and controls
196 lines (169 loc) · 8.05 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
/*----------------------------------------------------------------------------*/
/* */
/* MIT License */
/* */
/* Copyright (c) 2022 James Pearman */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining a */
/* copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be included */
/* in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE */
/* */
/* Module: comp_debug.h */
/* Created: 6 April 2022 */
/* */
/*----------------------------------------------------------------------------*/
#ifndef COMP_DEBUG_CLASS_H
#define COMP_DEBUG_CLASS_H
#include "v5.h"
#include "v5_cpp.h"
// I'm using a couple of private APIs to allow this code to work with most
// VEXcode user programs and over lay the information and thread count.
extern "C" {
void vexDisplayClipRegionSetWithIndex( int32_t index, int32_t x1, int32_t y1, int32_t x2, int32_t y2 );
void *vexTaskGetCallbackAndId( uint32_t index, int *callback_id );
}
class competition_debug {
private:
vex::thread _t1; // our update thread
vex::competition *_c1; // pointer to user code competition class instance
vex::brain::lcd _lcd; // local instance of brain::lcd for drawing on the V5 screen
enum class tCompStateType {
kCompStateUnknown = 0,
kCompStateDisabled,
kCompStateDriver,
kCompStateAuton
};
// current state of competition event triggers
tCompStateType _state = tCompStateType::kCompStateUnknown;
public:
competition_debug( vex::competition &c ) {
// pointer to competition instance
_c1 = &c;
// create thread to handle status display
_t1 = vex::thread( status_loop, static_cast<void *>(this) );
}
~competition_debug(){
// stop our update thread
_t1.interrupt();
};
// the update thread needs to be a statuc member function, we pass pointer to
// class instance as argument
static int status_loop( void *arg ) {
if( arg == NULL )
return(0);
competition_debug *instance = static_cast<competition_debug *>(arg);
vex::devices devs;
vex::timer t1;
vex::color currentStatusColor = vex::color(0x000000);
vex::color newStatusColor = vex::color(0x808080);
vex::color textColor = vex::color(0x000000);
int loop_ctr = 0;
// get maximum number of tasks we support
int max_tasks = vex::thread::hardware_concurrency();
// set clip region for all tasks, we need to use a private API for this.
// It stops other tasks that, for example, may clear the screen from removing
// the competition status.
//
for ( int i=0; i<max_tasks; i++ ) {
vexDisplayClipRegionSetWithIndex( i, 10, 25, 470, 230);
}
// loop forever monitoring competition status
while(1) {
if( currentStatusColor != newStatusColor ) {
instance->_lcd.setClipRegion(0, 0, 480, 240);
instance->_lcd.setPenWidth(10);
instance->_lcd.setPenColor(newStatusColor);
instance->_lcd.drawRectangle(5, 10, 465, 220, vex::transparent);
instance->_lcd.setPenWidth(1);
instance->_lcd.drawRectangle(0, 0, 480, 25, newStatusColor);
instance->_lcd.setFillColor(newStatusColor);
currentStatusColor = newStatusColor;
loop_ctr = 0;
}
// limit drawing to the top 25 rows of pixels
instance->_lcd.setClipRegion(0, 0, 480, 25);
instance->_lcd.setPenColor(textColor);
bool bCompetition = instance->_c1->isCompetitionSwitch() || instance->_c1->isFieldControl();
bool bRadioAvailable = (devs.numberOf(V5_DeviceType::kDeviceTypeRadioSensor) != 0);
// show radio status
if( !bRadioAvailable ) {
instance->_lcd.printAt( 380, 20, "No Radio " );
}
else {
instance->_lcd.printAt( 380, 20, " " );
}
if( loop_ctr-- <= 0 ) {
loop_ctr = 10;
int nt = count_threads();
instance->_lcd.printAt( 220, 20, "Threads %3d", nt );
}
// Update status
switch( instance->_state ) {
default:
instance->_lcd.printAt( 10, 20, "Comp Not Activated " );
break;
case tCompStateType::kCompStateDisabled:
instance->_lcd.printAt( 10, 20, "Disabled " );
break;
case tCompStateType::kCompStateDriver:
instance->_lcd.printAt( 10, 20, "Driver %7.2f", t1.time()/1000.0 );
break;
case tCompStateType::kCompStateAuton:
instance->_lcd.printAt( 10, 20, "Autonomous %7.2f", t1.time()/1000.0 );
break;
}
// monitor competition state changes
// these are mevents that latch
if( instance->_c1->DISABLED ) {
newStatusColor = vex::red;
textColor = vex::yellow;
instance->_state = tCompStateType::kCompStateDisabled;
}
else
if( instance->_c1->DRIVER_CONTROL ) {
newStatusColor = vex::green;
textColor = vex::black;
instance->_state = tCompStateType::kCompStateDriver;
t1.clear();
}
else
if( instance->_c1->AUTONOMOUS ) {
newStatusColor = vex::blue;
textColor = vex::white;
instance->_state = tCompStateType::kCompStateAuton;
t1.clear();
}
vex::this_thread::sleep_for(25);
}
return 0;
}
static int count_threads() {
int callback_id = 0;
// get maximum number of tasks we support
int max_tasks = vex::thread::hardware_concurrency();
int n = 0;
for( int i=0;i<max_tasks;i++) {
void * callback = (void *)vexTaskGetCallbackAndId(i, &callback_id);
if( callback != NULL ) {
n++;
}
}
return n;
}
};
#endif // COMP_DEBUG_CLASS_H