/* Copyright 2019 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Test motion_sense_fifo. */ #include "stdio.h" #include "motion_sense_fifo.h" #include "test_util.h" #include "util.h" #include "hwtimer.h" #include "timer.h" #include "accelgyro.h" #include struct motion_sensor_t motion_sensors[] = { [BASE] = {}, [LID] = {}, }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); uint32_t mkbp_last_event_time; static struct ec_response_motion_sensor_data data[CONFIG_ACCEL_FIFO_SIZE]; static uint16_t data_bytes_read; static int test_insert_async_event(void) { int read_count; motion_sense_fifo_insert_async_event(motion_sensors, ASYNC_EVENT_FLUSH); motion_sense_fifo_insert_async_event(motion_sensors + 1, ASYNC_EVENT_ODR); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 2, "%d"); TEST_EQ(data_bytes_read, (int)(2 * sizeof(struct ec_response_motion_sensor_data)), "%d"); TEST_BITS_SET(data[0].flags, ASYNC_EVENT_FLUSH); TEST_BITS_CLEARED(data[0].flags, MOTIONSENSE_SENSOR_FLAG_ODR); TEST_EQ(data[0].sensor_num, 0, "%d"); TEST_BITS_SET(data[1].flags, ASYNC_EVENT_ODR); TEST_BITS_CLEARED(data[1].flags, MOTIONSENSE_SENSOR_FLAG_FLUSH); TEST_EQ(data[1].sensor_num, 1, "%d"); return EC_SUCCESS; } static int test_wake_up_needed(void) { data[0].flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; motion_sense_fifo_stage_data(data, motion_sensors, 0, 100); TEST_EQ(motion_sense_fifo_wake_up_needed(), 0, "%d"); motion_sense_fifo_commit_data(); TEST_EQ(motion_sense_fifo_wake_up_needed(), 1, "%d"); return EC_SUCCESS; } static int test_wake_up_needed_overflow(void) { int i; data[0].flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; motion_sense_fifo_stage_data(data, motion_sensors, 0, 100); data[0].flags = 0; /* * Using CONFIG_ACCEL_FIFO_SIZE / 2 since 2 entries are inserted per * 'data': * - a timestamp * - the data */ for (i = 0; i < (CONFIG_ACCEL_FIFO_SIZE / 2); i++) motion_sense_fifo_stage_data(data, motion_sensors, 0, 101 + i); TEST_EQ(motion_sense_fifo_wake_up_needed(), 1, "%d"); return EC_SUCCESS; } static int test_adding_timestamp(void) { int read_count; motion_sense_fifo_add_timestamp(100); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 1, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, 100, "%u"); return EC_SUCCESS; } static int test_stage_data_sets_xyz(void) { motion_sensors->oversampling_ratio = 1; motion_sensors->oversampling = 0; data->data[0] = 1; data->data[1] = 2; data->data[2] = 3; motion_sense_fifo_stage_data(data, motion_sensors, 3, 100); TEST_EQ(motion_sensors->xyz[0], 1, "%d"); TEST_EQ(motion_sensors->xyz[1], 2, "%d"); TEST_EQ(motion_sensors->xyz[2], 3, "%d"); return EC_SUCCESS; } static int test_stage_data_removed_oversample(void) { int read_count; motion_sensors->oversampling_ratio = 2; motion_sensors->oversampling = 0; data->data[0] = 1; data->data[1] = 2; data->data[2] = 3; motion_sense_fifo_stage_data(data, motion_sensors, 3, 100); data->data[0] = 4; data->data[1] = 5; data->data[2] = 6; motion_sense_fifo_stage_data(data, motion_sensors, 3, 110); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 3, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, 100, "%u"); TEST_BITS_CLEARED(data[1].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[1].data[0], 1, "%d"); TEST_EQ(data[1].data[1], 2, "%d"); TEST_EQ(data[1].data[2], 3, "%d"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[2].timestamp, 110, "%u"); return EC_SUCCESS; } static int test_stage_data_remove_all_oversampling(void) { int read_count; motion_sensors->oversampling_ratio = 0; motion_sensors->oversampling = 0; data->data[0] = 1; data->data[1] = 2; data->data[2] = 3; motion_sense_fifo_stage_data(data, motion_sensors, 3, 100); data->data[0] = 4; data->data[1] = 5; data->data[2] = 6; motion_sense_fifo_stage_data(data, motion_sensors, 3, 110); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 2, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, 100, "%u"); TEST_BITS_SET(data[1].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[1].timestamp, 110, "%u"); return EC_SUCCESS; } static int test_stage_data_evicts_data_with_timestamp(void) { int i, read_count; /* Fill the fifo */ motion_sensors->oversampling_ratio = 1; for (i = 0; i < CONFIG_ACCEL_FIFO_SIZE / 2; i++) motion_sense_fifo_stage_data(data, motion_sensors, 3, i * 100); /* Add a single entry (should evict 2) */ motion_sense_fifo_add_timestamp(CONFIG_ACCEL_FIFO_SIZE * 100); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, CONFIG_ACCEL_FIFO_SIZE - 1, "%d"); TEST_BITS_SET(data->flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data->timestamp, 100, "%u"); TEST_BITS_SET(data[CONFIG_ACCEL_FIFO_SIZE - 2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[CONFIG_ACCEL_FIFO_SIZE - 2].timestamp, CONFIG_ACCEL_FIFO_SIZE * 100, "%u"); return EC_SUCCESS; } static int test_add_data_no_spreading_when_different_sensors(void) { int read_count; uint32_t now = __hw_clock_source_read(); motion_sensors[0].oversampling_ratio = 1; motion_sensors[1].oversampling_ratio = 1; motion_sense_fifo_stage_data(data, motion_sensors, 3, now); motion_sense_fifo_stage_data(data, motion_sensors + 1, 3, now); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, now, "%u"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[2].timestamp, now, "%u"); return EC_SUCCESS; } static int test_add_data_no_spreading_different_timestamps(void) { int read_count; motion_sensors[0].oversampling_ratio = 1; motion_sense_fifo_stage_data(data, motion_sensors, 3, 100); motion_sense_fifo_stage_data(data, motion_sensors, 3, 120); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, 100, "%u"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[2].timestamp, 120, "%u"); return EC_SUCCESS; } static int test_spread_data_in_window(void) { uint32_t now; int read_count; motion_sensors[0].oversampling_ratio = 1; motion_sensors[0].collection_rate = 20000; /* ns */ now = __hw_clock_source_read(); motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 18000); motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 18000); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, now - 18000, "%u"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); /* TODO(b/142892004): mock __hw_clock_source_read so we can check for * exact TS. */ TEST_NEAR(data[2].timestamp, now, 2, "%u"); return EC_SUCCESS; } static int test_spread_data_by_collection_rate(void) { const uint32_t now = __hw_clock_source_read(); int read_count; motion_sensors[0].oversampling_ratio = 1; motion_sensors[0].collection_rate = 20000; /* ns */ motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, now - 20500, "%u"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[2].timestamp, now - 500, "%u"); return EC_SUCCESS; } static int test_spread_double_commit_same_timestamp(void) { const uint32_t now = __hw_clock_source_read(); int read_count; motion_sensors[0].oversampling_ratio = 1; motion_sensors[0].collection_rate = 20000; /* ns */ motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); motion_sense_fifo_commit_data(); motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, now - 20500, "%u"); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_GT(time_until(now - 20500, data[2].timestamp), 10000, "%u"); TEST_LE(time_until(now - 20500, data[2].timestamp), 20000, "%u"); return EC_SUCCESS; } static int test_commit_non_data_or_timestamp_entries(void) { const uint32_t now = __hw_clock_source_read(); int read_count; motion_sensors[0].oversampling_ratio = 1; motion_sensors[0].collection_rate = 20000; /* ns */ /* Insert non-data entry */ data[0].flags = MOTIONSENSE_SENSOR_FLAG_ODR; motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); /* Insert data entry */ data[0].flags = 0; motion_sense_fifo_stage_data(data, motion_sensors, 3, now - 20500); motion_sense_fifo_commit_data(); read_count = motion_sense_fifo_read( sizeof(data), CONFIG_ACCEL_FIFO_SIZE, data, &data_bytes_read); TEST_EQ(read_count, 4, "%d"); TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[0].timestamp, now - 20500, "%u"); TEST_BITS_SET(data[1].flags, MOTIONSENSE_SENSOR_FLAG_ODR); TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); TEST_EQ(data[2].timestamp, now - 20500, "%u"); return EC_SUCCESS; } void before_test(void) { motion_sense_fifo_commit_data(); motion_sense_fifo_read(sizeof(data), CONFIG_ACCEL_FIFO_SIZE, &data, &data_bytes_read); motion_sense_fifo_reset_wake_up_needed(); memset(data, 0, sizeof(data)); motion_sense_fifo_reset(); } void run_test(void) { test_reset(); motion_sense_fifo_init(); RUN_TEST(test_insert_async_event); RUN_TEST(test_wake_up_needed); RUN_TEST(test_wake_up_needed_overflow); RUN_TEST(test_adding_timestamp); RUN_TEST(test_stage_data_sets_xyz); RUN_TEST(test_stage_data_removed_oversample); RUN_TEST(test_stage_data_remove_all_oversampling); RUN_TEST(test_stage_data_evicts_data_with_timestamp); RUN_TEST(test_add_data_no_spreading_when_different_sensors); RUN_TEST(test_add_data_no_spreading_different_timestamps); RUN_TEST(test_spread_data_in_window); RUN_TEST(test_spread_data_by_collection_rate); RUN_TEST(test_spread_double_commit_same_timestamp); RUN_TEST(test_commit_non_data_or_timestamp_entries); test_print_result(); }