#include #include "unity.h" #include "light/nl_engine.h" static uint8_t last[NL_CH_COUNT]; static int calls; static void out(const uint8_t ch[NL_CH_COUNT], void *ctx) { (void)ctx; memcpy(last, ch, NL_CH_COUNT); calls++; } static nl_light_state_t st(bool on, uint8_t bri, nl_light_mode_t m, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) { nl_light_state_t s = {on, bri, m, r, g, b, ct}; return s; } static nl_visual_t cur(void) { nl_visual_t v; nl_engine_current(&v); return v; } static int sum(void) { int s = 0; for (int i = 0; i < NL_CH_COUNT; i++) s += last[i]; return s; } void setUp(void) { nl_engine_cfg_t cfg = {2700, 6500, out, NULL}; memset(last, 0xAA, sizeof last); calls = 0; nl_engine_init(&cfg); } void tearDown(void) {} static void test_init_is_dark_and_idle(void) { TEST_ASSERT_TRUE(calls >= 1); TEST_ASSERT_EQUAL_INT(0, sum()); TEST_ASSERT_EQUAL_UINT16(0, cur().bri); TEST_ASSERT_TRUE(nl_engine_idle()); } static void test_instant_set(void) { nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); nl_engine_set(&s, 0); TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); TEST_ASSERT_EQUAL_UINT8(0, last[NL_CH_CW]); TEST_ASSERT_TRUE(nl_engine_idle()); } static void test_fade_in_is_linear_in_brightness(void) { nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); nl_engine_set(&s, 1000); nl_engine_tick(500); TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); TEST_ASSERT_FALSE(nl_engine_idle()); nl_engine_tick(500); TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); TEST_ASSERT_TRUE(nl_engine_idle()); TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); } static void test_fade_out_keeps_current_color(void) { nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); nl_light_state_t off = st(false, 100, NL_MODE_WHITE, 0, 0, 0, 4000); nl_engine_set(&red, 0); nl_engine_set(&off, 1000); nl_engine_tick(500); TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); TEST_ASSERT_TRUE(last[NL_CH_R] > 0); nl_engine_tick(500); TEST_ASSERT_EQUAL_INT(0, sum()); TEST_ASSERT_TRUE(nl_engine_idle()); TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); /* target values applied at the end */ } static void test_mode_switch_passes_through_dark(void) { nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); nl_engine_set(&red, 0); nl_engine_set(&white, 1000); nl_engine_tick(250); TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); nl_engine_tick(250); TEST_ASSERT_EQUAL_UINT16(0, cur().bri); TEST_ASSERT_EQUAL_INT(0, sum()); nl_engine_tick(250); TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); nl_engine_tick(250); TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); TEST_ASSERT_TRUE(nl_engine_idle()); } static void test_leftover_time_carries_into_next_segment(void) { nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); nl_engine_set(&red, 0); nl_engine_set(&white, 1000); nl_engine_tick(750); TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); } static void test_new_target_starts_from_current_value(void) { nl_light_state_t full = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); nl_light_state_t dim = st(true, 20, NL_MODE_WHITE, 0, 0, 0, 2700); nl_engine_set(&full, 1000); nl_engine_tick(500); nl_engine_set(&dim, 1000); nl_engine_tick(500); TEST_ASSERT_EQUAL_UINT16(3500, cur().bri); } static void test_color_interpolates(void) { nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); nl_light_state_t blue = st(true, 100, NL_MODE_COLOR, 0, 0, 255, 2700); nl_engine_set(&red, 0); nl_engine_set(&blue, 1000); nl_engine_tick(500); TEST_ASSERT_INT_WITHIN(1, 128, cur().r); TEST_ASSERT_INT_WITHIN(1, 127, cur().b); } static void test_blink_overrides_and_restores(void) { nl_engine_blink(2); TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); TEST_ASSERT_FALSE(nl_engine_idle()); nl_engine_tick(300); TEST_ASSERT_EQUAL_INT(0, sum()); nl_engine_tick(300); TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); nl_engine_tick(300); TEST_ASSERT_EQUAL_INT(0, sum()); nl_engine_tick(300); TEST_ASSERT_EQUAL_INT(0, sum()); /* back to the (dark) state */ TEST_ASSERT_TRUE(nl_engine_idle()); } static void test_pulse(void) { nl_engine_pulse(true); uint8_t low = last[NL_CH_WW]; TEST_ASSERT_TRUE(low > 0); nl_engine_tick(1500); TEST_ASSERT_TRUE(last[NL_CH_WW] > low); TEST_ASSERT_FALSE(nl_engine_idle()); nl_engine_pulse(false); TEST_ASSERT_EQUAL_INT(0, sum()); TEST_ASSERT_TRUE(nl_engine_idle()); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_init_is_dark_and_idle); RUN_TEST(test_instant_set); RUN_TEST(test_fade_in_is_linear_in_brightness); RUN_TEST(test_fade_out_keeps_current_color); RUN_TEST(test_mode_switch_passes_through_dark); RUN_TEST(test_leftover_time_carries_into_next_segment); RUN_TEST(test_new_target_starts_from_current_value); RUN_TEST(test_color_interpolates); RUN_TEST(test_blink_overrides_and_restores); RUN_TEST(test_pulse); return UNITY_END(); }