summaryrefslogtreecommitdiff
path: root/include/object/ptalog.h
blob: 9d30a40193565a6a2ba446c0adf2a1fcb98122f3 (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
#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;
#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
		void passNop(Counter& counter)
		{
			kout << "[PTA] nop=" << counter.value << "/" << counter.overflow << 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()
		{
			kout << "[PTA] benchmark stop" << endl;
		}

		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 << " 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)
		{
			// 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);
		}
#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);
#else
			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

#ifdef PTALOG_TIMING
		inline void stopTransition(Counter& counter)
#else
		inline void stopTransition()
#endif
		{
#ifdef PTALOG_GPIO
#if !defined(PTALOG_GPIO_BEFORE) && !defined(PTALOG_GPIO_BAR)
			gpio.write(sync_pin, 0);
#endif
#endif
#ifdef PTALOG_TIMING
			log[log_index - 1].timer = counter.value;
			log[log_index - 1].overflow = counter.overflow;
#endif
		}
};

#endif