PicoExplorer library and example, basic text support for PicoGraphics

pull/1/head
Jonathan Williamson 2021-01-17 07:41:25 +00:00
rodzic cf92a8c113
commit 96d702ef9a
13 zmienionych plików z 8592 dodań i 5 usunięć

Wyświetl plik

@ -53,7 +53,9 @@ namespace pimoroni {
command(reg::MADCTL, 1, "\x04"); // row/column addressing order - rgb pixel order
command(reg::TEON, 1, "\x00"); // enable frame sync signal if used
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
}else if(width == 240 && height == 135) {
}
if(width == 240 && height == 135) {
command(reg::MADCTL, 1, "\x70");
command(reg::COLMOD, 1, "\x05");
}
@ -68,7 +70,9 @@ namespace pimoroni {
if(width == 240 && height == 240) {
command(reg::CASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 columns
command(reg::RASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 rows
}else if(width == 240 && height == 135) {
}
if(width == 240 && height == 135) {
command(reg::RASET, 4, "\x00\x35\x00\xbb"); // 53 .. 187 (135 rows)
command(reg::CASET, 4, "\x00\x28\x01\x17"); // 40 .. 279 (240 columns)
}

Wyświetl plik

@ -1,3 +1,4 @@
add_subdirectory(pico_display)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_scroll)
add_subdirectory(pico_scroll)
add_subdirectory(pico_explorer)

Wyświetl plik

@ -0,0 +1,10 @@
add_executable(
explorer
demo.cpp
)
# Pull in pico libraries that we need
target_link_libraries(explorer pico_stdlib pico_explorer)
# create map/bin/hex file etc.
pico_add_extra_outputs(explorer)

Wyświetl plik

@ -0,0 +1,170 @@
#include <string.h>
#include <math.h>
#include <vector>
#include <cstdlib>
#include "pico_explorer.hpp"
using namespace pimoroni;
extern unsigned char image_tif[];
extern unsigned int image_tif_len;
PicoExplorer pico_explorer;
/*
void pixel(int x, int y, uint16_t c) {
x *= 2;
y *= 2;
pico_display.frame_buffer[x + y * 240] = c;
pico_display.frame_buffer[x + 1 + y * 240] = c;
pico_display.frame_buffer[x + 1 + (y + 1) * 240] = c;
pico_display.frame_buffer[x + (y + 1) * 240] = c;
}
void rect(int x, int y, int w, int h, uint16_t c) {
for(int rx = x; rx < x + w; rx++) {
for(int ry = y; ry < y + h; ry++) {
pixel(rx, ry, c);
}
}
}*/
uint8_t arrow[] = {
0b00010000,
0b00110000,
0b01110000,
0b11111111,
0b11111111,
0b01110000,
0b00110000,
0b00010000
};
uint8_t tick[] = {
0b00000000,
0b00000010,
0b00000111,
0b01001110,
0b11111100,
0b00111000,
0b00010000,
0b00000000,
};
/*
void sprite(uint8_t *p, int x, int y, bool flip, uint16_t c) {
for(int ay = 0; ay < 8; ay++) {
uint8_t sl = p[ay];
for(int ax = 0; ax < 8; ax++) {
if(flip) {
if((0b10000000 >> ax) & sl) {
pixel(ax + x, ay + y, c);
}
}else{
if((0b1 << ax) & sl) {
pixel(ax + x, ay + y, c);
}
}
}
}
}*/
int main() {
pico_explorer.set_backlight(100);
// uint16_t white = pico_display.create_pen(255, 255, 255);
// uint16_t black = pico_display.create_pen(0, 0, 0);
// uint16_t red = pico_display.create_pen(255, 0, 0);
// uint16_t green = pico_display.create_pen(0, 255, 0);
// uint16_t dark_grey = pico_display.create_pen(20, 40, 60);
// uint16_t dark_green = pico_display.create_pen(10, 100, 10);
// uint16_t blue = pico_display.create_pen(0, 0, 255);
bool a_pressed = false;
bool b_pressed = false;
bool x_pressed = false;
bool y_pressed = false;
struct pt {
float x;
float y;
uint8_t r;
float dx;
float dy;
uint16_t pen;
};
std::vector<pt> shapes;
for(int i = 0; i < 100; i++) {
pt shape;
shape.x = rand() % 240;
shape.y = rand() % 135;
shape.r = (rand() % 10) + 3;
shape.dx = float(rand() % 255) / 128.0f;
shape.dy = float(rand() % 255) / 128.0f;
shape.pen = pico_explorer.create_pen(rand() % 255, rand() % 255, rand() % 255);
shapes.push_back(shape);
}
uint32_t i = 0;
while(true) {
pico_explorer.set_pen(120, 40, 60);
pico_explorer.rectangle(0, 0, pico_explorer.width, pico_explorer.height);
for(auto &shape : shapes) {
shape.x += shape.dx;
shape.y += shape.dy;
if(shape.x < 0) shape.dx *= -1;
if(shape.x >= pico_explorer.width) shape.dx *= -1;
if(shape.y < 0) shape.dy *= -1;
if(shape.y >= pico_explorer.height) shape.dy *= -1;
pico_explorer.set_pen(shape.pen);
pico_explorer.circle(shape.x, shape.y, shape.r);
}
float led_step = fmod(i / 20.0f, M_PI * 2.0f);
int r = (sin(led_step) * 25.0f) + 25.0f;
pico_explorer.set_led(r, r / 1.2f, r);
pico_explorer.set_pen(255, 255, 255);
pico_explorer.text("This is a test of some text data that should wrap nicely onto multiple lines which is dead useful like.", 10, 10, 180);
/*
if(pico_display.is_pressed(pico_display.A)) {
pico_display.rectangle(0, 0, 18, 18);
//sprite(tick, 5, 5, true, green);
}else{
//sprite(arrow, 10 + bounce, 10, true, white);
}
if(pico_display.is_pressed(pico_display.B)) {
pico_display.rectangle(0, 49, 18, 18);
//sprite(tick, 5, 54, true, green);
}else{
//sprite(arrow, 10 - bounce, 50, true, white);
}
if(pico_display.is_pressed(pico_display.X)) {
pico_display.rectangle(102, 0, 18, 18);
//sprite(tick, 107, 5, true, green);
}else{
//sprite(arrow, 102 - bounce, 10, false, white);
}
if(pico_display.is_pressed(pico_display.Y)) {
pico_display.rectangle(102, 49, 18, 18);
//sprite(tick, 107, 54, true, green);
}else{
//sprite(arrow, 102 + bounce, 50, false, white);
}
*/
// update screen
pico_explorer.update();
i++;
}
return 0;
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,4 +1,5 @@
add_subdirectory(pico_graphics)
add_subdirectory(pico_display)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_scroll)
add_subdirectory(pico_scroll)
add_subdirectory(pico_explorer)

Wyświetl plik

@ -0,0 +1,10 @@
add_library(pico_explorer INTERFACE)
target_sources(pico_explorer INTERFACE
${CMAKE_CURRENT_LIST_DIR}/pico_explorer.cpp
)
target_include_directories(pico_explorer INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(pico_explorer INTERFACE pico_stdlib hardware_pwm hardware_adc st7789 pico_graphics)

Wyświetl plik

@ -0,0 +1,69 @@
#include <math.h>
#include "hardware/pwm.h"
#include "pico_explorer.hpp"
const uint8_t LED_R = 6;
const uint8_t LED_G = 7;
const uint8_t LED_B = 8;
namespace pimoroni {
PicoExplorer::PicoExplorer()
: screen(240, 240, __fb), PicoGraphics(240, 240, __fb) {
// setup the rgb led for pwm control
pwm_config cfg = pwm_get_default_config();
pwm_config_set_output_polarity(&cfg, true, true);
// red
pwm_set_wrap(pwm_gpio_to_slice_num(LED_R), 65535);
pwm_init(pwm_gpio_to_slice_num(LED_R), &cfg, true);
gpio_set_function(LED_R, GPIO_FUNC_PWM);
// green
pwm_set_wrap(pwm_gpio_to_slice_num(LED_G), 65535);
pwm_init(pwm_gpio_to_slice_num(LED_G), &cfg, true);
gpio_set_function(LED_G, GPIO_FUNC_PWM);
// blue
pwm_set_wrap(pwm_gpio_to_slice_num(LED_B), 65535);
pwm_init(pwm_gpio_to_slice_num(LED_B), &cfg, true);
gpio_set_function(LED_B, GPIO_FUNC_PWM);
// setup button inputs
gpio_set_function(A, GPIO_FUNC_SIO); gpio_set_dir(A, GPIO_IN); gpio_pull_up(A);
gpio_set_function(B, GPIO_FUNC_SIO); gpio_set_dir(B, GPIO_IN); gpio_pull_up(B);
gpio_set_function(X, GPIO_FUNC_SIO); gpio_set_dir(X, GPIO_IN); gpio_pull_up(X);
gpio_set_function(Y, GPIO_FUNC_SIO); gpio_set_dir(Y, GPIO_IN); gpio_pull_up(Y);
// initialise the screen
screen.init();
}
void PicoExplorer::set_led(uint8_t r, uint8_t g, uint8_t b) {
// gamma correct the provided 0-255 brightness value onto a
// 0-65535 range for the pwm counter
static const float gamma = 2.8;
uint16_t value;
// red
value = (uint16_t)(pow((float)(r) / 255.0f, gamma) * 65536.0f + 0.5f);
pwm_set_gpio_level(LED_R, value);
// green
value = (uint16_t)(pow((float)(g) / 255.0f, gamma) * 65536.0f + 0.5f);
pwm_set_gpio_level(LED_G, value);
// blue
value = (uint16_t)(pow((float)(b) / 255.0f, gamma) * 65536.0f + 0.5f);
pwm_set_gpio_level(LED_B, value);
}
bool PicoExplorer::is_pressed(uint8_t button) {
return !gpio_get(button);
}
}

Wyświetl plik

@ -0,0 +1,27 @@
#pragma once
#include "../../drivers/st7789/st7789.hpp"
#include "../../libraries/pico_graphics/pico_graphics.hpp"
namespace pimoroni {
class PicoExplorer : public PicoGraphics {
uint16_t __fb[240 * 240];
ST7789 screen;
public:
PicoExplorer();
void set_backlight(uint8_t brightness) {screen.set_backlight(brightness);}
void update() {screen.update();}
void set_led(uint8_t r, uint8_t g, uint8_t b);
bool is_pressed(uint8_t button);
static const uint8_t A = 12;
static const uint8_t B = 13;
static const uint8_t X = 14;
static const uint8_t Y = 15;
};
}

Wyświetl plik

@ -1 +1 @@
add_library(pico_graphics pico_graphics.cpp)
add_library(pico_graphics font_data.cpp pico_graphics.cpp)

Wyświetl plik

@ -0,0 +1,110 @@
#include <cstdint>
uint8_t font_data[96][6] = {
{0x00,0x00,0x00,0x00,0x00,0x00}, //
{0x2e,0x00,0x00,0x00,0x00,0x00}, // !
{0x06,0x00,0x06,0x00,0x00,0x00}, // "
{0x14,0x3e,0x14,0x3e,0x14,0x00}, // #
{0x04,0x2a,0x3e,0x2a,0x10,0x00}, // $
{0x22,0x10,0x08,0x04,0x22,0x00}, // %
{0x14,0x2a,0x2a,0x2c,0x10,0x28}, // &
{0x06,0x00,0x00,0x00,0x00,0x00}, // '
{0x1c,0x22,0x00,0x00,0x00,0x00}, // (
{0x22,0x1c,0x00,0x00,0x00,0x00}, // )
{0x14,0x08,0x14,0x00,0x00,0x00}, // *
{0x08,0x1c,0x08,0x00,0x00,0x00}, // +
{0x60,0x00,0x00,0x00,0x00,0x00}, // ,
{0x08,0x08,0x08,0x00,0x00,0x00}, // -
{0x20,0x00,0x00,0x00,0x00,0x00}, // .
{0x30,0x0c,0x02,0x00,0x00,0x00}, // /
{0x1c,0x22,0x22,0x22,0x1e,0x00}, // 0
{0x02,0x3e,0x00,0x00,0x00,0x00}, // 1
{0x32,0x2a,0x2a,0x24,0x00,0x00}, // 2
{0x2a,0x2a,0x2a,0x16,0x00,0x00}, // 3
{0x0e,0x10,0x10,0x3e,0x10,0x00}, // 4
{0x2e,0x2a,0x2a,0x12,0x00,0x00}, // 5
{0x3c,0x2a,0x2a,0x2a,0x12,0x00}, // 6
{0x06,0x02,0x22,0x12,0x0e,0x00}, // 7
{0x14,0x2a,0x2a,0x2a,0x16,0x00}, // 8
{0x04,0x2a,0x2a,0x2a,0x1e,0x00}, // 9
{0x24,0x00,0x00,0x00,0x00,0x00}, // :
{0x64,0x00,0x00,0x00,0x00,0x00}, // ;
{0x08,0x14,0x22,0x00,0x00,0x00}, // <
{0x14,0x14,0x14,0x00,0x00,0x00}, // =
{0x22,0x14,0x08,0x00,0x00,0x00}, // >
{0x02,0x2a,0x0a,0x04,0x00,0x00}, // ?
{0x3c,0x02,0x1a,0x2a,0x22,0x1e}, // @
{0x3c,0x12,0x12,0x12,0x3e,0x00}, // A
{0x3c,0x2a,0x2a,0x2e,0x10,0x00}, // B
{0x1c,0x22,0x22,0x22,0x00,0x00}, // C
{0x3c,0x22,0x22,0x22,0x1c,0x00}, // D
{0x3c,0x2a,0x2a,0x2a,0x00,0x00}, // E
{0x3c,0x12,0x12,0x12,0x00,0x00}, // F
{0x3c,0x22,0x22,0x2a,0x1a,0x00}, // G
{0x3e,0x08,0x08,0x3e,0x00,0x00}, // H
{0x22,0x3e,0x22,0x00,0x00,0x00}, // I
{0x30,0x22,0x22,0x1e,0x00,0x00}, // J
{0x3e,0x08,0x0c,0x32,0x00,0x00}, // K
{0x3e,0x20,0x20,0x20,0x00,0x00}, // L
{0x3c,0x02,0x3c,0x02,0x3c,0x00}, // M
{0x3c,0x02,0x02,0x02,0x3e,0x00}, // N
{0x1c,0x22,0x22,0x22,0x1e,0x00}, // O
{0x3c,0x12,0x12,0x12,0x0e,0x00}, // P
{0x1c,0x22,0x22,0x62,0x1e,0x00}, // Q
{0x3c,0x12,0x12,0x32,0x0e,0x00}, // R
{0x24,0x2a,0x2a,0x12,0x00,0x00}, // S
{0x02,0x02,0x3e,0x02,0x02,0x00}, // T
{0x1e,0x20,0x20,0x20,0x1e,0x00}, // U
{0x0e,0x10,0x20,0x10,0x0e,0x00}, // V
{0x3e,0x20,0x1e,0x20,0x1e,0x00}, // W
{0x36,0x08,0x08,0x36,0x00,0x00}, // X
{0x26,0x28,0x28,0x1e,0x00,0x00}, // Y
{0x32,0x2a,0x2a,0x26,0x00,0x00}, // Z
{0x3e,0x22,0x00,0x00,0x00,0x00}, // [
{0x02,0x0c,0x30,0x00,0x00,0x00}, // "\"
{0x22,0x3e,0x00,0x00,0x00,0x00}, // ]
{0x04,0x02,0x04,0x00,0x00,0x00}, // ^
{0x20,0x20,0x20,0x00,0x00,0x00}, // _
{0x02,0x04,0x00,0x00,0x00,0x00}, // `
{0x3c,0x12,0x12,0x12,0x3e,0x00}, // a
{0x3c,0x2a,0x2a,0x2e,0x10,0x00}, // b
{0x1c,0x22,0x22,0x22,0x00,0x00}, // c
{0x3c,0x22,0x22,0x22,0x1c,0x00}, // d
{0x3c,0x2a,0x2a,0x2a,0x00,0x00}, // e
{0x3c,0x12,0x12,0x12,0x00,0x00}, // f
{0x3c,0x22,0x22,0x2a,0x1a,0x00}, // g
{0x3e,0x08,0x08,0x3e,0x00,0x00}, // h
{0x22,0x3e,0x22,0x00,0x00,0x00}, // i
{0x30,0x22,0x22,0x1e,0x00,0x00}, // j
{0x3e,0x08,0x0c,0x32,0x00,0x00}, // k
{0x3e,0x20,0x20,0x20,0x00,0x00}, // l
{0x3c,0x02,0x3c,0x02,0x3e,0x00}, // m
{0x3c,0x02,0x02,0x02,0x3e,0x00}, // n
{0x1c,0x22,0x22,0x22,0x1e,0x00}, // o
{0x3c,0x12,0x12,0x12,0x0e,0x00}, // p
{0x1c,0x22,0x22,0x62,0x1e,0x00}, // q
{0x3c,0x12,0x12,0x32,0x0e,0x00}, // r
{0x24,0x2a,0x2a,0x12,0x00,0x00}, // s
{0x02,0x02,0x3e,0x02,0x02,0x00}, // t
{0x1e,0x20,0x20,0x20,0x1e,0x00}, // u
{0x0e,0x10,0x20,0x10,0x0e,0x00}, // v
{0x3e,0x20,0x1e,0x20,0x1e,0x00}, // w
{0x36,0x08,0x08,0x36,0x00,0x00}, // x
{0x26,0x28,0x28,0x1e,0x00,0x00}, // y
{0x32,0x2a,0x2a,0x26,0x00,0x00}, // z
{0x08,0x3e,0x22,0x00,0x00,0x00}, // {
{0x3e,0x00,0x00,0x00,0x00,0x00}, // |
{0x22,0x3e,0x08,0x00,0x00,0x00}, // }
{0x04,0x02,0x02,0x00,0x00,0x00}, // ~
{0x00,0x00,0x00,0x00,0x00,0x00}
};
uint8_t character_widths[96] = {
3, 2, 4, 6, 6, 6, 7, 2, 3, 3, 4, 4, 2, 4, 2, 4,
6, 3, 5, 5, 6, 5, 6, 6, 6, 6, 2, 2, 4, 4, 4, 5,
7, 6, 6, 5, 6, 5, 5, 6, 5, 4, 5, 5, 5, 6, 6, 6,
6, 6, 6, 5, 6, 6, 6, 6, 5, 5, 5, 3, 4, 3, 4, 4,
3, 6, 6, 5, 6, 5, 5, 6, 5, 4, 5, 5, 5, 6, 6, 6,
6, 6, 6, 5, 6, 6, 6, 6, 5, 5, 5, 4, 2, 4, 4, 2
};

Wyświetl plik

@ -1,5 +1,8 @@
#include "pico_graphics.hpp"
extern uint8_t font_data[96][6];
extern uint8_t character_widths[96];
namespace pimoroni {
void PicoGraphics::set_pen(uint8_t r, uint8_t g, uint8_t b) {
@ -88,5 +91,56 @@ namespace pimoroni {
}
}
void PicoGraphics::character(const char c, int32_t x, int32_t y, uint8_t scale) {
uint8_t char_index = c - 32;
const uint8_t *d = &font_data[char_index][0];
for(uint8_t cx = 0; cx < character_widths[char_index]; cx++) {
for(uint8_t cy = 0; cy < 6; cy++) {
if((1U << cy) & *d) {
rectangle(x + (cx * scale), y + (cy * scale), scale, scale);
}
}
d++;
}
}
void PicoGraphics::text(const std::string &t, int32_t x, int32_t y, int32_t wrap) {
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
uint8_t scale = 2;
size_t i = 0;
while(i < t.length()) {
// find length of current word
size_t next_space = t.find(' ', i + 1);
if(next_space == std::string::npos) {
next_space = t.length();
}
uint16_t word_length = 0;
for(size_t j = i; j < next_space; j++) {
word_length += character_widths[t[j] - 32];
}
// if this word would exceed the wrap limit then
// move to the next line
if(co + word_length > wrap) {
co = 0;
lo += 7 * scale;
}
// draw word
for(size_t j = i; j < next_space; j++) {
character(t[j], x + co, y + lo, scale);
co += character_widths[t[j] - 32] * scale;
}
// move character offset to end of word and add a space
co += character_widths[0] * scale;
i = next_space + 1;
}
}
}

Wyświetl plik

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <string>
// a tiny little graphics library for our Pico products
// supports only 16-bit (565) RGB framebuffers
@ -27,6 +28,8 @@ namespace pimoroni {
void pixel_span(int32_t x, int32_t y, int32_t l);
void rectangle(int32_t x, int32_t y, int32_t w, int32_t h);
void circle(int32_t x, int32_t y, int32_t r);
void text(const std::string &t, int32_t x, int32_t y, int32_t wrap);
void character(const char c, int32_t x, int32_t y, uint8_t scale);
//void polygon(std::vector);
};