/* * Copyright (c) 2021, Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #define PIXEL_BIT(idx, val) (val ? BIT(idx) : 0) #define PIXEL_MASK(...) (FOR_EACH_IDX(PIXEL_BIT, (|), __VA_ARGS__)) static struct display_capabilities caps; static uint8_t buf[5]; static const struct display_buffer_descriptor buf_desc = { .buf_size = sizeof(buf), .width = 5, .height = 5, .pitch = 8, }; static void update_block_3x3(const struct device *dev) { int ret; static const uint8_t small_bufs[][2] = { { PIXEL_MASK(0, 1, 0) | PIXEL_MASK(0, 1, 0) << 4, PIXEL_MASK(0, 1, 0) }, { PIXEL_MASK(0, 0, 1) | PIXEL_MASK(0, 1, 0) << 4, PIXEL_MASK(1, 0, 0) }, { PIXEL_MASK(0, 0, 0) | PIXEL_MASK(1, 1, 1) << 4, PIXEL_MASK(0, 0, 0) }, { PIXEL_MASK(1, 0, 0) | PIXEL_MASK(0, 1, 0) << 4, PIXEL_MASK(0, 0, 1) }, }; static const struct display_buffer_descriptor small_buf_desc = { .buf_size = sizeof(small_bufs[0]), .width = 3, .height = 3, .pitch = 4, }; for (int i = 0; i < 4 * ARRAY_SIZE(small_bufs); ++i) { k_sleep(K_MSEC(100)); ret = display_write(dev, 1, 1, &small_buf_desc, small_bufs[i % 4]); if (ret < 0) { printk("display_write failed: %u/%d\n", __LINE__, ret); } } } static void update_block_5x5(const struct device *dev) { int ret; buf[0] = PIXEL_MASK(0, 0, 0, 0, 1); buf[1] = PIXEL_MASK(0, 0, 0, 1, 1); buf[2] = PIXEL_MASK(0, 0, 1, 1, 1); buf[3] = PIXEL_MASK(0, 1, 1, 1, 1); buf[4] = PIXEL_MASK(1, 1, 1, 1, 1); ret = display_write(dev, 0, 0, &buf_desc, buf); if (ret < 0) { printk("display_write failed: %u/%d\n", __LINE__, ret); } for (int i = 0; i < 4 * 5; ++i) { uint8_t tmp; k_sleep(K_MSEC(100)); tmp = buf[0]; buf[0] = buf[1]; buf[1] = buf[2]; buf[2] = buf[3]; buf[3] = buf[4]; buf[4] = tmp; ret = display_write(dev, 0, 0, &buf_desc, buf); if (ret < 0) { printk("display_write failed: %u/%d\n", __LINE__, ret); } } } static void show_all_brightness_levels(const struct device *dev) { int ret; uint8_t brightness = 0; do { --brightness; ret = display_set_brightness(dev, brightness); if (ret < 0) { printk("display_set_brightness failed: %u/%d\n", __LINE__, ret); } k_sleep(K_MSEC(5)); } while (brightness); } static void update_through_framebuffer(const struct device *dev) { uint8_t *framebuf = display_get_framebuffer(dev); uint8_t dimmed = 0; bool inc = false; enum { MIN_BRIGHTNESS = 0x0F, BLOCK_SIZE = 5, STEPS = BLOCK_SIZE - 1, RUNS = 4 }; if (!framebuf) { printk("frame buffer not available\n"); return; } /* Clear screen. */ memset(framebuf, 0, caps.x_resolution * caps.y_resolution); for (int i = 0; i < 1 + 3 * RUNS * STEPS; ++i) { k_sleep(K_MSEC(100)); for (uint8_t column = 0; column < BLOCK_SIZE; ++column) { for (uint8_t row = 0; row < BLOCK_SIZE; ++row) { uint8_t diff; uint8_t step = (0xFF - MIN_BRIGHTNESS) / STEPS; /* * Depending on the iteration, use different * pixel values for: * - vertical lines */ if (i < 1 * RUNS * STEPS) { diff = dimmed > column ? dimmed - column : column - dimmed; /* * - horizontal lines */ } else if (i < 2 * RUNS * STEPS) { diff = dimmed > row ? dimmed - row : row - dimmed; /* * - diagonal lines */ } else { uint8_t dist = column + row; diff = 2 * dimmed > dist ? 2 * dimmed - dist : dist - 2 * dimmed; step /= 2; } framebuf[column + row * caps.x_resolution] = MIN_BRIGHTNESS + diff * step; } } if (dimmed == 0 || dimmed == STEPS) { inc = !inc; } if (inc) { ++dimmed; } else { --dimmed; } } } int main(void) { printk("nRF LED matrix sample on %s\n", CONFIG_BOARD); int ret; const struct device *const dev = DEVICE_DT_GET_ONE(nordic_nrf_led_matrix); if (!dev) { printk("Display device not ready\n"); return 0; } display_get_capabilities(dev, &caps); if (!(caps.supported_pixel_formats & PIXEL_FORMAT_MONO01)) { printk("Expected pixel format not supported\n"); return 0; } ret = display_set_pixel_format(dev, PIXEL_FORMAT_MONO01); if (ret < 0) { printk("display_set_pixel_format failed: %u/%d\n", __LINE__, ret); } printk("Started\n"); for (;;) { ret = display_set_brightness(dev, 0x7F); if (ret < 0) { printk("display_set_brightness failed: %u/%d\n", __LINE__, ret); } buf[0] = PIXEL_MASK(1, 0, 1, 0, 1); buf[1] = PIXEL_MASK(1, 1, 0, 0, 1); buf[2] = PIXEL_MASK(1, 0, 1, 0, 1); buf[3] = PIXEL_MASK(1, 0, 0, 1, 1); buf[4] = PIXEL_MASK(1, 0, 1, 0, 1); ret = display_write(dev, 0, 0, &buf_desc, buf); if (ret < 0) { printk("display_write failed: %u/%d\n", __LINE__, ret); } ret = display_blanking_off(dev); if (ret < 0) { printk("display_blanking_off failed: %u/%d\n", __LINE__, ret); } k_sleep(K_MSEC(500)); update_block_3x3(dev); k_sleep(K_MSEC(500)); update_block_5x5(dev); k_sleep(K_MSEC(200)); ret = display_blanking_on(dev); if (ret < 0) { printk("display_blanking_on failed: %u/%d\n", __LINE__, ret); } k_sleep(K_MSEC(500)); ret = display_blanking_off(dev); if (ret < 0) { printk("display_blanking_off failed: %u/%d\n", __LINE__, ret); } k_sleep(K_MSEC(500)); show_all_brightness_levels(dev); update_through_framebuffer(dev); k_sleep(K_MSEC(500)); } return 0; }