CovidBracelet/src/display_pinetime.c

153 lines
4.4 KiB
C

/*
* Copyright (c) 2021 Tobias Schramm <t.schramm@t-sys.eu>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef PLATFORM_PINETIME
#include <device.h>
#include <display/cfb.h>
#include <drivers/gpio.h>
#include <u8x8.h>
#include "display_pinetime.h"
#define BACKLIGHT_LOW_OF_NODE DT_ALIAS(led0)
#define BACKLIGHT_MID_OF_NODE DT_ALIAS(led1)
#define BACKLIGHT_HI_OF_NODE DT_ALIAS(led2)
// dev and flags are the same for all backlight GPIOs
#define BACKLIGHT_DEVNAME DT_GPIO_LABEL(BACKLIGHT_LOW_OF_NODE, gpios)
#define BACKLIGHT_FLAGS (DT_GPIO_FLAGS(BACKLIGHT_LOW_OF_NODE, gpios) | GPIO_OUTPUT)
#define BACKLIGHT_LOW_PIN DT_GPIO_PIN(BACKLIGHT_LOW_OF_NODE, gpios)
#define BACKLIGHT_MID_PIN DT_GPIO_PIN(BACKLIGHT_MID_OF_NODE, gpios)
#define BACKLIGHT_HI_PIN DT_GPIO_PIN(BACKLIGHT_HI_OF_NODE, gpios)
static struct {
const struct device *display_dev;
const struct device *backlight_dev;
} pinetime_display;
static const u8x8_display_info_t pinetime_display_info = {
// Tile setup for u8x8
.tile_width = 240 / 8,
.tile_height = 240 / 8,
// Pixel setup for u8g2
.pixel_width = 240,
.pixel_height = 240,
};
static uint16_t tile_tmp[8 * 8];
// Represents a single u8x8 tile
const struct display_buffer_descriptor buffer_desc = {
.buf_size = sizeof(tile_tmp),
.width = 8,
.height = 8,
.pitch = 8
};
uint8_t u8x8_cmd_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
u8x8_tile_t *tile;
int i, x, y;
switch(msg) {
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &pinetime_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
tile = ((u8x8_tile_t *)arg_ptr);
uint8_t *tile_ptr = tile->tile_ptr;
for (i = 0; i < tile->cnt; i++) {
int rep = 0;
for (x = 0; x < 8; x++) {
uint8_t byte = *tile_ptr++;
for (y = 0; y < 8; y++) {
tile_tmp[x + y * 8] = (byte & (1 << y)) ? 0xffff : 0;
}
}
while (rep < arg_int) {
display_write(pinetime_display.display_dev, (tile->x_pos + i + rep) * 8, tile->y_pos * 8, &buffer_desc, tile_tmp);
rep++;
}
}
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if (arg_int) {
display_blanking_on(pinetime_display.display_dev);
} else {
display_blanking_off(pinetime_display.display_dev);
}
}
return 1;
}
static u8x8_t u8x8;
void pinetime_display_set_brightness(const uint8_t brightness) {
// Parse 3 MSB only
gpio_pin_set(pinetime_display.backlight_dev, BACKLIGHT_HI_PIN, brightness & 0x80);
gpio_pin_set(pinetime_display.backlight_dev, BACKLIGHT_MID_PIN, brightness & 0x40);
gpio_pin_set(pinetime_display.backlight_dev, BACKLIGHT_LOW_PIN, brightness & 0x20);
}
int pinetime_display_init() {
int err;
// Get display device
pinetime_display.display_dev = device_get_binding("ST7789V");
if (!pinetime_display.display_dev) {
return -ENODEV;
}
pinetime_display.backlight_dev = device_get_binding(BACKLIGHT_DEVNAME);
if (!pinetime_display.backlight_dev) {
return -ENODEV;
}
// Initialize backlight GPIOs
err = gpio_pin_configure(pinetime_display.backlight_dev, BACKLIGHT_LOW_PIN, BACKLIGHT_FLAGS);
if (err) {
return err;
}
err = gpio_pin_configure(pinetime_display.backlight_dev, BACKLIGHT_MID_PIN, BACKLIGHT_FLAGS);
if (err) {
return err;
}
err = gpio_pin_configure(pinetime_display.backlight_dev, BACKLIGHT_HI_PIN, BACKLIGHT_FLAGS);
if (err) {
return err;
}
pinetime_display_set_brightness(0);
// Set up graphics library
// Populate all hardware callbacks with dummy functions, we do already have a driver
u8x8_Setup(&u8x8, u8x8_cmd_cb, u8x8_dummy_cb, u8x8_dummy_cb, u8x8_dummy_cb);
u8x8_InitDisplay(&u8x8);
u8x8_ClearDisplay(&u8x8);
u8x8_SetPowerSave(&u8x8, true);
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_f);
return 0;
}
void pinetime_display_draw_string(uint8_t x, uint8_t y, const char *str) {
u8x8_DrawString(&u8x8, x, y, str);
}
void pinetime_display_set_powersave(bool powersave) {
u8x8_SetPowerSave(&u8x8, false);
if (powersave) {
pinetime_display_set_brightness(0);
}
}
#endif