blob: 30571240657325694ed2a024ea2a37ab116d981b (
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
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
|
/*
* Copyright 2020 Birte Kristina Friesel
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef PTALOG_H
#define PTALOG_H
#include <stdlib.h>
#include "driver/stdout.h"
#ifdef PTALOG_GPIO
#include "driver/gpio.h"
#if defined(PTALOG_GPIO_BEFORE) || defined(PTALOG_GPIO_BAR)
#include "arch.h"
#endif
#endif
#ifdef PTALOG_TIMING
#include "driver/counter.h"
#endif
class PTALog {
private:
PTALog(const PTALog& copy);
#ifdef PTALOG_GPIO
uint8_t sync_pin;
#endif
public:
typedef struct {
uint8_t transition_id;
#ifdef PTALOG_TIMING
counter_value_t timer;
counter_overflow_t overflow;
counter_value_t prev_state_timer;
counter_overflow_t prev_state_overflow;
#endif
#ifdef PTALOG_WITH_RETURNVALUES
uint16_t return_value;
#endif
} log_entry;
int const max_entry = 15;
log_entry log[16];
uint8_t log_index;
#ifdef PTALOG_GPIO
PTALog(uint8_t pin_number) : sync_pin(pin_number), log_index(0) {}
#else
PTALog() : log_index(0) {}
#endif
void passTransition(uint8_t transition_id)
{
log[log_index].transition_id = transition_id;
if (log_index < max_entry) {
log_index++;
}
}
#ifdef PTALOG_TIMING
/*
* This function is meant to estimate the overhead of counter.start()
* and counter.stop(). It immediately restarts the counter to ensure that
* state durations are captured accurately.
* This means that the overflow value is unusable. We assume that there
* are no overflows in this short time span.
*/
inline void passNop()
{
counter.start();
counter.stop();
counter.start(); // .value is kept until .stop
kout << "[PTA] nop=" << counter.value << "/" << 0 << endl;
}
#endif
void reset()
{
log_index = 0;
}
void startBenchmark(uint8_t id)
{
kout << "[PTA] benchmark start, id=" << dec << id << endl;
#ifdef PTALOG_GPIO
gpio.output(sync_pin);
#endif
}
void stopBenchmark()
{
#ifdef PTALOG_TIMING
counter.stop();
kout << "[PTA] benchmark stop, cycles=" << counter.value << "/" << counter.overflow << endl;
#else
kout << "[PTA] benchmark stop" << endl;
#endif
}
void dump(uint16_t trace_id)
{
kout << "[PTA] trace=" << dec << trace_id << " count=" << log_index << endl;
for (uint8_t i = 0; i < log_index; i++) {
kout << "[PTA] transition=" << log[i].transition_id;
#ifdef PTALOG_TIMING
kout << " prevcycles=" << log[i].prev_state_timer << "/" << log[i].prev_state_overflow;
kout << " cycles=" << log[i].timer << "/" << log[i].overflow;
#endif
#ifdef PTALOG_WITH_RETURNVALUES
kout << " return=" << log[i].return_value;
#endif
kout << endl;
}
}
#ifdef PTALOG_GPIO_BAR
void startTransition(char const *code, uint8_t code_length)
{
counter.stop();
log[log_index - 1].prev_state_timer = counter.value;
log[log_index - 1].prev_state_overflow = counter.overflow;
// Quiet zone (must last at least 10x longer than a module)
arch.sleep_ms(60);
for (uint8_t byte = 0; byte < code_length; byte++) {
for (uint16_t mask = 0x01; mask <= 0x80; mask <<= 1) {
// a single module, which is part of a bar
gpio.write(sync_pin, code[byte] & mask ? 1 : 0);
arch.sleep_ms(5);
}
}
gpio.write(sync_pin, 0);
// Quiet zone
arch.sleep_ms(60);
counter.start();
}
#else
inline void startTransition()
{
#ifdef PTALOG_GPIO_BEFORE
gpio.write(sync_pin, 1);
arch.sleep_ms(10);
gpio.write(sync_pin, 0);
arch.sleep_ms(10);
#endif
#ifdef PTALOG_TIMING
counter.stop();
log[log_index - 1].prev_state_timer = counter.value;
log[log_index - 1].prev_state_overflow = counter.overflow;
counter.start();
#endif
#if defined(PTALOG_GPIO) && !defined(PTALOG_GPIO_BEFORE)
gpio.write(sync_pin, 1);
#endif
}
#endif
#ifdef PTALOG_WITH_RETURNVALUES
inline void logReturn(uint16_t ret)
{
log[log_index - 1].return_value = ret;
}
#endif
inline void stopTransition()
{
#if defined(PTALOG_GPIO) && !defined(PTALOG_GPIO_BEFORE) && !defined(PTALOG_GPIO_BAR)
gpio.write(sync_pin, 0);
#endif
#ifdef PTALOG_TIMING
counter.stop();
log[log_index - 1].timer = counter.value;
log[log_index - 1].overflow = counter.overflow;
counter.start();
#endif
}
};
#endif
|