PicoVector: C++ basic bringup.

unicorn-test
Phil Howard 2024-06-11 14:39:06 +01:00 zatwierdzone przez Phil Howard
rodzic 5457b99ae3
commit 1813eaafe2
14 zmienionych plików z 207 dodań i 230 usunięć

3
.gitmodules vendored
Wyświetl plik

@ -25,6 +25,3 @@
[submodule "drivers/mlx90640/src"]
path = drivers/mlx90640/src
url = https://github.com/melexis/mlx90640-library
[submodule "libraries/pico_vector/pretty_poly"]
path = libraries/pico_vector/pretty_poly
url = https://github.com/lowfatcode/pretty-poly/

Wyświetl plik

@ -1,14 +1,3 @@
add_subdirectory(mandelbrot)
set(OUTPUT_NAME pico_display2_demo)
add_executable(
${OUTPUT_NAME}
pico_display_2_demo.cpp
)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})
include(pico_display_2_demo.cmake)
include(pico_display_2_vector.cmake)

Wyświetl plik

@ -0,0 +1,10 @@
add_executable(
pico_display_2_demo
pico_display_2_demo.cpp
)
# Pull in pico libraries that we need
target_link_libraries(pico_display_2_demo pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
# create map/bin/hex file etc.
pico_add_extra_outputs(pico_display_2_demo)

Wyświetl plik

@ -0,0 +1,41 @@
function(static_asset NAME PATH)
get_filename_component(PATH ${PATH} ABSOLUTE)
get_filename_component(ASSET ${PATH} NAME)
get_filename_component(PATH ${PATH} DIRECTORY)
set(OBJNAME ${ASSET}.o)
add_custom_command(OUTPUT ${OBJNAME}
DEPENDS ${PATH}/${ASSET}
COMMENT "Building ${OBJNAME}"
WORKING_DIRECTORY "${PATH}"
COMMAND ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${ASSET}
COMMAND ${CMAKE_OBJDUMP} -t ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME}
)
# TODO figure out how to make static resources work
## COMMAND ${CMAKE_OBJCOPY} --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME})
target_sources(${NAME} PRIVATE ${OBJNAME})
endfunction()
add_executable(
pico_display_2_vector
pico_display_2_vector.cpp
)
# Pull in pico libraries that we need
target_link_libraries(pico_display_2_vector
pico_stdlib
hardware_spi
hardware_pwm
hardware_dma
pico_display_2
st7789
pico_graphics
pico_vector
)
static_asset(pico_display_2_vector ${CMAKE_CURRENT_LIST_DIR}/vector/DynaPuff-Medium.af)
pico_enable_stdio_usb(pico_display_2_vector 0)
pico_enable_stdio_uart(pico_display_2_vector 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(pico_display_2_vector)

Wyświetl plik

@ -0,0 +1,66 @@
#include <string.h>
#include <math.h>
#include <vector>
#include <cstdlib>
#include "libraries/pico_display_2/pico_display_2.hpp"
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "libraries/pico_vector/pico_vector.hpp"
using namespace pimoroni;
ST7789 st7789(320, 240, ROTATE_180, false, get_spi_pins(BG_SPI_FRONT));
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);
uint8_t vector_mem[PicoVector::pretty_poly_buffer_size()];
PicoVector vector(&graphics);
extern char _binary_DynaPuff_Medium_af_start[];
extern size_t _binary_DynaPuff_Medium_af_size;
int main() {
stdio_init_all();
Pen BG = graphics.create_pen(120, 40, 60);
Pen TEXT = graphics.create_pen(255, 255, 255);
st7789.set_backlight(255);
vector.set_font(_binary_DynaPuff_Medium_af_start, 30);
unsigned int a = 0;
while (true) {
Point text_location(0, 0);
graphics.set_pen(BG);
graphics.clear();
graphics.set_pen(TEXT);
graphics.text("Hello World", text_location, 320);
pp_point_t outline[] = {{-64, -64}, {64, -64}, {64, 64}, {-64, 64}};
pp_point_t hole[] = {{ -32, 32}, { 32, 32}, { 32, -32}, { -32, -32}};
pp_path_t paths[] = {
{.points = outline, .count = 4},
{.points = hole, .count = 4}
};
pp_poly_t poly = {.paths = paths, .count = 2};
pp_mat3_t pos = pp_mat3_identity();
pp_mat3_translate(&pos, 50, 50);
pp_mat3_rotate(&pos, a);
vector.draw(&poly);
vector.text("Hello World", &pos);
// update screen
st7789.update(&graphics);
a += 1;
if (a > 359) {
a = 0;
}
}
return 0;
}

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,36 @@
#include "af-file-io.h"
#include "string.h"
static size_t ptr = 0;
void* fileio_open(const char* filename) {
ptr = 0;
return NULL;
}
void fileio_close(void* fhandle) {
ptr = 0;
return;
}
size_t fileio_read(void* fhandle, void *buf, size_t len) {
memcpy(buf, fhandle + ptr, len);
ptr += len;
return len;
}
int fileio_getc(void* fhandle) {
uint8_t *f = fhandle;
int c = f[ptr];
ptr += 1;
return c;
}
size_t fileio_tell(void* fhandle) {
return ptr;
}
size_t fileio_seek(void* fhandle, size_t pos) {
ptr = pos;
return ptr;
}

Wyświetl plik

@ -1,7 +1,9 @@
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void* fileio_open(const char* filename);
void fileio_close(void* fhandle);
@ -13,4 +15,6 @@ int fileio_getc(void* fhandle);
size_t fileio_tell(void* fhandle);
size_t fileio_seek(void* fhandle, size_t pos);
}
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,24 @@
#include "af-memory.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void *af_malloc(size_t size) {
return malloc(size);
}
void *af_realloc(void *p, size_t size) {
return realloc(p, size);
}
void af_free(void *p) {
free(p);
}
void af_debug(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = printf(fmt, ap);
va_end(ap);
(void)ret;
}

Wyświetl plik

@ -1,6 +1,12 @@
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *af_malloc(size_t size);
void *af_realloc(void *p, size_t size);
void af_free(void *p);
void af_debug(const char *fmt, ...);
}
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,136 +0,0 @@
#include <cstdint>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <optional>
#include <map>
#include "alright_fonts.hpp"
namespace alright_fonts {
/*
utility functions
*/
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint) {
if(tm.face.glyphs.count(codepoint) == 1) {
glyph_t glyph = tm.face.glyphs[codepoint];
return {0, 0, ((glyph.advance * tm.size) / 128), tm.size};
}
return {0, 0, 0, 0};
}
/*
render functions
*/
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform) {
if(tm.face.glyphs.count(codepoint) == 1) {
glyph_t glyph = tm.face.glyphs[codepoint];
pp_transform(transform);
pp_render(&glyph.contours);
}
}
/*
load functions
*/
// big endian stream value helpers
uint16_t ru16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
int16_t rs16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
uint32_t ru32(file_io &ifs) {uint8_t dw[4]; ifs.read((char *)dw, 4); return dw[0] << 24 | dw[1] << 16 | dw[2] << 8 | dw[3];}
uint8_t ru8(file_io &ifs) {uint8_t w; ifs.read(&w, 1); return w;}
int8_t rs8(file_io &ifs) {int8_t w; ifs.read(&w, 1); return w;}
bool face_t::load(file_io &ifs) {
char marker[4];
ifs.read(marker, sizeof(marker));
// check header magic bytes are present
if(memcmp(marker, "af!?", 4) != 0) {
// doesn't start with magic marker
return false;
}
// number of glyphs embedded in font file
this->glyph_count = ru16(ifs);
// extract flags and ensure none set
this->flags = ru16(ifs);
if(this->flags != 0) {
// unknown flags set
return false;
}
// extract glyph dictionary
uint16_t glyph_entry_size = 9;
uint32_t contour_data_offset = 8 + this->glyph_count * glyph_entry_size;
for(auto i = 0; i < this->glyph_count; i++) {
glyph_t g;
g.codepoint = ru16(ifs);
g.bounds.x = rs8(ifs);
g.bounds.y = rs8(ifs);
g.bounds.w = ru8(ifs);
g.bounds.h = ru8(ifs);
g.advance = ru8(ifs);
g.contours.paths = (pp_path_t *)malloc(sizeof(pp_path_t) * 10);
if(ifs.fail()) {
// could not read glyph dictionary entry
return false;
}
// allocate space for the contour data and read it from the font file
uint16_t contour_data_length = ru16(ifs);
// remember where we are in the dictionary
int pos = ifs.tell();
// read contour data
ifs.seek(contour_data_offset);
while(true) {
// get number of points in contour
uint16_t count = ru16(ifs);
// if count is zero then this is the end of contour marker
if(count == 0) {
break;
}
// allocate space to store point data for contour and read
// from file
g.contours.paths[g.contours.count].points = (pp_point_t *)malloc(sizeof(pp_point_t) * count);
ifs.read((char *)g.contours.paths[g.contours.count].points, sizeof(pp_point_t) * count);
g.contours.count ++;
}
// return back to position in dictionary
ifs.seek(pos);
contour_data_offset += contour_data_length;
if(ifs.fail()) {
// could not read glyph contour data
return false;
}
this->glyphs[g.codepoint] = g;
}
return true;
}
bool face_t::load(std::string_view path) {
file_io ifs(path);
if(ifs.fail()) {
// could not open file
return false;
}
return load(ifs);
}
}

Wyświetl plik

@ -1,74 +0,0 @@
#include <cstdint>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <optional>
#include <map>
#include "pretty-poly.h"
#include "file_io.hpp"
namespace alright_fonts {
struct glyph_t {
uint16_t codepoint;
pp_rect_t bounds;
uint8_t advance;
pp_poly_t contours;
};
struct face_t {
uint16_t glyph_count;
uint16_t flags;
std::map<uint16_t, glyph_t> glyphs;
face_t() {};
face_t(file_io &ifs) {load(ifs);}
face_t(std::string_view path) {load(path);}
bool load(file_io &ifs);
bool load(std::string_view path);
};
enum alignment_t {
left = 0,
center = 1,
right = 2,
justify = 4,
top = 8,
bottom = 16
};
struct text_metrics_t {
face_t face; // font to write in
int size; // text size in pixels
uint scroll; // vertical scroll offset
int line_height; // spacing between lines (%)
int letter_spacing; // spacing between characters
int word_spacing; // spacing between words
alignment_t align; // horizontal and vertical alignment
//optional<mat3_t> transform; // arbitrary transformation
pp_antialias_t antialiasing = PP_AA_X4; // level of antialiasing to apply
void set_size(int s) {
size = s;
line_height = size;
letter_spacing = 0;
word_spacing = size / 2;
}
text_metrics_t() {};
};
/*
utility functions
*/
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint);
/*
render functions
*/
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform);
}

Wyświetl plik

@ -4,7 +4,8 @@ endif()
add_library(pico_vector
${CMAKE_CURRENT_LIST_DIR}/pico_vector.cpp
${CMAKE_CURRENT_LIST_DIR}/alright_fonts.cpp
${CMAKE_CURRENT_LIST_DIR}/af-file-io.c
${CMAKE_CURRENT_LIST_DIR}/af-memory.c
)
target_include_directories(pico_vector INTERFACE ${CMAKE_CURRENT_LIST_DIR})

Wyświetl plik

@ -112,7 +112,20 @@ namespace pimoroni {
return result;
}
pp_point_t text(std::string_view text, pp_mat3_t *t);
bool set_font(void* font, unsigned int font_size) {
if(text_metrics.face) {
af_free(text_metrics.face->glyphs);
af_free(text_metrics.face);
}
text_metrics.face = (af_face_t *)af_malloc(sizeof(af_face_t));
bool result = af_load_font_file(font, text_metrics.face);
set_font_size(font_size);
return result;
}
pp_point_t text(std::string_view text, pp_mat3_t *t=nullptr);
void transform(pp_path_t *path, pp_mat3_t *t);
void transform(pp_poly_t *poly, pp_mat3_t *t);