initialize repository
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
21
CMakeLists.txt
Normal file
21
CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
set(PICO_SDK_PATH /home/sl/pico-sdk)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(GPIOTest)
|
||||
|
||||
set(PICO_PSRAM_CS_PIN 47 CACHE STRING "GPIO used as Chip Select for PSRAM")
|
||||
set(PICO_PSRAM_SIZE_BYTES 8388608 CACHE STRING "PSRAM size in bytes")
|
||||
pico_sdk_init()
|
||||
|
||||
add_executable(program main.c st7789.c graphics.c utf8.c ds1302.c beep.c)
|
||||
target_link_libraries(program pico_stdlib pico_bootrom pico_rand hardware_gpio hardware_pwm hardware_spi hardware_regs hardware_psram pico_stdio_usb pico_time pico_sync)
|
||||
#target_compile_definitions(program PRIVATE PICO_PSRAM_CS_PIN=${PICO_PSRAM_CS_PIN} PICO_PSRAM_SIZE_BYTES=${PICO_PSRAM_CS_PIN})
|
||||
target_compile_definitions(program PRIVATE PICO_PSRAM_CS_PIN=0 PICO_PSRAM_SIZE_BYTES=8388608)
|
||||
|
||||
pico_enable_stdio_usb(program 1)
|
||||
|
||||
pico_embed_pt_in_binary(program "${CMAKE_CURRENT_LIST_DIR}/partition_table.json")
|
||||
|
||||
pico_add_extra_outputs(program)
|
||||
162
ds1302.c
Normal file
162
ds1302.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "ds1302.h"
|
||||
|
||||
void _prepare_read(uint8_t address);
|
||||
void _prepare_write(uint8_t address);
|
||||
uint8_t _read_byte();
|
||||
void _write_byte(uint8_t value);
|
||||
void _make_clock_cycle();
|
||||
|
||||
void _end_transfer();
|
||||
|
||||
#define REG_SECONDS 0x80 // SEC
|
||||
#define REG_MINUTES 0x82 // MIN
|
||||
#define REG_HOUR 0x84 // HR
|
||||
#define REG_DATE 0x86 // DATE
|
||||
#define REG_MONTH 0x88 // MONTH
|
||||
#define REG_DAY 0x8A // DAY
|
||||
#define REG_YEAR 0x8C // YEAR
|
||||
#define REG_WP 0x8E // CONTROL
|
||||
// TRICKLE CHARGER 1001000_ 0x90
|
||||
#define REG_BURST 0xBE // CLOCK BURST
|
||||
|
||||
#define REG_RAM00 0xC0
|
||||
#define REG_RAM_BURST 0xFE
|
||||
|
||||
void ds1302_init() {
|
||||
gpio_init(PIN_RTC_RESET);
|
||||
gpio_set_dir(PIN_RTC_RESET, GPIO_OUT);
|
||||
gpio_put(PIN_RTC_RESET, LOW);
|
||||
|
||||
gpio_init(PIN_RTC_CLOCK);
|
||||
gpio_set_dir(PIN_RTC_CLOCK, GPIO_OUT);
|
||||
gpio_put(PIN_RTC_CLOCK, LOW);
|
||||
|
||||
gpio_init(PIN_RTC_IO);
|
||||
gpio_set_dir(PIN_RTC_IO, GPIO_IN);
|
||||
}
|
||||
|
||||
int ds1302_is_clock_halted() {
|
||||
_prepare_read(REG_SECONDS);
|
||||
uint8_t seconds = _read_byte();
|
||||
_end_transfer();
|
||||
return (seconds & 0b10000000);
|
||||
}
|
||||
|
||||
void ds1302_get_datetime(DateTime *dt) {
|
||||
_prepare_read(REG_BURST);
|
||||
dt->second = ds1302_decode_bcd(_read_byte() & 0b01111111);
|
||||
dt->minute = ds1302_decode_bcd(_read_byte() & 0b01111111);
|
||||
dt->hour = ds1302_decode_bcd(_read_byte() & 0b00111111);
|
||||
dt->day = ds1302_decode_bcd(_read_byte() & 0b00111111);
|
||||
dt->month = ds1302_decode_bcd(_read_byte() & 0b00011111);
|
||||
dt->dow = ds1302_decode_bcd(_read_byte() & 0b00000111);
|
||||
dt->year = ds1302_decode_bcd(_read_byte() & 0b01111111);
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_set_datetime(DateTime *dt) {
|
||||
// disable write protection
|
||||
_prepare_write(REG_WP);
|
||||
_write_byte(0b00000000); // 0, false
|
||||
_end_transfer();
|
||||
// OR call writeProtect(0)
|
||||
|
||||
_prepare_write(REG_BURST);
|
||||
_write_byte(ds1302_encode_bcd(dt->second % 60));
|
||||
_write_byte(ds1302_encode_bcd(dt->minute % 60));
|
||||
_write_byte(ds1302_encode_bcd(dt->hour % 24));
|
||||
_write_byte(ds1302_encode_bcd(dt->day % 32));
|
||||
_write_byte(ds1302_encode_bcd(dt->month % 13));
|
||||
_write_byte(ds1302_encode_bcd(dt->dow % 8));
|
||||
_write_byte(ds1302_encode_bcd(dt->year % 100));
|
||||
_write_byte(0b10000000);
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_halt() {
|
||||
_prepare_write(REG_SECONDS);
|
||||
_write_byte(0b10000000);
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void _prepare_read(uint8_t address) {
|
||||
gpio_set_dir(PIN_RTC_IO, GPIO_OUT);
|
||||
gpio_put(PIN_RTC_RESET, HIGH);
|
||||
uint8_t command = 0b10000001 | address;
|
||||
_write_byte(command);
|
||||
gpio_set_dir(PIN_RTC_IO, GPIO_IN);
|
||||
}
|
||||
|
||||
void _prepare_write(uint8_t address) {
|
||||
gpio_set_dir(PIN_RTC_IO, GPIO_OUT);
|
||||
gpio_put(PIN_RTC_RESET, HIGH);
|
||||
uint8_t command = 0b10000000 | address;
|
||||
_write_byte(command);
|
||||
}
|
||||
|
||||
void _end_transfer() { gpio_put(PIN_RTC_RESET, LOW); }
|
||||
|
||||
uint8_t _read_byte() {
|
||||
uint8_t byte = 0;
|
||||
for (uint8_t b = 0; b < 8; b++) {
|
||||
if (gpio_get(PIN_RTC_IO) == HIGH)
|
||||
byte |= 0x01 << b;
|
||||
_make_clock_cycle();
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
void _write_byte(uint8_t value) {
|
||||
for (uint8_t b = 0; b < 8; b++) {
|
||||
gpio_put(PIN_RTC_IO, (value & 0x01) ? HIGH : LOW);
|
||||
_make_clock_cycle();
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _make_clock_cycle() {
|
||||
gpio_put(PIN_RTC_CLOCK, HIGH);
|
||||
sleep_us(1);
|
||||
gpio_put(PIN_RTC_CLOCK, LOW);
|
||||
sleep_us(1);
|
||||
}
|
||||
|
||||
void ds1302_get_ram_byte(uint8_t addr, uint8_t *data) {
|
||||
_prepare_read(addr);
|
||||
*data = _read_byte();
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_set_ram_byte(uint8_t addr, uint8_t *data) {
|
||||
_prepare_write(addr);
|
||||
_write_byte(*data);
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_set_write_protection(int enable) {
|
||||
_prepare_write(REG_WP);
|
||||
_write_byte(enable);
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_write_ram_bulk(const uint8_t *data, int len) {
|
||||
if (len <= 0 || len > 31) {
|
||||
return;
|
||||
}
|
||||
_prepare_write(REG_RAM_BURST);
|
||||
for (int i = 0; i < len; i++) {
|
||||
_write_byte(data[i]);
|
||||
}
|
||||
_end_transfer();
|
||||
}
|
||||
|
||||
void ds1302_read_ram_bulk(uint8_t *data, int len) {
|
||||
if (len <= 0 || len > 31) {
|
||||
return;
|
||||
}
|
||||
_prepare_read(REG_RAM_BURST);
|
||||
for (int i = 0; i < len; i++) {
|
||||
data[i] = _read_byte();
|
||||
}
|
||||
_end_transfer();
|
||||
}
|
||||
84
ds1302.h
Normal file
84
ds1302.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Ds1302.h
|
||||
*
|
||||
* @version 1.0.3
|
||||
* @author Rafa Couto <caligari@treboada.net>
|
||||
* @license GNU Affero General Public License v3.0
|
||||
* @see https://github.com/Treboada/Ds1302
|
||||
*
|
||||
* adapted for Pico by Ken Webb, 27 Oct 2022
|
||||
*
|
||||
* 31 Oct 2022
|
||||
* I am using additional ideas and code on ds1302 Ram from :
|
||||
* https://github.com/msparks/arduino-ds1302 Matt Sparks no license?
|
||||
* "Arduino library for the DS1302 Real Time Clock chip"
|
||||
* includes "Setting and accessing the 31 bytes of static RAM. Single-byte and multi-byte (burst) modes are supported."
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DS_1302_H
|
||||
#define _DS_1302_H
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pins.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// the following defines are from Arduino.h
|
||||
// these are needed in Ds1302.cpp
|
||||
#define HIGH 0x1
|
||||
#define LOW 0x0
|
||||
|
||||
typedef struct {
|
||||
uint8_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint8_t dow;
|
||||
} DateTime;
|
||||
|
||||
/**
|
||||
* Months of year
|
||||
*/
|
||||
enum MONTH {
|
||||
MONTH_JAN = 1,
|
||||
MONTH_FEB = 2,
|
||||
MONTH_MAR = 3,
|
||||
MONTH_APR = 4,
|
||||
MONTH_MAY = 5,
|
||||
MONTH_JUN = 6,
|
||||
MONTH_JUL = 7,
|
||||
MONTH_AUG = 8,
|
||||
MONTH_SET = 9,
|
||||
MONTH_OCT = 10,
|
||||
MONTH_NOV = 11,
|
||||
MONTH_DEC = 12
|
||||
};
|
||||
|
||||
/**
|
||||
* Days of week
|
||||
*/
|
||||
enum DOW { DOW_MON = 1, DOW_TUE = 2, DOW_WED = 3, DOW_THU = 4, DOW_FRI = 5, DOW_SAT = 6, DOW_SUN = 7 };
|
||||
|
||||
void ds1302_init();
|
||||
int ds1302_is_clock_halted();
|
||||
void ds1302_halt();
|
||||
void ds1302_get_datetime(DateTime *dt);
|
||||
void ds1302_set_datetime(DateTime *dt);
|
||||
|
||||
void ds1302_get_ram_byte(uint8_t addr, uint8_t *data);
|
||||
void ds1302_set_ram_byte(uint8_t addr, uint8_t *data);
|
||||
|
||||
void ds1302_set_write_protection(int enable);
|
||||
|
||||
void ds1302_write_ram_bulk(const uint8_t *data, int len);
|
||||
void ds1302_read_ram_bulk(uint8_t *data, int len);
|
||||
|
||||
inline uint8_t ds1302_encode_bcd(uint8_t dec) { return ((dec / 10 * 16) + (dec % 10)); }
|
||||
|
||||
inline uint8_t ds1302_decode_bcd(uint8_t bcd) { return ((bcd / 16 * 10) + (bcd % 16)); }
|
||||
|
||||
#endif // _DS_1302_H
|
||||
521
font_ubuntu.h
Normal file
521
font_ubuntu.h
Normal file
@@ -0,0 +1,521 @@
|
||||
// Header File for SSD1306 characters
|
||||
// Generated with TTF2BMH, edited manually
|
||||
// Font Ubuntu Regular
|
||||
// Font Size: 24
|
||||
const char GLYPH_MISSING[] = {254, 2, 194, 226, 98, 98, 226, 194, 130, 2, 254, 0, 255, 0, 0, 0, 192, 248,
|
||||
62, 15, 3, 0, 255, 0, 127, 64, 64, 64, 76, 76, 64, 64, 64, 64, 127, 0};
|
||||
const char GLYPH_EXCLAMATION_MARK[] = {254, 254, 63, 63, 7, 7};
|
||||
const char GLYPH_QUOTATION_MARK[] = {63, 63, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_NUMBER_SIGN[] = {192, 192, 192, 240, 254, 206, 192, 192, 192, 192, 192, 240, 254, 206, 192,
|
||||
48, 48, 252, 255, 51, 48, 48, 48, 48, 48, 252, 255, 51, 48, 48,
|
||||
0, 7, 7, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0};
|
||||
const char GLYPH_DOLLAR_SIGN[] = {240, 248, 152, 12, 12, 15, 15, 12, 12, 24, 0, 0, 1, 3, 3, 7, 6,
|
||||
12, 12, 24, 240, 224, 3, 7, 6, 6, 6, 62, 62, 6, 7, 3, 1};
|
||||
const char GLYPH_PERCENT_SIGN[] = {248, 252, 14, 6, 6, 14, 252, 248, 0, 0, 128, 224, 120, 60, 14, 2, 0,
|
||||
1, 3, 7, 6, 6, 7, 195, 225, 120, 30, 7, 1, 248, 252, 14, 6, 6,
|
||||
0, 0, 0, 0, 4, 7, 3, 1, 0, 0, 0, 0, 1, 3, 7, 6, 6};
|
||||
const char GLYPH_AMPERSAND[] = {0, 0, 120, 252, 142, 6, 6, 134, 206, 252, 120, 0, 0, 0, 0,
|
||||
240, 248, 12, 7, 7, 7, 15, 29, 57, 112, 192, 192, 112, 60, 12,
|
||||
0, 3, 3, 7, 6, 6, 6, 6, 6, 3, 3, 1, 3, 6, 4};
|
||||
const char GLYPH_APOSTROPHE[] = {63, 63, 0, 0, 0, 0};
|
||||
const char GLYPH_LEFT_PARENTHESIS[] = {128, 224, 120, 14, 3, 1, 255, 255, 0, 0, 0, 0, 0, 3, 15, 56, 96, 192};
|
||||
const char GLYPH_RIGHT_PARENTHESIS[] = {1, 3, 14, 120, 224, 128, 0, 0, 0, 0, 255, 255, 192, 96, 56, 15, 3, 0};
|
||||
const char GLYPH_ASTERISK[] = {16, 56, 48, 176, 238, 126, 238, 176, 48, 56, 16, 0, 0, 2, 7, 3, 0,
|
||||
1, 3, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_PLUS_SIGN[] = {0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 255,
|
||||
255, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_COMMA[] = {0, 0, 0, 0, 0, 0, 96, 127, 15};
|
||||
const char GLYPH_HYPHEN_MINUS[] = {0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_FULL_STOP[] = {0, 0, 0, 0, 0, 0, 7, 7, 7};
|
||||
const char GLYPH_SOLIDUS[] = {0, 0, 0, 0, 0, 0, 224, 248, 31, 7, 0, 0, 128, 224, 124,
|
||||
31, 3, 0, 0, 0, 240, 124, 15, 3, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_DIGIT_ZERO[] = {192, 240, 60, 12, 6, 6, 6, 6, 6, 12, 60, 240, 192, 63, 255, 192, 0, 0, 0, 0,
|
||||
0, 0, 0, 192, 255, 63, 0, 0, 3, 3, 6, 6, 6, 6, 7, 3, 1, 0, 0};
|
||||
const char GLYPH_DIGIT_ONE[] = {32, 112, 48, 56, 28, 254, 254, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_DIGIT_TWO[] = {8, 12, 14, 6, 6, 6, 6, 142, 252, 248, 0, 0, 192, 224, 112, 56, 12,
|
||||
6, 3, 1, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_DIGIT_THREE[] = {4, 12, 6, 6, 6, 6, 6, 134, 140, 252, 120, 0, 0, 0, 0, 3, 3, 3,
|
||||
3, 7, 7, 140, 252, 240, 3, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_DIGIT_FOUR[] = {0, 0, 0, 128, 192, 224, 56, 60, 30, 254, 254, 0, 0, 56, 60, 55, 51, 49, 48, 48,
|
||||
48, 48, 255, 255, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0};
|
||||
const char GLYPH_DIGIT_FIVE[] = {0, 0, 254, 254, 6, 6, 6, 6, 6, 6, 0, 0, 3, 3, 3, 3, 3,
|
||||
7, 6, 14, 252, 248, 3, 7, 6, 6, 6, 6, 6, 7, 3, 1, 0};
|
||||
const char GLYPH_DIGIT_SIX[] = {0, 192, 240, 56, 24, 12, 12, 6, 6, 6, 6, 0, 127, 255, 134, 3, 3, 3,
|
||||
3, 3, 7, 142, 252, 248, 0, 1, 3, 7, 6, 6, 6, 6, 7, 3, 1, 0};
|
||||
const char GLYPH_DIGIT_SEVEN[] = {6, 6, 6, 6, 6, 6, 134, 230, 118, 30, 14, 0, 0, 0, 0, 240, 126,
|
||||
15, 1, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_DIGIT_EIGHT[] = {112, 248, 140, 142, 6, 6, 6, 6, 6, 14, 140, 252, 112, 240, 249, 141, 7, 7, 3, 2,
|
||||
6, 7, 15, 157, 252, 240, 0, 1, 3, 7, 6, 6, 6, 6, 6, 7, 3, 1, 0};
|
||||
const char GLYPH_DIGIT_NINE[] = {240, 248, 28, 14, 6, 6, 6, 6, 12, 28, 248, 224, 1, 7, 7, 14, 12, 12,
|
||||
12, 140, 204, 246, 127, 15, 0, 6, 6, 6, 6, 3, 3, 3, 1, 0, 0, 0};
|
||||
const char GLYPH_COLON[] = {192, 192, 192, 1, 1, 1, 7, 7, 7};
|
||||
const char GLYPH_SEMICOLON[] = {192, 192, 192, 1, 1, 1, 96, 127, 15};
|
||||
const char GLYPH_LESS_THAN_SIGN[] = {0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 192, 128,
|
||||
28, 28, 28, 54, 54, 119, 99, 99, 193, 193, 193, 128, 128,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0};
|
||||
const char GLYPH_EQUALS_SIGN[] = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 49, 49, 49, 49, 49, 49,
|
||||
49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_GREATER_THAN_SIGN[] = {128, 192, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 128, 193, 193, 193, 99, 99, 119, 54, 54, 28, 28, 28,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_QUESTION_MARK[] = {4, 6, 6, 6, 6, 6, 142, 252, 120, 0, 0, 0, 56, 62,
|
||||
7, 3, 1, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0};
|
||||
const char GLYPH_COMMERCIAL_AT[] = {0, 192, 240, 120, 24, 12, 12, 142, 198, 198, 198, 198, 198, 198, 204, 12,
|
||||
255, 255, 129, 0, 0, 126, 255, 195, 129, 0, 0, 0, 0, 255, 255, 0,
|
||||
0, 3, 15, 30, 24, 56, 48, 113, 99, 99, 99, 99, 99, 97, 99, 3};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_A[] = {0, 0, 0, 0, 0, 192, 240, 60, 14, 60, 240, 192, 0, 0, 0, 0, 0,
|
||||
0, 0, 224, 248, 62, 55, 49, 48, 48, 48, 49, 55, 62, 248, 224, 0, 0,
|
||||
4, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 4};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_B[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 12, 156, 248, 240, 0,
|
||||
255, 255, 6, 6, 6, 6, 6, 6, 6, 7, 15, 141, 248, 240,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_C[] = {128, 240, 120, 28, 12, 14, 6, 6, 6, 6, 6, 12, 12,
|
||||
63, 255, 224, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 7, 3};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_D[] = {254, 254, 6, 6, 6, 6, 6, 6, 14, 12, 12, 24, 120, 224, 128,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 224, 127, 31,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_E[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 255, 255, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_F[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 6, 255, 255, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_G[] = {128, 240, 120, 28, 12, 6, 6, 6, 6, 6, 6, 12, 4,
|
||||
63, 255, 224, 128, 0, 0, 0, 0, 0, 0, 0, 252, 252,
|
||||
0, 0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 7, 3};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_H[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254,
|
||||
255, 255, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 255, 255,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_I[] = {254, 254, 255, 255, 7, 7};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_J[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 128, 255, 255, 2, 3, 6, 6, 6, 6, 6, 7, 3, 1, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_K[] = {254, 254, 0, 0, 128, 192, 96, 48, 24, 12, 6, 2, 0, 0,
|
||||
255, 255, 6, 15, 29, 24, 56, 112, 224, 192, 128, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 6, 4};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_L[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_M[] = {0, 254, 126, 60, 240, 192, 0, 0, 0, 0, 0, 0, 192, 240, 60, 126,
|
||||
255, 255, 0, 0, 0, 3, 15, 124, 240, 240, 124, 15, 3, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_N[] = {254, 252, 28, 56, 112, 192, 128, 0, 0, 0, 0, 0, 0, 254, 254,
|
||||
255, 255, 0, 0, 0, 0, 1, 3, 14, 28, 56, 112, 192, 255, 255,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_O[] = {192, 240, 120, 28, 12, 14, 6, 6, 6, 6, 14, 12, 28, 120, 240, 192,
|
||||
63, 255, 224, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 224, 255, 31,
|
||||
0, 0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_P[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 12, 28, 248, 240,
|
||||
255, 255, 12, 12, 12, 12, 12, 12, 12, 6, 7, 3, 1,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_Q[] = {192, 240, 120, 28, 12, 14, 6, 6, 6, 6, 14, 12, 28, 120, 240, 192,
|
||||
63, 255, 224, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 224, 127, 31,
|
||||
0, 0, 1, 3, 3, 6, 6, 30, 62, 118, 98, 99, 193, 193, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_R[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 12, 28, 248, 240, 0,
|
||||
255, 255, 12, 12, 12, 12, 12, 12, 60, 118, 231, 195, 1, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 6};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_S[] = {248, 252, 140, 6, 6, 6, 6, 6, 6, 14, 4, 0, 0, 1, 1, 3, 3, 6,
|
||||
6, 12, 12, 24, 248, 224, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_T[] = {6, 6, 6, 6, 6, 6, 254, 254, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 255,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_U[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254,
|
||||
127, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 255, 127,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_V[] = {6, 30, 252, 224, 0, 0, 0, 0, 0, 0, 0, 0, 224, 252, 30, 2,
|
||||
0, 0, 0, 7, 31, 252, 224, 128, 128, 224, 252, 31, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 7, 7, 3, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_W[] = {
|
||||
14, 254, 248, 0, 0, 0, 0, 0, 128, 248, 120, 224, 0, 0, 0, 0, 0, 0, 1, 31, 255, 240, 0, 224, 252, 31,
|
||||
3, 0, 3, 31, 252, 224, 0, 240, 0, 0, 0, 1, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 7, 7};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_X[] = {2, 6, 28, 56, 224, 192, 0, 0, 192, 224, 56, 28, 6, 2,
|
||||
0, 0, 128, 224, 112, 57, 15, 15, 57, 112, 224, 128, 0, 0,
|
||||
4, 7, 3, 1, 0, 0, 0, 0, 0, 0, 1, 3, 7, 4};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_Y[] = {2, 14, 60, 240, 192, 0, 0, 0, 0, 192, 240, 60, 14, 2,
|
||||
0, 0, 0, 0, 1, 7, 254, 254, 7, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_CAPITAL_LETTER_Z[] = {6, 6, 6, 6, 6, 6, 6, 134, 198, 102, 54, 30, 14,
|
||||
0, 128, 224, 112, 24, 12, 7, 1, 0, 0, 0, 0, 0,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_LEFT_SQUARE_BRACKET[] = {255, 255, 1, 1, 1, 1, 255, 255, 0, 0, 0, 0, 255, 255, 192, 192, 192, 192};
|
||||
const char GLYPH_REVERSE_SOLIDUS[] = {7, 31, 248, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 31, 124,
|
||||
224, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 124, 240, 128};
|
||||
const char GLYPH_RIGHT_SQUARE_BRACKET[] = {1, 1, 1, 1, 255, 255, 0, 0, 0, 0, 255, 255, 192, 192, 192, 192, 255, 255};
|
||||
const char GLYPH_CIRCUMFLEX_ACCENT[] = {0, 128, 224, 240, 124, 62, 14, 62, 124, 240, 224, 128, 0, 2, 7, 3, 1, 0, 0, 0,
|
||||
0, 0, 1, 3, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LOW_LINE[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192};
|
||||
const char GLYPH_GRAVE_ACCENT[] = {1, 3, 7, 14, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_A[] = {0, 96, 96, 96, 96, 96, 96, 96, 192, 192, 128, 224, 240, 48, 24, 24, 24,
|
||||
24, 24, 24, 255, 255, 1, 3, 7, 6, 6, 6, 6, 6, 6, 7, 7};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_B[] = {255, 255, 192, 96, 96, 96, 96, 96, 192, 192, 128, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 193, 255, 126,
|
||||
3, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_C[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 96, 126, 255, 129, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 3, 3, 6, 6, 6, 6, 6, 7};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_D[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 192, 255, 255,
|
||||
126, 255, 193, 0, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
0, 1, 3, 3, 7, 6, 6, 6, 6, 6, 7, 3};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_E[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 224, 192, 128, 0,
|
||||
126, 255, 153, 24, 24, 24, 24, 24, 24, 24, 25, 31, 30,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_F[] = {252, 255, 99, 97, 97, 97, 97, 1, 255, 255, 0, 0,
|
||||
0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_G[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 96, 224, 192,
|
||||
62, 255, 193, 128, 0, 0, 0, 0, 0, 128, 255, 255,
|
||||
0, 96, 193, 193, 195, 195, 195, 195, 227, 113, 63, 31};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_H[] = {255, 255, 96, 96, 96, 96, 96, 224, 192, 192, 0, 255, 255, 0, 0, 0, 0,
|
||||
0, 0, 1, 255, 255, 7, 7, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_I[] = {227, 227, 255, 255, 7, 7};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_J[] = {0, 0, 227, 227, 0, 0, 255, 255, 192, 224, 127, 63};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_K[] = {255, 255, 0, 0, 0, 0, 128, 192, 96, 32, 32, 0, 255, 255, 24, 60, 54, 115,
|
||||
225, 192, 128, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 1, 3, 7, 6, 4};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_L[] = {255, 255, 0, 0, 255, 255, 0, 0, 3, 7, 6, 6};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_M[] = {192, 224, 96, 96, 96, 96, 96, 224, 192, 192, 64, 96, 96, 96, 96, 224,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_N[] = {192, 224, 96, 96, 96, 96, 96, 224, 192, 192, 0, 255, 255, 0, 0, 0, 0,
|
||||
0, 0, 1, 255, 255, 7, 7, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_O[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 192, 192, 128, 0,
|
||||
126, 255, 129, 0, 0, 0, 0, 0, 0, 0, 131, 255, 126,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_P[] = {192, 224, 96, 96, 96, 96, 96, 224, 192, 192, 128, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 131, 255, 126,
|
||||
255, 255, 3, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_Q[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 96, 224, 192,
|
||||
126, 255, 129, 0, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 3, 255, 255};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_R[] = {192, 224, 96, 96, 96, 96, 96, 96, 255, 255, 0, 0,
|
||||
0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_S[] = {128, 192, 224, 96, 96, 96, 96, 96, 224, 0, 7, 15, 12, 28, 24,
|
||||
24, 56, 48, 240, 224, 3, 6, 6, 6, 6, 6, 6, 7, 3, 1};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_T[] = {254, 254, 96, 96, 96, 96, 96, 0, 255, 255, 0, 0,
|
||||
0, 0, 0, 0, 1, 3, 7, 6, 6, 6, 6, 3};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_U[] = {224, 224, 0, 0, 0, 0, 0, 0, 0, 224, 224, 255, 255, 128, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 0, 3, 3, 7, 6, 6, 6, 6, 6, 7, 3};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_V[] = {96, 224, 192, 0, 0, 0, 0, 0, 0, 192, 224, 96, 0, 3, 31, 252, 240, 128,
|
||||
128, 240, 252, 31, 3, 0, 0, 0, 0, 0, 3, 7, 7, 3, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_W[] = {
|
||||
96, 224, 128, 0, 0, 0, 0, 0, 224, 224, 128, 0, 0, 0, 0, 0, 128, 224, 0, 7, 63, 252, 224, 0, 224, 254, 31,
|
||||
1, 31, 252, 224, 0, 224, 252, 63, 7, 0, 0, 0, 1, 7, 7, 7, 1, 0, 0, 0, 0, 7, 7, 7, 1, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_X[] = {32, 96, 224, 128, 0, 0, 0, 0, 0, 128, 224, 96, 32,
|
||||
0, 0, 128, 195, 231, 126, 24, 126, 231, 195, 128, 0, 0,
|
||||
4, 6, 7, 1, 0, 0, 0, 0, 0, 1, 7, 6, 4};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_Y[] = {32, 224, 192, 0, 0, 0, 0, 0, 0, 192, 224, 32,
|
||||
0, 1, 15, 62, 248, 192, 0, 224, 252, 31, 3, 0,
|
||||
192, 192, 192, 192, 97, 127, 31, 7, 0, 0, 0, 0};
|
||||
const char GLYPH_LATIN_SMALL_LETTER_Z[] = {96, 96, 96, 96, 96, 96, 96, 224, 224, 224, 0, 128, 224, 112, 56,
|
||||
12, 7, 3, 1, 0, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_LEFT_CURLY_BRACKET[] = {0, 0, 254, 255, 3, 1, 1, 24, 60, 247, 227,
|
||||
0, 0, 0, 0, 0, 63, 127, 224, 192, 192};
|
||||
const char GLYPH_VERTICAL_LINE[] = {255, 255, 255, 255, 255, 255};
|
||||
const char GLYPH_RIGHT_CURLY_BRACKET[] = {1, 1, 3, 255, 254, 0, 0, 0, 0, 0, 227,
|
||||
247, 60, 24, 192, 192, 224, 127, 63, 0, 0};
|
||||
const char GLYPH_NUMERO_SIGN[] = {254, 254, 28, 56, 224, 192, 0, 0, 0, 0, 0, 0, 254, 254, 255, 255, 0, 0, 0, 1, 7,
|
||||
14, 56, 112, 192, 128, 255, 255, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_BE[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 255, 255, 3, 3, 3, 3,
|
||||
3, 3, 6, 142, 252, 248, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_GHE[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 6, 255, 255, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_DE[] = {
|
||||
0, 0, 0, 0, 0, 0, 254, 254, 6, 6, 6, 6, 6, 6, 254, 254, 0, 0, 0, 0, 0, 0, 192, 252, 63, 3, 0,
|
||||
0, 0, 0, 0, 0, 255, 255, 0, 0, 254, 254, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 254, 254};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_IO[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 255, 255, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_ZHE[] = {2, 6, 12, 24, 48, 96, 192, 128, 0, 0, 254, 254, 0, 0, 128, 192, 96,
|
||||
0, 0, 128, 192, 96, 56, 28, 7, 3, 2, 255, 255, 2, 3, 7, 28, 56,
|
||||
4, 7, 3, 1, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_ZE[] = {0, 4, 14, 6, 6, 6, 6, 6, 14, 140, 252, 240, 0,
|
||||
0, 0, 0, 6, 6, 6, 6, 6, 7, 15, 29, 248, 240,
|
||||
3, 3, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_I[] = {254, 254, 0, 0, 0, 0, 0, 0, 128, 192, 224, 112, 24, 252, 254,
|
||||
255, 255, 192, 96, 56, 28, 14, 7, 3, 1, 0, 0, 0, 255, 255,
|
||||
7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_SHORT_I[] = {
|
||||
254, 254, 0, 0, 0, 0, 0, 0, 128, 192, 224, 112, 24, 252, 254, 255, 255, 192, 96, 56, 28, 14, 7,
|
||||
3, 1, 0, 0, 0, 255, 255, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_KA[] = {254, 254, 0, 0, 128, 192, 96, 48, 24, 12, 6, 2, 0, 0,
|
||||
255, 255, 6, 15, 29, 24, 56, 112, 224, 192, 128, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 6, 4};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_EL[] = {0, 0, 0, 0, 0, 0, 254, 254, 6, 6, 6, 6, 6, 6, 254, 254,
|
||||
0, 0, 0, 128, 192, 252, 63, 3, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
6, 6, 7, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_PE[] = {254, 254, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 254, 254,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_U[] = {2, 14, 60, 240, 192, 0, 0, 0, 0, 0, 224, 252, 30, 2,
|
||||
0, 0, 0, 0, 3, 15, 188, 240, 124, 31, 3, 0, 0, 0,
|
||||
0, 6, 6, 6, 6, 7, 3, 1, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_EF[] = {128, 224, 112, 56, 24, 24, 12, 12, 12, 255, 255, 12, 12,
|
||||
12, 24, 24, 56, 15, 63, 112, 224, 192, 192, 128, 128, 128,
|
||||
255, 255, 128, 128, 128, 192, 192, 224, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 7, 7, 1, 1, 1, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_TSE[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 254, 254};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_CHE[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254,
|
||||
3, 15, 14, 28, 24, 24, 24, 24, 24, 24, 255, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_SHA[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0, 0, 0, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_SHCHA[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0, 0, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_HARD_SIGN[] = {6, 6, 6, 6, 6, 254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 255, 255, 3, 3, 3, 3, 3, 3, 6, 142, 252, 248,
|
||||
0, 0, 0, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_YERU[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254,
|
||||
255, 255, 3, 3, 3, 3, 3, 3, 6, 142, 252, 248, 0, 0, 0, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0, 0, 0, 0, 7};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_SOFT_SIGN[] = {254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 255, 3, 3, 3, 3, 3, 3, 6, 142, 252, 248,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_E[] = {12, 12, 6, 6, 6, 6, 6, 6, 12, 28, 120, 240, 192,
|
||||
0, 0, 0, 6, 6, 6, 6, 6, 6, 134, 230, 255, 63,
|
||||
3, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0, 0};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_YU[] = {254, 254, 0, 0, 0, 0, 128, 224, 120, 24, 12, 14, 6, 6, 6, 6,
|
||||
255, 255, 6, 6, 6, 6, 63, 255, 224, 128, 0, 0, 0, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 0, 1, 3, 3, 7, 6, 6, 6, 6};
|
||||
const char GLYPH_CYRILLIC_CAPITAL_LETTER_YA[] = {0, 240, 248, 28, 12, 6, 6, 6, 6, 6, 6, 6, 254, 254,
|
||||
0, 1, 131, 231, 126, 28, 12, 12, 12, 12, 12, 12, 255, 255,
|
||||
4, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_BE[] = {192, 248, 220, 198, 102, 99, 99, 99, 97, 193, 193, 129, 0,
|
||||
127, 255, 192, 0, 0, 0, 0, 0, 0, 0, 129, 255, 126,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 3, 3, 1, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_VE[] = {224, 224, 96, 96, 96, 96, 224, 192, 128, 0, 255, 255, 24, 24, 24,
|
||||
24, 28, 63, 247, 224, 7, 7, 6, 6, 6, 6, 6, 7, 3, 1};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_GHE[] = {224, 224, 96, 96, 96, 96, 96, 96, 96, 255, 255, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_DE[] = {0, 0, 0, 0, 0, 224, 224, 96, 96, 96, 96, 224, 224, 0, 0,
|
||||
0, 0, 0, 128, 240, 255, 15, 0, 0, 0, 0, 255, 255, 0, 0,
|
||||
126, 126, 6, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 126, 126};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_IO[] = {0, 128, 192, 199, 103, 103, 96, 96, 103, 231, 199, 128, 0,
|
||||
126, 255, 153, 24, 24, 24, 24, 24, 24, 24, 25, 31, 30,
|
||||
0, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_ZHE[] = {
|
||||
0, 32, 96, 224, 192, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 192, 224, 96, 0, 0, 0, 128, 193, 99, 54, 28, 8,
|
||||
255, 255, 8, 28, 54, 99, 193, 128, 0, 4, 6, 7, 1, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 1, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_ZE[] = {192, 96, 96, 96, 96, 96, 96, 96, 192, 192, 128, 0, 0, 0, 24, 24, 24,
|
||||
24, 24, 60, 255, 227, 3, 6, 6, 6, 6, 6, 6, 6, 7, 3, 1};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_I[] = {224, 224, 0, 0, 0, 0, 0, 0, 128, 192, 224, 224,
|
||||
255, 255, 192, 224, 112, 60, 30, 7, 3, 1, 255, 255,
|
||||
7, 7, 3, 1, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHORT_I[] = {224, 224, 1, 3, 7, 6, 6, 7, 131, 193, 224, 224,
|
||||
255, 255, 192, 224, 112, 60, 30, 7, 3, 1, 255, 255,
|
||||
7, 7, 3, 1, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_KA[] = {224, 224, 0, 0, 0, 0, 128, 192, 96, 32, 0, 0,
|
||||
255, 255, 24, 60, 54, 115, 225, 192, 128, 0, 0, 0,
|
||||
7, 7, 0, 0, 0, 0, 0, 1, 3, 7, 6, 4};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_EL[] = {0, 0, 0, 0, 224, 224, 96, 96, 96, 96, 96, 96, 224, 224,
|
||||
0, 0, 128, 224, 255, 31, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
6, 7, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_EM[] = {192, 224, 96, 192, 0, 0, 0, 0, 0, 0, 0, 192, 96, 224, 224,
|
||||
255, 255, 0, 1, 15, 56, 224, 128, 224, 56, 15, 1, 0, 255, 255,
|
||||
7, 7, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_EN[] = {224, 224, 0, 0, 0, 0, 0, 0, 0, 224, 224, 255, 255, 24, 24, 24, 24,
|
||||
24, 24, 24, 255, 255, 7, 7, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_PE[] = {224, 224, 96, 96, 96, 96, 96, 96, 96, 224, 224, 255, 255, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 7, 7, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_TE[] = {96, 96, 96, 96, 224, 224, 96, 96, 96, 96, 0, 0, 0, 0, 255,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_EF[] = {
|
||||
0, 128, 128, 192, 224, 96, 96, 255, 255, 96, 96, 224, 192, 128, 128, 0, 126, 255, 195, 0, 0, 0, 0, 255,
|
||||
255, 0, 0, 0, 0, 195, 255, 126, 0, 1, 3, 3, 7, 6, 6, 255, 255, 6, 6, 7, 3, 1, 0, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_TSE[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 126, 126};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_CHE[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 15, 31, 56, 48, 48,
|
||||
48, 48, 48, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHA[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 224,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHCHA[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 224,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_HARD_SIGN[] = {96, 96, 96, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 12, 12, 12, 12, 12, 12, 28, 24, 248, 240,
|
||||
0, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_YERU[] = {224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224,
|
||||
255, 255, 12, 12, 12, 12, 12, 12, 24, 248, 240, 0, 0, 0, 255, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 1, 0, 0, 0, 7, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SOFT_SIGN[] = {224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 12, 12, 12,
|
||||
12, 12, 28, 248, 240, 7, 7, 6, 6, 6, 6, 6, 7, 3, 1};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_E[] = {64, 96, 96, 96, 96, 96, 192, 192, 128, 0, 0, 0, 0, 24, 24,
|
||||
24, 24, 153, 255, 126, 7, 6, 6, 6, 6, 6, 7, 3, 1, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_YU[] = {224, 224, 0, 0, 0, 0, 128, 192, 192, 96, 96, 96, 96, 96, 192, 192,
|
||||
255, 255, 24, 24, 24, 126, 255, 129, 0, 0, 0, 0, 0, 0, 0, 131,
|
||||
7, 7, 0, 0, 0, 0, 1, 3, 3, 6, 6, 6, 6, 6, 3, 3};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_YA[] = {0, 128, 192, 192, 96, 96, 96, 96, 96, 224, 224,
|
||||
0, 15, 159, 248, 112, 48, 48, 48, 48, 255, 255,
|
||||
4, 7, 3, 0, 0, 0, 0, 0, 0, 7, 7};
|
||||
|
||||
const char GLYPH_WIDTH[143] = {
|
||||
2, 7, 15, 11, 17, 15, 2, 6, 6, 11, 12, 3, 6, 3, 10, 13, 7, 11, 12, 13, 11, 12, 11, 13, 12, 3, 3, 13, 12,
|
||||
13, 9, 16, 17, 14, 13, 15, 12, 11, 13, 14, 2, 11, 14, 12, 16, 15, 16, 13, 16, 14, 12, 14, 14, 16, 17, 14, 14, 13,
|
||||
6, 11, 6, 13, 13, 5, 11, 12, 10, 12, 13, 8, 12, 11, 2, 4, 12, 4, 16, 11, 13, 12, 12, 8, 10, 8, 11, 12, 18,
|
||||
13, 12, 10, 7, 2, 7, 14, 12, 11, 18, 12, 17, 13, 15, 15, 14, 16, 14, 14, 17, 16, 12, 16, 16, 17, 16, 12, 13, 16,
|
||||
14, 13, 10, 9, 15, 13, 18, 11, 12, 12, 12, 14, 15, 11, 11, 10, 16, 12, 10, 16, 16, 15, 16, 10, 10, 16, 11};
|
||||
|
||||
const char *GLYPH_ADDR[143] = {
|
||||
GLYPH_EXCLAMATION_MARK,
|
||||
GLYPH_QUOTATION_MARK,
|
||||
GLYPH_NUMBER_SIGN,
|
||||
GLYPH_DOLLAR_SIGN,
|
||||
GLYPH_PERCENT_SIGN,
|
||||
GLYPH_AMPERSAND,
|
||||
GLYPH_APOSTROPHE,
|
||||
GLYPH_LEFT_PARENTHESIS,
|
||||
GLYPH_RIGHT_PARENTHESIS,
|
||||
GLYPH_ASTERISK,
|
||||
GLYPH_PLUS_SIGN,
|
||||
GLYPH_COMMA,
|
||||
GLYPH_HYPHEN_MINUS,
|
||||
GLYPH_FULL_STOP,
|
||||
GLYPH_SOLIDUS,
|
||||
GLYPH_DIGIT_ZERO,
|
||||
GLYPH_DIGIT_ONE,
|
||||
GLYPH_DIGIT_TWO,
|
||||
GLYPH_DIGIT_THREE,
|
||||
GLYPH_DIGIT_FOUR,
|
||||
GLYPH_DIGIT_FIVE,
|
||||
GLYPH_DIGIT_SIX,
|
||||
GLYPH_DIGIT_SEVEN,
|
||||
GLYPH_DIGIT_EIGHT,
|
||||
GLYPH_DIGIT_NINE,
|
||||
GLYPH_COLON,
|
||||
GLYPH_SEMICOLON,
|
||||
GLYPH_LESS_THAN_SIGN,
|
||||
GLYPH_EQUALS_SIGN,
|
||||
GLYPH_GREATER_THAN_SIGN,
|
||||
GLYPH_QUESTION_MARK,
|
||||
GLYPH_COMMERCIAL_AT,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_A,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_B,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_C,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_D,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_E,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_F,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_G,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_H,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_I,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_J,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_K,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_L,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_M,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_N,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_O,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_P,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_Q,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_R,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_S,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_T,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_U,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_V,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_W,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_X,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_Y,
|
||||
GLYPH_LATIN_CAPITAL_LETTER_Z,
|
||||
GLYPH_LEFT_SQUARE_BRACKET,
|
||||
GLYPH_REVERSE_SOLIDUS,
|
||||
GLYPH_RIGHT_SQUARE_BRACKET,
|
||||
GLYPH_CIRCUMFLEX_ACCENT,
|
||||
GLYPH_LOW_LINE,
|
||||
GLYPH_GRAVE_ACCENT,
|
||||
GLYPH_LATIN_SMALL_LETTER_A,
|
||||
GLYPH_LATIN_SMALL_LETTER_B,
|
||||
GLYPH_LATIN_SMALL_LETTER_C,
|
||||
GLYPH_LATIN_SMALL_LETTER_D,
|
||||
GLYPH_LATIN_SMALL_LETTER_E,
|
||||
GLYPH_LATIN_SMALL_LETTER_F,
|
||||
GLYPH_LATIN_SMALL_LETTER_G,
|
||||
GLYPH_LATIN_SMALL_LETTER_H,
|
||||
GLYPH_LATIN_SMALL_LETTER_I,
|
||||
GLYPH_LATIN_SMALL_LETTER_J,
|
||||
GLYPH_LATIN_SMALL_LETTER_K,
|
||||
GLYPH_LATIN_SMALL_LETTER_L,
|
||||
GLYPH_LATIN_SMALL_LETTER_M,
|
||||
GLYPH_LATIN_SMALL_LETTER_N,
|
||||
GLYPH_LATIN_SMALL_LETTER_O,
|
||||
GLYPH_LATIN_SMALL_LETTER_P,
|
||||
GLYPH_LATIN_SMALL_LETTER_Q,
|
||||
GLYPH_LATIN_SMALL_LETTER_R,
|
||||
GLYPH_LATIN_SMALL_LETTER_S,
|
||||
GLYPH_LATIN_SMALL_LETTER_T,
|
||||
GLYPH_LATIN_SMALL_LETTER_U,
|
||||
GLYPH_LATIN_SMALL_LETTER_V,
|
||||
GLYPH_LATIN_SMALL_LETTER_W,
|
||||
GLYPH_LATIN_SMALL_LETTER_X,
|
||||
GLYPH_LATIN_SMALL_LETTER_Y,
|
||||
GLYPH_LATIN_SMALL_LETTER_Z,
|
||||
GLYPH_LEFT_CURLY_BRACKET,
|
||||
GLYPH_VERTICAL_LINE,
|
||||
GLYPH_RIGHT_CURLY_BRACKET,
|
||||
GLYPH_NUMERO_SIGN,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_BE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_GHE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_DE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_IO,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_ZHE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_ZE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_I,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_SHORT_I,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_KA,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_EL,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_PE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_U,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_EF,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_TSE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_CHE,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_SHA,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_SHCHA,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_HARD_SIGN,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_YERU,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_SOFT_SIGN,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_E,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_YU,
|
||||
GLYPH_CYRILLIC_CAPITAL_LETTER_YA,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_BE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_VE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_GHE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_DE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_IO,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_ZHE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_ZE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_I,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_SHORT_I,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_KA,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_EL,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_EM,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_EN,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_PE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_TE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_EF,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_TSE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_CHE,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_SHA,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_SHCHA,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_HARD_SIGN,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_YERU,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_SOFT_SIGN,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_E,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_YU,
|
||||
GLYPH_CYRILLIC_SMALL_LETTER_YA,
|
||||
};
|
||||
|
||||
inline int glyph_index_for_code_point(int codePoint) {
|
||||
const int cyrillicTable[] = {32, 94, 33, 95, 96, 36, 98, 99, 100, 101, 102, 103, 44, 39, 46, 104,
|
||||
47, 34, 51, 105, 106, 55, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
|
||||
64, 117, 118, 119, 120, 68, 122, 123, 124, 125, 126, 127, 128, 129, 78, 130,
|
||||
79, 66, 131, 88, 132, 87, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142};
|
||||
if (codePoint < 32)
|
||||
return -1;
|
||||
else if (codePoint < 126)
|
||||
return codePoint - 33;
|
||||
else if (codePoint < 0x401)
|
||||
return -1;
|
||||
else if (codePoint == 0x401)
|
||||
return 97;
|
||||
else if (codePoint < 0x410)
|
||||
return -1;
|
||||
else if (codePoint < 0x450)
|
||||
return cyrillicTable[codePoint - 0x410];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
225
graphics.c
Normal file
225
graphics.c
Normal file
@@ -0,0 +1,225 @@
|
||||
#include "graphics.h"
|
||||
#include "font_ubuntu.h"
|
||||
#include "utf8.h"
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
void lcd_draw_horizontal_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t y1 = y + 8;
|
||||
uint16_t x0 = x + 7;
|
||||
uint16_t w = 32;
|
||||
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
x0 += 2;
|
||||
w -= 4;
|
||||
y = y1;
|
||||
y1 = y + 7;
|
||||
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_vertical_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t x1 = x + 8;
|
||||
uint16_t y0 = y + 7;
|
||||
uint16_t h = 32;
|
||||
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
y0 += 2;
|
||||
h -= 4;
|
||||
x = x1;
|
||||
x1 = x + 7;
|
||||
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_horizontal_small_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t y1 = y + 6;
|
||||
uint16_t x0 = x + 5;
|
||||
uint16_t w = 24;
|
||||
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
x0 += 2;
|
||||
w -= 4;
|
||||
y = y1;
|
||||
y1 = y + 5;
|
||||
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_vertical_small_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t x1 = x + 6;
|
||||
uint16_t y0 = y + 5;
|
||||
uint16_t h = 24;
|
||||
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
y0 += 2;
|
||||
h -= 4;
|
||||
x = x1;
|
||||
x1 = x + 5;
|
||||
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_horizontal_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t y1 = y + 4;
|
||||
uint16_t x0 = x + 3;
|
||||
uint16_t w = 16;
|
||||
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
x0 += 2;
|
||||
w -= 4;
|
||||
y = y1;
|
||||
y1 = y + 3;
|
||||
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
||||
_draw_h_strip(x0, i, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_vertical_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
uint16_t x1 = x + 4;
|
||||
uint16_t y0 = y + 3;
|
||||
uint16_t h = 16;
|
||||
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
y0 += 2;
|
||||
h -= 4;
|
||||
x = x1;
|
||||
x1 = x + 3;
|
||||
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
||||
_draw_v_strip(i, y0, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t DIGIT_MASKS[10] = {0b1110111, 0b0100100, 0b1011101, 0b1101101, 0b0101110,
|
||||
0b1101011, 0b1111011, 0b0100101, 0b1111111, 0b1101111};
|
||||
|
||||
void lcd_draw_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
||||
const uint16_t SEGMENT_OFFSETS[7][2] = {{9, 0}, {0, 9}, {49, 9}, {9, 49}, {0, 58}, {49, 58}, {9, 99}};
|
||||
for (int seg = 0; seg < 7; ++seg) {
|
||||
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
||||
if (seg == 0 || seg == 3 || seg == 6)
|
||||
lcd_draw_horizontal_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
else
|
||||
lcd_draw_vertical_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_small_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
||||
const uint16_t SEGMENT_OFFSETS[7][2] = {{7, 0}, {0, 7}, {37, 7}, {7, 37}, {0, 44}, {37, 44}, {7, 74}};
|
||||
for (int seg = 0; seg < 7; ++seg) {
|
||||
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
||||
if (seg == 0 || seg == 3 || seg == 6)
|
||||
lcd_draw_horizontal_small_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
else
|
||||
lcd_draw_vertical_small_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_xsmall_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
||||
const uint16_t SEGMENT_OFFSETS[7][2] = {{4, 0}, {0, 4}, {23, 4}, {4, 23}, {0, 27}, {23, 27}, {4, 46}};
|
||||
for (int seg = 0; seg < 7; ++seg) {
|
||||
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
||||
if (seg == 0 || seg == 3 || seg == 6)
|
||||
lcd_draw_horizontal_xsmall_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
else
|
||||
lcd_draw_vertical_xsmall_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_decimal_point(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
_draw_h_strip(x + 4 - i, y + i, 8 + i, color);
|
||||
}
|
||||
for (int i = 5; i < 9; ++i) {
|
||||
_draw_h_strip(x, y + i, 12, color);
|
||||
}
|
||||
for (int i = 9; i < 13; ++i) {
|
||||
_draw_h_strip(x, y + i, 20 - i, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_write_string(const char *string, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
static uint16_t glyphPixels[24 * 24];
|
||||
while (*string) {
|
||||
int character = decode_code_point(&string);
|
||||
if (character != 32) {
|
||||
int glyphIndex = glyph_index_for_code_point(character);
|
||||
const uint8_t *glyph;
|
||||
int8_t glyphWidth;
|
||||
if (glyphIndex != -1) {
|
||||
glyph = GLYPH_ADDR[glyphIndex];
|
||||
glyphWidth = GLYPH_WIDTH[glyphIndex];
|
||||
} else {
|
||||
glyph = GLYPH_MISSING;
|
||||
glyphWidth = 12;
|
||||
}
|
||||
int row = 0, col = 0;
|
||||
for (int byte = 0; byte < glyphWidth * 3; ++byte) {
|
||||
int rem = glyph[byte];
|
||||
for (int bit = 0; bit < 8; ++bit) {
|
||||
glyphPixels[(row * 8 + bit) * (glyphWidth + LETTER_SPACING) + col] = (rem & 1) ? color : bgColor;
|
||||
rem >>= 1;
|
||||
}
|
||||
if (++col == glyphWidth) {
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 24; ++j) {
|
||||
for (int i = 0; i < LETTER_SPACING; ++i)
|
||||
glyphPixels[j * (glyphWidth + LETTER_SPACING) + glyphWidth + i] = 0;
|
||||
}
|
||||
st7789_caset(x, x + glyphWidth + LETTER_SPACING - 1);
|
||||
st7789_raset(y, y + 24 - 1);
|
||||
st7789_write(glyphPixels, 24 * (glyphWidth + LETTER_SPACING) * sizeof(uint16_t));
|
||||
x += glyphWidth + LETTER_SPACING;
|
||||
} else {
|
||||
lcd_fill_rectangle(x, y, 12, 24, bgColor);
|
||||
x += 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lcd_string_width(const char *string) {
|
||||
int width = 0;
|
||||
while (*string) {
|
||||
int character = decode_code_point(&string);
|
||||
if (character == 32) {
|
||||
width += 12;
|
||||
continue;
|
||||
} else {
|
||||
int glyphIndex = glyph_index_for_code_point(character);
|
||||
if (glyphIndex != -1) {
|
||||
width += GLYPH_WIDTH[glyphIndex] + 1;
|
||||
} else {
|
||||
width += 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
62
graphics.h
Normal file
62
graphics.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef VELOMETER_GRAPHICS_H
|
||||
#define VELOMETER_GRAPHICS_H
|
||||
#include "st7789.h"
|
||||
|
||||
#define LCD_OFFSET_X 2
|
||||
#define LCD_OFFSET_Y 34
|
||||
#define LCD_WIDTH 320
|
||||
#define LCD_HEIGHT 172
|
||||
#define LETTER_SPACING 2
|
||||
|
||||
static inline void _set_pixel(uint16_t x, uint16_t y, uint16_t color) {
|
||||
st7789_set_cursor(x, y);
|
||||
st7789_put(color);
|
||||
}
|
||||
|
||||
static inline void _draw_h_strip(uint16_t x, uint16_t y, uint16_t len, uint16_t color) {
|
||||
st7789_caset(x, x + len - 1);
|
||||
st7789_raset(y, y);
|
||||
while (len--) {
|
||||
st7789_put(color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _draw_v_strip(uint16_t x, uint16_t y, uint16_t len, uint16_t color) {
|
||||
st7789_caset(x, x);
|
||||
st7789_raset(y, y + len - 1);
|
||||
while (len--) {
|
||||
st7789_put(color);
|
||||
}
|
||||
}
|
||||
|
||||
inline void lcd_set_pixel(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
st7789_set_cursor(x, y);
|
||||
st7789_put(color);
|
||||
}
|
||||
|
||||
inline void lcd_fill_rectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
st7789_caset(x, x + w - 1);
|
||||
st7789_raset(y, y + h - 1);
|
||||
for (uint16_t i = 0; i < w * h; ++i) {
|
||||
st7789_put(color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_draw_horizontal_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_vertical_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_horizontal_small_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_vertical_small_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_horizontal_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_vertical_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_draw_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor);
|
||||
void lcd_draw_small_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor);
|
||||
void lcd_draw_xsmall_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor);
|
||||
void lcd_draw_decimal_point(uint16_t x, uint16_t y, uint16_t color);
|
||||
void lcd_write_string(const char *string, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor);
|
||||
int lcd_string_width(const char *string);
|
||||
|
||||
#endif
|
||||
589
main.c
Normal file
589
main.c
Normal file
@@ -0,0 +1,589 @@
|
||||
#include <boot/picobin.h>
|
||||
#include <hardware/flash.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <hardware/psram.h>
|
||||
#include <hardware/pwm.h>
|
||||
#include <hardware/regs/intctrl.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include <pico/critical_section.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "beep.h"
|
||||
#include "ds1302.h"
|
||||
#include "graphics.h"
|
||||
#include "pins.h"
|
||||
#include "st7789.h"
|
||||
|
||||
#define LOGGING
|
||||
|
||||
#define HALL_SENSOR_DEBOUNCE_DELAY_us 10000
|
||||
#define BUTTON_DEBOUNCE_DELAY_us 3000
|
||||
#define BUTTON_HOLD_TIME_ms 1000
|
||||
#define TICKS_PER_REVOLUTION 6
|
||||
#define SPEED_MEASUREMENT_INTERVAL_ms 100
|
||||
#define SPEED_MEASUREMENT_WINDOW_SIZE 16
|
||||
|
||||
#define SPEED_MEASUREMENT_WINDOW_INTERVAL (SPEED_MEASUREMENT_INTERVAL_ms * SPEED_MEASUREMENT_WINDOW_SIZE)
|
||||
|
||||
enum GUIScreen {
|
||||
MAIN_SCREEN,
|
||||
SETTINGS_SCREEN,
|
||||
};
|
||||
|
||||
enum DisplayMode {
|
||||
DISPLAY_MODE_SPEED,
|
||||
DISPLAY_MODE_DISTANCE,
|
||||
};
|
||||
|
||||
struct GUIState {
|
||||
uint screen;
|
||||
union {
|
||||
struct {
|
||||
uint displayMode;
|
||||
bool displayModeChanged;
|
||||
} mainScreen;
|
||||
struct {
|
||||
//...
|
||||
} settingsScreen;
|
||||
} screenState;
|
||||
};
|
||||
|
||||
void on_gpio_interrupt(uint pin, uint32_t eventMask);
|
||||
int64_t hall_sensor_debounce_callback(alarm_id_t alarmId, void *userData);
|
||||
int64_t button_debounce_callback(alarm_id_t alarmId, void *userData);
|
||||
int64_t button_hold_callback(alarm_id_t alarmId, void *userData);
|
||||
bool speed_measure_timer_callback(repeating_timer_t *rt);
|
||||
void on_button_short_press(uint button);
|
||||
void on_button_long_press(uint button);
|
||||
|
||||
void update_lcd();
|
||||
void gui_init(struct GUIState *state);
|
||||
void init_button_states();
|
||||
void save_to_rtc();
|
||||
bool load_from_rtc();
|
||||
void reset();
|
||||
|
||||
const uint8_t FRONT_BUTTON_PINS[4] = {PIN_BUTTON_0, PIN_BUTTON_1, PIN_BUTTON_2, PIN_BUTTON_3};
|
||||
|
||||
const uint16_t BRIGHTNESS_CONVERT_TABLE_X[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
|
||||
const uint16_t BRIGHTNESS_CONVERT_TABLE_Y[] = {0, 7, 12, 21, 37, 64, 111, 194, 338, 588, 1024};
|
||||
const size_t BRIGHTNESS_CONVERT_LABLE_LEN = 11;
|
||||
|
||||
const uint millimetersPerRevolution = 1540;
|
||||
const uint cmphPerTpw = 360000 * millimetersPerRevolution / SPEED_MEASUREMENT_WINDOW_INTERVAL /
|
||||
TICKS_PER_REVOLUTION; // cm/hour per Ticks/window
|
||||
const uint cmPerTick = millimetersPerRevolution / TICKS_PER_REVOLUTION / 10; // cm per tick
|
||||
|
||||
int16_t convert_brightness(int16_t input) {
|
||||
for (int i = 0; i < BRIGHTNESS_CONVERT_LABLE_LEN - 1; ++i) {
|
||||
if (input < BRIGHTNESS_CONVERT_TABLE_X[i + 1]) {
|
||||
int16_t x0 = BRIGHTNESS_CONVERT_TABLE_X[i];
|
||||
int16_t x1 = BRIGHTNESS_CONVERT_TABLE_X[i + 1];
|
||||
int16_t y0 = BRIGHTNESS_CONVERT_TABLE_Y[i];
|
||||
int16_t y1 = BRIGHTNESS_CONVERT_TABLE_Y[i + 1];
|
||||
return y0 + (y1 - y0) * (input - x0) / (x1 - x0);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// for debouncing
|
||||
alarm_id_t hallSensorDebounceAlarm = 0;
|
||||
bool hallSensorLastState = 0;
|
||||
bool hallSensorPrevState = 0;
|
||||
|
||||
struct {
|
||||
alarm_id_t debounceAlarm, holdAlarm;
|
||||
bool currentState, prevState, isHeld;
|
||||
} buttonStates[4];
|
||||
|
||||
// for debug (and for the future)
|
||||
absolute_time_t lastWheelTickTime = 0;
|
||||
|
||||
// for speed measurement
|
||||
uint8_t intervalWheelTicks[SPEED_MEASUREMENT_WINDOW_SIZE];
|
||||
uint8_t currentInterval = 0;
|
||||
uint16_t ticksPerWindow = 0;
|
||||
// critical_section_t intervalWheelTicksCritSec;
|
||||
repeating_timer_t speedMeasureTimer;
|
||||
|
||||
uint totalTicks = 0;
|
||||
|
||||
DateTime currentDatetime;
|
||||
|
||||
// unused currently
|
||||
// repeating_timer_t audioPlaybackTimer;
|
||||
|
||||
struct GUIState guiState;
|
||||
|
||||
const uint16_t *find_splash_image_offset(const uint16_t *start) {
|
||||
const uint16_t marker[3] = {0x6f66, 0x626f, 0x7261};
|
||||
for (int offs = 0; offs < 2 * 1024 * 1024; ++offs) {
|
||||
if (start[offs + 0] == marker[0] && start[offs + 1] == marker[1] && start[offs + 2] == marker[2]) {
|
||||
return start + offs;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifdef LOGGING
|
||||
stdio_usb_init();
|
||||
#endif
|
||||
|
||||
// display init
|
||||
const struct st7789_config displayConfig = {
|
||||
.spi = PICO_DEFAULT_SPI_INSTANCE(),
|
||||
.gpio_din = PIN_LCD_SDA,
|
||||
.gpio_clk = PIN_LCD_SCL,
|
||||
.gpio_cs = PIN_LCD_CS,
|
||||
.gpio_dc = PIN_LCD_DATA_COMMAND,
|
||||
.gpio_rst = PIN_LCD_RESET,
|
||||
.gpio_bl = PIN_LCD_BACKLIGHT,
|
||||
};
|
||||
st7789_init(&displayConfig, LCD_WIDTH + LCD_OFFSET_X, LCD_HEIGHT + LCD_OFFSET_Y);
|
||||
|
||||
// splash image (just for fun)
|
||||
const uint16_t *splashImage = (const uint16_t *)(XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + 1581056);
|
||||
if (splashImage) {
|
||||
st7789_caset(LCD_OFFSET_X, LCD_OFFSET_X + 317);
|
||||
st7789_raset(LCD_OFFSET_Y, LCD_OFFSET_Y + 171);
|
||||
st7789_write(splashImage, 318 * 172 * sizeof(uint16_t));
|
||||
} else {
|
||||
rom_reset_usb_boot(0, 0);
|
||||
}
|
||||
sleep_ms(1000);
|
||||
|
||||
#ifdef LOGGING
|
||||
if (psram_is_available()) {
|
||||
printf("PSRAM available. detecting size... ");
|
||||
size_t psramSize = psram_detect_size();
|
||||
printf("%u\n", psramSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
// critical_section_init(&intervalWheelTicksCritSec);
|
||||
add_repeating_timer_ms(SPEED_MEASUREMENT_INTERVAL_ms, speed_measure_timer_callback, NULL, &speedMeasureTimer);
|
||||
|
||||
gpio_set_irq_callback(on_gpio_interrupt);
|
||||
|
||||
gpio_init(PIN_BEEPER);
|
||||
gpio_set_dir(PIN_BEEPER, GPIO_OUT);
|
||||
|
||||
// hall sensor
|
||||
gpio_init(PIN_MAIN_HALL_SENSOR);
|
||||
gpio_pull_up(PIN_MAIN_HALL_SENSOR);
|
||||
gpio_set_irq_enabled(PIN_MAIN_HALL_SENSOR, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
|
||||
|
||||
// on-board LED
|
||||
gpio_init(25);
|
||||
gpio_set_dir(25, true);
|
||||
|
||||
// front buttons
|
||||
init_button_states();
|
||||
gpio_init_mask(0b1111 << 15);
|
||||
for (int pin = 15; pin <= 18; ++pin) {
|
||||
gpio_pull_up(pin);
|
||||
gpio_set_irq_enabled(pin, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
|
||||
}
|
||||
|
||||
irq_set_enabled(IO_IRQ_BANK0, 1);
|
||||
|
||||
ds1302_init();
|
||||
|
||||
DateTime tmp = {26, 9, 9, 15, 10, 0, DOW_WED};
|
||||
// ds1302_set_datetime(&tmp);
|
||||
|
||||
load_from_rtc();
|
||||
|
||||
gpio_set_function(PIN_LCD_BACKLIGHT, GPIO_FUNC_PWM);
|
||||
pwm_set_wrap(BACKLIGHT_PWM_SLICE, 1024);
|
||||
pwm_set_chan_level(BACKLIGHT_PWM_SLICE, BACKLIGHT_PWM_CHANNEL, 1024);
|
||||
pwm_set_enabled(BACKLIGHT_PWM_SLICE, true);
|
||||
|
||||
gpio_set_function(7, GPIO_FUNC_PWM);
|
||||
pwm_set_wrap(3, 256);
|
||||
pwm_set_chan_level(3, PWM_CHAN_B, 0);
|
||||
pwm_set_enabled(3, true);
|
||||
|
||||
gui_init(&guiState);
|
||||
|
||||
absolute_time_t nextLcdUpdateTime = delayed_by_ms(get_absolute_time(), 50);
|
||||
absolute_time_t nextClockUpdateTime = get_absolute_time();
|
||||
absolute_time_t nextSaveToRtcTime = delayed_by_ms(get_absolute_time(), 10000);
|
||||
|
||||
while (true) {
|
||||
absolute_time_t t = get_absolute_time();
|
||||
if (t >= nextClockUpdateTime) {
|
||||
nextClockUpdateTime = delayed_by_ms(t, 1000);
|
||||
ds1302_get_datetime(¤tDatetime);
|
||||
printf("time is %i %i %i %i %i %i %i\n", currentDatetime.year, currentDatetime.month, currentDatetime.day,
|
||||
currentDatetime.dow, currentDatetime.hour, currentDatetime.minute, currentDatetime.second);
|
||||
}
|
||||
if (t >= nextLcdUpdateTime) {
|
||||
nextLcdUpdateTime = delayed_by_ms(t, 50);
|
||||
update_lcd();
|
||||
if (gpio_get(PIN_BUTTON_0) == 0 && gpio_get(PIN_BUTTON_3) == 0) {
|
||||
rom_reset_usb_boot(0, 0);
|
||||
}
|
||||
}
|
||||
if (t >= nextSaveToRtcTime) {
|
||||
nextSaveToRtcTime = delayed_by_ms(t, 10000);
|
||||
save_to_rtc();
|
||||
}
|
||||
sleep_until(nextLcdUpdateTime);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_gpio_interrupt(uint pin, uint32_t eventMask) {
|
||||
if (pin == PIN_MAIN_HALL_SENSOR) {
|
||||
if (eventMask & GPIO_IRQ_EDGE_RISE)
|
||||
hallSensorLastState = 0;
|
||||
if (eventMask & GPIO_IRQ_EDGE_FALL)
|
||||
hallSensorLastState = 1;
|
||||
if (hallSensorDebounceAlarm)
|
||||
cancel_alarm(hallSensorDebounceAlarm);
|
||||
hallSensorDebounceAlarm =
|
||||
add_alarm_in_us(HALL_SENSOR_DEBOUNCE_DELAY_us, hall_sensor_debounce_callback, NULL, false);
|
||||
gpio_acknowledge_irq(pin, eventMask);
|
||||
} else if (pin == PIN_BUTTON_0 || pin == PIN_BUTTON_1 || pin == PIN_BUTTON_2 || pin == PIN_BUTTON_3) {
|
||||
uint buttonIndex;
|
||||
switch (pin) {
|
||||
case PIN_BUTTON_0:
|
||||
buttonIndex = 0;
|
||||
break;
|
||||
case PIN_BUTTON_1:
|
||||
buttonIndex = 1;
|
||||
break;
|
||||
case PIN_BUTTON_2:
|
||||
buttonIndex = 2;
|
||||
break;
|
||||
case PIN_BUTTON_3:
|
||||
buttonIndex = 3;
|
||||
}
|
||||
auto buttonState = &buttonStates[buttonIndex];
|
||||
// if (eventMask & GPIO_IRQ_EDGE_RISE)
|
||||
// buttonState->currentState = 0;
|
||||
// if (eventMask & GPIO_IRQ_EDGE_FALL)
|
||||
// buttonState->currentState = 1;
|
||||
// buttonState->currentState = !gpio_get(pin);
|
||||
if (buttonState->debounceAlarm != -1)
|
||||
cancel_alarm(buttonState->debounceAlarm);
|
||||
buttonState->debounceAlarm =
|
||||
add_alarm_in_us(BUTTON_DEBOUNCE_DELAY_us, button_debounce_callback, (void *)buttonIndex, false);
|
||||
gpio_acknowledge_irq(pin, eventMask);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t hall_sensor_debounce_callback(alarm_id_t alarmId, void *userData) {
|
||||
(void)alarmId;
|
||||
(void)userData;
|
||||
if (hallSensorLastState != hallSensorPrevState) {
|
||||
absolute_time_t now = get_absolute_time();
|
||||
lastWheelTickTime = now;
|
||||
++intervalWheelTicks[currentInterval];
|
||||
++totalTicks;
|
||||
|
||||
gpio_put(25, !gpio_get(25));
|
||||
hallSensorPrevState = hallSensorLastState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t button_debounce_callback(alarm_id_t alarmId, void *userData) {
|
||||
(void)alarmId;
|
||||
uint buttonIndex = (uint)userData;
|
||||
auto buttonState = &buttonStates[buttonIndex];
|
||||
bool currentState = !gpio_get(FRONT_BUTTON_PINS[buttonIndex]);
|
||||
if (currentState != buttonState->prevState) {
|
||||
buttonState->prevState = currentState;
|
||||
if (buttonState->holdAlarm != -1) {
|
||||
cancel_alarm(buttonState->holdAlarm);
|
||||
}
|
||||
if (currentState == 1) {
|
||||
buttonState->holdAlarm = add_alarm_in_ms(BUTTON_HOLD_TIME_ms, button_hold_callback, (void *)buttonIndex, false);
|
||||
} else {
|
||||
buttonState->holdAlarm = -1;
|
||||
if (!buttonState->isHeld)
|
||||
on_button_short_press(buttonIndex);
|
||||
else
|
||||
buttonState->isHeld = false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t button_hold_callback(alarm_id_t alarmId, void *userData) {
|
||||
(void)alarmId;
|
||||
uint buttonIndex = (uint)userData;
|
||||
auto buttonState = &buttonStates[buttonIndex];
|
||||
buttonState->holdAlarm = -1;
|
||||
buttonState->isHeld = true;
|
||||
on_button_long_press(buttonIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_button_short_press(uint button) {
|
||||
// beep(60, 900);
|
||||
#ifdef LOGGING
|
||||
printf("button %i short press\n", button);
|
||||
#endif
|
||||
if (button == 3 && guiState.screen == MAIN_SCREEN) {
|
||||
uint oldDispMode = guiState.screenState.mainScreen.displayMode;
|
||||
if (oldDispMode == DISPLAY_MODE_SPEED)
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE;
|
||||
else
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_SPEED;
|
||||
guiState.screenState.mainScreen.displayModeChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void on_button_long_press(uint button) {
|
||||
// beep(60, 1273);
|
||||
#ifdef LOGGING
|
||||
printf("button %i long press\n");
|
||||
#endif
|
||||
if (button == 2 && buttonStates[3].isHeld ||
|
||||
button == 3 && buttonStates[2].isHeld) { // if buttons 2 & 3 pressed and held simultaneously...
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool speed_measure_timer_callback(repeating_timer_t *rt) {
|
||||
(void)rt;
|
||||
|
||||
uint16_t sum = 0;
|
||||
/*
|
||||
printf("window: ");
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
sum += intervalWheelTicks[i];
|
||||
if (currentInterval == i)
|
||||
printf("[%i] ", intervalWheelTicks[i]);
|
||||
else
|
||||
printf("%i ", intervalWheelTicks[i]);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
sum += intervalWheelTicks[i];
|
||||
}
|
||||
currentInterval = (currentInterval + 1) % 16;
|
||||
intervalWheelTicks[currentInterval] = 0;
|
||||
ticksPerWindow = sum;
|
||||
// printf("Total %i \r", sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
// speed is in "2.1" decimal fixed-point, in km/h
|
||||
void draw_speed(uint value) {
|
||||
#define DIGITS_START_X 20
|
||||
#define DIGITS_START_Y 37
|
||||
#define DIGIT_WIDTH 64
|
||||
#define DIGIT_SPACING 8
|
||||
|
||||
if (value > 999)
|
||||
value = 999;
|
||||
|
||||
uint16_t color;
|
||||
if (value >= 300)
|
||||
color = 0xfd04;
|
||||
else if (value >= 200)
|
||||
color = 0xfe84;
|
||||
else if (value >= 150)
|
||||
color = 0xdfe4;
|
||||
else if (value >= 100)
|
||||
color = 0x6fe4;
|
||||
else if (value >= 50)
|
||||
color = 0x27fb;
|
||||
else
|
||||
color = 0x04ff;
|
||||
|
||||
lcd_draw_digit(value / 100, DIGITS_START_X, DIGITS_START_Y, color, 0x0000);
|
||||
lcd_draw_digit((value / 10) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, color, 0x0000);
|
||||
lcd_draw_decimal_point(DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING, DIGITS_START_Y + 101, color);
|
||||
lcd_draw_digit(value % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + 5, DIGITS_START_Y, color, 0x0000);
|
||||
|
||||
#undef DIGITS_START_X
|
||||
#undef DIGITS_START_Y
|
||||
#undef DIGIT_WIDTH
|
||||
#undef DIGIT_SPACING
|
||||
}
|
||||
|
||||
// distance is in "2.3" decimal fixed-point, in kilometers
|
||||
void draw_distance(uint value) {
|
||||
#define DIGITS_START_X 20
|
||||
#define DIGITS_START_Y 37
|
||||
#define SMALL_DIGITS_Y_OFFSET 28
|
||||
#define XSMALL_DIGITS_Y_OFFSET 28
|
||||
#define DIGIT_WIDTH 64
|
||||
#define SMALL_DIGIT_WIDTH 48
|
||||
#define XSMALL_DIGIT_WIDTH 30
|
||||
#define DIGIT_SPACING 8
|
||||
#define SMALL_DIGIT_SPACING 6
|
||||
#define XSMALL_DIGIT_SPACING 4
|
||||
|
||||
if (value > 99999)
|
||||
value = 99999;
|
||||
|
||||
lcd_draw_digit(value / 10000, DIGITS_START_X, DIGITS_START_Y, 0xffff, 0x0000);
|
||||
lcd_draw_digit((value / 1000) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, 0xffff, 0x0000);
|
||||
lcd_draw_decimal_point(DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING, DIGITS_START_Y + 101, 0xffff);
|
||||
lcd_draw_small_digit((value / 100) % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + 10,
|
||||
DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000);
|
||||
lcd_draw_small_digit((value / 10) % 10,
|
||||
DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + SMALL_DIGIT_WIDTH + SMALL_DIGIT_SPACING +
|
||||
10,
|
||||
DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000);
|
||||
lcd_draw_xsmall_digit(value % 10,
|
||||
DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + SMALL_DIGIT_WIDTH * 2 +
|
||||
SMALL_DIGIT_SPACING + XSMALL_DIGIT_SPACING + 10,
|
||||
DIGITS_START_Y + XSMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000);
|
||||
|
||||
#undef DIGITS_START_X
|
||||
#undef DIGITS_START_Y
|
||||
#undef DIGIT_WIDTH
|
||||
#undef DIGIT_SPACING
|
||||
}
|
||||
|
||||
void update_lcd() {
|
||||
if (guiState.screen == MAIN_SCREEN) {
|
||||
if (guiState.screenState.mainScreen.displayModeChanged) {
|
||||
// lcd_fill_rectangle(49, 27, 213, 113, 0x0000);
|
||||
st7789_fill(0x0000);
|
||||
guiState.screenState.mainScreen.displayModeChanged = false;
|
||||
}
|
||||
|
||||
if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_SPEED) {
|
||||
uint convertedSpeed = ticksPerWindow * cmphPerTpw / 10000;
|
||||
draw_speed(convertedSpeed);
|
||||
lcd_write_string("Скорость", 20, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("км/ч", 241, 126, 0xffff, 0x0000);
|
||||
} else if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_DISTANCE) {
|
||||
uint convertedDistance = totalTicks * cmPerTick / 100;
|
||||
draw_distance(convertedDistance);
|
||||
lcd_write_string("Расстояние", 20, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("км", 280, 126, 0xffff, 0x0000);
|
||||
}
|
||||
|
||||
char timeDisplay[6];
|
||||
memset(timeDisplay, ' ', sizeof(timeDisplay));
|
||||
timeDisplay[5] = 0;
|
||||
sprintf(timeDisplay, "%i:%02i", currentDatetime.hour, currentDatetime.minute);
|
||||
lcd_write_string(timeDisplay, 320 - 20 - lcd_string_width(timeDisplay), 0, 0xffff, 0x0000);
|
||||
lcd_fill_rectangle(320 - 160, 0, 140 - lcd_string_width(timeDisplay), 24, 0x0000);
|
||||
} else if (guiState.screen == SETTINGS_SCREEN) {
|
||||
}
|
||||
}
|
||||
|
||||
void gui_init(struct GUIState *state) {
|
||||
state->screen = 0;
|
||||
state->screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE;
|
||||
state->screenState.mainScreen.displayModeChanged = true;
|
||||
}
|
||||
|
||||
void init_button_states() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
buttonStates[i].debounceAlarm = -100;
|
||||
buttonStates[i].holdAlarm = -1;
|
||||
buttonStates[i].currentState = 0;
|
||||
buttonStates[i].prevState = 0;
|
||||
buttonStates[i].isHeld = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
pwm_set_chan_level(BACKLIGHT_PWM_SLICE, BACKLIGHT_PWM_CHANNEL, 0); // turn off the screen
|
||||
(*((volatile uint32_t *)(PPB_BASE + 0x0ED0C))) = 0x5FA0004; // weird trick to actually reset the controller
|
||||
}
|
||||
|
||||
void save_to_rtc() {
|
||||
printf("saving distance to RTC... ");
|
||||
static bool savedBefore = false;
|
||||
static uint savedDistance;
|
||||
uint8_t buffer[31];
|
||||
memset(buffer, 0, 31);
|
||||
uint newDistance = totalTicks * cmPerTick / 10;
|
||||
if (savedBefore && newDistance == savedDistance) {
|
||||
printf("skipped saving\n");
|
||||
return;
|
||||
}
|
||||
|
||||
*(uint *)(buffer + 0) = newDistance;
|
||||
|
||||
uint16_t checksum = 0;
|
||||
for (int i = 0; i < 29; ++i) {
|
||||
checksum += buffer[i];
|
||||
}
|
||||
*(uint16_t *)(buffer + 29) = checksum;
|
||||
|
||||
uint8_t checkBuffer[31];
|
||||
int limit = 10;
|
||||
do {
|
||||
printf("\nattempting to write...\n");
|
||||
ds1302_set_write_protection(0);
|
||||
// for (int i = 0; i < 31; ++i) {
|
||||
// ds1302_set_ram_byte(0xC0 + i * 2, buffer + i);
|
||||
// sleep_us(2);
|
||||
// }
|
||||
ds1302_write_ram_bulk(buffer, 31);
|
||||
for (int i = 0; i < 30; ++i)
|
||||
printf("%02x ", buffer[i]);
|
||||
printf("%02x\n", buffer[30]);
|
||||
ds1302_read_ram_bulk(checkBuffer, 31);
|
||||
printf("attempting to read back...\n");
|
||||
for (int i = 0; i < 30; ++i)
|
||||
printf("%02x ", checkBuffer[i]);
|
||||
printf("%02x\n", checkBuffer[30]);
|
||||
if (limit-- == 0)
|
||||
break;
|
||||
} while (memcmp(buffer, checkBuffer, 31) != 0);
|
||||
|
||||
#ifdef LOGGING
|
||||
for (int i = 0; i < 30; ++i)
|
||||
printf("%02x ", buffer[i]);
|
||||
printf("%02x\n", buffer[30]);
|
||||
#endif
|
||||
|
||||
savedDistance = newDistance;
|
||||
savedBefore = true;
|
||||
#ifdef LOGGING
|
||||
printf("saved\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool load_from_rtc() {
|
||||
uint8_t buffer[31];
|
||||
ds1302_read_ram_bulk(buffer, 31);
|
||||
|
||||
#ifdef LOGGING
|
||||
for (int i = 0; i < 30; ++i)
|
||||
printf("%02x ", buffer[i]);
|
||||
printf("%02x\n", buffer[30]);
|
||||
#endif
|
||||
|
||||
uint16_t checksum = *(uint16_t *)(buffer + 29);
|
||||
uint16_t actualChecksum = 0;
|
||||
for (int i = 0; i < 29; ++i) {
|
||||
actualChecksum += buffer[i];
|
||||
}
|
||||
if (actualChecksum != checksum) {
|
||||
#ifdef LOGGING
|
||||
printf("discarding invalid data in RTC memory\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
uint savedDistance = *(uint *)(buffer + 0);
|
||||
totalTicks = savedDistance * 10 / cmPerTick;
|
||||
#ifdef LOGGING
|
||||
printf("successfully loaded data from RTC memory\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
15
partition_table.json
Normal file
15
partition_table.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": [1, 0],
|
||||
"unpartitioned": {
|
||||
"families": ["absolute"],
|
||||
"permissions": {
|
||||
"secure": "rw",
|
||||
"nonsecure": "rw",
|
||||
"bootloader": "rw"
|
||||
}
|
||||
},
|
||||
"partitions": [
|
||||
{"name": "app", "id": 0, "size": "1536K", "families": ["rp2350-arm-s"], "permissions": {"secure": "rw", "nonsecure": "rw", "bootloader": "rw"}},
|
||||
{"name": "splash", "id": 1, "size": "112K", "families": ["data"], "permissions": {"secure": "rw", "nonsecure": "rw", "bootloader": "rw"}}
|
||||
]
|
||||
}
|
||||
121
pico_sdk_import.cmake
Normal file
121
pico_sdk_import.cmake
Normal file
@@ -0,0 +1,121 @@
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
# following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
|
||||
endif ()
|
||||
|
||||
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
|
||||
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
|
||||
endif()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||
)
|
||||
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||
FetchContent_Populate(
|
||||
pico_sdk
|
||||
QUIET
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||
GIT_SUBMODULES_RECURSE FALSE
|
||||
|
||||
SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src
|
||||
BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build
|
||||
SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild
|
||||
)
|
||||
else ()
|
||||
FetchContent_Populate(
|
||||
pico_sdk
|
||||
QUIET
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||
|
||||
SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src
|
||||
BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build
|
||||
SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild
|
||||
)
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
28
pins.h
Normal file
28
pins.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef VELOMETER_PINS_H
|
||||
#define VELOMETER_PINS_H
|
||||
|
||||
#define PIN_LCD_CS 1
|
||||
#define PIN_LCD_SCL 2
|
||||
#define PIN_LCD_SDA 3
|
||||
#define PIN_LCD_DATA_COMMAND 4
|
||||
#define PIN_LCD_RESET 5
|
||||
|
||||
#define PIN_LCD_BACKLIGHT 6
|
||||
#define BACKLIGHT_PWM_SLICE 3
|
||||
#define BACKLIGHT_PWM_CHANNEL 0
|
||||
|
||||
#define PIN_RTC_RESET 9
|
||||
#define PIN_RTC_CLOCK 10
|
||||
#define PIN_RTC_IO 11
|
||||
|
||||
#define PIN_BEEPER 12
|
||||
|
||||
#define PIN_BUTTON_0 15
|
||||
#define PIN_BUTTON_1 16
|
||||
#define PIN_BUTTON_2 17
|
||||
#define PIN_BUTTON_3 18
|
||||
|
||||
#define PIN_MAIN_HALL_SENSOR 23
|
||||
#define PIN_AUX_HALL_SENSOR 24
|
||||
|
||||
#endif
|
||||
BIN
splash.png
Normal file
BIN
splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
214
st7789.c
Normal file
214
st7789.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "st7789.h"
|
||||
|
||||
static struct st7789_config st7789_cfg;
|
||||
static uint16_t st7789_width;
|
||||
static uint16_t st7789_height;
|
||||
static bool st7789_data_mode = false;
|
||||
|
||||
void st7789_cmd(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
spi_set_format(st7789_cfg.spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
} else {
|
||||
spi_set_format(st7789_cfg.spi, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
|
||||
}
|
||||
st7789_data_mode = false;
|
||||
|
||||
sleep_us(1);
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_put(st7789_cfg.gpio_cs, 0);
|
||||
}
|
||||
gpio_put(st7789_cfg.gpio_dc, 0);
|
||||
sleep_us(1);
|
||||
|
||||
spi_write_blocking(st7789_cfg.spi, &cmd, sizeof(cmd));
|
||||
|
||||
if (len) {
|
||||
sleep_us(1);
|
||||
gpio_put(st7789_cfg.gpio_dc, 1);
|
||||
sleep_us(1);
|
||||
|
||||
spi_write_blocking(st7789_cfg.spi, data, len);
|
||||
}
|
||||
|
||||
sleep_us(1);
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_put(st7789_cfg.gpio_cs, 1);
|
||||
}
|
||||
gpio_put(st7789_cfg.gpio_dc, 1);
|
||||
sleep_us(1);
|
||||
}
|
||||
|
||||
void st7789_caset(uint16_t xs, uint16_t xe) {
|
||||
uint8_t data[] = {
|
||||
xs >> 8,
|
||||
xs & 0xff,
|
||||
xe >> 8,
|
||||
xe & 0xff,
|
||||
};
|
||||
|
||||
// CASET (2Ah): Column Address Set
|
||||
st7789_cmd(0x2a, data, sizeof(data));
|
||||
}
|
||||
|
||||
void st7789_raset(uint16_t ys, uint16_t ye) {
|
||||
uint8_t data[] = {
|
||||
ys >> 8,
|
||||
ys & 0xff,
|
||||
ye >> 8,
|
||||
ye & 0xff,
|
||||
};
|
||||
|
||||
// RASET (2Bh): Row Address Set
|
||||
st7789_cmd(0x2b, data, sizeof(data));
|
||||
}
|
||||
|
||||
void st7789_init(const struct st7789_config *config, uint16_t width, uint16_t height) {
|
||||
memcpy(&st7789_cfg, config, sizeof(st7789_cfg));
|
||||
st7789_width = width;
|
||||
st7789_height = height;
|
||||
|
||||
spi_init(st7789_cfg.spi, 125 * 1000 * 1000);
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
spi_set_format(st7789_cfg.spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
} else {
|
||||
spi_set_format(st7789_cfg.spi, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
|
||||
}
|
||||
|
||||
gpio_set_function(st7789_cfg.gpio_din, GPIO_FUNC_SPI);
|
||||
gpio_set_function(st7789_cfg.gpio_clk, GPIO_FUNC_SPI);
|
||||
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_init(st7789_cfg.gpio_cs);
|
||||
}
|
||||
gpio_init(st7789_cfg.gpio_dc);
|
||||
gpio_init(st7789_cfg.gpio_rst);
|
||||
gpio_init(st7789_cfg.gpio_bl);
|
||||
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_set_dir(st7789_cfg.gpio_cs, GPIO_OUT);
|
||||
}
|
||||
gpio_set_dir(st7789_cfg.gpio_dc, GPIO_OUT);
|
||||
gpio_set_dir(st7789_cfg.gpio_rst, GPIO_OUT);
|
||||
gpio_set_dir(st7789_cfg.gpio_bl, GPIO_OUT);
|
||||
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_put(st7789_cfg.gpio_cs, 1);
|
||||
}
|
||||
gpio_put(st7789_cfg.gpio_dc, 1);
|
||||
gpio_put(st7789_cfg.gpio_rst, 1);
|
||||
sleep_ms(100);
|
||||
|
||||
// SWRESET (01h): Software Reset
|
||||
st7789_cmd(0x01, NULL, 0);
|
||||
sleep_ms(150);
|
||||
|
||||
// SLPOUT (11h): Sleep Out
|
||||
st7789_cmd(0x11, NULL, 0);
|
||||
sleep_ms(50);
|
||||
|
||||
// COLMOD (3Ah): Interface Pixel Format
|
||||
// - RGB interface color format = 65K of RGB interface
|
||||
// - Control interface color format = 16bit/pixel
|
||||
st7789_cmd(0x3a, (uint8_t[]){0x55}, 1);
|
||||
sleep_ms(10);
|
||||
|
||||
// MADCTL (36h): Memory Data Access Control
|
||||
// - Page Address Order = Top to Bottom
|
||||
// - Column Address Order = Left to Right
|
||||
// - Page/Column Order = Normal Mode
|
||||
// - Line Address Order = LCD Refresh Top to Bottom
|
||||
// - RGB/BGR Order = RGB
|
||||
// - Display Data Latch Data Order = LCD Refresh Left to Right
|
||||
st7789_cmd(0x36, (uint8_t[]){0xA0}, 1);
|
||||
|
||||
st7789_caset(0, width);
|
||||
st7789_raset(0, height);
|
||||
|
||||
// INVON (21h): Display Inversion On
|
||||
st7789_cmd(0x21, NULL, 0);
|
||||
sleep_ms(10);
|
||||
|
||||
// NORON (13h): Normal Display Mode On
|
||||
st7789_cmd(0x13, NULL, 0);
|
||||
sleep_ms(10);
|
||||
|
||||
// DISPON (29h): Display On
|
||||
st7789_cmd(0x29, NULL, 0);
|
||||
sleep_ms(10);
|
||||
|
||||
st7789_fill(0x0000);
|
||||
sleep_ms(50);
|
||||
gpio_put(st7789_cfg.gpio_bl, 1);
|
||||
}
|
||||
|
||||
void st7789_ramwr() {
|
||||
sleep_us(1);
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_put(st7789_cfg.gpio_cs, 0);
|
||||
}
|
||||
gpio_put(st7789_cfg.gpio_dc, 0);
|
||||
sleep_us(1);
|
||||
|
||||
// RAMWR (2Ch): Memory Write
|
||||
uint8_t cmd = 0x2c;
|
||||
spi_write_blocking(st7789_cfg.spi, &cmd, sizeof(cmd));
|
||||
|
||||
sleep_us(1);
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
gpio_put(st7789_cfg.gpio_cs, 0);
|
||||
}
|
||||
gpio_put(st7789_cfg.gpio_dc, 1);
|
||||
sleep_us(1);
|
||||
}
|
||||
|
||||
void st7789_write(const void *data, size_t len) {
|
||||
if (!st7789_data_mode) {
|
||||
st7789_ramwr();
|
||||
|
||||
if (st7789_cfg.gpio_cs > -1) {
|
||||
spi_set_format(st7789_cfg.spi, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
} else {
|
||||
spi_set_format(st7789_cfg.spi, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
|
||||
}
|
||||
|
||||
st7789_data_mode = true;
|
||||
}
|
||||
|
||||
spi_write16_blocking(st7789_cfg.spi, data, len / 2);
|
||||
}
|
||||
|
||||
void st7789_put(uint16_t pixel) { st7789_write(&pixel, sizeof(pixel)); }
|
||||
|
||||
void st7789_fill(uint16_t pixel) {
|
||||
int num_pixels = st7789_width * st7789_height;
|
||||
|
||||
st7789_set_cursor(0, 0);
|
||||
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
st7789_put(pixel);
|
||||
}
|
||||
}
|
||||
|
||||
void st7789_set_cursor(uint16_t x, uint16_t y) {
|
||||
st7789_caset(x, st7789_width);
|
||||
st7789_raset(y, st7789_height);
|
||||
}
|
||||
|
||||
void st7789_vertical_scroll(uint16_t row) {
|
||||
uint8_t data[] = {(row >> 8) & 0xff, row & 0x00ff};
|
||||
|
||||
// VSCSAD (37h): Vertical Scroll Start Address of RAM
|
||||
st7789_cmd(0x37, data, sizeof(data));
|
||||
}
|
||||
33
st7789.h
Normal file
33
st7789.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PICO_ST7789_H_
|
||||
#define _PICO_ST7789_H_
|
||||
|
||||
#include "hardware/spi.h"
|
||||
|
||||
struct st7789_config {
|
||||
spi_inst_t *spi;
|
||||
uint gpio_din;
|
||||
uint gpio_clk;
|
||||
int gpio_cs;
|
||||
uint gpio_dc;
|
||||
uint gpio_rst;
|
||||
uint gpio_bl;
|
||||
};
|
||||
|
||||
void st7789_cmd(uint8_t cmd, const uint8_t *data, size_t len);
|
||||
void st7789_init(const struct st7789_config *config, uint16_t width, uint16_t height);
|
||||
void st7789_write(const void *data, size_t len);
|
||||
void st7789_put(uint16_t pixel);
|
||||
void st7789_fill(uint16_t pixel);
|
||||
void st7789_caset(uint16_t xs, uint16_t xe);
|
||||
void st7789_raset(uint16_t ys, uint16_t ye);
|
||||
void st7789_set_cursor(uint16_t x, uint16_t y);
|
||||
void st7789_vertical_scroll(uint16_t row);
|
||||
|
||||
#endif
|
||||
59
utf8.c
Normal file
59
utf8.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "utf8.h"
|
||||
|
||||
// This macro tests if a char is a continuation byte in utf8.
|
||||
#define IS_CONT(x) (((x) & 0xc0) == 0x80)
|
||||
|
||||
// This returns the code point encoded at **s and advances *s to point to the
|
||||
// next character. Thus it can easily be used in a loop.
|
||||
int decode_code_point(const char **s) {
|
||||
int k = **s ? __builtin_clz(~(**s << 24)) : 0; // Count # of leading 1 bits.
|
||||
int mask = (1 << (8 - k)) - 1; // All 1s with k leading 0s.
|
||||
int value = **s & mask;
|
||||
// k = 0 for one-byte code points; otherwise, k = #total bytes.
|
||||
for (++(*s), --k; k > 0 && IS_CONT(**s); --k, ++(*s)) {
|
||||
value <<= 6;
|
||||
value += (**s & 0x3F);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// This assumes that `code` is <= 0x10FFFF and ensures that nothing will be
|
||||
// written at or beyond `end`. It advances *s so it's easy to use in a loop.
|
||||
void encode_code_point(char **s, char *end, int code) {
|
||||
char val[4];
|
||||
int lead_byte_max = 0x7F;
|
||||
int val_index = 0;
|
||||
while (code > lead_byte_max) {
|
||||
val[val_index++] = (code & 0x3F) | 0x80;
|
||||
code >>= 6;
|
||||
lead_byte_max >>= (val_index == 1 ? 2 : 1);
|
||||
}
|
||||
val[val_index++] = (code & lead_byte_max) | (~lead_byte_max << 1);
|
||||
while (val_index-- && *s < end) {
|
||||
**s = val[val_index];
|
||||
(*s)++;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns 0 if no split was needed.
|
||||
int split_into_surrogates(int code, int *surr1, int *surr2) {
|
||||
if (code <= 0xFFFF)
|
||||
return 0;
|
||||
*surr2 = 0xDC00 | (code & 0x3FF); // Save the low 10 bits.
|
||||
code >>= 10; // Drop the low 10 bits.
|
||||
// If `code` now has low bits "uuu uuxx xxxx", then the bits of *surr are
|
||||
// "1101 10ww wwxx xxxx" where wwww = (uuuuu - 1).
|
||||
*surr1 = 0xD800 | ((code & 0x7FF) - 0x40);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This expects to be used in a loop and see all code points in *code. Start
|
||||
// *old at 0; this function updates *old for you - don't change it after
|
||||
// initialization. This returns 0 when *code is the 1st of a surrogate pair;
|
||||
// otherwise use *code as the final code point.
|
||||
int join_from_surrogates(int *old, int *code) {
|
||||
if (*old)
|
||||
*code = (((*old & 0x3FF) + 0x40) << 10) + (*code & 0x3FF);
|
||||
*old = ((*code & 0xD800) == 0xD800 ? *code : 0);
|
||||
return !(*old);
|
||||
}
|
||||
9
utf8.h
Normal file
9
utf8.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef VELOMETER_UTF8_H
|
||||
#define VELOMETER_UTF8_H
|
||||
|
||||
int decode_code_point(const char **s);
|
||||
void encode_code_point(char **s, char *end, int code);
|
||||
int split_into_surrogates(int code, int *surr1, int *surr2);
|
||||
int join_from_surrogates(int *old, int *code);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user