#include "unity.h" #include "light/nl_color.h" void setUp(void) {} void tearDown(void) {} static nl_visual_t vis(uint16_t bri, nl_light_mode_t mode, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) { nl_visual_t v = {bri, mode, r, g, b, ct}; return v; } static void test_cie_endpoints(void) { TEST_ASSERT_EQUAL_UINT16(0, nl_cie_level(0)); TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(10000)); TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(12000)); TEST_ASSERT_UINT16_WITHIN(1, 73, nl_cie_level(100)); /* 1 % -> L=1 -> Y=1/903.3 */ TEST_ASSERT_UINT16_WITHIN(3, 12071, nl_cie_level(5000)); /* 50 % -> ((66/116)^3) */ } static void test_cie_monotonic(void) { uint16_t prev = 0; for (uint16_t b = 1; b <= 10000; b++) { uint16_t v = nl_cie_level(b); TEST_ASSERT_TRUE(v >= prev); TEST_ASSERT_TRUE(v > 0); prev = v; } } static void test_ct_fraction(void) { TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2700, 2700, 6500)); TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2000, 2700, 6500)); TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(6500, 2700, 6500)); TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(9000, 2700, 6500)); /* mired midpoint of 2700 K (370.4) and 6500 K (153.8) is 262.1 mired = 3815 K */ TEST_ASSERT_UINT16_WITHIN(400, 32768, nl_ct_cw_fraction(3815, 2700, 6500)); } static void test_white_endpoints(void) { uint8_t ch[NL_CH_COUNT]; nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 2700); nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_WW]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); v.ct = 6500; nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_CW]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); } static void test_white_mix_keeps_total(void) { uint8_t ch[NL_CH_COUNT]; nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 3815); nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_UINT8_WITHIN(3, 128, ch[NL_CH_CW]); TEST_ASSERT_INT_WITHIN(1, 255, ch[NL_CH_CW] + ch[NL_CH_WW]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_R]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_G]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); } static void test_color_mode(void) { uint8_t ch[NL_CH_COUNT]; nl_visual_t v = vis(10000, NL_MODE_COLOR, 255, 120, 0, 2700); nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_R]); TEST_ASSERT_UINT8_WITHIN(1, 120, ch[NL_CH_G]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); } static void test_one_percent_is_visible(void) { uint8_t ch[NL_CH_COUNT]; nl_visual_t v = vis(100, NL_MODE_COLOR, 255, 0, 0, 2700); nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_EQUAL_UINT8(1, ch[NL_CH_R]); v = vis(100, NL_MODE_WHITE, 0, 0, 0, 3000); nl_visual_to_channels(&v, 2700, 6500, ch); TEST_ASSERT_EQUAL_INT(1, ch[NL_CH_CW] + ch[NL_CH_WW]); } static void test_zero_brightness_is_dark(void) { uint8_t ch[NL_CH_COUNT]; nl_visual_t v = vis(0, NL_MODE_COLOR, 255, 255, 255, 2700); nl_visual_to_channels(&v, 2700, 6500, ch); for (int i = 0; i < NL_CH_COUNT; i++) TEST_ASSERT_EQUAL_UINT8(0, ch[i]); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_cie_endpoints); RUN_TEST(test_cie_monotonic); RUN_TEST(test_ct_fraction); RUN_TEST(test_white_endpoints); RUN_TEST(test_white_mix_keeps_total); RUN_TEST(test_color_mode); RUN_TEST(test_one_percent_is_visible); RUN_TEST(test_zero_brightness_is_dark); return UNITY_END(); }