blob: 96b2e96a918815eea0949863af0c746ab5b0a4f1 [file] [log] [blame]
Ravago Jones09067de2023-03-29 18:44:43 -07001#include "frc971/can_logger/asc_logger.h"
2
3#include <linux/can.h>
4
5namespace frc971 {
6namespace can_logger {
7
8AscLogger::AscLogger(aos::EventLoop *event_loop, const std::string &filename)
9 : output_(filename), event_loop_(event_loop) {
10 CHECK(output_);
11 event_loop->MakeWatcher(
12 "/can", [this](const CanFrame &frame) { HandleFrame(frame); });
13}
14
15void AscLogger::HandleFrame(const CanFrame &frame) {
16 if (!first_frame_monotonic_) {
17 aos::monotonic_clock::time_point time(
18 std::chrono::nanoseconds(frame.monotonic_timestamp_ns()));
19
20 first_frame_monotonic_ = time;
21
22 WriteHeader(output_, event_loop_->realtime_now());
23 }
24
25 WriteFrame(output_, frame);
26}
27
28void AscLogger::WriteHeader(std::ostream &file,
29 aos::realtime_clock::time_point start_time) {
30 file << "date " << start_time << "\n";
31 file << "base hex timetamps absolute\n";
32 file << "no internal events logged\n";
33}
34
35namespace {
36
37static const unsigned char len2dlc[] = {
38 0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
39 9, 9, 9, 9, /* 9 - 12 */
40 10, 10, 10, 10, /* 13 - 16 */
41 11, 11, 11, 11, /* 17 - 20 */
42 12, 12, 12, 12, /* 21 - 24 */
43 13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
44 14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
45 14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
46 15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
47 15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
48
49/* map the sanitized data length to an appropriate data length code */
50unsigned char can_fd_len2dlc(unsigned char len) {
51 if (len > 64) return 0xF;
52
53 return len2dlc[len];
54}
55
56#define ASC_F_RTR 0x00000010
57#define ASC_F_FDF 0x00001000
58#define ASC_F_BRS 0x00002000
59#define ASC_F_ESI 0x00004000
60
61} // namespace
62
63void AscLogger::WriteFrame(std::ostream &file, const CanFrame &frame) {
64 aos::monotonic_clock::time_point frame_timestamp(
65 std::chrono::nanoseconds(frame.monotonic_timestamp_ns()));
66
67 std::chrono::duration<double> time(frame_timestamp -
68 first_frame_monotonic_.value());
69
70 // TODO: maybe this should not be hardcoded
71 const int device_id = 1;
72
73 // EFF/SFF is set in the MSB
74 bool is_extended_frame_format = frame.can_id() & CAN_EFF_FLAG;
75
76 uint32_t id_mask = is_extended_frame_format ? CAN_EFF_MASK : CAN_SFF_MASK;
77 int id = frame.can_id() & id_mask;
78
79 // data length code
80 int dlc = can_fd_len2dlc(frame.data()->size());
81
82 const uint8_t flags = frame.flags();
83
84 uint32_t asc_flags = 0;
85
86 // Mark it as a CAN FD Frame
87 asc_flags = ASC_F_FDF;
88
89 // Pass through the bit rate switch flag
90 // indicates that it used a second bitrate for payload data
91 if (flags & CANFD_BRS) {
92 asc_flags |= ASC_F_BRS;
93 }
94
95 // ESI is the error state indicator of the transmitting node
96 if (flags & CANFD_ESI) {
97 asc_flags |= ASC_F_ESI;
98 }
99
100 file << std::fixed << time.count() << " ";
101
102 file << "CANFD ";
103
104 file << std::setfill(' ') << std::setw(3) << std::right << device_id << " ";
105
106 file << "Rx ";
107
108 std::stringstream formatted_id;
109 formatted_id << std::hex << std::uppercase << std::setfill('0') << id
110 << std::dec;
111 if (is_extended_frame_format) {
112 formatted_id << "x";
113 }
114
115 file << std::setfill(' ') << std::setw(11) << formatted_id.str();
116 file << " ";
117
118 file << ((flags & CANFD_BRS) ? '1' : '0') << " ";
119 file << ((flags & CANFD_ESI) ? '1' : '0') << " ";
120
121 file << std::hex << std::nouppercase << dlc << std::dec << " ";
122
123 // actual data length
124 file << std::setfill(' ') << std::setw(2) << frame.data()->size();
125
126 file << std::hex << std::uppercase;
127 for (uint8_t byte : *frame.data()) {
128 file << " " << std::setfill('0') << std::setw(2) << static_cast<int>(byte);
129 }
130 file << std::dec;
131
132 // these are hardcoded in log2asc too, I don't know why
133 file << " 130000 130 ";
134 file << std::setfill(' ') << std::setw(8) << std::hex << asc_flags
135 << std::dec;
136 file << " 0 0 0 0 0";
137
138 file << "\n";
139}
140
141} // namespace can_logger
142} // namespace frc971