ssd1306 more functions (#310)

SSD1306 2D drawing/text functions, new example, builtin fonts support
This commit is contained in:
Zaltora 2016-12-13 14:42:23 +01:00 committed by Ruslan V. Uss
parent 61c3d509e5
commit 7432c019f7
39 changed files with 145365 additions and 5 deletions

View file

@ -3,6 +3,7 @@
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <timers.h>
#include <string.h>
#include <ssd1306/ssd1306.h>
@ -45,6 +46,11 @@ static const ssd1306_t dev = {
/* Local frame buffer */
static uint8_t buffer[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8];
TimerHandle_t scrol_timer_handle = NULL; // Timer handler
#define SECOND (1000 / portTICK_PERIOD_MS)
static void ssd1306_task(void *pvParameters)
{
@ -58,7 +64,7 @@ static void ssd1306_task(void *pvParameters)
ssd1306_set_whole_display_lighting(&dev, false);
bool fwd = false;
while (1) {
vTaskDelay(2000 / portTICK_PERIOD_MS);
vTaskDelay(2*SECOND);
printf("%s: still alive, flipping!\n", __FUNCTION__);
ssd1306_set_scan_direction_fwd(&dev, fwd);
fwd = !fwd;
@ -67,11 +73,22 @@ static void ssd1306_task(void *pvParameters)
error_loop:
printf("%s: error while loading framebuffer into SSD1306\n", __func__);
for(;;){
vTaskDelay(2000 / portTICK_PERIOD_MS);
vTaskDelay(2*SECOND);
printf("%s: error loop\n", __FUNCTION__);
}
}
void scrolling_timer(TimerHandle_t h)
{
static bool scrol = true ;
if(scrol)
ssd1306_start_scroll_hori(&dev, false, 0, 7, FRAME_25);
else
ssd1306_stop_scroll(&dev);
printf("Scrolling status: %s\n", (scrol)? "On" : "Off");
scrol=!scrol ;
}
void user_init(void)
{
// Setup HW
@ -86,11 +103,16 @@ void user_init(void)
while (ssd1306_init(&dev) != 0)
{
printf("%s: failed to init SSD1306 lcd\n", __func__);
vTaskDelay(1000/portTICK_PERIOD_MS);
vTaskDelay(SECOND);
}
ssd1306_set_whole_display_lighting(&dev, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
vTaskDelay(SECOND);
// Create user interface task
xTaskCreate(ssd1306_task, "ssd1306_task", 256, NULL, 2, NULL);
//Scrolling timer
scrol_timer_handle = xTimerCreate("fps_timer", 10*SECOND, pdTRUE, NULL, scrolling_timer);
xTimerStart(scrol_timer_handle, 0);
}

View file

@ -0,0 +1,24 @@
PROGRAM = SSD1306_fps
EXTRA_COMPONENTS = extras/ssd1306 extras/i2c extras/fonts
# include a lot of builtin fonts
FONTS_GLCD_5X7 = 1
FONTS_BITOCRA_4X7 = 1
FONTS_BITOCRA_6X11 = 1
FONTS_BITOCRA_7X13 = 1
FONTS_TERMINUS_6X12_ISO8859_1 = 1
FONTS_TERMINUS_8X14_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_8X14_ISO8859_1 = 1
FONTS_TERMINUS_10X18_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_10X18_ISO8859_1 = 1
FONTS_TERMINUS_11X22_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_11X22_ISO8859_1 = 1
FONTS_TERMINUS_12X24_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_12X24_ISO8859_1 = 1
FONTS_TERMINUS_14X28_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_14X28_ISO8859_1 = 1
FONTS_TERMINUS_16X32_ISO8859_1 = 1
FONTS_TERMINUS_BOLD_16X32_ISO8859_1 = 1
include ../../common.mk

185
examples/ssd1306_fps/main.c Normal file
View file

@ -0,0 +1,185 @@
#include <espressif/esp_common.h>
#include <esp/uart.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <timers.h>
#include <string.h>
#include <ssd1306/ssd1306.h>
#define LOAD_ICON_X 54
#define LOAD_ICON_Y 42
#define LOAD_ICON_SIZE 20
#define CIRCLE_COUNT_ICON_X 100
#define CIRCLE_COUNT_ICON_Y 52
/* Remove this line if your display connected by SPI */
#define I2C_CONNECTION
#ifdef I2C_CONNECTION
#include <i2c/i2c.h>
#endif
#include "fonts/fonts.h"
/* Change this according to you schematics and display size */
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
#ifdef I2C_CONNECTION
#define PROTOCOL SSD1306_PROTO_I2C
#define ADDR SSD1306_I2C_ADDR_0
#define SCL_PIN 5
#define SDA_PIN 4
#else
#define PROTOCOL SSD1306_PROTO_SPI4
#define CS_PIN 5
#define DC_PIN 4
#endif
#define DEFAULT_FONT FONT_FACE_TERMINUS_6X12_ISO8859_1
/* Declare device descriptor */
static const ssd1306_t dev = {
.protocol = PROTOCOL,
#ifdef I2C_CONNECTION
.addr = ADDR,
#else
.cs_pin = CS_PIN,
.dc_pin = DC_PIN,
#endif
.width = DISPLAY_WIDTH,
.height = DISPLAY_HEIGHT
};
/* Local frame buffer */
static uint8_t buffer[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8];
TimerHandle_t fps_timer_handle = NULL; // Timer handler
TimerHandle_t font_timer_handle = NULL;
uint8_t frame_done = 0; // number of frame send.
uint8_t fps = 0; // image per second.
const font_info_t *font = NULL; // current font
font_face_t font_face = 0;
#define SECOND (1000 / portTICK_PERIOD_MS)
static void ssd1306_task(void *pvParameters)
{
printf("%s: Started user interface task\n", __FUNCTION__);
vTaskDelay(SECOND);
ssd1306_set_whole_display_lighting(&dev, false);
char text[20];
uint8_t x0 = LOAD_ICON_X;
uint8_t y0 = LOAD_ICON_Y;
uint8_t x1 = LOAD_ICON_X + LOAD_ICON_SIZE;
uint8_t y1 = LOAD_ICON_Y + LOAD_ICON_SIZE;
uint16_t count = 0;
while (1) {
ssd1306_fill_rectangle(&dev, buffer, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT/2, OLED_COLOR_BLACK);
ssd1306_draw_string(&dev, buffer, font, 0, 0, "Hello, esp-open-rtos!", OLED_COLOR_WHITE, OLED_COLOR_BLACK);
sprintf(text, "FPS: %u ", fps);
ssd1306_draw_string(&dev, buffer, font_builtin_fonts[DEFAULT_FONT], 0, 45, text, OLED_COLOR_WHITE, OLED_COLOR_BLACK);
// generate loading icon
ssd1306_draw_line(&dev, buffer, x0, y0, x1, y1, OLED_COLOR_BLACK);
if (x0 < (LOAD_ICON_X + LOAD_ICON_SIZE)) {
x0++;
x1--;
}
else if (y0 < (LOAD_ICON_Y + LOAD_ICON_SIZE)) {
y0++;
y1--;
}
else {
x0 = LOAD_ICON_X;
y0 = LOAD_ICON_Y;
x1 = LOAD_ICON_X + LOAD_ICON_SIZE;
y1 = LOAD_ICON_Y + LOAD_ICON_SIZE;
}
ssd1306_draw_line(&dev, buffer, x0, y0, x1, y1, OLED_COLOR_WHITE);
ssd1306_draw_rectangle(&dev, buffer, LOAD_ICON_X, LOAD_ICON_Y,
LOAD_ICON_SIZE + 1, LOAD_ICON_SIZE + 1, OLED_COLOR_WHITE);
// generate circle counting
for (uint8_t i = 0; i < 10; i++) {
if ((count >> i) & 0x01)
ssd1306_draw_circle(&dev, buffer, CIRCLE_COUNT_ICON_X, CIRCLE_COUNT_ICON_Y, i, OLED_COLOR_BLACK);
}
count = count == 0x03FF ? 0 : count + 1;
for (uint8_t i = 0; i < 10; i++) {
if ((count>>i) & 0x01)
ssd1306_draw_circle(&dev,buffer, CIRCLE_COUNT_ICON_X, CIRCLE_COUNT_ICON_Y, i, OLED_COLOR_WHITE);
}
if (ssd1306_load_frame_buffer(&dev, buffer))
goto error_loop;
frame_done++;
}
error_loop:
printf("%s: error while loading framebuffer into SSD1306\n", __func__);
for (;;) {
vTaskDelay(2 * SECOND);
printf("%s: error loop\n", __FUNCTION__);
}
}
void fps_timer(TimerHandle_t h)
{
fps = frame_done; // Save number of frame already send to screen
frame_done = 0;
}
void font_timer(TimerHandle_t h)
{
do {
if (++font_face >= font_builtin_fonts_count)
font_face = 0;
font = font_builtin_fonts[font_face];
} while (!font);
printf("Selected builtin font %d\n", font_face);
}
void user_init(void)
{
//uncomment to test with CPU overclocked
//sdk_system_update_cpu_freq(160);
// Setup HW
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
#ifdef I2C_CONNECTION
i2c_init(SCL_PIN, SDA_PIN);
#endif
while (ssd1306_init(&dev) != 0) {
printf("%s: failed to init SSD1306 lcd\n", __func__);
vTaskDelay(SECOND);
}
ssd1306_set_whole_display_lighting(&dev, true);
vTaskDelay(SECOND);
font = font_builtin_fonts[font_face];
// Create user interface task
xTaskCreate(ssd1306_task, "ssd1306_task", 256, NULL, 2, NULL);
fps_timer_handle = xTimerCreate("fps_timer", SECOND, pdTRUE, NULL, fps_timer);
xTimerStart(fps_timer_handle, 0);
font_timer_handle = xTimerCreate("font_timer", 5 * SECOND, pdTRUE, NULL, font_timer);
xTimerStart(font_timer_handle, 0);
}

20
extras/fonts/LICENSE Normal file
View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

97
extras/fonts/OFL.txt Normal file
View file

@ -0,0 +1,97 @@
Copyright (c) <dates>, <Copyright Holder> (<URL|email>),
with Reserved Font Name <Reserved Font Name>.
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>),
with Reserved Font Name <additional Reserved Font Name>.
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>).
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

42
extras/fonts/component.mk Normal file
View file

@ -0,0 +1,42 @@
# Component makefile for extras/fonts
# expected anyone using this component includes it as 'fonts/fonts.h'
INC_DIRS += $(fonts_ROOT)..
# args for passing into compile rule generation
fonts_SRC_DIR = $(fonts_ROOT)
FONTS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
# default builtin fonts
include $(FONTS_DIR)defaults.mk
fonts_CFLAGS = $(CFLAGS) \
-DFONTS_GLCD_5X7=$(FONTS_GLCD_5X7) \
-DFONTS_ROBOTO_8PT=$(FONTS_ROBOTO_8PT) \
-DFONTS_ROBOTO_10PT=$(FONTS_ROBOTO_10PT) \
-DFONTS_BITOCRA_4X7=$(FONTS_BITOCRA_4X7) \
-DFONTS_BITOCRA_6X11=$(FONTS_BITOCRA_6X11) \
-DFONTS_BITOCRA_7X13=$(FONTS_BITOCRA_7X13) \
-DFONTS_TERMINUS_6X12_ISO8859_1=$(FONTS_TERMINUS_6X12_ISO8859_1) \
-DFONTS_TERMINUS_8X14_ISO8859_1=$(FONTS_TERMINUS_8X14_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_8X14_ISO8859_1=$(FONTS_TERMINUS_BOLD_8X14_ISO8859_1) \
-DFONTS_TERMINUS_10X18_ISO8859_1=$(FONTS_TERMINUS_10X18_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_10X18_ISO8859_1=$(FONTS_TERMINUS_BOLD_10X18_ISO8859_1) \
-DFONTS_TERMINUS_11X22_ISO8859_1=$(FONTS_TERMINUS_11X22_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_11X22_ISO8859_1=$(FONTS_TERMINUS_BOLD_11X22_ISO8859_1) \
-DFONTS_TERMINUS_12X24_ISO8859_1=$(FONTS_TERMINUS_12X24_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_12X24_ISO8859_1=$(FONTS_TERMINUS_BOLD_12X24_ISO8859_1) \
-DFONTS_TERMINUS_14X28_ISO8859_1=$(FONTS_TERMINUS_14X28_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_14X28_ISO8859_1=$(FONTS_TERMINUS_BOLD_14X28_ISO8859_1) \
-DFONTS_TERMINUS_16X32_ISO8859_1=$(FONTS_TERMINUS_16X32_ISO8859_1) \
-DFONTS_TERMINUS_BOLD_16X32_ISO8859_1=$(FONTS_TERMINUS_BOLD_16X32_ISO8859_1) \
-DFONTS_TERMINUS_6X12_KOI8_R=$(FONTS_TERMINUS_6X12_KOI8_R) \
-DFONTS_TERMINUS_8X14_KOI8_R=$(FONTS_TERMINUS_8X14_KOI8_R) \
-DFONTS_TERMINUS_BOLD_8X14_KOI8_R=$(FONTS_TERMINUS_BOLD_8X14_KOI8_R) \
-DFONTS_TERMINUS_14X28_KOI8_R=$(FONTS_TERMINUS_14X28_KOI8_R) \
-DFONTS_TERMINUS_BOLD_14X28_KOI8_R=$(FONTS_TERMINUS_BOLD_14X28_KOI8_R) \
-DFONTS_TERMINUS_16X32_KOI8_R=$(FONTS_TERMINUS_16X32_KOI8_R) \
-DFONTS_TERMINUS_BOLD_16X32_KOI8_R=$(FONTS_TERMINUS_BOLD_16X32_KOI8_R)
$(eval $(call component_compile_rules,fonts))

View file

@ -0,0 +1,993 @@
/**
* This file contains generated binary font data.
*
* Font: BitOCRA
* Size: 4x7
* Charset: ASCII
* 96 characters (32..127)
*
* Copyright (c) 2011, Aaron Christianson <ninjaaron@gmail.com> (https://github.com/ninjaaron)
* Licensed under the OFL v1.1
*
* Generated: Mon Dec 12 00:46:53 2016
*/
#ifndef _EXTRAS_FONTS_FONT_BITOCRA_4X7_ASCII_H_
#define _EXTRAS_FONTS_FONT_BITOCRA_4X7_ASCII_H_
static const uint8_t _fonts_bitocra_4x7_ascii_bitmaps[] = {
/* Index: 0x00, char: \x20, offset: 0x0000 */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x01, char: \x21, offset: 0x0007 */
0x00, /* ........ */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x02, char: \x22, offset: 0x000e */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x03, char: \x23, offset: 0x0015 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x04, char: \x24, offset: 0x001c */
0x00, /* ........ */
0x40, /* .#...... */
0xe0, /* ###..... */
0xc0, /* ##...... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x40, /* .#...... */
/* Index: 0x05, char: \x25, offset: 0x0023 */
0x00, /* ........ */
0x80, /* #....... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x80, /* #....... */
0x20, /* ..#..... */
0x00, /* ........ */
/* Index: 0x06, char: \x26, offset: 0x002a */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0x50, /* .#.#.... */
0xa0, /* #.#..... */
0x50, /* .#.#.... */
0x00, /* ........ */
/* Index: 0x07, char: \x27, offset: 0x0031 */
0x00, /* ........ */
0x60, /* .##..... */
0x40, /* .#...... */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x08, char: \x28, offset: 0x0038 */
0x00, /* ........ */
0x20, /* ..#..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x20, /* ..#..... */
/* Index: 0x09, char: \x29, offset: 0x003f */
0x00, /* ........ */
0x40, /* .#...... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0x40, /* .#...... */
/* Index: 0x0a, char: \x2a, offset: 0x0046 */
0x00, /* ........ */
0x40, /* .#...... */
0xe0, /* ###..... */
0x40, /* .#...... */
0xa0, /* #.#..... */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x0b, char: \x2b, offset: 0x004d */
0x00, /* ........ */
0x00, /* ........ */
0x40, /* .#...... */
0xe0, /* ###..... */
0x40, /* .#...... */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x0c, char: \x2c, offset: 0x0054 */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
/* Index: 0x0d, char: \x2d, offset: 0x005b */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x0e, char: \x2e, offset: 0x0062 */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x0f, char: \x2f, offset: 0x0069 */
0x00, /* ........ */
0x20, /* ..#..... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x80, /* #....... */
0x80, /* #....... */
/* Index: 0x10, char: \x30, offset: 0x0070 */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x11, char: \x31, offset: 0x0077 */
0x00, /* ........ */
0xc0, /* ##...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x12, char: \x32, offset: 0x007e */
0x00, /* ........ */
0xe0, /* ###..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x13, char: \x33, offset: 0x0085 */
0x00, /* ........ */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x60, /* .##..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x14, char: \x34, offset: 0x008c */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0x00, /* ........ */
/* Index: 0x15, char: \x35, offset: 0x0093 */
0x00, /* ........ */
0xe0, /* ###..... */
0x80, /* #....... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x16, char: \x36, offset: 0x009a */
0x00, /* ........ */
0xc0, /* ##...... */
0x80, /* #....... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x17, char: \x37, offset: 0x00a1 */
0x00, /* ........ */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x18, char: \x38, offset: 0x00a8 */
0x00, /* ........ */
0x60, /* .##..... */
0x60, /* .##..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x19, char: \x39, offset: 0x00af */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x60, /* .##..... */
0x00, /* ........ */
/* Index: 0x1a, char: \x3a, offset: 0x00b6 */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x40, /* .#...... */
0x00, /* ........ */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x1b, char: \x3b, offset: 0x00bd */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x40, /* .#...... */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
/* Index: 0x1c, char: \x3c, offset: 0x00c4 */
0x00, /* ........ */
0x20, /* ..#..... */
0x40, /* .#...... */
0x80, /* #....... */
0x40, /* .#...... */
0x20, /* ..#..... */
0x00, /* ........ */
/* Index: 0x1d, char: \x3d, offset: 0x00cb */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0x00, /* ........ */
0xe0, /* ###..... */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x1e, char: \x3e, offset: 0x00d2 */
0x00, /* ........ */
0x80, /* #....... */
0x40, /* .#...... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x1f, char: \x3f, offset: 0x00d9 */
0x00, /* ........ */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
0x40, /* .#...... */
/* Index: 0x20, char: \x40, offset: 0x00e0 */
0x00, /* ........ */
0xf0, /* ####.... */
0x90, /* #..#.... */
0x50, /* .#.#.... */
0xd0, /* ##.#.... */
0xf0, /* ####.... */
0x00, /* ........ */
/* Index: 0x21, char: \x41, offset: 0x00e7 */
0x00, /* ........ */
0x60, /* .##..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x22, char: \x42, offset: 0x00ee */
0x00, /* ........ */
0xc0, /* ##...... */
0xc0, /* ##...... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x23, char: \x43, offset: 0x00f5 */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0x80, /* #....... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x24, char: \x44, offset: 0x00fc */
0x00, /* ........ */
0xc0, /* ##...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0x00, /* ........ */
/* Index: 0x25, char: \x45, offset: 0x0103 */
0x00, /* ........ */
0xe0, /* ###..... */
0x80, /* #....... */
0xc0, /* ##...... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x26, char: \x46, offset: 0x010a */
0x00, /* ........ */
0xe0, /* ###..... */
0x80, /* #....... */
0xc0, /* ##...... */
0x80, /* #....... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x27, char: \x47, offset: 0x0111 */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x28, char: \x48, offset: 0x0118 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x29, char: \x49, offset: 0x011f */
0x00, /* ........ */
0xe0, /* ###..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x2a, char: \x4a, offset: 0x0126 */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x2b, char: \x4b, offset: 0x012d */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x2c, char: \x4c, offset: 0x0134 */
0x00, /* ........ */
0x80, /* #....... */
0x80, /* #....... */
0x80, /* #....... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x2d, char: \x4d, offset: 0x013b */
0x00, /* ........ */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x2e, char: \x4e, offset: 0x0142 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x2f, char: \x4f, offset: 0x0149 */
0x00, /* ........ */
0x60, /* .##..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x30, char: \x50, offset: 0x0150 */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x80, /* #....... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x31, char: \x51, offset: 0x0157 */
0x00, /* ........ */
0x60, /* .##..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0x60, /* .##..... */
/* Index: 0x32, char: \x52, offset: 0x015e */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x33, char: \x53, offset: 0x0165 */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x34, char: \x54, offset: 0x016c */
0x00, /* ........ */
0xe0, /* ###..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x35, char: \x55, offset: 0x0173 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x36, char: \x56, offset: 0x017a */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x37, char: \x57, offset: 0x0181 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x38, char: \x58, offset: 0x0188 */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x40, /* .#...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x39, char: \x59, offset: 0x018f */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x3a, char: \x5a, offset: 0x0196 */
0x00, /* ........ */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x40, /* .#...... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x3b, char: \x5b, offset: 0x019d */
0x00, /* ........ */
0xe0, /* ###..... */
0xc0, /* ##...... */
0xc0, /* ##...... */
0xc0, /* ##...... */
0xc0, /* ##...... */
0xe0, /* ###..... */
/* Index: 0x3c, char: \x5c, offset: 0x01a4 */
0x00, /* ........ */
0x80, /* #....... */
0x80, /* #....... */
0x40, /* .#...... */
0x40, /* .#...... */
0x20, /* ..#..... */
0x20, /* ..#..... */
/* Index: 0x3d, char: \x5d, offset: 0x01ab */
0x00, /* ........ */
0xe0, /* ###..... */
0x60, /* .##..... */
0x60, /* .##..... */
0x60, /* .##..... */
0x60, /* .##..... */
0xe0, /* ###..... */
/* Index: 0x3e, char: \x5e, offset: 0x01b2 */
0x00, /* ........ */
0x40, /* .#...... */
0xa0, /* #.#..... */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x3f, char: \x5f, offset: 0x01b9 */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0xf0, /* ####.... */
/* Index: 0x40, char: \x60, offset: 0x01c0 */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x41, char: \x61, offset: 0x01c7 */
0x00, /* ........ */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x42, char: \x62, offset: 0x01ce */
0x00, /* ........ */
0x80, /* #....... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x43, char: \x63, offset: 0x01d5 */
0x00, /* ........ */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x44, char: \x64, offset: 0x01dc */
0x00, /* ........ */
0x20, /* ..#..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x45, char: \x65, offset: 0x01e3 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xe0, /* ###..... */
0x80, /* #....... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x46, char: \x66, offset: 0x01ea */
0x00, /* ........ */
0x60, /* .##..... */
0x80, /* #....... */
0xe0, /* ###..... */
0x80, /* #....... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x47, char: \x67, offset: 0x01f1 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
/* Index: 0x48, char: \x68, offset: 0x01f8 */
0x00, /* ........ */
0x80, /* #....... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x49, char: \x69, offset: 0x01ff */
0x40, /* .#...... */
0x00, /* ........ */
0xc0, /* ##...... */
0x40, /* .#...... */
0x40, /* .#...... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x4a, char: \x6a, offset: 0x0206 */
0x20, /* ..#..... */
0x00, /* ........ */
0x60, /* .##..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
/* Index: 0x4b, char: \x6b, offset: 0x020d */
0x00, /* ........ */
0x80, /* #....... */
0xa0, /* #.#..... */
0xc0, /* ##...... */
0xc0, /* ##...... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x4c, char: \x6c, offset: 0x0214 */
0x00, /* ........ */
0xc0, /* ##...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x60, /* .##..... */
0x00, /* ........ */
/* Index: 0x4d, char: \x6d, offset: 0x021b */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x4e, char: \x6e, offset: 0x0222 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x4f, char: \x6f, offset: 0x0229 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x50, char: \x70, offset: 0x0230 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x80, /* #....... */
0x80, /* #....... */
/* Index: 0x51, char: \x71, offset: 0x0237 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0x20, /* ..#..... */
/* Index: 0x52, char: \x72, offset: 0x023e */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0x80, /* #....... */
0x80, /* #....... */
0x80, /* #....... */
0x00, /* ........ */
/* Index: 0x53, char: \x73, offset: 0x0245 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0x80, /* #....... */
0x60, /* .##..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x54, char: \x74, offset: 0x024c */
0x00, /* ........ */
0x40, /* .#...... */
0x60, /* .##..... */
0x40, /* .#...... */
0x40, /* .#...... */
0x60, /* .##..... */
0x00, /* ........ */
/* Index: 0x55, char: \x75, offset: 0x0253 */
0x00, /* ........ */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x56, char: \x76, offset: 0x025a */
0x00, /* ........ */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x57, char: \x77, offset: 0x0261 */
0x00, /* ........ */
0x00, /* ........ */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x58, char: \x78, offset: 0x0268 */
0x00, /* ........ */
0x00, /* ........ */
0xa0, /* #.#..... */
0x40, /* .#...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0x00, /* ........ */
/* Index: 0x59, char: \x79, offset: 0x026f */
0x00, /* ........ */
0x00, /* ........ */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x20, /* ..#..... */
0xe0, /* ###..... */
/* Index: 0x5a, char: \x7a, offset: 0x0276 */
0x00, /* ........ */
0x00, /* ........ */
0xe0, /* ###..... */
0x60, /* .##..... */
0xc0, /* ##...... */
0xe0, /* ###..... */
0x00, /* ........ */
/* Index: 0x5b, char: \x7b, offset: 0x027d */
0x00, /* ........ */
0x60, /* .##..... */
0x40, /* .#...... */
0xc0, /* ##...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x60, /* .##..... */
/* Index: 0x5c, char: \x7c, offset: 0x0284 */
0x00, /* ........ */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x40, /* .#...... */
0x00, /* ........ */
/* Index: 0x5d, char: \x7d, offset: 0x028b */
0x00, /* ........ */
0xc0, /* ##...... */
0x40, /* .#...... */
0x60, /* .##..... */
0x40, /* .#...... */
0x40, /* .#...... */
0xc0, /* ##...... */
/* Index: 0x5e, char: \x7e, offset: 0x0292 */
0x00, /* ........ */
0x00, /* ........ */
0x20, /* ..#..... */
0xe0, /* ###..... */
0x80, /* #....... */
0x00, /* ........ */
0x00, /* ........ */
/* Index: 0x5f, char: \x7f, offset: 0x0299 */
0x00, /* ........ */
0x40, /* .#...... */
0x40, /* .#...... */
0xa0, /* #.#..... */
0xa0, /* #.#..... */
0xe0, /* ###..... */
0x00, /* ........ */
};
const font_char_desc_t _fonts_bitocra_4x7_ascii_descriptors[] = {
{ 0x04, 0x0000 }, /* Index: 0x00, char: \x20 */
{ 0x04, 0x0007 }, /* Index: 0x01, char: \x21 */
{ 0x04, 0x000e }, /* Index: 0x02, char: \x22 */
{ 0x04, 0x0015 }, /* Index: 0x03, char: \x23 */
{ 0x04, 0x001c }, /* Index: 0x04, char: \x24 */
{ 0x04, 0x0023 }, /* Index: 0x05, char: \x25 */
{ 0x04, 0x002a }, /* Index: 0x06, char: \x26 */
{ 0x04, 0x0031 }, /* Index: 0x07, char: \x27 */
{ 0x04, 0x0038 }, /* Index: 0x08, char: \x28 */
{ 0x04, 0x003f }, /* Index: 0x09, char: \x29 */
{ 0x04, 0x0046 }, /* Index: 0x0a, char: \x2a */
{ 0x04, 0x004d }, /* Index: 0x0b, char: \x2b */
{ 0x04, 0x0054 }, /* Index: 0x0c, char: \x2c */
{ 0x04, 0x005b }, /* Index: 0x0d, char: \x2d */
{ 0x04, 0x0062 }, /* Index: 0x0e, char: \x2e */
{ 0x04, 0x0069 }, /* Index: 0x0f, char: \x2f */
{ 0x04, 0x0070 }, /* Index: 0x10, char: \x30 */
{ 0x04, 0x0077 }, /* Index: 0x11, char: \x31 */
{ 0x04, 0x007e }, /* Index: 0x12, char: \x32 */
{ 0x04, 0x0085 }, /* Index: 0x13, char: \x33 */
{ 0x04, 0x008c }, /* Index: 0x14, char: \x34 */
{ 0x04, 0x0093 }, /* Index: 0x15, char: \x35 */
{ 0x04, 0x009a }, /* Index: 0x16, char: \x36 */
{ 0x04, 0x00a1 }, /* Index: 0x17, char: \x37 */
{ 0x04, 0x00a8 }, /* Index: 0x18, char: \x38 */
{ 0x04, 0x00af }, /* Index: 0x19, char: \x39 */
{ 0x04, 0x00b6 }, /* Index: 0x1a, char: \x3a */
{ 0x04, 0x00bd }, /* Index: 0x1b, char: \x3b */
{ 0x04, 0x00c4 }, /* Index: 0x1c, char: \x3c */
{ 0x04, 0x00cb }, /* Index: 0x1d, char: \x3d */
{ 0x04, 0x00d2 }, /* Index: 0x1e, char: \x3e */
{ 0x04, 0x00d9 }, /* Index: 0x1f, char: \x3f */
{ 0x04, 0x00e0 }, /* Index: 0x20, char: \x40 */
{ 0x04, 0x00e7 }, /* Index: 0x21, char: \x41 */
{ 0x04, 0x00ee }, /* Index: 0x22, char: \x42 */
{ 0x04, 0x00f5 }, /* Index: 0x23, char: \x43 */
{ 0x04, 0x00fc }, /* Index: 0x24, char: \x44 */
{ 0x04, 0x0103 }, /* Index: 0x25, char: \x45 */
{ 0x04, 0x010a }, /* Index: 0x26, char: \x46 */
{ 0x04, 0x0111 }, /* Index: 0x27, char: \x47 */
{ 0x04, 0x0118 }, /* Index: 0x28, char: \x48 */
{ 0x04, 0x011f }, /* Index: 0x29, char: \x49 */
{ 0x04, 0x0126 }, /* Index: 0x2a, char: \x4a */
{ 0x04, 0x012d }, /* Index: 0x2b, char: \x4b */
{ 0x04, 0x0134 }, /* Index: 0x2c, char: \x4c */
{ 0x04, 0x013b }, /* Index: 0x2d, char: \x4d */
{ 0x04, 0x0142 }, /* Index: 0x2e, char: \x4e */
{ 0x04, 0x0149 }, /* Index: 0x2f, char: \x4f */
{ 0x04, 0x0150 }, /* Index: 0x30, char: \x50 */
{ 0x04, 0x0157 }, /* Index: 0x31, char: \x51 */
{ 0x04, 0x015e }, /* Index: 0x32, char: \x52 */
{ 0x04, 0x0165 }, /* Index: 0x33, char: \x53 */
{ 0x04, 0x016c }, /* Index: 0x34, char: \x54 */
{ 0x04, 0x0173 }, /* Index: 0x35, char: \x55 */
{ 0x04, 0x017a }, /* Index: 0x36, char: \x56 */
{ 0x04, 0x0181 }, /* Index: 0x37, char: \x57 */
{ 0x04, 0x0188 }, /* Index: 0x38, char: \x58 */
{ 0x04, 0x018f }, /* Index: 0x39, char: \x59 */
{ 0x04, 0x0196 }, /* Index: 0x3a, char: \x5a */
{ 0x04, 0x019d }, /* Index: 0x3b, char: \x5b */
{ 0x04, 0x01a4 }, /* Index: 0x3c, char: \x5c */
{ 0x04, 0x01ab }, /* Index: 0x3d, char: \x5d */
{ 0x04, 0x01b2 }, /* Index: 0x3e, char: \x5e */
{ 0x04, 0x01b9 }, /* Index: 0x3f, char: \x5f */
{ 0x04, 0x01c0 }, /* Index: 0x40, char: \x60 */
{ 0x04, 0x01c7 }, /* Index: 0x41, char: \x61 */
{ 0x04, 0x01ce }, /* Index: 0x42, char: \x62 */
{ 0x04, 0x01d5 }, /* Index: 0x43, char: \x63 */
{ 0x04, 0x01dc }, /* Index: 0x44, char: \x64 */
{ 0x04, 0x01e3 }, /* Index: 0x45, char: \x65 */
{ 0x04, 0x01ea }, /* Index: 0x46, char: \x66 */
{ 0x04, 0x01f1 }, /* Index: 0x47, char: \x67 */
{ 0x04, 0x01f8 }, /* Index: 0x48, char: \x68 */
{ 0x04, 0x01ff }, /* Index: 0x49, char: \x69 */
{ 0x04, 0x0206 }, /* Index: 0x4a, char: \x6a */
{ 0x04, 0x020d }, /* Index: 0x4b, char: \x6b */
{ 0x04, 0x0214 }, /* Index: 0x4c, char: \x6c */
{ 0x04, 0x021b }, /* Index: 0x4d, char: \x6d */
{ 0x04, 0x0222 }, /* Index: 0x4e, char: \x6e */
{ 0x04, 0x0229 }, /* Index: 0x4f, char: \x6f */
{ 0x04, 0x0230 }, /* Index: 0x50, char: \x70 */
{ 0x04, 0x0237 }, /* Index: 0x51, char: \x71 */
{ 0x04, 0x023e }, /* Index: 0x52, char: \x72 */
{ 0x04, 0x0245 }, /* Index: 0x53, char: \x73 */
{ 0x04, 0x024c }, /* Index: 0x54, char: \x74 */
{ 0x04, 0x0253 }, /* Index: 0x55, char: \x75 */
{ 0x04, 0x025a }, /* Index: 0x56, char: \x76 */
{ 0x04, 0x0261 }, /* Index: 0x57, char: \x77 */
{ 0x04, 0x0268 }, /* Index: 0x58, char: \x78 */
{ 0x04, 0x026f }, /* Index: 0x59, char: \x79 */
{ 0x04, 0x0276 }, /* Index: 0x5a, char: \x7a */
{ 0x04, 0x027d }, /* Index: 0x5b, char: \x7b */
{ 0x04, 0x0284 }, /* Index: 0x5c, char: \x7c */
{ 0x04, 0x028b }, /* Index: 0x5d, char: \x7d */
{ 0x04, 0x0292 }, /* Index: 0x5e, char: \x7e */
{ 0x04, 0x0299 }, /* Index: 0x5f, char: \x7f */
};
const font_info_t _fonts_bitocra_4x7_ascii_info =
{
.height = 7, /* Character height */
.c = 0, /* C */
.char_start = 32, /* Start character */
.char_end = 127, /* End character */
.char_descriptors = _fonts_bitocra_4x7_ascii_descriptors, /* Character descriptor array */
.bitmap = _fonts_bitocra_4x7_ascii_bitmaps, /* Character bitmap array */
};
#endif /* _EXTRAS_FONTS_FONT_BITOCRA_4X7_ASCII_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

39
extras/fonts/defaults.mk Normal file
View file

@ -0,0 +1,39 @@
#########################################
# Default built-in fonts
#########################################
# FIXME
FONTS_GLCD_5X7 ?= 1
FONTS_ROBOTO_8PT ?= 0
FONTS_ROBOTO_10PT ?= 0
# BitOCRA
FONTS_BITOCRA_4X7 ?= 0
FONTS_BITOCRA_6X11 ?= 0
FONTS_BITOCRA_7X13 ?= 0
# Terminus, ISO8859-1 (Latin-1)
FONTS_TERMINUS_6X12_ISO8859_1 ?= 0
FONTS_TERMINUS_8X14_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_8X14_ISO8859_1 ?= 0
FONTS_TERMINUS_10X18_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_10X18_ISO8859_1 ?= 0
FONTS_TERMINUS_11X22_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_11X22_ISO8859_1 ?= 0
FONTS_TERMINUS_12X24_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_12X24_ISO8859_1 ?= 0
FONTS_TERMINUS_14X28_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_14X28_ISO8859_1 ?= 0
FONTS_TERMINUS_16X32_ISO8859_1 ?= 0
FONTS_TERMINUS_BOLD_16X32_ISO8859_1 ?= 0
# Terminus, KOI8-R
FONTS_TERMINUS_6X12_KOI8_R ?= 0
FONTS_TERMINUS_8X14_KOI8_R ?= 0
FONTS_TERMINUS_BOLD_8X14_KOI8_R ?= 0
FONTS_TERMINUS_14X28_KOI8_R ?= 0
FONTS_TERMINUS_BOLD_14X28_KOI8_R ?= 0
FONTS_TERMINUS_16X32_KOI8_R ?= 0
FONTS_TERMINUS_BOLD_16X32_KOI8_R ?= 0

259
extras/fonts/fonts.c Normal file
View file

@ -0,0 +1,259 @@
/**
* LCD/OLED fonts library
*
* FIXME: License?
*
* @date: 8 dec. 2016
* Author: zaltora
*/
#include "fonts.h"
#ifndef FONTS_GLCD_5X7
#define FONTS_GLCD_5X7 1
#endif
#if FONTS_GLCD_5X7
#include "data/font_glcd_5x7.h"
#endif
#if FONTS_ROBOTO_8PT
#include "data/font_roboto_8pt.h"
#endif
#if FONTS_ROBOTO_10PT
#include "data/font_roboto_10pt.h"
#endif
#if FONTS_BITOCRA_4X7
#include "data/font_bitocra_4x7_ascii.h"
#endif
#if FONTS_BITOCRA_6X11
#include "data/font_bitocra_6x11_iso8859_1.h"
#endif
#if FONTS_BITOCRA_7X13
#include "data/font_bitocra_7x13_iso8859_1.h"
#endif
#if FONTS_TERMINUS_6X12_ISO8859_1
#include "data/font_terminus_6x12_iso8859_1.h"
#endif
#if FONTS_TERMINUS_8X14_ISO8859_1
#include "data/font_terminus_8x14_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_8X14_ISO8859_1
#include "data/font_terminus_bold_8x14_iso8859_1.h"
#endif
#if FONTS_TERMINUS_10X18_ISO8859_1
#include "data/font_terminus_10x18_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_10X18_ISO8859_1
#include "data/font_terminus_bold_10x18_iso8859_1.h"
#endif
#if FONTS_TERMINUS_11X22_ISO8859_1
#include "data/font_terminus_11x22_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_11X22_ISO8859_1
#include "data/font_terminus_bold_11x22_iso8859_1.h"
#endif
#if FONTS_TERMINUS_12X24_ISO8859_1
#include "data/font_terminus_12x24_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_12X24_ISO8859_1
#include "data/font_terminus_bold_12x24_iso8859_1.h"
#endif
#if FONTS_TERMINUS_14X28_ISO8859_1
#include "data/font_terminus_14x28_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_14X28_ISO8859_1
#include "data/font_terminus_bold_14x28_iso8859_1.h"
#endif
#if FONTS_TERMINUS_16X32_ISO8859_1
#include "data/font_terminus_16x32_iso8859_1.h"
#endif
#if FONTS_TERMINUS_BOLD_16X32_ISO8859_1
#include "data/font_terminus_bold_16x32_iso8859_1.h"
#endif
#if FONTS_TERMINUS_6X12_KOI8_R
#include "data/font_terminus_6x12_koi8_r.h"
#endif
#if FONTS_TERMINUS_8X14_KOI8_R
#include "data/font_terminus_8x14_koi8_r.h"
#endif
#if FONTS_TERMINUS_BOLD_8X14_KOI8_R
#include "data/font_terminus_bold_8x14_koi8_r.h"
#endif
#if FONTS_TERMINUS_14X28_KOI8_R
#include "data/font_terminus_14x28_koi8_r.h"
#endif
#if FONTS_TERMINUS_BOLD_14X28_KOI8_R
#include "data/font_terminus_bold_14x28_koi8_r.h"
#endif
#if FONTS_TERMINUS_16X32_KOI8_R
#include "data/font_terminus_16x32_koi8_r.h"
#endif
#if FONTS_TERMINUS_BOLD_16X32_KOI8_R
#include "data/font_terminus_bold_16x32_koi8_r.h"
#endif
/////////////////////////////////////////////
// FIXME: this declaration is noisy
const font_info_t *font_builtin_fonts[] =
{
#if FONTS_GLCD_5X7
[FONT_FACE_GLCD5x7] = &_fonts_glcd_5x7_info,
#else
[FONT_FACE_GLCD5x7] = NULL,
#endif
#if FONTS_ROBOTO_8PT
[FONT_FACE_ROBOTO_8PT] = &_fonts_roboto_8pt_info,
#else
[FONT_FACE_ROBOTO_8PT] = NULL,
#endif
#if FONTS_ROBOTO_10PT
[FONT_FACE_ROBOTO_10PT] = &_fonts_roboto_10pt_info,
#else
[FONT_FACE_ROBOTO_10PT] = NULL,
#endif
#if FONTS_BITOCRA_4X7
[FONT_FACE_BITOCRA_4X7] = &_fonts_bitocra_4x7_ascii_info,
#else
[FONT_FACE_BITOCRA_4X7] = NULL,
#endif
#if FONTS_BITOCRA_6X11
[FONT_FACE_BITOCRA_6X11] = &_fonts_bitocra_6x11_iso8859_1_info,
#else
[FONT_FACE_BITOCRA_6X11] = NULL,
#endif
#if FONTS_BITOCRA_7X13
[FONT_FACE_BITOCRA_7X13] = &_fonts_bitocra_7x13_iso8859_1_info,
#else
[FONT_FACE_BITOCRA_7X13] = NULL,
#endif
#if FONTS_TERMINUS_6X12_ISO8859_1
[FONT_FACE_TERMINUS_6X12_ISO8859_1] = &_fonts_terminus_6x12_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_6X12_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_8X14_ISO8859_1
[FONT_FACE_TERMINUS_8X14_ISO8859_1] = &_fonts_terminus_8x14_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_8X14_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_8X14_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_8X14_ISO8859_1] = &_fonts_terminus_bold_8x14_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_8X14_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_10X18_ISO8859_1
[FONT_FACE_TERMINUS_10X18_ISO8859_1] = &_fonts_terminus_10x18_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_10X18_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_10X18_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_10X18_ISO8859_1] = &_fonts_terminus_bold_10x18_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_10X18_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_11X22_ISO8859_1
[FONT_FACE_TERMINUS_11X22_ISO8859_1] = &_fonts_terminus_11x22_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_11X22_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_11X22_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_11X22_ISO8859_1] = &_fonts_terminus_bold_11x22_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_11X22_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_12X24_ISO8859_1
[FONT_FACE_TERMINUS_12X24_ISO8859_1] = &_fonts_terminus_12x24_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_12X24_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_12X24_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_12X24_ISO8859_1] = &_fonts_terminus_bold_12x24_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_12X24_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_14X28_ISO8859_1
[FONT_FACE_TERMINUS_14X28_ISO8859_1] = &_fonts_terminus_14x28_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_14X28_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_14X28_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_14X28_ISO8859_1] = &_fonts_terminus_bold_14x28_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_14X28_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_16X32_ISO8859_1
[FONT_FACE_TERMINUS_16X32_ISO8859_1] = &_fonts_terminus_16x32_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_16X32_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_16X32_ISO8859_1
[FONT_FACE_TERMINUS_BOLD_16X32_ISO8859_1] = &_fonts_terminus_bold_16x32_iso8859_1_info,
#else
[FONT_FACE_TERMINUS_BOLD_16X32_ISO8859_1] = NULL,
#endif
#if FONTS_TERMINUS_6X12_KOI8_R
[FONT_FACE_TERMINUS_6X12_KOI8_R] = &_fonts_terminus_6x12_koi8_r_info,
#else
[FONT_FACE_TERMINUS_6X12_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_8X14_KOI8_R
[FONT_FACE_TERMINUS_8X14_KOI8_R] = &_fonts_terminus_8x14_koi8_r_info,
#else
[FONT_FACE_TERMINUS_8X14_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_8X14_KOI8_R
[FONT_FACE_TERMINUS_BOLD_8X14_KOI8_R] = &_fonts_terminus_bold_8x14_koi8_r_info,
#else
[FONT_FACE_TERMINUS_BOLD_8X14_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_14X28_KOI8_R
[FONT_FACE_TERMINUS_14X28_KOI8_R] = &_fonts_terminus_14x28_koi8_r_info,
#else
[FONT_FACE_TERMINUS_14X28_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_14X28_KOI8_R
[FONT_FACE_TERMINUS_BOLD_14X28_KOI8_R] = &_fonts_terminus_bold_14x28_koi8_r_info,
#else
[FONT_FACE_TERMINUS_BOLD_14X28_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_16X32_KOI8_R
[FONT_FACE_TERMINUS_16X32_KOI8_R] = &_fonts_terminus_16x32_koi8_r_info,
#else
[FONT_FACE_TERMINUS_16X32_KOI8_R] = NULL,
#endif
#if FONTS_TERMINUS_BOLD_16X32_KOI8_R
[FONT_FACE_TERMINUS_BOLD_16X32_KOI8_R] = &_fonts_terminus_bold_16x32_koi8_r_info,
#else
[FONT_FACE_TERMINUS_BOLD_16X32_KOI8_R] = NULL,
#endif
};
const size_t font_builtin_fonts_count = (sizeof(font_builtin_fonts) / sizeof(font_info_t *));
/////////////////////////////////////////////
uint16_t font_measure_string(const font_info_t *fnt, const char *s)
{
if (!s || !fnt) return 0;
uint16_t res = 0;
while (*s)
{
const font_char_desc_t *d = font_get_char_desc(fnt, *s);
if (d)
res += d->width + fnt->c;
s++;
}
return res > 0 ? res - fnt->c : 0;
}

105
extras/fonts/fonts.h Normal file
View file

@ -0,0 +1,105 @@
/**
* LCD/OLED fonts library
*
* Copyright (c) 2016 Ruslan V. Uss (https://github.com/UncleRus),
* Zaltora (https://github.com/Zaltora)
* MIT Licensed as described in the file LICENSE
*/
#ifndef _EXTRAS_FONTS_H_
#define _EXTRAS_FONTS_H_
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
FONT_FACE_GLCD5x7 = 0,
FONT_FACE_ROBOTO_8PT,
FONT_FACE_ROBOTO_10PT,
FONT_FACE_BITOCRA_4X7,
FONT_FACE_BITOCRA_6X11,
FONT_FACE_BITOCRA_7X13,
FONT_FACE_TERMINUS_6X12_ISO8859_1,
FONT_FACE_TERMINUS_8X14_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_8X14_ISO8859_1,
FONT_FACE_TERMINUS_10X18_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_10X18_ISO8859_1,
FONT_FACE_TERMINUS_11X22_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_11X22_ISO8859_1,
FONT_FACE_TERMINUS_12X24_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_12X24_ISO8859_1,
FONT_FACE_TERMINUS_14X28_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_14X28_ISO8859_1,
FONT_FACE_TERMINUS_16X32_ISO8859_1,
FONT_FACE_TERMINUS_BOLD_16X32_ISO8859_1,
FONT_FACE_TERMINUS_6X12_KOI8_R,
FONT_FACE_TERMINUS_8X14_KOI8_R,
FONT_FACE_TERMINUS_BOLD_8X14_KOI8_R,
FONT_FACE_TERMINUS_14X28_KOI8_R,
FONT_FACE_TERMINUS_BOLD_14X28_KOI8_R,
FONT_FACE_TERMINUS_16X32_KOI8_R,
FONT_FACE_TERMINUS_BOLD_16X32_KOI8_R,
} font_face_t;
/**
* Character descriptor
*/
typedef struct _font_char_desc
{
uint8_t width; ///< Character width in pixel
uint16_t offset; ///< Offset of this character in bitmap
} font_char_desc_t;
/**
* Font information
*/
typedef struct _font_info
{
uint8_t height; ///< Character height in pixel, all characters have same height
uint8_t c; ///< Simulation of "C" width in TrueType term, the space between adjacent characters
char char_start; ///< First character
char char_end; ///< Last character
const font_char_desc_t *char_descriptors; ///< descriptor for each character
const uint8_t *bitmap; ///< Character bitmap
} font_info_t;
/**
* Built-in fonts
*/
extern const font_info_t *font_builtin_fonts[];
extern const size_t font_builtin_fonts_count;
/**
* Find character decriptor in font
* @param fnt Poniter to font information struct
* @param c Character
* @return Character descriptor or NULL if no character found
*/
inline const font_char_desc_t *font_get_char_desc(const font_info_t *fnt, char c)
{
return c < fnt->char_start || c > fnt->char_end
? NULL
: fnt->char_descriptors + c - fnt->char_start;
}
/**
* Calculate width of string in pixels
* @param fnt Poniter to font information struct
* @param s String
* @return String width
*/
uint16_t font_measure_string(const font_info_t *fnt, const char *s);
#ifdef __cplusplus
}
#endif
#endif /* _EXTRAS_FONTS_H_ */

View file

@ -0,0 +1,90 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, os
from PIL import Image, ImageFont, ImageDraw
import argparse
import jinja2
import re
import time
def gen_char(index, c, im):
bw = (im.size[0] + 7) // 8
res = {
'index': index,
'code': c,
'offset': bw * im.size[1] * index,
'rows': []
}
data = tuple(im.getdata())
for row in range(im.size[1]):
r = {
'data': [],
'asc': [],
}
for b in range(bw):
byte = 0
for i in range(8):
idx = b * 8 + i
bit = data[row * im.size[0] + idx] if idx < im.size[0] else 0
if bit:
byte |= 1
r['asc'].append('#')
else:
r['asc'].append('.')
byte <<= 1
r['data'].append(byte >> 1)
r['asc'] = ''.join(r['asc'])
res['rows'].append(r)
return res
def main(args):
fnt = ImageFont.load(args.font)
size = fnt.getsize('A')
im = Image.new('RGB', size)
draw = ImageDraw.Draw(im)
if args.last - args.first < 1:
raise ValueError('Invalid --first or --last')
chars = []
for idx in range(args.last - args.first + 1):
draw.rectangle(((0, 0), size), fill = 0)
draw.text((0, 0), chr(idx + args.first), font=fnt)
chars.append(gen_char(idx, idx + args.first, im.convert('1')))
env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(os.path.abspath(__file__))), finalize=lambda x: '' if x is None else x)
print(env.get_template(args.template).render({
'font': {
'name': args.name,
'size': size,
'charset': args.charset,
'first': args.first,
'last': args.last,
},
'chars': chars,
'created': time.ctime()
}))
_CLEAN_RE = re.compile(r'[^a-z0-9_]', re.I)
def clean_str(s):
return _CLEAN_RE.sub('_', s)
if __name__ == "__main__":
parser=argparse.ArgumentParser(description='Fixed fonts converter')
parser.add_argument('-f', '--font', type=str, required=True, help='PIL font filename')
parser.add_argument('-n', '--name', type=clean_str, required=True, help='Font name')
parser.add_argument('-c', '--charset', type=clean_str, required=True, help='Charset')
parser.add_argument('--first', type=int, help='First character', default=1)
parser.add_argument('--last', type=int, help='Last character', default=255)
parser.add_argument('-t', '--template', type=str, help='Template filename', default='template.c')
main(parser.parse_args(sys.argv[1:]))

View file

@ -0,0 +1,51 @@
{%- set header_id -%}
_EXTRAS_FONTS_FONT_{{ font.name|upper }}_{{ font.size[0] }}X{{ font.size[1] }}_{{ font.charset|upper }}_H_
{%- endset -%}
{%- set font_size -%}
{{ font.size[0] }}x{{ font.size[1] }}
{%- endset -%}
{%- set font_prefix -%}
_fonts_{{ font.name|lower }}_{{ font_size }}_{{ font.charset|lower }}
{%- endset -%}
/**
* This file contains generated binary font data.
*
* Font: {{ font.name }}
* Size: {{ font_size }}
* Charset: {{ font.charset }}
* {{ chars|length }} characters ({{ font.first }}..{{ font.last }})
*
* License: FIXME
*
* Generated: {{ created }}
*/
#ifndef {{ header_id }}
#define {{ header_id }}
static const uint8_t {{ font_prefix }}_bitmaps[] = {
{%- for char in chars %}
/* {{ 'Index: 0x%02x, char: \\x%02x, offset: 0x%04x'|format(char.index, char.code, char.offset) }} */
{%- for row in char.rows %}
{% for byte in row.data %}{{ '0x%02x'|format(byte) }}, {% endfor -%} /* {{ row.asc }} */
{%- endfor -%}
{%- endfor %}
};
const font_char_desc_t {{ font_prefix }}_descriptors[] = {
{%- for char in chars %}
{ {{ '0x%02x'|format(font.size[0]) }}, {{ '0x%04x'|format(char.offset) }} }, /* {{ 'Index: 0x%02x, char: \\x%02x'|format(char.index, char.code) }} */
{%- endfor %}
};
const font_info_t {{ font_prefix }}_info =
{
.height = {{ font.size[1] }}, /* Character height */
.c = 0, /* C */
.char_start = {{ font.first }}, /* Start character */
.char_end = {{ font.last }}, /* End character */
.char_descriptors = {{ font_prefix }}_descriptors, /* Character descriptor array */
.bitmap = {{ font_prefix }}_bitmaps, /* Character bitmap array */
};
#endif /* {{ header_id }} */

View file

@ -3,10 +3,11 @@
*
* Copyright (c) 2016 urx (https://github.com/urx),
* Ruslan V. Uss (https://github.com/UncleRus)
* Zaltora (https://github.com/Zaltora)
*
* MIT Licensed as described in the file LICENSE
*
* @todo Scrolling, fonts
* @todo HW scrolling, sprites
*/
#include "ssd1306.h"
#include <stdio.h>
@ -62,12 +63,22 @@
#define SSD1306_CHARGE_PUMP_EN (0x14)
#define SSD1306_CHARGE_PUMP_DIS (0x10)
#define SSD1306_SCROLL_HOR_LEFT (0x27)
#define SSD1306_SCROLL_HOR_RIGHT (0x26)
#define SSD1306_SCROLL_HOR_VER_LEFT (0x2A)
#define SSD1306_SCROLL_HOR_VER_RIGHT (0x29)
#define SSD1306_SCROLL_ENABLE (0x2F)
#define SSD1306_SCROLL_DISABLE (0x2E)
#ifdef SSD1306_DEBUG
#define debug(fmt, ...) printf("%s: " fmt "\n", "SSD1306", ## __VA_ARGS__)
#else
#define debug(fmt, ...)
#endif
#define abs(x) ((x)<0 ? -(x) : (x))
#define swap(x, y) do { typeof(x) temp##x##y = x; x = y; y = temp##x##y; } while (0)
/* Issue a command to SSD1306 device
* I2C proto format:
* |S|Slave Address|W|ACK|0x00|Command|Ack|P|
@ -403,4 +414,603 @@ int ssd1306_load_xbm(const ssd1306_t *dev, uint8_t *xbm, uint8_t *fb)
return ssd1306_load_frame_buffer(dev, fb);
}
int ssd1306_draw_pixel(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ssd1306_color_t color)
{
uint16_t index;
if ((x >= dev->width) || (x < 0) || (y >= dev->height) || (y < 0))
return -EINVAL;
index = x + (y / 8) * dev->width;
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= (1 << (y & 7));
break;
case OLED_COLOR_BLACK:
fb[index] &= ~(1 << (y & 7));
break;
case OLED_COLOR_INVERT:
fb[index] ^= (1 << (y & 7));
break;
default:
break;
}
return 0;
}
int ssd1306_draw_hline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, ssd1306_color_t color)
{
uint16_t index;
uint8_t mask, t;
// boundary check
if ((x >= dev->width) || (x < 0) || (y >= dev->height) || (y < 0))
return -EINVAL;
if (w == 0)
return -EINVAL;
if (x + w > dev->width)
w = dev->width - x;
t = w;
index = x + (y / 8) * dev->width;
mask = 1 << (y & 7);
switch (color)
{
case OLED_COLOR_WHITE:
while (t--)
{
fb[index] |= mask;
++index;
}
break;
case OLED_COLOR_BLACK:
mask = ~mask;
while (t--)
{
fb[index] &= mask;
++index;
}
break;
case OLED_COLOR_INVERT:
while (t--)
{
fb[index] ^= mask;
++index;
}
break;
default:
break;
}
return 0;
}
int ssd1306_draw_vline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t h, ssd1306_color_t color)
{
uint16_t index;
uint8_t mask, mod, t;
// boundary check
if ((x >= dev->width) || (x < 0) || (y >= dev->height) || (y < 0))
return -EINVAL;
if (h == 0)
return -EINVAL;
if (y + h > dev->height)
h = dev->height - y;
t = h;
index = x + (y / 8) * dev->width;
mod = y & 7;
if (mod) // partial line that does not fit into byte at top
{
// Magic from Adafruit
mod = 8 - mod;
static const uint8_t premask[8] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
mask = premask[mod];
if (t < mod)
mask &= (0xFF >> (mod - t));
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
}
if (t < mod)
return 0;
t -= mod;
index += dev->width;
}
if (t >= 8) // byte aligned line at middle
{
switch (color)
{
case OLED_COLOR_WHITE:
do
{
fb[index] = 0xff;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_BLACK:
do
{
fb[index] = 0x00;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_INVERT:
do
{
fb[index] = ~fb[index];
index += dev->width;
t -= 8;
} while (t >= 8);
break;
default:
break;
}
}
if (t) // partial line at bottom
{
mod = t & 7;
static const uint8_t postmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
mask = postmask[mod];
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
}
}
return 0;
}
int ssd1306_draw_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, uint8_t h, ssd1306_color_t color)
{
int err = 0;
if ((err = ssd1306_draw_hline(dev, fb, x, y, w, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x, y + h - 1, w, color)))
return err;
if ((err = ssd1306_draw_vline(dev, fb, x, y, h, color)))
return err;
return ssd1306_draw_vline(dev, fb, x + w - 1, y, h, color);
}
int ssd1306_fill_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, uint8_t h, ssd1306_color_t color)
{
// Can be optimized?
uint8_t i;
int err = 0;
for (i = x; i < x + w; ++i)
if ((err = ssd1306_draw_vline(dev, fb, i, y, h, color)))
return err;
return 0;
}
int ssd1306_draw_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0, uint8_t r, ssd1306_color_t color)
{
// Refer to http://en.wikipedia.org/wiki/Midpoint_circle_algorithm for the algorithm
int8_t x = r;
int8_t y = 1;
int16_t radius_err = 1 - x;
int err = 0;
if (r == 0)
return -EINVAL;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - r, y0, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 + r, y0, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0 - r, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0 + r, color)))
return err;
while (x >= y)
{
if ((err = ssd1306_draw_pixel(dev, fb, x0 + x, y0 + y, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - x, y0 + y, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 + x, y0 - y, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - x, y0 - y, color)))
return err;
if (x != y)
{
/* Otherwise the 4 drawings below are the same as above, causing
* problem when color is INVERT
*/
if ((err = ssd1306_draw_pixel(dev, fb, x0 + y, y0 + x, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - y, y0 + x, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 + y, y0 - x, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - y, y0 - x, color)))
return err;
}
++y;
if (radius_err < 0) {
radius_err += 2 * y + 1;
}
else {
--x;
radius_err += 2 * (y - x + 1);
}
}
return 0;
}
int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0, uint8_t r, ssd1306_color_t color)
{
int8_t x = 1;
int8_t y = r;
int16_t radius_err = 1 - y;
int8_t x1;
int err = 0;
if (r == 0)
return -EINVAL;
if ((err = ssd1306_draw_vline(dev, fb, x0, y0 - r, 2 * r + 1, color))) // Center vertical line
return err;
while (y >= x)
{
if ((err = ssd1306_draw_vline(dev, fb, x0 - x, y0 - y, 2 * y + 1, color)))
return err;
if ((err = ssd1306_draw_vline(dev, fb, x0 + x, y0 - y, 2 * y + 1, color)))
return err;
if (color != OLED_COLOR_INVERT)
{
if ((err = ssd1306_draw_vline(dev, fb, x0 - y, y0 - x, 2 * x + 1, color)))
return err;
if ((err = ssd1306_draw_vline(dev, fb, x0 + y, y0 - x, 2 * x + 1, color)))
return err;
}
++x;
if (radius_err < 0) {
radius_err += 2 * x + 1;
}
else {
--y;
radius_err += 2 * (x - y + 1);
}
}
if (color == OLED_COLOR_INVERT)
{
x1 = x; // Save where we stopped
y = 1;
x = r;
radius_err = 1 - x;
if ((err = ssd1306_draw_hline(dev, fb, x0 + x1, y0, r - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - r, y0, r - x1 + 1, color)))
return err;
while (x >= y)
{
if ((err = ssd1306_draw_hline(dev, fb, x0 + x1, y0 - y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 + x1, y0 + y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 - y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 + y, x - x1 + 1, color)))
return err;
++y;
if (radius_err < 0) {
radius_err += 2 * y + 1;
}
else {
--x;
radius_err += 2 * (y - x + 1);
}
}
}
return 0;
}
int ssd1306_draw_line(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0,
int16_t x1, int16_t y1, ssd1306_color_t color)
{
if ((x0 >= dev->width) || (x0 < 0) || (y0 >= dev->height) || (y0 < 0))
return -EINVAL;
if ((x1 >= dev->width) || (x1 < 0) || (y1 >= dev->height) || (y1 < 0))
return -EINVAL;
int err;
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t errx = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;
}
for (; x0 <= x1; x0++) {
if (steep) {
if ((err = ssd1306_draw_pixel(dev, fb, y0, x0, color)))
return err;
} else {
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0, color)))
return err;
}
errx -= dy;
if (errx < 0) {
y0 += ystep;
errx += dx;
}
}
return 0;
}
int ssd1306_draw_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
{
int err;
if ((err = ssd1306_draw_line(dev, fb, x0, y0, x1, y1, color)))
return err;
if ((err = ssd1306_draw_line(dev, fb, x1, y1, x2, y2, color)))
return err;
return ssd1306_draw_line(dev, fb, x2, y2, x0, y0, color);
}
int ssd1306_fill_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
{
int16_t a, b, y, last;
int err;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
swap(y0, y1); swap(x0, x1);
}
if (y1 > y2) {
swap(y2, y1); swap(x2, x1);
}
if (y0 > y1) {
swap(y0, y1); swap(x0, x1);
}
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if (x1 < a) a = x1;
else if (x1 > b) b = x1;
if (x2 < a) a = x2;
else if (x2 > b) b = x2;
if ((err = ssd1306_draw_hline(dev, fb, a, y0, b - a + 1, color)))
return err;
return 0;
}
int16_t
dx01 = x1 - x0,
dy01 = y1 - y0,
dx02 = x2 - x0,
dy02 = y2 - y0,
dx12 = x2 - x1,
dy12 = y2 - y1,
sa = 0,
sb = 0;
// For upper part of triangle, find scanline crossings for segments
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
// is included here (and second loop will be skipped, avoiding a /0
// error there), otherwise scanline y1 is skipped here and handled
// in the second loop...which also avoids a /0 error here if y0=y1
// (flat-topped triangle).
if (y1 == y2) last = y1; // Include y1 scanline
else last = y1 - 1; // Skip it
for (y = y0; y <= last; y++) {
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
/* longhand:
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b) swap(a, b);
if ((err = ssd1306_draw_hline(dev, fb, a, y, b - a + 1, color)))
return err;
}
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for (; y <= y2; y++) {
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
/* longhand:
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b) swap(a, b);
if ((err = ssd1306_draw_hline(dev, fb, a, y, b - a + 1, color)))
return err;
}
return 0;
}
int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb,
const font_info_t *font, uint8_t x, uint8_t y, char c,
ssd1306_color_t foreground, ssd1306_color_t background)
{
uint8_t i, j;
const uint8_t *bitmap;
uint8_t line = 0;
int err;
if (font == NULL)
return 0;
const font_char_desc_t *d = font_get_char_desc(font, c);
if (d == NULL)
return 0;
bitmap = font->bitmap + d->offset;
for (j = 0; j < font->height; ++j) {
for (i = 0; i < d->width; ++i) {
if (i % 8 == 0) {
line = bitmap[(d->width + 7) / 8 * j + i / 8]; // line data
}
if (line & 0x80) {
err = ssd1306_draw_pixel(dev, fb, x + i, y + j, foreground);
}
else {
switch (background)
{
case OLED_COLOR_TRANSPARENT:
// Not drawing for transparent background
break;
case OLED_COLOR_WHITE:
case OLED_COLOR_BLACK:
err = ssd1306_draw_pixel(dev, fb, x + i, y + j, background);
break;
case OLED_COLOR_INVERT:
// I don't know why I need invert background
break;
}
}
if (err) return -ERANGE ;
line = line << 1;
}
}
return d->width;
}
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb,
const font_info_t *font, uint8_t x, uint8_t y, char *str,
ssd1306_color_t foreground, ssd1306_color_t background)
{
uint8_t t = x;
int err;
if (font == NULL || str == NULL)
return 0;
while (*str)
{
if ((err = ssd1306_draw_char(dev, fb, font, x, y, *str, foreground, background)) < 0 )
return err;
x += err;
++str;
if (*str)
x += font->c;
}
return x - t;
}
int ssd1306_stop_scroll(const ssd1306_t *dev)
{
return ssd1306_command(dev, SSD1306_SCROLL_DISABLE);
}
int ssd1306_start_scroll_hori(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, ssd1306_scroll_t frame)
{
int err;
if (way)
{
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_LEFT)))
return err;
}
else
{
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_RIGHT)))
return err;
}
if (!ssd1306_command(dev, 0x00) && //dummy
!ssd1306_command(dev, (start&0x07)) &&
!ssd1306_command(dev, frame) &&
!ssd1306_command(dev, (stop&0x07)) &&
!ssd1306_command(dev, 0x00) && //dummy
!ssd1306_command(dev, 0xFF) && //dummy
!ssd1306_command(dev, SSD1306_SCROLL_ENABLE)) {
return 0;
}
return -EIO;
}
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame)
{
//this function dont work well if no vertical setting.
if ((!dy) || (dy > 63))
return -EINVAL;
int err;
//vertical scrolling selection (all screen)
if ((err = ssd1306_command(dev, 0xA3)))
return err;
if ((err = ssd1306_command(dev, 0)))
return err;
if ((err = ssd1306_command(dev, dev->height)))
return err;
if (way)
{
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_VER_LEFT)))
return err;
}
else
{
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_VER_RIGHT)))
return err;
}
if (!ssd1306_command(dev, 0x00) && //dummy
!ssd1306_command(dev, (start&0x07)) &&
!ssd1306_command(dev, frame) &&
!ssd1306_command(dev, (stop&0x07)) &&
!ssd1306_command(dev, dy) &&
!ssd1306_command(dev, SSD1306_SCROLL_ENABLE)) {
return 0;
}
return -EIO;
}

View file

@ -3,6 +3,7 @@
*
* Copyright (c) 2016 urx (https://github.com/urx),
* Ruslan V. Uss (https://github.com/UncleRus)
* Zaltora (https://github.com/Zaltora)
*
* MIT Licensed as described in the file LICENSE
*/
@ -12,6 +13,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <fonts/fonts.h>
#include "config.h"
@ -63,6 +65,33 @@ typedef enum
SSD1306_ADDR_MODE_PAGE
} ssd1306_mem_addr_mode_t;
/**
* Drawing color
*/
typedef enum
{
OLED_COLOR_TRANSPARENT = -1, //!< Transparent (not drawing)
OLED_COLOR_BLACK = 0, //!< Black (pixel off)
OLED_COLOR_WHITE = 1, //!< White (or blue, yellow, pixel on)
OLED_COLOR_INVERT = 2, //!< Invert pixel (XOR)
} ssd1306_color_t;
/**
* Scrolling time frame interval
*/
typedef enum
{
FRAME_5 = 0,
FRAME_64,
FRAME_128,
FRAME_256,
FRAME_3,
FRAME_4,
FRAME_25,
FRAME_2
} ssd1306_scroll_t;
/**
* Issue a single command on SSD1306.
* @param dev Pointer to device descriptor
@ -275,6 +304,192 @@ int ssd1306_set_deseltct_lvl(const ssd1306_t *dev, uint8_t lvl);
*/
int ssd1306_set_whole_display_lighting(const ssd1306_t *dev, bool light);
/**
* Draw one pixel
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x X coordinate
* @param y Y coordinate
* @param color Color of the pixel
* @return Non-zero if error occured
*/
int ssd1306_draw_pixel(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ssd1306_color_t color);
/**
* Draw a horizontal line
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x X coordinate or starting (left) point
* @param y Y coordinate or starting (left) point
* @param w Line width
* @param color Color of the line
* @return Non-zero if error occured
*/
int ssd1306_draw_hline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, ssd1306_color_t color);
/**
* Draw a vertical line
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x X coordinate or starting (top) point
* @param y Y coordinate or starting (top) point
* @param h Line height
* @param color Color of the line
* @return Non-zero if error occured
*/
int ssd1306_draw_vline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t h, ssd1306_color_t color);
/**
* Draw a line
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x0 First x point coordinate
* @param y0 First y point coordinate
* @param x1 Second x point coordinate
* @param y1 Second y point coordinate
* @param color Color of the line
* @return Non-zero if error occured
*/
int ssd1306_draw_line(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, ssd1306_color_t color);
/**
* Draw a rectangle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x X coordinate or starting (top left) point
* @param y Y coordinate or starting (top left) point
* @param w Rectangle width
* @param h Rectangle height
* @param color Color of the rectangle border
* @return Non-zero if error occured
*/
int ssd1306_draw_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, uint8_t h, ssd1306_color_t color);
/**
* Draw a filled rectangle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x X coordinate or starting (top left) point
* @param y Y coordinate or starting (top left) point
* @param w Rectangle width
* @param h Rectangle height
* @param color Color of the rectangle
* @return Non-zero if error occured
*/
int ssd1306_fill_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, uint8_t h, ssd1306_color_t color);
/**
* Draw a circle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x0 X coordinate or center
* @param y0 Y coordinate or center
* @param r Radius
* @param color Color of the circle border
* @return Non-zero if error occured
*/
int ssd1306_draw_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0, uint8_t r, ssd1306_color_t color);
/**
* Draw a filled circle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x0 X coordinate or center
* @param y0 Y coordinate or center
* @param r Radius
* @param color Color of the circle
* @return Non-zero if error occured
*/
int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0, uint8_t r, ssd1306_color_t color);
/**
* Draw a triangle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x0 First x point coordinate
* @param y0 First y point coordinate
* @param x1 Second x point coordinate
* @param y1 Second y point coordinate
* @param x2 third x point coordinate
* @param y2 third y point coordinate
* @param color Color of the triangle border
* @return Non-zero if error occured
*/
int ssd1306_draw_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, ssd1306_color_t color);
/**
* Draw a filled triangle
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param x0 First x point coordinate
* @param y0 First y point coordinate
* @param x1 Second x point coordinate
* @param y1 Second y point coordinate
* @param x2 third x point coordinate
* @param y2 third y point coordinate
* @param color Color of the triangle
* @return Non-zero if error occured
*/
int ssd1306_fill_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, ssd1306_color_t color);
/**
* Draw one character using currently selected font
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param font Pointer to font info structure
* @param x X position of character (top-left corner)
* @param y Y position of character (top-left corner)
* @param c The character to draw
* @param foreground Character color
* @param background Background color
* @return Width of the character or negative value if error occured
*/
int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char c, ssd1306_color_t foreground, ssd1306_color_t background);
/**
* Draw one character using currently selected font
* @param dev Pointer to device descriptor
* @param fb Pointer to framebuffer. Framebuffer size = width * height / 8
* @param font Pointer to font info structure
* @param x X position of character (top-left corner)
* @param y Y position of character (top-left corner)
* @param str The string to draw
* @param foreground Character color
* @param background Background color
* @return Width of the string or negative value if error occured
*/
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char *str, ssd1306_color_t foreground, ssd1306_color_t background);
/**
* Stop scrolling (the ram data needs to be rewritten)
* @param dev Pointer to device descriptor
* @return Non-zero if error occured
*/
int ssd1306_stop_scroll(const ssd1306_t *dev);
/**
* Start horizontal scrolling
* @param dev Pointer to device descriptor
* @param way Orientation ( true: left // false: right )
* @param start Page address start
* @param stop Page address stop
* @param frame Time interval between each scroll
* @return Non-zero if error occured
*/
int ssd1306_start_scroll_hori(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, ssd1306_scroll_t frame);
/**
* Start horizontal+vertical scrolling (cant vertical scrolling)
* @param dev Pointer to device descriptor
* @param way Orientation ( true: left // false: right )
* @param start Page address start
* @param stop Page address stop
* @param dy vertical size shifting (min : 1 // max: 63 )
* @param frame Time interval between each scroll
* @return Non-zero if error occured
*/
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame);
#ifdef __cplusplus
extern "C"
}