Viertes Analog-Profil neben den SM2135EH-Lampen: PWM-Kanaele R=PB13 (ch1), G=PB16 (ch2), B=PB15 (ch3) bei 800 Hz, PIN-belegt aus der Original-Firmware (qcl_build_config_lamp.h, HARDWARE_MOBL_LED_SHIELD). Kein CW/WW-Zweig: ct_min == ct_max ist das Erkennungszeichen fuer 'weiss = RGB-Mischung', nl_color.c gibt in diesem Fall alle drei Farbkanalgleich. Neues Bauziel in allen Skripten; test_release zaehlt Dateizahlen jetzt aus TARGETS statt hart 8/16.
130 lines
4.3 KiB
C
130 lines
4.3 KiB
C
#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_rgb_only_white_mode(void)
|
|
{
|
|
uint8_t ch[NL_CH_COUNT];
|
|
/* ct_min == ct_max: RGB-only board, white = equal RGB mix, no division. */
|
|
nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 4000);
|
|
nl_visual_to_channels(&v, 4000, 4000, ch);
|
|
TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_R]);
|
|
TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_G]);
|
|
TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_B]);
|
|
TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]);
|
|
TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]);
|
|
v.bri = 100; /* 1 % stays visible */
|
|
nl_visual_to_channels(&v, 4000, 4000, ch);
|
|
TEST_ASSERT_EQUAL_UINT8(1, ch[NL_CH_R]);
|
|
}
|
|
|
|
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_rgb_only_white_mode);
|
|
RUN_TEST(test_zero_brightness_is_dark);
|
|
return UNITY_END();
|
|
}
|