-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_logging.cpp
More file actions
159 lines (139 loc) · 4.69 KB
/
data_logging.cpp
File metadata and controls
159 lines (139 loc) · 4.69 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
#include "data_logging.h"
#include "log_format.h"
#include "log_checksum.h"
/**
* @brief Forward decleration of the ID recieving function
*/
template<typename T>
constexpr ReadingDiscriminant get_discriminant();
/**
* @brief macro to associate a certain sensor with a specific number ID
*/
#define ASSOCIATE(ty, id) template<> constexpr ReadingDiscriminant get_discriminant<ty>() { return ReadingDiscriminant::id; }
ASSOCIATE(IMU, ID_IMU)
ASSOCIATE(Barometer, ID_BAROMETER)
ASSOCIATE(Voltage, ID_VOLTAGE)
ASSOCIATE(GPS, ID_GPS)
ASSOCIATE(Magnetometer, ID_MAGNETOMETER)
ASSOCIATE(KalmanData, ID_KALMAN)
ASSOCIATE(FSMState, ID_FSM)
ASSOCIATE(PyroState, ID_PYRO)
ASSOCIATE(CameraData, ID_CAMERADATA)
ASSOCIATE(AngularKalmanData, ID_ANGULARKALMAN)
ASSOCIATE(IMU_SFLP, ID_SFLP)
/**
* @brief writes a reading, with its ID, timestamp, and data to a specific sink
*
* @param sink the LogSink to write to
* @param reading the data to read
*/
template<typename T>
void log_reading(LogSink& sink, Reading<T>& reading) {
ReadingDiscriminant discriminant = get_discriminant<T>();
sink.write((uint8_t*) &discriminant, sizeof(ReadingDiscriminant));
sink.write((uint8_t*) &reading.timestamp_ms, sizeof(uint32_t));
sink.write((uint8_t*) &reading.data, sizeof(T));
}
/**
* @brief writes a SensorData's entire queue reading to a sink
*
* @param sink the LogSink to write to
* @param sensor_data the sensor data, with queue, to write from
*
* @return the number of packets written to the LogSink
*/
template<typename T>
uint32_t log_from_sensor_data(LogSink& sink, SensorData<T>& sensor_data) {
Reading<T> reading;
uint32_t read = 0;
while (read < 20 && sensor_data.getQueued(&reading)) {
log_reading(sink, reading);
read++;
}
return read;
}
/**
* @brief Initializes a specific LogSink
*
* @param sink the LogSink to initialize
*/
void log_begin(LogSink& sink) {
uint32_t checksum = LOG_CHECKSUM;
sink.write((uint8_t*) &checksum, 4);
}
/**
* @brief logs all sensor data from the rocket
*
* @param sink the LogSink to write data to
* @param data the rocket which holds all the sensor data to write
*/
void log_data(LogSink& sink, RocketData& data) {
log_from_sensor_data(sink, data.imu);
log_from_sensor_data(sink, data.sflp);
log_from_sensor_data(sink, data.barometer);
log_from_sensor_data(sink, data.voltage);
log_from_sensor_data(sink, data.gps);
log_from_sensor_data(sink, data.magnetometer);
log_from_sensor_data(sink, data.fsm_state);
log_from_sensor_data(sink, data.kalman);
log_from_sensor_data(sink, data.angular_kalman_data);
log_from_sensor_data(sink, data.pyro);
log_from_sensor_data(sink, data.cam_data);
}
#ifndef SILSIM
#define MAX_FILES 999
/**
* @brief names a new file for a log sink depending on the files currently on said LogSink
*
* @param fileName buffer to write the file name to
* @param fileExtensionParam the file extension required for the file
* @param fs the FileSystem to check files off of
*
* @return buffer contianing string of file name
*/
char* sdFileNamer(char* fileName, char* fileExtensionParam, FS& fs, uint16_t file_num, int* fileno_out) {
char fileExtension[strlen(fileExtensionParam) + 1];
strcpy(fileExtension, fileExtensionParam);
char inputName[256] = {0};
strcpy(inputName, "/");
strcat(inputName, fileName);
strcat(inputName, fileExtension);
// checks to see if file already exists and adds 1 to filename if it does.
bool exists = fs.exists(inputName);
if (exists) {
bool fileExists = false;
// We will start at file_num, which is default 0 if eeprom is erased
int i = file_num;
while (!fileExists) {
if (i > MAX_FILES) {
// max number of files reached. Don't want to overflow
// fileName[]. Will write new data to already existing
// data999.csv
strcpy(inputName, "/");
strcat(inputName, fileName);
strcat(inputName, "999");
strcat(inputName, fileExtension);
*fileno_out = 999;
break;
}
// converts int i to char[]
char iStr[16] = {0};
itoa(i, iStr, 10);
// writes "(sensor)_data(number).csv to fileNameTemp"
strcpy(inputName, "/");
strcat(inputName, fileName);
strcat(inputName, iStr);
strcat(inputName, fileExtension);
if (!fs.exists(inputName)) {
fileExists = true;
*fileno_out = i + 1;
}
i++;
}
} else {
*fileno_out = 0;
}
strcpy(fileName, inputName);
return fileName;
}
#endif