Skip to content

Commit 7f619fd

Browse files
committed
muse s anthena timestamp rework
Signed-off-by: Andrey Parfenov <a1994ndrey@gmail.com>
1 parent a7bd30b commit 7f619fd

3 files changed

Lines changed: 53 additions & 34 deletions

File tree

src/board_controller/muse/inc/muse_anthena.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ class MuseAnthena : public BLELibBoard
4242
std::condition_variable cv;
4343
std::vector<std::pair<simpleble_uuid_t, simpleble_uuid_t>> notified_characteristics;
4444
std::pair<simpleble_uuid_t, simpleble_uuid_t> control_characteristics;
45-
bool timestamp_initialized;
46-
uint32_t first_device_tick;
47-
double first_host_timestamp;
45+
double last_eeg_timestamp;
46+
double last_aux_timestamp;
47+
double last_anc_timestamp;
4848
double last_battery;
4949
std::string muse_preset;
5050
bool enable_low_latency;
@@ -57,10 +57,12 @@ class MuseAnthena : public BLELibBoard
5757
std::string bytes_to_string (const uint8_t *data, size_t size);
5858
void handle_data_notification (const uint8_t *data, size_t size);
5959
void parse_sensor_payload (
60-
uint8_t tag, uint8_t sequence_num, uint32_t device_tick, const uint8_t *data, size_t size);
60+
uint8_t tag, uint8_t sequence_num, double host_timestamp, const uint8_t *data, size_t size);
6161
bool get_sensor_config (uint8_t tag, SensorConfig &config);
6262
int get_optics_canonical_index (uint8_t tag, int channel);
63-
double get_sample_timestamp (uint32_t device_tick, int sample_index, double sampling_rate);
63+
void reset_timestamps ();
64+
static double get_sample_timestamp (double last_timestamp, double current_timestamp,
65+
int sample_index, int n_samples, double sampling_rate);
6466

6567
public:
6668
MuseAnthena (int board_id, struct BrainFlowInputParams params);

src/board_controller/muse/inc/muse_anthena_constants.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,5 @@
1111
// info for equations
1212
#define MUSE_ANTHENA_ACCELEROMETER_SCALE_FACTOR 0.0000610352
1313
#define MUSE_ANTHENA_GYRO_SCALE_FACTOR -0.0074768
14-
#define MUSE_ANTHENA_DEVICE_CLOCK_HZ 256000.0
1514
#define MUSE_ANTHENA_EEG_SCALE_FACTOR (1450.0 / 16383.0)
1615
#define MUSE_ANTHENA_OPTICS_SCALE_FACTOR 1.0

src/board_controller/muse/muse_anthena.cpp

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,7 @@ MuseAnthena::MuseAnthena (int board_id, struct BrainFlowInputParams params)
263263
muse_adapter = NULL;
264264
muse_peripheral = NULL;
265265
is_streaming = false;
266-
timestamp_initialized = false;
267-
first_device_tick = 0;
268-
first_host_timestamp = 0.0;
266+
reset_timestamps ();
269267
last_battery = 0.0;
270268
muse_preset = "p1041";
271269
enable_low_latency = true;
@@ -486,9 +484,7 @@ int MuseAnthena::start_stream (int buffer_size, const char *streamer_params)
486484
if (res == (int)BrainFlowExitCodes::STATUS_OK)
487485
{
488486
std::lock_guard<std::mutex> callback_guard (callback_lock);
489-
timestamp_initialized = false;
490-
first_device_tick = 0;
491-
first_host_timestamp = 0.0;
487+
reset_timestamps ();
492488
last_battery = 0.0;
493489
}
494490
if (res == (int)BrainFlowExitCodes::STATUS_OK)
@@ -555,7 +551,7 @@ int MuseAnthena::stop_stream ()
555551
res = (int)BrainFlowExitCodes::STREAM_ALREADY_RUN_ERROR;
556552
}
557553
is_streaming = false;
558-
timestamp_initialized = false;
554+
reset_timestamps ();
559555
return res;
560556
}
561557

@@ -744,8 +740,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size)
744740

745741
const uint8_t *packet = data + offset;
746742
uint8_t packet_index = packet[1];
747-
uint32_t device_tick =
748-
cast_32bit_to_uint32_little_endian ((const unsigned char *)(packet + 2));
743+
double packet_host_timestamp = get_timestamp ();
749744
uint8_t primary_tag = packet[9];
750745
const uint8_t *packet_data = packet + PACKET_HEADER_SIZE;
751746
size_t packet_data_size = packet_len - PACKET_HEADER_SIZE;
@@ -758,8 +753,8 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size)
758753
primary_config.variable_length ? packet_data_size : primary_config.data_len;
759754
if ((primary_data_len > 0) && (primary_data_len <= packet_data_size))
760755
{
761-
parse_sensor_payload (
762-
primary_tag, packet_index, device_tick, packet_data, primary_data_len);
756+
parse_sensor_payload (primary_tag, packet_index, packet_host_timestamp, packet_data,
757+
primary_data_len);
763758
packet_data_offset = primary_data_len;
764759
}
765760
else
@@ -799,7 +794,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size)
799794
break;
800795
}
801796

802-
parse_sensor_payload (tag, subpacket_index, device_tick,
797+
parse_sensor_payload (tag, subpacket_index, packet_host_timestamp,
803798
packet_data + packet_data_offset + SUBPACKET_HEADER_SIZE, sensor_data_len);
804799
packet_data_offset += SUBPACKET_HEADER_SIZE + sensor_data_len;
805800
}
@@ -809,7 +804,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size)
809804
}
810805

811806
void MuseAnthena::parse_sensor_payload (
812-
uint8_t tag, uint8_t sequence_num, uint32_t device_tick, const uint8_t *data, size_t size)
807+
uint8_t tag, uint8_t sequence_num, double host_timestamp, const uint8_t *data, size_t size)
813808
{
814809
SensorConfig config;
815810
if (!get_sensor_config (tag, config))
@@ -872,10 +867,11 @@ void MuseAnthena::parse_sensor_payload (
872867
}
873868
}
874869
}
875-
package[(size_t)timestamp_channel] =
876-
get_sample_timestamp (device_tick, sample, config.sampling_rate);
870+
package[(size_t)timestamp_channel] = get_sample_timestamp (
871+
last_eeg_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate);
877872
push_package (package.data (), (int)BrainFlowPresets::DEFAULT_PRESET);
878873
}
874+
last_eeg_timestamp = host_timestamp;
879875
return;
880876
}
881877

@@ -911,10 +907,11 @@ void MuseAnthena::parse_sensor_payload (
911907
(double)raw * MUSE_ANTHENA_GYRO_SCALE_FACTOR;
912908
}
913909
}
914-
package[(size_t)timestamp_channel] =
915-
get_sample_timestamp (device_tick, sample, config.sampling_rate);
910+
package[(size_t)timestamp_channel] = get_sample_timestamp (
911+
last_aux_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate);
916912
push_package (package.data (), (int)BrainFlowPresets::AUXILIARY_PRESET);
917913
}
914+
last_aux_timestamp = host_timestamp;
918915
return;
919916
}
920917

@@ -947,26 +944,47 @@ void MuseAnthena::parse_sensor_payload (
947944
}
948945
}
949946

950-
package[(size_t)timestamp_channel] =
951-
get_sample_timestamp (device_tick, sample, config.sampling_rate);
947+
package[(size_t)timestamp_channel] = get_sample_timestamp (
948+
last_anc_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate);
952949
push_package (package.data (), (int)BrainFlowPresets::ANCILLARY_PRESET);
953950
}
951+
last_anc_timestamp = host_timestamp;
954952
}
955953
}
956954

957-
double MuseAnthena::get_sample_timestamp (
958-
uint32_t device_tick, int sample_index, double sampling_rate)
955+
void MuseAnthena::reset_timestamps ()
959956
{
960-
if (!timestamp_initialized)
957+
last_eeg_timestamp = -1.0;
958+
last_aux_timestamp = -1.0;
959+
last_anc_timestamp = -1.0;
960+
}
961+
962+
double MuseAnthena::get_sample_timestamp (double last_timestamp, double current_timestamp,
963+
int sample_index, int n_samples, double sampling_rate)
964+
{
965+
if ((n_samples <= 0) || (sampling_rate <= 0.0))
966+
{
967+
return current_timestamp;
968+
}
969+
970+
if (last_timestamp <= 0.0)
971+
{
972+
return current_timestamp - (double)(n_samples - sample_index - 1) / sampling_rate;
973+
}
974+
975+
if (current_timestamp <= last_timestamp)
976+
{
977+
return current_timestamp;
978+
}
979+
980+
double sample_timestamp = last_timestamp + (double)(sample_index + 1) / sampling_rate;
981+
if (sample_timestamp <= current_timestamp)
961982
{
962-
timestamp_initialized = true;
963-
first_device_tick = device_tick;
964-
first_host_timestamp = get_timestamp ();
983+
return sample_timestamp;
965984
}
966985

967-
uint32_t elapsed_ticks = device_tick - first_device_tick;
968-
return first_host_timestamp + (double)elapsed_ticks / MUSE_ANTHENA_DEVICE_CLOCK_HZ +
969-
(double)sample_index / sampling_rate;
986+
double step = (current_timestamp - last_timestamp) / (double)n_samples;
987+
return last_timestamp + step * (double)(sample_index + 1);
970988
}
971989

972990
std::string MuseAnthena::bytes_to_string (const uint8_t *data, size_t size)

0 commit comments

Comments
 (0)