-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy path_scans.ino
291 lines (254 loc) · 10.6 KB
/
_scans.ino
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
// fyi, numer of runs to take for rx pins check
// nruns = passive parallel scan loops
// active parallel scan = sizeof(txpatterns) * sizeof(rxpins) * nruns
// active per pin scan = sizeof(txpatterns) * sizeof(txpins) * sizeof(rxpins-1 for current tx pin)
/* passive_parallel_scan
* Assume there is an active RX line presenting data.
* this is usefull only for tool verfication. An active RX
* would negate the need to use a serial detection tool. You
* could just use an oscilloscope.
*/
void passive_parallel_scan (uint32_t usperrx)
{
ppgm(PSTR("-> passive_parallel_scan()\r\n"));
pfmt( " listens to all pins in parallel for %lu microseconds\r\n",usperrx);
ppgm(PSTR(" tx stimulation and baudrate check not needed\r\n"));
ppgm(PSTR(" prints pins whose bits change at the end of test\r\n"));
microsbegin();
byte testmode = 0;
if (usperrx <= 1)
testmode = 1;
byte state;
uint32_t usstop = micros() + usperrx;
#ifdef DEBUGLOOPS
uint32_t loops = 0;
#endif
while (micros() <= usstop || testmode) {
for (byte rx = 0; rx < pinslen; rx++) {
#ifdef DEBUGLOOPS
loops++;
#endif
state = digitalRead(pins[rx]) ? HIGH : LOW; // BUGBUG?
#ifdef DEBUGSTATEBUF
pfmt("cmp: %d != bitRead(pinstatebuf[%d]=%d, %d)=%d\r\n",state, rx/8, pinstatebuf[rx/8], rx%8, bitRead(pinstatebuf[rx/8], rx%8) );
#endif
if (state != bitRead(pinstatebuf[rx/8], rx%8) ) {
append_to_report(rx, state);
bitWrite(pinstatebuf[rx/8], rx%8, state); // need to check the efficiency of bitWrite
}
}
if(testmode) // run only one iteration
break;
}
print_report();
ustotime(microselapsed());
#ifdef DEBUGLOOPS
pfmt("loops: %lu\r\n",loops);
#endif
}
/* active_parallel_scan
* Assume there is an active RX line presenting data.
* will send a txpattern wakeup pattern hoping this will
* stimulate the target to start printing to the console
* (it is common that some terminals require you send a
* carriage return before they present a login screen)
* all non-tx pins are then scanned in parallel
*/
void active_parallel_scan (uint32_t usperrx)
{
ppgm(PSTR("-> active_parallel_scan\r\n"));
pfmt( " listens to all non tx pins in parallel for %lu microseconds\r\n",usperrx);
ppgm(PSTR(" sends wakeup stimulant to tx pin at defined baudrates\r\n"));
ppgm(PSTR(" prints pins whose bits change during test\r\n"));
microsbegin();
byte testmode = 0;
if (usperrx <= 1)
testmode = 1;
uint32_t usstop;
uint16_t baud_i;
byte pat, tx, rx, state;
#ifdef DEBUGLOOPS
uint32_t loops=0;
#endif
for (baud_i = 0; baud_i < baudrateslen; baud_i++) {
pfmt("baud: %lu\r\n",baudrates[baud_i]);
softserial_setup(baudrates[baud_i]);
for (pat = 0; pat < txpatternslen; pat++) {
for (tx = 0; tx < pinslen; tx++) {
#ifdef SHOWTXSTATUS
pfmt("0x%02X -> %s\r\n",txpatterns[pat],pinnames[tx]);
#endif
pinMode(pins[tx], OUTPUT);
softserial_write(pins[tx], txpatterns[pat]);
usstop = micros() + usperrx;
while (micros() <= usstop || testmode){
for (rx = 0; rx < pinslen; rx++) {
if(rx == tx) continue;
#ifdef DEBUGLOOPS
loops++;
#endif
state = digitalRead(pins[rx]) ? HIGH : LOW; // BUGBUG?
if (state != bitRead(pinstatebuf[rx/8], rx%8) ) {
append_to_report(rx, state);
bitWrite(pinstatebuf[rx/8], rx%8, state);
}
}
if (testmode)
break; // run combined iterations only once
}
pinMode(pins[tx], INPUT); // reset
digitalWrite(pins[tx], HIGH); // pull-up resistor
print_report(tx, txpatterns[pat]);
}
}
}
ustotime(microselapsed());
#ifdef DEBUGLOOPS
pfmt("loops: %lu\r\n",loops);
#endif
}
/* active_per_pin_scan
* exactly the same as active_parallel_scan except that
* the each RX pin is scanned individually
*/
void active_per_pin_scan (uint32_t usperrx)
{
ppgm(PSTR("-> active_per_pin_scan\r\n"));
pfmt( " listens to 1 rx pin at a time for %lu microseconds\r\n",usperrx);
ppgm(PSTR(" sends wakeup stimulant to tx pin at defined baudrates\r\n"));
ppgm(PSTR(" prints pins whose bits change during test\r\n"));
microsbegin();
byte testmode = 0;
if (usperrx <= 1)
testmode = 1;
uint32_t usstop;
uint16_t baud_i;
byte pat,tx,rx,state;
#ifdef DEBUGLOOPS
uint32_t loops=0;
#endif
for (pat=0; pat < txpatternslen; pat++) {
for (tx=0; tx < pinslen; tx++) {
#ifdef SHOWTXSTATUS
pfmt("0x%02X -> txpin %s\r\n",txpatterns[pat],pinnames[tx]);
#endif
pinMode(pins[tx], OUTPUT);
// no need to delay before read. just need to be sure we can
// poll all pins long enough to detect low serial baud.
for (rx=0; rx < pinslen; rx++) {
if(rx==tx) continue; // no need to digitalRead(rxpin)
for (baud_i=0; baud_i < baudrateslen; baud_i++) {
pfmt("tx:%s rx:%s baud:%lu \r\n",pinnames[tx],pinnames[rx],baudrates[baud_i]);
softserial_setup(baudrates[baud_i]);
softserial_write(pins[tx], txpatterns[pat]);
usstop = usperrx+micros();
while (micros() <= usstop || testmode) {
#ifdef DEBUGLOOPS
loops++;
#endif
state = digitalRead(pins[rx]) ? HIGH : LOW; // BUGBUG?
#ifdef DEBUGSTATEBUF
pfmt("cmp: %d != bitRead(pinstatebuf[%d]=%d, %d)=%d\r\n",state, rx/8, pinstatebuf[rx/8], rx%8, bitRead(pinstatebuf[rx/8], pat%8) );
#endif
if (state != bitRead(pinstatebuf[rx/8], rx%8) ) {
append_to_report(rx, state);
bitWrite(pinstatebuf[rx/8], rx%8, state);
}
if (testmode)
break; // read pin once
}
print_report(tx,txpatterns[pat]);
}
}
pinMode(pins[tx], INPUT); // reset to INPUT
digitalWrite(pins[tx], HIGH); //pull-up
}
}
#ifdef DEBUGLOOPS
pfmt("loops: %lu\r\n",loops);
#endif
}
/* pins_state
* prints the current high/low state of all the pins
*/
void pins_state ()
{
// align names and pin state columns by finding the max string length
ppgm(PSTR("pin: "));
for (byte i = 0; i < pinslen; i++) {
pfmt("%s ", pinnames[i]);
}
ppgm(PSTR("\r\nstatebuf: "));
for (byte i = 0; i < pinslen; i++) {
// align columns using space:
for (byte j = 0; j < strlen(pinnames[i])-1; j++)
pfmt(" ");
pfmt("%d ", bitRead(pinstatebuf[i/8], i%8));
}
ppgm(PSTR("\r\ncurrent: "));
for (int i = 0; i < pinslen; i++) {
for (byte j = 0; j < strlen(pinnames[i])-1; j++)
pfmt(" ");
pfmt("%d ", digitalRead(pins[i]));
}
ppgm(PSTR("\r\n"));
}
void append_to_report(byte rxpin_i, byte state)
{
if ( reportbuf_i <= reportbuflen-2 ) {
reportbuf[reportbuf_i++] = rxpin_i;
reportbuf[reportbuf_i++] = state;
}
else {
pfmt("."); // indication that memory is full
}
}
// return 1 if anything was reported
byte print_report(int16_t tx, uint16_t txpattern)
{
byte ret=0;
if (reportbuf_i>0) {
ret=1;
if (tx >= 0) {
pfmt("\t0x%02X -> %s:\t", txpattern,pinnames[tx]);
}
for (uint16_t i=0; i<=reportbuf_i-2;) {
// if (i%(pinslen)==0)
if (i%16==0 && i!=0)
pfmt("\r\n \t");
pfmt("%s=%d ",pinnames[reportbuf[i++]],reportbuf[i++]);
}
pfmt("\r\n");
//clear_report_buffer(); // resource intensive
reportbuf_i=0;
}
return ret;
}
void print_report()
{
print_report(-1,0);
}
void clear_report_buffer()
{
for (uint16_t i=0; i<reportbuflen; i++)
reportbuf[i]=0;
reportbuf_i=0;
}
/*
void print_report_buffer()
{
for (uint16_t i=0; i<reportbuflen; i++) {
if (i%32==0) {
pfmt("\r\n");
}
pfmt("%d ", reportbuf[i]);
}
}
void print_all_pins ()
{
pfmt("\r\n");
for (int i=0; i<pinslen; i++)
pfmt("%d ", digitalRead(pins[i]));
pfmt("\r\n");
}
*/