blob: 26eeb8bfa3aa1775fb1fdbfb215134fba06b67dc [file] [log] [blame]
/*
* Copyright (c) 2021, Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/display.h>
#include <string.h>
#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;
}
}
}
void main(void)
{
printk("nRF LED matrix sample on %s\n", CONFIG_BOARD);
int ret;
const struct device *dev = DEVICE_DT_GET_ONE(nordic_nrf_led_matrix);
if (!dev) {
printk("Display device not ready\n");
return;
}
display_get_capabilities(dev, &caps);
if (!(caps.supported_pixel_formats & PIXEL_FORMAT_MONO01)) {
printk("Expected pixel format not supported\n");
return;
}
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));
}
}