Projekt automatického zalévání květin s řízením pomocí webu.
Schéma zapojení
Zdrojové kódy
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(PROJECT_NAME kytky)
set(PICO_BOARD pico_w)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(HOSTNAME kytka1)
if(DEFINED HOSTNAME)
add_compile_definitions(CYW43_HOST_NAME=\"${HOSTNAME}\")
endif()
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(${PROJECT_NAME} C CXX ASM)
pico_sdk_init()
message("Running makefsdata python script")
execute_process(COMMAND
python3 makefsdata.py
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
add_executable(${PROJECT_NAME}
main.c
ssd1306.c
)
# nastaveni vyhrazeneho mista ve XIP flash pro konfiguracni data
pico_set_linker_script(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_custom.ld)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(${PROJECT_NAME}
pico_cyw43_arch_lwip_threadsafe_background
pico_lwip_http
pico_stdlib
hardware_adc
hardware_i2c
)
# volby pro linker
target_link_options( ${PROJECT_NAME} PRIVATE -Xlinker --print-memory-usage)
pico_enable_stdio_usb( ${PROJECT_NAME} TRUE)
pico_enable_stdio_uart(${PROJECT_NAME} FALSE)
pico_add_extra_outputs(${PROJECT_NAME})
link:memmap_custom.ld
/* Based on GCC ARM embedded samples.
Defines the following symbols for use by code:
__exidx_start
__exidx_end
__etext
__data_start__
__preinit_array_start
__preinit_array_end
__init_array_start
__init_array_end
__fini_array_start
__fini_array_end
__data_end__
__bss_start__
__bss_end__
__end__
end
__HeapLimit
__StackLimit
__StackTop
__stack (== StackTop)
*/
__PERSISTENT_STORAGE_LEN = 16k ;
MEMORY
{
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k - __PERSISTENT_STORAGE_LEN
FLASH_PERSISTENT(rw) : ORIGIN = 0x10000000 + (2048k - __PERSISTENT_STORAGE_LEN) , LENGTH = __PERSISTENT_STORAGE_LEN
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
}
ENTRY(_entry_point)
SECTIONS
{
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
and checksummed. It is usually built by the boot_stage2 target
in the Raspberry Pi Pico SDK
*/
.flash_begin : {
__flash_binary_start = .;
} > FLASH
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > FLASH
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
/* The second stage will always enter the image at the start of .text.
The debugger will use the ELF entry point, which is the _entry_point
symbol if present, otherwise defaults to start of .text.
This can be used to transfer control back to the bootrom on debugger
launches only, to perform proper flash setup.
*/
.text : {
__logical_binary_start = .;
KEEP (*(.vectors))
KEEP (*(.binary_info_header))
__binary_info_header_end = .;
KEEP (*(.reset))
/* TODO revisit this now memset/memcpy/float in ROM */
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
* FLASH ... we will include any thing excluded here in .data below by default */
*(.init)
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
*(.fini)
/* Pull all c'tors into .text */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* Followed by destructors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.eh_frame*)
. = ALIGN(4);
} > FLASH
.rodata : {
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
. = ALIGN(4);
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
. = ALIGN(4);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* Machine inspectable binary information */
. = ALIGN(4);
__binary_info_start = .;
.binary_info :
{
KEEP(*(.binary_info.keep.*))
*(.binary_info.*)
} > FLASH
__binary_info_end = .;
. = ALIGN(4);
/* End of .text-like segments */
__etext = .;
.section_persisitent : {
"ADDR_PERSISTENT" = .;
} > FLASH_PERSISTENT
.ram_vector_table (COPY): {
*(.ram_vector_table)
} > RAM
.data : {
__data_start__ = .;
*(vtable)
*(.time_critical*)
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
*(.text*)
. = ALIGN(4);
*(.rodata*)
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
*(.after_data.*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__mutex_array_start = .);
KEEP(*(SORT(.mutex_array.*)))
KEEP(*(.mutex_array))
PROVIDE_HIDDEN (__mutex_array_end = .);
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH
.uninitialized_data (COPY): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
*(.scratch_x.*)
. = ALIGN(4);
__scratch_x_end__ = .;
} > SCRATCH_X AT > FLASH
__scratch_x_source__ = LOADADDR(.scratch_x);
.scratch_y : {
__scratch_y_start__ = .;
*(.scratch_y.*)
. = ALIGN(4);
__scratch_y_end__ = .;
} > SCRATCH_Y AT > FLASH
__scratch_y_source__ = LOADADDR(.scratch_y);
.bss : {
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack*_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later
*
* stack1 section may be empty/missing if platform_launch_core1 is not used */
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
{
*(.stack*)
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
} > FLASH
/* stack limit is poorly named, but historically is maximum heap ptr */
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
/* todo assert on extra code */
}
main.c
/* Web server na Pico W -- automatické zalévání květin
* version 0.2
* (c) Jirka Chráska 2026, <jirka@lixis.cz>
* BSD-licence
*/
#include "lwip/apps/httpd.h"
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "flash_utils.h"
#include "hardware/flash.h"
#include "lwip/netif.h"
#include "lwipopts.h"
// hranice sucha
// #define SUCHO 1.0 // nad 1V napětí na čidlu vlhkosti je sucho
// #define PORUCHA_CIDLA 0.3 // pod 0.3V budeme považovat za poruchu
float SUCHO = 1.0;
float PORUCHA_CIDLA = 0.3;
#include "ssi.h"
#include "cgi.h"
#include "ssd1306.h"
#include "font_spleen_8x5.h"
#include "font_spleen_16x8a.h"
#include "setupWifi.h"
// hostname
const char MY_HOSTNAME[] = "kytky";
// ---------------------------------------------------------------------------
// nastavení OLED displeje
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
#define I2C_ADDRESS 0x3C
#define I2C_FREQ 400000
#define SLEEPTIME 55
void setup_gpios(void) {
i2c_init(i2c_default, I2C_FREQ);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
}
// buffery pro zobrazení na displeji
#define BUFLEN 128
char buf[BUFLEN];
char ip4adresa[BUFLEN];
char hostname_ssid[BUFLEN];
char msg1[BUFLEN];
char msg2[BUFLEN];
char msg3[BUFLEN];
// struktura displeje SSD1306
ssd1306_t disp;
// ---------------------------------------------------------------------------
// známé sítě
const uint8_t *flash_target_content;
// struktura údajů o známé síti
typedef struct wifi_zname {
char* ssid; // jméno sítě
char* pass; // heslo v otevřeném textu
char* auth; // způsob autorizace
char* ipv6; // umí síť IPv6 (y/n)
char* ipv4; // umí síť IPv4 (y/n)
int rssi; // aktuální síla signálu
struct wifi_zname * next; // ukazatel na další prvek seznamu
} ZNAME_WIFI;
// ukazatel na počátek seznamu známých sítí
ZNAME_WIFI* zwifi = NULL;
// vytvoří seznam známých Wifi, ke kterým se můžeme připojit
void napln_zname_wifi(void)
{
char *wifidata; // pomocný ukazatel do XIP flash
ZNAME_WIFI *zw;
flash_target_content = (const uint8_t *) getAddressPersistent();
for( int i=0; i<8; i++ ){
wifidata = (char*) flash_target_content+(i*128);
zw = malloc(sizeof(ZNAME_WIFI));
if(zw != NULL) {
zw->ssid = wifidata+5;
// printf("%p ssid='%s' ", wifidata, zw->ssid);
int len = strlen(zw->ssid)+6;
zw->pass = wifidata+len+5;
// printf("%p pass='%s' ", wifidata, zw->pass);
len += strlen(zw->pass)+6;
zw->auth = wifidata+len+5;
// printf("%p auth='%s' ", wifidata, zw->auth);
len += strlen(zw->auth)+6;
zw->ipv6 = wifidata+len+5;
//printf("%p ipv6='%s' ", wifidata, zw->ipv6);
len += strlen(zw->ipv6)+6;
zw->ipv4 = wifidata+len+5;
// printf("%p ipv4='%s'\n", wifidata, zw->ipv4);
// počáteční signál -120 dBm
zw->rssi = -120;
if( zwifi != NULL ) { // v seznamu už něco máme
zw->next = zwifi;
} else { // vkládáme první prvek (v seznamu bude poslední)
zw->next = NULL;
}
zwifi = zw;
} else {
printf("Nedostatek paměti.\n");
break;
}
}
}
// najde v seznamu známou WiFi podle ssid
ZNAME_WIFI * najdi_wifi(const char *ssid)
{
for( ZNAME_WIFI *zw = zwifi; zw!=NULL; zw=zw->next ) {
if(strcmp(zw->ssid, ssid) == 0 ) {
return zw;
}
}
return NULL;
}
// najde v seznamu Wifi s nejlepším signálem
ZNAME_WIFI *najdi_nejvetsi_rssi( void )
{
int rssi = -120;
ZNAME_WIFI *res = NULL;
for( ZNAME_WIFI *zw = zwifi; zw!=NULL; zw=zw->next ) {
if(zw->rssi > rssi) {
res = zw;
rssi = zw->rssi;
}
}
return res;
}
// uvolní seznam známých wifi
void zrus_zname_wifi( void )
{
for( ZNAME_WIFI *ptr=zwifi; ptr!=NULL; ) {
ZNAME_WIFI *ptr2 = ptr;
ptr = ptr->next;
free(ptr2);
}
}
// callback, výsledky skenování
static int scan_result(void *env, const cyw43_ev_scan_result_t *result)
{
if (result)
{
ZNAME_WIFI *znam = najdi_wifi( result->ssid );
if( znam != NULL) {
if( result->rssi > znam->rssi ) {
znam->rssi = result->rssi;
}
printf("ssid: %-32s rssi: %4d chan: %3d mac: %02x:%02x:%02x:%02x:%02x:%02x sec: %s known: %s\n",
result->ssid, result->rssi, result->channel,
result->bssid[0], result->bssid[1], result->bssid[2],
result->bssid[3], result->bssid[4], result->bssid[5],
(result->auth_mode == 5) ? "WPA2_MIXED_PSK" :
(result->auth_mode == 7) ? "WPA_TKIP_PSK" :
(result->auth_mode == 0) ? "OPEN" : "UNKNOWN",
"yes" );
} else {
printf("ssid: %-32s rssi: %4d chan: %3d mac: %02x:%02x:%02x:%02x:%02x:%02x sec: %s known: %s\n",
result->ssid, result->rssi, result->channel,
result->bssid[0], result->bssid[1], result->bssid[2],
result->bssid[3], result->bssid[4], result->bssid[5],
(result->auth_mode == 5) ? "WPA2_MIXED_PSK" :
(result->auth_mode == 7) ? "WPA_TKIP_PSK" :
(result->auth_mode == 0) ? "OPEN" : "UNKNOWN",
"no" );
}
}
return 0;
}
// připojení k AP
int connect( ZNAME_WIFI *zw, const char * hostname )
{
uint32_t country = CYW43_COUNTRY_CZECH_REPUBLIC;
uint32_t auth;
if( strcmp(zw->auth,"WPA2_MIXED_PSK") == 0) auth = CYW43_AUTH_WPA2_MIXED_PSK;
if( strcmp(zw->auth,"WPA_TKIP_PSK") == 0) auth = CYW43_AUTH_WPA_TKIP_PSK;
return setup(country, zw->ssid, zw->pass, auth, hostname );
}
// --------------------------------------------------------------------------------------------
// teplota na Picu
float tempC = 0.0;
// naměřená vlhkost pomocí čidla
// vyšší napětí nad 1 V znamená sucho v misce květináče
float vlhkost = 0.0;
bool porucha = false;
// pomocná proměnná
float voltage = 0.0;
// --------------------------------------------------------------------------------------------
// relé má obrácenou logiku: zapnuto 0, vypnuto 1
#define RELE_VYPNUTO 1
#define RELE_ZAPNUTO 0
#define MAX_CAS_ZALEVANI 10000 // v milisekundách
volatile bool casovac_vyprsel = false;
// obsluha časovače
int64_t zalevani_alarm_callback( alarm_id_t id, __unused void *user_data )
{
casovac_vyprsel = true;
gpio_put(RELE_PIN,RELE_VYPNUTO); // vypínáme čerpadlo
return 0;
}
// obsluha zalévání
void zalevej( bool ano )
{
if( porucha ) {
gpio_put(RELE_PIN, RELE_VYPNUTO);
return;
}
if( ano == true && gpio_get(RELE_PIN)== RELE_VYPNUTO ) {
gpio_put(RELE_PIN, RELE_ZAPNUTO);
// nastavení časovače maximální doby zalévání
// po uplynutí časovače se čerpadlo vypne v každém případě
add_alarm_in_ms( MAX_CAS_ZALEVANI, zalevani_alarm_callback, NULL, false);
}
// je dosaženo dostatečné hladiny zalití
if( ano == false ) {
gpio_put(RELE_PIN, RELE_VYPNUTO);
}
}
// --------------------------------------------------------------------------------------------
int main() {
gpio_init(RELE_PIN);
gpio_set_dir(RELE_PIN, GPIO_OUT);
gpio_put(RELE_PIN,RELE_VYPNUTO);
stdio_init_all();
memset(buf,'\0', BUFLEN);
memset(ip4adresa,'\0', BUFLEN);
memset(hostname_ssid,'\0', BUFLEN);
memset(msg1,'\0', BUFLEN);
memset(msg2,'\0', BUFLEN);
memset(msg3,'\0', BUFLEN);
// pauza na nahození sériové linky při ladění
// sleep_ms(20000);
adc_init();
adc_set_temp_sensor_enabled(true);
setup_gpios();
disp.external_vcc = false;
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, i2c_default);
ssd1306_clear(&disp);
// mastavení WiFi
napln_zname_wifi();
// inicializace cyw43 chipu
if (cyw43_arch_init())
{
printf("failed to initialise\n");
return 1;
}
// Picow nastavíme jako stanici
cyw43_arch_enable_sta_mode();
cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_STA, true, CYW43_COUNTRY_CZECH_REPUBLIC);
cyw43_wifi_scan_options_t scan_options = {0};
// začínáme skenovat sítě
int err = cyw43_wifi_scan(&cyw43_state, &scan_options, NULL, scan_result);
while (true)
{
printf("Skenujeme ... \n");
snprintf(msg1,128,"Wifi scan");
ssd1306_draw_string_with_font(&disp, 0, 39, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
if (!cyw43_wifi_scan_active(&cyw43_state))
break;
sleep_ms(1000);
}
printf("Scan je hotov.\n");
cyw43_arch_deinit();
ssd1306_clear(&disp);
snprintf(msg1,128,"Wifi scan OK");
ssd1306_draw_string_with_font(&disp, 0, 39, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
ZNAME_WIFI *zw = najdi_nejvetsi_rssi();
if( zw != NULL ) { // máme wifi k připojení
bool error = false;
printf("Nejlepší signál %d má ssid %s sem se připojíme.\n", zw->rssi, zw->ssid);
ssd1306_clear(&disp);
snprintf(msg1,128,"%s: signal %d dBm", zw->ssid, zw->rssi);
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
int connection_status = 0;
int cekani = 0;
do {
printf("Připojuji se k AP %s.\n",zw->ssid);
ssd1306_clear(&disp);
snprintf(msg1,128,"%s: signal %d dBm", zw->ssid, zw->rssi);
snprintf(msg2,128,"Connecting ...");
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_8x5, msg1);
ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_8x5, msg2);
ssd1306_show(&disp);
connection_status = connect(zw, MY_HOSTNAME );
} while ( connection_status != CYW43_LINK_UP && !timer_fired);
if( timer_fired ) {
printf("Problém s připojením AP %s, není přidělena adresa.\n",zw->ssid);
ssd1306_clear(&disp);
snprintf(msg1,128,"%s: signal %d dBm", zw->ssid, zw->rssi);
snprintf(msg2,128,"Cannot connect.");
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_8x5, msg1);
ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_8x5, msg2);
ssd1306_show(&disp);
}
if( connection_status == CYW43_LINK_UP ) {
struct netif *n = &cyw43_state.netif[CYW43_ITF_STA];
cyw43_arch_lwip_begin();
netif_set_hostname(n,MY_HOSTNAME);
netif_set_up(n);
cyw43_arch_lwip_end();
snprintf(hostname_ssid,BUFLEN-1,"Hostname:%s", MY_HOSTNAME);
ssd1306_draw_string_with_font(&disp, 0, 30, 1, font_spleen_8x5, hostname_ssid);
// Jsem připojen
snprintf(ip4adresa,20,ip4addr_ntoa(netif_ip4_addr(netif_list)));
printf("Připojen k %s: %s IP: %s\n", zw->ssid, MY_HOSTNAME, buf );
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_16x8a, ip4adresa);
ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_8x5, zw->ssid );
ssd1306_show(&disp);
ssd1306_show(&disp);
// Initializace web serveru
httpd_init();
printf("Http server nahozen.\n");
snprintf(msg1,128,"Http %s OK", MY_HOSTNAME);
ssd1306_draw_string_with_font(&disp, 0, 39, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
// Konfigurace SSI a CGI handleru
ssi_init();
printf("SSI Handler nahozen.\n");
snprintf(msg2,128,"SSI handler OK");
ssd1306_draw_string_with_font(&disp, 0, 47, 1, font_spleen_8x5, msg2);
ssd1306_show(&disp);
cgi_init();
printf("CGI Handler nahozen.\n");
snprintf(msg3,128,"CGI handler OK");
ssd1306_draw_string_with_font(&disp, 0, 55, 1, font_spleen_8x5, msg3);
ssd1306_show(&disp);
} else {
sprintf(msg1,"Wifi %s nefunguje.\n",zw->ssid);
ssd1306_draw_string_with_font(&disp, 0, 39, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
}
} else { // nenalezena žádná wifi, kam se možno připojit
sprintf(msg1,"Nemame wifi.\n",zw->ssid);
ssd1306_draw_string_with_font(&disp, 0, 39, 1, font_spleen_8x5, msg1);
ssd1306_show(&disp);
}
// Nekonečná smyčka měření a zalévání
while(1) {
// měření vlhkosti
adc_select_input(0);
vlhkost = adc_read() * REF_VOLT / (1 << 12);
sleep_ms(50);
// měření interní teploty Pica (dost nepřené)
adc_select_input(4);
voltage = adc_read() * REF_VOLT / (1 << 12);
tempC = 22.0f - (voltage - 0.706f) / 0.001721f;
sleep_ms(50);
// zobrazení na displeji
ssd1306_clear(&disp);
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_16x8a, ip4adresa);
snprintf(msg1, 128, "%s SSID: %s", MY_HOSTNAME, zw->ssid);
ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_8x5, msg1);
if(vlhkost > PORUCHA_CIDLA) {
snprintf(msg2, 128, "Vlhkost: %5.3f", vlhkost);
} else {
snprintf(msg2, 128, "Porucha!", vlhkost);
}
ssd1306_draw_string_with_font(&disp, 0, 32, 1, font_spleen_16x8a, msg2);
ssd1306_show(&disp);
snprintf(msg3, 128, "Teplota: %5.1f", tempC);
ssd1306_draw_string_with_font(&disp, 0, 48, 1, font_spleen_16x8a, msg3);
ssd1306_show(&disp);
// rozhodnutí zda zalévat
if( vlhkost > PORUCHA_CIDLA ) {
porucha = false;
if( vlhkost > SUCHO ) { // mělo by se zalít
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
zalevej(true);
} else {
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
zalevej(false);
}
} else {
// detekována porucha čidla
porucha = true;
gpio_put(RELE_PIN, RELE_VYPNUTO);
}
sleep_ms(500);
}
}
// eof
setupWifi.h
/* Nastavení Wifi karty */
volatile bool timer_fired = false;
int64_t alarm_callback( alarm_id_t id, __unused void *user_data )
{
printf("Timer %d fired!\n", (int) id);
timer_fired = true;
return 0;
}
int setup(uint32_t country, const char *ssid, const char *pass, uint32_t auth, const char *hostname)
{
if (cyw43_arch_init_with_country(country))
{
return 1;
}
cyw43_arch_enable_sta_mode();
if (hostname != NULL)
{
netif_set_hostname(netif_default, hostname);
}
if (cyw43_arch_wifi_connect_async(ssid, pass, auth))
{
return 2;
}
int flashrate = 1000;
int status = CYW43_LINK_UP + 1;
// k připojení na Wifi nastavíme timeout 10s
add_alarm_in_ms(10000, alarm_callback, NULL, false);
while (status >= 0 && !timer_fired && status != CYW43_LINK_UP)
{
int new_status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA);
if (new_status != status)
{
status = new_status;
flashrate = flashrate / (status + 1);
printf("Stav připojení: %d %d\n", status, flashrate);
}
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
sleep_ms(flashrate);
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
sleep_ms(flashrate);
}
if (status < 0)
{
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
}
else
{
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
}
return status;
}
cgi.h
#include "lwip/apps/httpd.h"
#include "pico/cyw43_arch.h"
#define RELE_PIN 15
// CGI handler which is run when a request for /led.cgi is detected
const char * cgi_led_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
// Check if an request for LED has been made (/led.cgi?led=x)
if (strcmp(pcParam[0] , "led") == 0){
// Look at the argument to check if LED is to be turned on (x=1) or off (x=0)
if(strcmp(pcValue[0], "0") == 0) {
// cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
gpio_put(RELE_PIN, 1);
} else if(strcmp(pcValue[0], "1") == 0) {
// cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
gpio_put(RELE_PIN, 0);
}
}
// Send the index page back to the user
return "/index.shtml";
}
// tCGI Struct
// Fill this with all of the CGI requests and their respective handlers
static const tCGI cgi_handlers[] = {
{
// Html request for "/led.cgi" triggers cgi_handler
"/led.cgi", cgi_led_handler
},
};
void cgi_init(void)
{
http_set_cgi_handlers(cgi_handlers, 1);
}
ssh.h
#include "lwip/apps/httpd.h"
#include "pico/cyw43_arch.h"
#include "hardware/adc.h"
#define REF_VOLT 3.3f
#define RELE_PIN 15
// SSI tags - tag length limited to 8 bytes by default
const char * ssi_tags[] = {"volt","temp","led"};
u16_t ssi_handler(int iIndex, char *pcInsert, int iInsertLen) {
size_t printed;
switch (iIndex) {
case 0: // vlhkost
{
adc_select_input(0);
const float voltage = adc_read() * REF_VOLT / (1 << 12);
if( voltage > SUCHO ) {
printed = snprintf(pcInsert, iInsertLen, "%f V, sucho", voltage);
} else if( voltage <= SUCHO && voltage > PORUCHA_CIDLA ) {
printed = snprintf(pcInsert, iInsertLen, "%f V, normální", voltage);
} else {
printed = snprintf(pcInsert, iInsertLen, "%f V, porucha čidla!", voltage);
}
}
break;
case 1: // teplota
{
adc_select_input(4);
const float voltage = adc_read() * REF_VOLT / (1 << 12);
const float tempC = 22.0f - (voltage - 0.706f) / 0.001721f;
printed = snprintf(pcInsert, iInsertLen, "%f", tempC);
}
break;
case 2: // led
{
bool cerpadlo = gpio_get(RELE_PIN);
if(cerpadlo == true){
printed = snprintf(pcInsert, iInsertLen, "vypnuto");
}
else{
printed = snprintf(pcInsert, iInsertLen, "zapnuto");
}
}
break;
default:
printed = 0;
break;
}
return (u16_t)printed;
}
// Initialise the SSI handler
void ssi_init()
{
http_set_ssi_handler(ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags));
}
lwipopts.h
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)]
// allow override in some examples
#ifndef NO_SYS
#define NO_SYS 1
#endif
// allow override in some examples
#ifndef LWIP_SOCKET
#define LWIP_SOCKET 0
#endif
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 4000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
// This section enables HTTPD server with SSI, SGI
// and tells server which converted HTML files to use
#define LWIP_HTTPD 1
#define LWIP_HTTPD_SSI 1
#define LWIP_HTTPD_CGI 1
#define LWIP_HTTPD_SSI_INCLUDE_TAG 0
#define HTTPD_FSDATA_FILE "htmldata.c"
html_files/index.shtml
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Mgr. Ing. Jiří Chráska">
<title>Automatické zalévání květin</title>
<style>
* {margin 0; padding: 0; font-size: 1em; font-family: 'Segoe UI', Tahoma, sans-serif;}
body {background-color: #dcdcdc;}
h1 {color: #00008b; font-family: verdana; font-size: 120%;}
h2 {color: #00008b; font-family: verdana; font-size: 100%;}
button {margin: 5px; padding: 10px;}
</style>
<script>
setTimeout(() => { document.location.reload(true);}, 5000);
</script>
</head>
<body> <h1>Automatické zalévání květin</h1>
<br>
<h2>Stav na květině:</h2>
<p>Vlhkost: <!--#volt--> V</p>
<p>Teplota: <!--#temp--> °C</p>
<p>Čerpadlo je: <!--#led--></p>
<div><a href="/index.shtml"><button>Aktualizovat měření</button></a></div>
<br>
<h2>Ruční zalití:</h2>
<div><a href="/led.cgi?led=1"><button>Ručně zalít</button></a></div>
<div><a href="/led.cgi?led=0"><button>Vypnout zalévání</button></a></div>
<br>
<br>
</body>
</html>
Displej SSD1306 128x64
ssd1306.c
/*
MIT License
Copyright (c) 2021 David Schramm
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.
*/
#include <pico/stdlib.h>
#include <hardware/i2c.h>
#include <pico/binary_info.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ssd1306.h"
#include "font.h"
inline static void swap(int32_t *a, int32_t *b) {
int32_t *t=a;
*a=*b;
*b=*t;
}
inline static void fancy_write(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, char *name) {
switch(i2c_write_blocking(i2c, addr, src, len, false)) {
case PICO_ERROR_GENERIC:
printf("[%s] addr not acknowledged!\n", name);
break;
case PICO_ERROR_TIMEOUT:
printf("[%s] timeout!\n", name);
break;
default:
//printf("[%s] wrote successfully %lu bytes!\n", name, len);
break;
}
}
inline static void ssd1306_write(ssd1306_t *p, uint8_t val) {
uint8_t d[2]= {0x00, val};
fancy_write(p->i2c_i, p->address, d, 2, "ssd1306_write");
}
bool ssd1306_init(ssd1306_t *p, uint16_t width, uint16_t height, uint8_t address, i2c_inst_t *i2c_instance) {
p->width=width;
p->height=height;
p->pages=height/8;
p->address=address;
p->i2c_i=i2c_instance;
p->bufsize=(p->pages)*(p->width);
if((p->buffer=malloc(p->bufsize+1))==NULL) {
p->bufsize=0;
return false;
}
++(p->buffer);
// from https://github.com/makerportal/rpi-pico-ssd1306
uint8_t cmds[]= {
SET_DISP,
// timing and driving scheme
SET_DISP_CLK_DIV,
0x80,
SET_MUX_RATIO,
height - 1,
SET_DISP_OFFSET,
0x00,
// resolution and layout
SET_DISP_START_LINE,
// charge pump
SET_CHARGE_PUMP,
p->external_vcc?0x10:0x14,
SET_SEG_REMAP | 0x01, // column addr 127 mapped to SEG0
SET_COM_OUT_DIR | 0x08, // scan from COM[N] to COM0
SET_COM_PIN_CFG,
width>2*height?0x02:0x12,
// display
SET_CONTRAST,
0xff,
SET_PRECHARGE,
p->external_vcc?0x22:0xF1,
SET_VCOM_DESEL,
0x30, // or 0x40?
SET_ENTIRE_ON, // output follows RAM contents
SET_NORM_INV, // not inverted
SET_DISP | 0x01,
// address setting
SET_MEM_ADDR,
0x00, // horizontal
};
for(size_t i=0; i<sizeof(cmds); ++i)
ssd1306_write(p, cmds[i]);
return true;
}
inline void ssd1306_deinit(ssd1306_t *p) {
free(p->buffer-1);
}
inline void ssd1306_poweroff(ssd1306_t *p) {
ssd1306_write(p, SET_DISP|0x00);
}
inline void ssd1306_poweron(ssd1306_t *p) {
ssd1306_write(p, SET_DISP|0x01);
}
inline void ssd1306_contrast(ssd1306_t *p, uint8_t val) {
ssd1306_write(p, SET_CONTRAST);
ssd1306_write(p, val);
}
inline void ssd1306_invert(ssd1306_t *p, uint8_t inv) {
ssd1306_write(p, SET_NORM_INV | (inv & 1));
}
inline void ssd1306_clear(ssd1306_t *p) {
memset(p->buffer, 0, p->bufsize);
}
void ssd1306_clear_pixel(ssd1306_t *p, uint32_t x, uint32_t y) {
if(x>=p->width || y>=p->height) return;
p->buffer[x+p->width*(y>>3)]&=~(0x1<<(y&0x07));
}
void ssd1306_draw_pixel(ssd1306_t *p, uint32_t x, uint32_t y) {
if(x>=p->width || y>=p->height) return;
p->buffer[x+p->width*(y>>3)]|=0x1<<(y&0x07); // y>>3==y/8 && y&0x7==y%8
}
void ssd1306_draw_line(ssd1306_t *p, int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
if(x1>x2) {
swap(&x1, &x2);
swap(&y1, &y2);
}
if(x1==x2) {
if(y1>y2)
swap(&y1, &y2);
for(int32_t i=y1; i<=y2; ++i)
ssd1306_draw_pixel(p, x1, i);
return;
}
float m=(float) (y2-y1) / (float) (x2-x1);
for(int32_t i=x1; i<=x2; ++i) {
float y=m*(float) (i-x1)+(float) y1;
ssd1306_draw_pixel(p, i, (uint32_t) y);
}
}
void ssd1306_clear_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
for(uint32_t i=0; i<width; ++i)
for(uint32_t j=0; j<height; ++j)
ssd1306_clear_pixel(p, x+i, y+j);
}
void ssd1306_draw_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
for(uint32_t i=0; i<width; ++i)
for(uint32_t j=0; j<height; ++j)
ssd1306_draw_pixel(p, x+i, y+j);
}
void ssd1306_draw_empty_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
ssd1306_draw_line(p, x, y, x+width, y);
ssd1306_draw_line(p, x, y+height, x+width, y+height);
ssd1306_draw_line(p, x, y, x, y+height);
ssd1306_draw_line(p, x+width, y, x+width, y+height);
}
void ssd1306_draw_char_with_font(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint8_t *font, char c) {
if(c<font[3]||c>font[4])
return;
uint32_t parts_per_line=(font[0]>>3)+((font[0]&7)>0);
// printf("\nF8[x,y]=[%3d,%2d] scale=%1d char=%02x, ppl=%d\n",x,y,scale,c,parts_per_line);
for(uint8_t w=0; w<font[1]; ++w) { // width
uint32_t pp=(c-font[3])*font[1]*parts_per_line+w*parts_per_line+5;
// printf("pp=%d: ",pp);
for(uint32_t lp=0; lp<parts_per_line; ++lp) {
uint8_t line=font[pp];
// printf("line=%02x, ",line);
for(int8_t j=0; j<8; ++j, line>>=1) {
if(line & 1)
ssd1306_draw_square(p, x+w*scale, y+((lp<<3)+j)*scale, scale, scale);
}
++pp;
}
}
}
void ssd1306_draw_string_with_font(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint8_t *font, const char *s) {
for(int32_t x_n=x; *s; x_n+=(font[1]+font[2])*scale) {
if( *s == '.' || *s == ',' || *s == ';' || *s == ':' || *s == '!') { // setrime misto
x_n--; x_n--;
}
ssd1306_draw_char_with_font(p, x_n, y, scale, font, *(s++));
}
}
void ssd1306_draw_char(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, char c) {
ssd1306_draw_char_with_font(p, x, y, scale, font_8x5, c);
}
void ssd1306_draw_string(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const char *s) {
ssd1306_draw_string_with_font(p, x, y, scale, font_8x5, s);
}
static inline uint32_t ssd1306_bmp_get_val(const uint8_t *data, const size_t offset, uint8_t size) {
switch(size) {
case 1:
return data[offset];
case 2:
return data[offset]|(data[offset+1]<<8);
case 4:
return data[offset]|(data[offset+1]<<8)|(data[offset+2]<<16)|(data[offset+3]<<24);
default:
__builtin_unreachable();
}
__builtin_unreachable();
}
void ssd1306_bmp_show_image_with_offset(ssd1306_t *p, const uint8_t *data, const long size, uint32_t x_offset, uint32_t y_offset) {
if(size<54) // data smaller than header
return;
const uint32_t bfOffBits=ssd1306_bmp_get_val(data, 10, 4);
const uint32_t biSize=ssd1306_bmp_get_val(data, 14, 4);
const uint32_t biWidth=ssd1306_bmp_get_val(data, 18, 4);
const int32_t biHeight=(int32_t) ssd1306_bmp_get_val(data, 22, 4);
const uint16_t biBitCount=(uint16_t) ssd1306_bmp_get_val(data, 28, 2);
const uint32_t biCompression=ssd1306_bmp_get_val(data, 30, 4);
if(biBitCount!=1) // image not monochrome
return;
if(biCompression!=0) // image compressed
return;
const int table_start=14+biSize;
uint8_t color_val=0;
for(uint8_t i=0; i<2; ++i) {
if(!((data[table_start+i*4]<<16)|(data[table_start+i*4+1]<<8)|data[table_start+i*4+2])) {
color_val=i;
break;
}
}
uint32_t bytes_per_line=(biWidth/8)+(biWidth&7?1:0);
if(bytes_per_line&3)
bytes_per_line=(bytes_per_line^(bytes_per_line&3))+4;
const uint8_t *img_data=data+bfOffBits;
int32_t step=biHeight>0?-1:1;
int32_t border=biHeight>0?-1:-biHeight;
for(uint32_t y=biHeight>0?biHeight-1:0; y!=(uint32_t)border; y+=step) {
for(uint32_t x=0; x<biWidth; ++x) {
if(((img_data[x>>3]>>(7-(x&7)))&1)==color_val)
ssd1306_draw_pixel(p, x_offset+x, y_offset+y);
}
img_data+=bytes_per_line;
}
}
inline void ssd1306_bmp_show_image(ssd1306_t *p, const uint8_t *data, const long size) {
ssd1306_bmp_show_image_with_offset(p, data, size, 0, 0);
}
void ssd1306_show(ssd1306_t *p) {
uint8_t payload[]= {SET_COL_ADDR, 0, p->width-1, SET_PAGE_ADDR, 0, p->pages-1};
if(p->width==64) {
payload[1]+=32;
payload[2]+=32;
}
for(size_t i=0; i<sizeof(payload); ++i)
ssd1306_write(p, payload[i]);
*(p->buffer-1)=0x40;
fancy_write(p->i2c_i, p->address, p->buffer-1, p->bufsize+1, "ssd1306_show");
}
ssd1306.h
/*
MIT License
Copyright (c) 2021 David Schramm
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.
*/
/**
* @file ssd1306.h
*
* simple driver for ssd1306 displays
*/
#ifndef _inc_ssd1306
#define _inc_ssd1306
#include <pico/stdlib.h>
#include <hardware/i2c.h>
/**
* @brief defines commands used in ssd1306
*/
typedef enum {
SET_CONTRAST = 0x81,
SET_ENTIRE_ON = 0xA4,
SET_NORM_INV = 0xA6,
SET_DISP = 0xAE,
SET_MEM_ADDR = 0x20,
SET_COL_ADDR = 0x21,
SET_PAGE_ADDR = 0x22,
SET_DISP_START_LINE = 0x40,
SET_SEG_REMAP = 0xA0,
SET_MUX_RATIO = 0xA8,
SET_COM_OUT_DIR = 0xC0,
SET_DISP_OFFSET = 0xD3,
SET_COM_PIN_CFG = 0xDA,
SET_DISP_CLK_DIV = 0xD5,
SET_PRECHARGE = 0xD9,
SET_VCOM_DESEL = 0xDB,
SET_CHARGE_PUMP = 0x8D
} ssd1306_command_t;
/**
* @brief holds the configuration
*/
typedef struct {
uint8_t width; /**< width of display */
uint8_t height; /**< height of display */
uint8_t pages; /**< stores pages of display (calculated on initialization*/
uint8_t address; /**< i2c address of display*/
i2c_inst_t *i2c_i; /**< i2c connection instance */
bool external_vcc; /**< whether display uses external vcc */
uint8_t *buffer; /**< display buffer */
size_t bufsize; /**< buffer size */
} ssd1306_t;
/**
* @brief initialize display
*
* @param[in] p : pointer to instance of ssd1306_t
* @param[in] width : width of display
* @param[in] height : heigth of display
* @param[in] address : i2c address of display
* @param[in] i2c_instance : instance of i2c connection
*
* @return bool.
* @retval true for Success
* @retval false if initialization failed
*/
bool ssd1306_init(ssd1306_t *p, uint16_t width, uint16_t height, uint8_t address, i2c_inst_t *i2c_instance);
/**
* @brief deinitialize display
*
* @param[in] p : instance of display
*
*/
void ssd1306_deinit(ssd1306_t *p);
/**
* @brief turn off display
*
* @param[in] p : instance of display
*
*/
void ssd1306_poweroff(ssd1306_t *p);
/**
@brief turn on display
@param[in] p : instance of display
*/
void ssd1306_poweron(ssd1306_t *p);
/**
@brief set contrast of display
@param[in] p : instance of display
@param[in] val : contrast
*/
void ssd1306_contrast(ssd1306_t *p, uint8_t val);
/**
@brief set invert display
@param[in] p : instance of display
@param[in] inv : inv==0: disable inverting, inv!=0: invert
*/
void ssd1306_invert(ssd1306_t *p, uint8_t inv);
/**
@brief display buffer, should be called on change
@param[in] p : instance of display
*/
void ssd1306_show(ssd1306_t *p);
/**
@brief clear display buffer
@param[in] p : instance of display
*/
void ssd1306_clear(ssd1306_t *p);
/**
@brief clear pixel on buffer
@param[in] p : instance of display
@param[in] x : x position
@param[in] y : y position
*/
void ssd1306_clear_pixel(ssd1306_t *p, uint32_t x, uint32_t y);
/**
@brief draw pixel on buffer
@param[in] p : instance of display
@param[in] x : x position
@param[in] y : y position
*/
void ssd1306_draw_pixel(ssd1306_t *p, uint32_t x, uint32_t y);
/**
@brief draw line on buffer
@param[in] p : instance of display
@param[in] x1 : x position of starting point
@param[in] y1 : y position of starting point
@param[in] x2 : x position of end point
@param[in] y2 : y position of end point
*/
void ssd1306_draw_line(ssd1306_t *p, int32_t x1, int32_t y1, int32_t x2, int32_t y2);
/**
@brief clear square at given position with given size
@param[in] p : instance of display
@param[in] x : x position of starting point
@param[in] y : y position of starting point
@param[in] width : width of square
@param[in] height : height of square
*/
void ssd1306_clear_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
/**
@brief draw filled square at given position with given size
@param[in] p : instance of display
@param[in] x : x position of starting point
@param[in] y : y position of starting point
@param[in] width : width of square
@param[in] height : height of square
*/
void ssd1306_draw_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
/**
@brief draw empty square at given position with given size
@param[in] p : instance of display
@param[in] x : x position of starting point
@param[in] y : y position of starting point
@param[in] width : width of square
@param[in] height : height of square
*/
void ssd1306_draw_empty_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
/**
@brief draw monochrome bitmap with offset
@param[in] p : instance of display
@param[in] data : image data (whole file)
@param[in] size : size of image data in bytes
@param[in] x_offset : offset of horizontal coordinate
@param[in] y_offset : offset of vertical coordinate
*/
void ssd1306_bmp_show_image_with_offset(ssd1306_t *p, const uint8_t *data, const long size, uint32_t x_offset, uint32_t y_offset);
/**
@brief draw monochrome bitmap
@param[in] p : instance of display
@param[in] data : image data (whole file)
@param[in] size : size of image data in bytes
*/
void ssd1306_bmp_show_image(ssd1306_t *p, const uint8_t *data, const long size);
/**
@brief draw char with given font
@param[in] p : instance of display
@param[in] x : x starting position of char
@param[in] y : y starting position of char
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] font : pointer to font
@param[in] c : character to draw
*/
void ssd1306_draw_char_with_font(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint8_t *font, char c);
/**
@brief draw char with builtin font
@param[in] p : instance of display
@param[in] x : x starting position of char
@param[in] y : y starting position of char
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] c : character to draw
*/
void ssd1306_draw_char(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, char c);
/**
@brief draw string with given font
@param[in] p : instance of display
@param[in] x : x starting position of text
@param[in] y : y starting position of text
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] font : pointer to font
@param[in] s : text to draw
*/
void ssd1306_draw_string_with_font(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint8_t *font, const char *s );
/**
@brief draw string with builtin font
@param[in] p : instance of display
@param[in] x : x starting position of text
@param[in] y : y starting position of text
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] s : text to draw
*/
void ssd1306_draw_string(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const char *s);
// for fonts 16x8 we must use unit16_t
/**
@brief draw char with given font
@param[in] p : instance of display
@param[in] x : x starting position of char
@param[in] y : y starting position of char
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] font : pointer to font 16x8
@param[in] c : character to draw
*/
void ssd1306_draw_char_with_font16(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint16_t *font, char c);
/**
@brief draw string with given font
@param[in] p : instance of display
@param[in] x : x starting position of text
@param[in] y : y starting position of text
@param[in] scale : scale font to n times of original size (default should be 1)
@param[in] font : pointer to font
@param[in] s : text to draw
*/
void ssd1306_draw_string_with_font16(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t scale, const uint16_t *font, const char *s );
#endif
font_spleen_16x8a.h
/* Spleen font 16x8a
* (c) Jirka Chráska 2024, <jirka@lixis.cz>
* BSD license
*/
#ifndef _inc_font_spleen_8x16a
#define _inc_font_xpleen_8x16a
/*
* Format
* <height>, <width>, <additional spacing per char>, <first ascii char>, <last ascii char>,
* <data>
*/
/* data format, character encoding ISO-8859-2 with added characters.
In a column first uint8_t is lower 8 row of bit matrix, next uint8_t is higher 8 row of bit matrix.
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 0
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 1
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 2
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 3
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 4
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 5
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 6
-------------------------
|h0|h1|h2|h3|h4|h5|h6|h7| bit 7
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 0
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 1
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 2
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 3
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 4
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 5
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 6
-------------------------
|d0|d1|d2|d3|d4|d5|d6|d7| bit 7
-------------------------
*/
const uint8_t font_spleen_16x8a[] =
{
16, 8, 1, 1, 0xff,
// d0, h0 d1 h1 d2 h2 d3 h3 d4 h4 d5 h5 d6 h6 d7 h7 char code character
0xf8,0x07, 0x04,0x08, 0x94,0x08, 0x04,0x09, 0x04,0x09, 0x94,0x08, 0x04,0x08, 0xf8,0x07, // 0x01 držtička
0xf8,0x07, 0xfc,0x0f, 0x6c,0x0f, 0xfc,0x0e, 0xfc,0x0e, 0x6c,0x0f, 0xfc,0x0f, 0xf8,0x07, // 0x02 držtička černá
0xe0,0x00, 0xf0,0x01, 0xf0,0x03, 0xe0,0x07, 0xf0,0x03, 0xf0,0x01, 0xe0,0x00, 0x00,0x00, // 0x03 srdce
0x00,0x01, 0x80,0x03, 0xc0,0x07, 0xe0,0x0f, 0xc0,0x07, 0x80,0x03, 0x00,0x01, 0x00,0x00, // 0x04 kára
0xc0,0x01, 0xc0,0x01, 0xf0,0x09, 0x38,0x0e, 0x38,0x0e, 0xf0,0x09, 0xc0,0x01, 0xc0,0x01, // 0x05 žaludy
0xc0,0x00, 0xe0,0x01, 0xf0,0x09, 0xf8,0x0f, 0xf8,0x0f, 0xf0,0x09, 0xe0,0x01, 0xc0,0x00, // 0x06 zelený
0x00,0x00, 0x00,0x00, 0x80,0x01, 0xc0,0x03, 0xc0,0x03, 0x80,0x01, 0x00,0x00, 0x00,0x00, // 0x07 velká tečka
0xff,0xff, 0xff,0xff, 0x7f,0xfe, 0x3f,0xfc, 0x3f,0xfc, 0x7f,0xfe, 0xff,0xff, 0xff,0xff, // 0x08 velká inverzní tečka
0x00,0x00, 0xc0,0x03, 0xe0,0x07, 0x20,0x04, 0x20,0x04, 0xe0,0x07, 0xc0,0x03, 0x00,0x00, // 0x09 kroužek
0xff,0xff, 0x3f,0xfc, 0x1f,0xf8, 0xdf,0xfb, 0xdf,0xfb, 0x1f,0xf8, 0x3f,0xfc, 0xff,0xff, // 0x0a inverzní kroužek
0x00,0x00, 0x80,0x07, 0xc0,0x0f, 0x60,0x08, 0x74,0x08, 0xdc,0x0f, 0x8c,0x07, 0x3c,0x00, // 0x0b maskulinum
0x00,0x00, 0x78,0x00, 0xfc,0x02, 0x84,0x0f, 0x84,0x0f, 0xfc,0x02, 0x78,0x00, 0x00,0x00, // 0x0c feminimum
0x00,0x0c, 0xfc,0x0f, 0xfc,0x03, 0x14,0x00, 0x14,0x00, 0x1c,0x00, 0x1c,0x00, 0x00,0x00, // 0x0d fajfka
0x00,0x0c, 0xfc,0x0f, 0xfc,0x03, 0x14,0x00, 0x14,0x06, 0xfc,0x07, 0xfc,0x01, 0x00,0x00, // 0x0e noty
0xa0,0x02, 0xa0,0x02, 0xc0,0x01, 0x78,0x0f, 0x78,0x0f, 0xc0,0x01, 0xa0,0x02, 0xa0,0x02, // 0x0f pavouk
0xff,0xff, 0xfe,0x7f, 0xfc,0x3f, 0xf8,0x1f, 0xf0,0x0f, 0xe0,0x07, 0xc0,0x03, 0x80,0x01, // 0x10 velká šipka doprava
0x80,0x01, 0xc0,0x03, 0xe0,0x07, 0xf0,0x0f, 0xf8,0x1f, 0xfc,0x3f, 0xfe,0x7f, 0xff,0xff, // 0x11 velká šipka doleva
0x00,0x00, 0x10,0x02, 0x18,0x06, 0xfc,0x0f, 0xfc,0x0f, 0x18,0x06, 0x10,0x02, 0x00,0x00, // 0x12 šipka nahoru a dolu
0x00,0x00, 0xfc,0x0d, 0xfc,0x0d, 0x00,0x00, 0x00,0x00, 0xfc,0x0d, 0xfc,0x0d, 0x00,0x00, // 0x13 dva vykřičníky
0x38,0x00, 0x7c,0x00, 0x44,0x00, 0xfc,0x0f, 0x04,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0x14 konec odstavce
0x00,0x00, 0xcc,0x23, 0xfe,0x67, 0x32,0x44, 0x22,0x4c, 0xe6,0x7f, 0xc4,0x33, 0x00,0x00, // 0x15 paragraf
0x00,0x0f, 0x00,0x0f, 0x00,0x0f, 0x00,0x0f, 0x00,0x0f, 0x00,0x0f, 0x00,0x0f, 0x00,0x00, // 0x16 kvádr
0x00,0x00, 0x10,0x12, 0x18,0x16, 0xfc,0x1f, 0xfc,0x1f, 0x18,0x16, 0x10,0x12, 0x00,0x00, // 0x17 šipka nahoru a dolu s podstavou
0x00,0x00, 0x10,0x00, 0x18,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x18,0x00, 0x10,0x00, 0x00,0x00, // 0x18 šipka nahoru
0x00,0x00, 0x00,0x02, 0x00,0x06, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x06, 0x00,0x02, 0x00,0x00, // 0x19 šipka dolů
0x80,0x00, 0x80,0x00, 0x80,0x00, 0x80,0x00, 0xa0,0x02, 0xc0,0x01, 0x80,0x00, 0x00,0x00, // 0x1a šipka vpravo
0x80,0x00, 0xc0,0x01, 0xa0,0x02, 0x80,0x00, 0x80,0x00, 0x80,0x00, 0x80,0x00, 0x00,0x00, // 0x1b šipka vlevo
0x80,0x07, 0x80,0x07, 0x00,0x04, 0x00,0x04, 0x00,0x04, 0x00,0x04, 0x00,0x04, 0x00,0x00, // 0x1c pravý úhel
0x80,0x00, 0xc0,0x01, 0xe0,0x03, 0x80,0x00, 0xe0,0x03, 0xc0,0x01, 0x80,0x00, 0x00,0x00, // 0x1d šipky vlevo a vpravo
0x00,0x0c, 0x00,0x0f, 0xc0,0x0f, 0xe0,0x0f, 0xc0,0x0f, 0x00,0x0f, 0x00,0x0c, 0x00,0x00, // 0x1e pyramida
0x60,0x00, 0xe0,0x01, 0xe0,0x07, 0xe0,0x0f, 0xe0,0x07, 0xe0,0x01, 0x60,0x00, 0x00,0x00, // 0x1f obrácená pyramida
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x20 prázdný znak mezera
0x00,0x00, 0x00,0x00, 0x00,0x00, 0xfc,0x1b, 0xfc,0x1b, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x21 ! vykřičník
0x00,0x00, 0x1e,0x00, 0x1e,0x00, 0x00,0x00, 0x00,0x00, 0x1e,0x00, 0x1e,0x00, 0x00,0x00, // 0x22 "
0x10,0x02, 0xfc,0x0f, 0xfc,0x0f, 0x10,0x02, 0xfc,0x0f, 0xfc,0x0f, 0x10,0x02, 0x00,0x00, // 0x23 #
0x38,0x00, 0x7c,0x08, 0x44,0x08, 0xfe,0x1f, 0x44,0x08, 0xc4,0x0f, 0x84,0x07, 0x00,0x00, // 0x24 $
0x00,0x00, 0x18,0x0c, 0x18,0x0f, 0xc0,0x03, 0xf0,0x00, 0x3c,0x06, 0x0c,0x06, 0x00,0x00, // 0x25 %
0x00,0x07, 0xb8,0x0f, 0xfc,0x08, 0xc4,0x09, 0x7c,0x0f, 0x38,0x06, 0x00,0x09, 0x00,0x00, // 0x26 &
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x1e,0x00, 0x1e,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x27 '
0x00,0x00, 0xe0,0x01, 0xf8,0x07, 0x1c,0x0e, 0x06,0x18, 0x02,0x10, 0x02,0x10, 0x00,0x00, // 0x28 (
0x00,0x00, 0x02,0x10, 0x02,0x10, 0x06,0x18, 0x1c,0x0e, 0xf8,0x07, 0xe0,0x01, 0x00,0x00, // 0x29 )
0x80,0x00, 0x90,0x04, 0xb0,0x06, 0xe0,0x03, 0xe0,0x03, 0xb0,0x06, 0x90,0x04, 0x80,0x00, // 0x2a *
0x00,0x00, 0x80,0x00, 0x80,0x00, 0xe0,0x03, 0xe0,0x03, 0x80,0x00, 0x80,0x00, 0x00,0x00, // 0x2b +
0x00,0x00, 0x00,0x00, 0x00,0x10, 0x00,0x1c, 0x00,0x0c, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x2c ,
0x00,0x00, 0x40,0x00, 0x40,0x00, 0x40,0x00, 0x40,0x00, 0x40,0x00, 0x40,0x00, 0x00,0x00, // 0x2d -
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x0c, 0x00,0x0c, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x2e .
0x00,0x18, 0x00,0x1e, 0x80,0x07, 0xe0,0x01, 0x78,0x00, 0x1e,0x00, 0x06,0x00, 0x00,0x00, // 0x2f /
0xf8,0x07, 0xfc,0x0f, 0x84,0x09, 0xc4,0x08, 0x64,0x08, 0xfc,0x0f, 0xf8,0x07, 0x00,0x00, // 0x30 0
0x00,0x00, 0x30,0x08, 0x18,0x08, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x08, 0x00,0x08, 0x00,0x00, // 0x31 1
0x08,0x0c, 0x0c,0x0e, 0x04,0x0b, 0x84,0x09, 0xc4,0x08, 0x7c,0x0c, 0x38,0x0c, 0x00,0x00, // 0x32 2
0x08,0x04, 0x0c,0x0c, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xfc,0x0f, 0xb8,0x07, 0x00,0x00, // 0x33 3
0xfc,0x01, 0xfc,0x01, 0x00,0x01, 0x00,0x01, 0xf0,0x0f, 0xf0,0x0f, 0x00,0x01, 0x00,0x00, // 0x34 4
0x7c,0x04, 0x7c,0x0c, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xcc,0x0f, 0x8c,0x07, 0x00,0x00, // 0x35 5
0xf8,0x07, 0xfc,0x0f, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xcc,0x0f, 0x88,0x07, 0x00,0x00, // 0x36 6
0x0c,0x00, 0x0c,0x00, 0x04,0x0f, 0x84,0x0f, 0xc4,0x00, 0x7c,0x00, 0x3c,0x00, 0x00,0x00, // 0x37 7
0xb8,0x07, 0xfc,0x0f, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xfc,0x0f, 0xb8,0x07, 0x00,0x00, // 0x38 8
0x78,0x04, 0xfc,0x0c, 0x84,0x08, 0x84,0x08, 0x84,0x08, 0xfc,0x0f, 0xf8,0x07, 0x00,0x00, // 0x39 9
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x60,0x0c, 0x60,0x0c, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x3a :
0x00,0x00, 0x00,0x00, 0x00,0x10, 0x60,0x1c, 0x60,0x0c, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x3b ;
0x00,0x00, 0xc0,0x00, 0xe0,0x01, 0x30,0x03, 0x18,0x06, 0x0c,0x0c, 0x04,0x08, 0x00,0x00, // 0x3c <
0x00,0x00, 0x20,0x01, 0x20,0x01, 0x20,0x01, 0x20,0x01, 0x20,0x01, 0x20,0x01, 0x00,0x00, // 0x3d =
0x00,0x00, 0x04,0x08, 0x0c,0x0c, 0x18,0x06, 0x30,0x03, 0xe0,0x01, 0xc0,0x00, 0x00,0x00, // 0x3e >
0x08,0x00, 0x0c,0x00, 0x84,0x0d, 0xc4,0x0d, 0x64,0x00, 0x3c,0x00, 0x18,0x00, 0x00,0x00, // 0x3f ?
0xf0,0x07, 0xf8,0x0f, 0x08,0x08, 0xe8,0x0b, 0xe8,0x0b, 0x08,0x0a, 0xf0,0x03, 0x00,0x00, // 0x40 @
0xf8,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x44,0x00, 0xfc,0x0f, 0xf8,0x0f, 0x00,0x00, // 0x41 A LATIN CAPITAL LETTER A
0xfc,0x0f, 0xfc,0x0f, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xfc,0x0f, 0xb8,0x07, 0x00,0x00, // 0x42 B LATIN CAPITAL LETTER B
0xf8,0x07, 0xfc,0x0f, 0x04,0x08, 0x04,0x08, 0x04,0x08, 0x04,0x08, 0x04,0x08, 0x00,0x00, // 0x43 C LATIN CAPITAL LETTER C
0xfc,0x0f, 0xfc,0x0f, 0x04,0x08, 0x04,0x08, 0x04,0x08, 0xfc,0x0f, 0xf8,0x07, 0x00,0x00, // 0x44 D LATIN CAPITAL LETTER D
0xf8,0x07, 0xfc,0x0f, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0x04,0x08, 0x04,0x08, 0x00,0x00, // 0x45 E LATIN CAPITAL LETTER E
0xf8,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x44,0x00, 0x04,0x00, 0x04,0x00, 0x00,0x00, // 0x46 F LATIN CAPITAL LETTER F
0xf8,0x07, 0xfc,0x0f, 0x04,0x08, 0x44,0x08, 0x44,0x08, 0xc4,0x0f, 0xc4,0x0f, 0x00,0x00, // 0x47 G LATIN CAPITAL LETTER G
0xfc,0x0f, 0xfc,0x0f, 0x40,0x00, 0x40,0x00, 0x40,0x00, 0xfc,0x00f, 0xfc,0x0f, 0x00,0x00, // 0x48 H LATIN CAPITAL LETTER H
0x00,0x00, 0x04,0x08, 0x04,0x08, 0xfc,0x0f, 0xfc,0x0f, 0x04,0x08, 0x04,0x08, 0x00,0x00, // 0x49 I LATIN CAPITAL LETTER I
0x00,0x04, 0x04,0x0c, 0x04,0x08, 0xfc,0x0f, 0xfc,0x07, 0x04,0x00, 0x04,0x00, 0x00,0x00, // 0x4a J LATIN CAPITAL LETTER J
0xfc,0x0f, 0xfc,0x0f, 0x40,0x00, 0xe0,0x00, 0xb0,0x01, 0x1c,0x0f, 0x0c,0x0e, 0x00,0x00, // 0x4b K LATIN CAPITAL LETTER K
0xfc,0x0f, 0xfc,0x0f, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x00, // 0x4c L LATIN CAPITAL LETTER L
0xfc,0x0f, 0xfc,0x0f, 0x18,0x00, 0x30,0x00, 0x18,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0x4d M LATIN CAPITAL LETTER M
0xfc,0x0f, 0xfc,0x0f, 0x30,0x00, 0xc0,0x00, 0x00,0x03, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0x4e N LATIN CAPITAL LETTER N
0xf8,0x07, 0xfc,0x0f, 0x04,0x08, 0x04,0x08, 0x04,0x08, 0xfc,0x0f, 0xf8,0x07, 0x00,0x00, // 0x4f O LATIN CAPITAL LETTER O
0xfc,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x44,0x00, 0x7c,0x00, 0x38,0x00, 0x00,0x00, // 0x50 P LATIN CAPITAL LETTER P
0xf8,0x07, 0xfc,0x0f, 0x04,0x08, 0x04,0x1e, 0x04,0x38, 0xfc,0x2f, 0xf8,0x07, 0x00,0x00, // 0x51 Q LATIN CAPITAL LETTER Q
0xfc,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x44,0x00, 0xfc,0x0f, 0xb8,0x0f, 0x00,0x00, // 0x52 R LATIN CAPITAL LETTER R
0x38,0x08, 0x7c,0x08, 0x44,0x08, 0x44,0x08, 0x44,0x08, 0xc4,0x0f, 0x84,0x07, 0x00,0x00, // 0x53 S LATIN CAPITAL LETTER S
0x04,0x00, 0x04,0x00, 0x04,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x04,0x00, 0x04,0x00, 0x04,0x00, // 0x54 T LATIN CAPITAL LETTER T
0xfc,0x07, 0xfc,0x0f, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0xfc,0x0f, 0xfc,0x07, 0x00,0x00, // 0x55 U LATIN CAPITAL LETTER U
0xfc,0x01, 0xfc,0x03, 0x00,0x06, 0x00,0x0c, 0x00,0x06, 0xfc,0x03, 0xfc,0x01, 0x00,0x00, // 0x56 V LATIN CAPITAL LETTER V
0xfc,0x0f, 0xfc,0x0f, 0x00,0x06, 0x00,0x03, 0x00,0x06, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0x57 W LATIN CAPITAL LETTER W
0x1c,0x0f, 0xbc,0x0f, 0xe0,0x00, 0x40,0x00, 0xe0,0x00, 0xbc,0x0f, 0x1c,0x0f, 0x00,0x00, // 0x58 X LATIN CAPITAL LETTER X
0x3c,0x08, 0x7c,0x08, 0x40,0x08, 0x40,0x08, 0x40,0x08, 0xfc,0x0f, 0xfc,0x07, 0x00,0x00, // 0x59 Y LATIN CAPITAL LETTER Y
0x04,0x0e, 0x04,0x0f, 0x84,0x09, 0xc4,0x08, 0x64,0x08, 0x3c,0x08, 0x1c,0x08, 0x00,0x00, // 0x5a Z LATIN CAPITAL LETTER Z
0x00,0x00, 0x00,0x00, 0xfe,0x1f, 0xfe,0x1f, 0x02,0x10, 0x02,0x10, 0x02,0x10, 0x00,0x00, // 0x5b [
0x06,0x00, 0x1e,0x00, 0x78,0x00, 0xe0,0x01, 0x80,0x07, 0x00,0x1e, 0x00,0x18, 0x00,0x00, // 0x5c "\"
0x00,0x00, 0x02,0x10, 0x02,0x10, 0x02,0x10, 0xfe,0x1f, 0xfe,0x1f, 0x00,0x00, 0x00,0x00, // 0x5d ]
0x10,0x00, 0x18,0x00, 0x0c,0x00, 0x06,0x00, 0x0c,0x00, 0x18,0x00, 0x10,0x00, 0x00,0x00, // 0x5e ^
0x00,0x40, 0x00,0x40, 0x00,0x40, 0x00,0x40, 0x00,0x40, 0x00,0x40, 0x00,0x40, 0x00,0x00, // 0x5f _ podtržítko
0x00,0x00, 0x00,0x00, 0x02,0x00, 0x06,0x00, 0x0c,0x00, 0x08,0x00, 0x00,0x00, 0x00,0x00, // 0x60 `
0x00,0x07, 0xa0,0x0f, 0xa0,0x08, 0xa0,0x08, 0xa0,0x08, 0xe0,0x0f, 0xc0,0x0f, 0x00,0x00, // 0x61 a LATIN SMALL LETTER a
0xfc,0x0f, 0xfc,0x0f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0xe0,0x0f, 0xc0,0x07, 0x00,0x00, // 0x62 b LATIN SMALL LETTER b
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0x00,0x00, // 0x63 c LATIN SMALL LETTER c
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0x64 d LATIN SMALL LETTER d
0xc0,0x07, 0xe0,0x0f, 0x20,0x09, 0x20,0x09, 0x20,0x09, 0xe0,0x09, 0xe0,0x09, 0x00,0x00, // 0x65 e LATIN SMALL LETTER e
0x00,0x00, 0x40,0x00, 0xf8,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x04,0x00, 0x00,0x00, // 0x66 f LATIN SMALL LETTER f
0xc0,0x47, 0xe0,0x4f, 0x20,0x48, 0x20,0x48, 0x20,0x48, 0xe0,0x7f, 0xc0,0x37, 0x00,0x00, // 0x67 g LATIN SMALL LETTER g
0xfc,0x0f, 0xfc,0x0f, 0x20,0x00, 0x20,0x00, 0x20,0x00, 0xe0,0x0f, 0xc0,0x0f, 0x00,0x00, // 0x68 h LATIN SMALL LETTER h
0x00,0x00, 0x00,0x00, 0x20,0x00, 0xec,0x0f, 0xec,0x0f, 0x00,0x08, 0x00,0x00, 0x00,0x00, // 0x69 i LATIN SMALL LETTER i
0x00,0x00, 0x00,0x40, 0x00,0x40, 0xec,0x7f, 0xec,0x3f, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x6a j LATIN SMALL LETTER j
0xfc,0x0f, 0xfc,0x0f, 0x80,0x01, 0xc0,0x03, 0x60,0x06, 0x20,0x0c, 0x00,0x08, 0x00,0x00, // 0x6b k LATIN SMALL LETTER k
0x00,0x00, 0x00,0x00, 0xfc,0x07, 0xfc,0x0f, 0x00,0x08, 0x00,0x08, 0x00,0x00, 0x00,0x00, // 0x6c l LATIN SMALL LETTER l
0xe0,0x0f, 0xe0,0x0f, 0x20,0x00, 0xc0,0x03, 0x20,0x00, 0xe0,0x0f, 0xc0,0x0f, 0x00,0x00, // 0x6d m LATIN SMALL LETTER m
0xe0,0x0f, 0xe0,0x0f, 0x20,0x00, 0x20,0x00, 0x20,0x00, 0xe0,0x0f, 0xc0,0x0f, 0x00,0x00, // 0x6e n LATIN SMALL LETTER n
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0xe0,0x0f, 0xc0,0x07, 0x00,0x00, // 0x6f o LATIN SMALL LETTER o
0xe0,0x7f, 0xe0,0x7f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0xe0,0x0f, 0xc0,0x07, 0x00,0x00, // 0x70 p LATIN SMALL LETTER p
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x08, 0x20,0x08, 0xe0,0x7f, 0xe0,0x7f, 0x00,0x00, // 0x71 q LATIN SMALL LETTER q
0xc0,0x0f, 0xe0,0x0f, 0x20,0x00, 0x20,0x00, 0x20,0x00, 0x60,0x00, 0x60,0x00, 0x00,0x00, // 0x72 r LATIN SMALL LETTER r
0xc0,0x08, 0xe0,0x09, 0x20,0x09, 0x20,0x09, 0x20,0x09, 0x20,0x0f, 0x20,0x06, 0x00,0x00, // 0x73 s LATIN SMALL LETTER s
0x00,0x00, 0x20,0x00, 0xfc,0x07, 0xfc,0x0f, 0x20,0x08, 0x20,0x08, 0x00,0x08, 0x00,0x00, // 0x74 t LATIN SMALL LETTER t
0xe0,0x07, 0xe0,0x0f, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0xe0,0x0f, 0xe0,0x0f, 0x00,0x00, // 0x75 u LATIN SMALL LETTER u
0xe0,0x01, 0xe0,0x03, 0x00,0x06, 0x00,0x0c, 0x00,0x06, 0xe0,0x03, 0xe0,0x01, 0x00,0x00, // 0x76 v LATIN SMALL LETTER v
0xe0,0x07, 0xe0,0x0f, 0x00,0x08, 0x80,0x07, 0x00,0x08, 0xe0,0x0f, 0xe0,0x0f, 0x00,0x00, // 0x77 w LATIN SMALL LETTER w
0x20,0x0c, 0x60,0x0e, 0xc0,0x03, 0x80,0x01, 0xc0,0x03, 0x60,0x0e, 0x20,0x0c, 0x00,0x00, // 0x78 x LATIN SMALL LETTER x
0xe0,0x47, 0xe0,0x4f, 0x00,0x48, 0x00,0x48, 0x00,0x48, 0xe0,0x7f, 0xe0,0x3f, 0x00,0x00, // 0x79 y LATIN SMALL LETTER y
0x20,0x08, 0x20,0x0c, 0x20,0x0e, 0x20,0x0b, 0xa0,0x09, 0xe0,0x08, 0x60,0x08, 0x00,0x00, // 0x7a z LATIN SMALL LETTER z
0x00,0x00, 0xc0,0x00, 0xc0,0x00, 0xfc,0x0f, 0x3e,0x1f, 0x02,0x10, 0x02,0x10, 0x00,0x00, // 0x7b { LEFT CURLY BRACKET
0x00,0x00, 0x00,0x00, 0x00,0x00, 0xfe,0x1f, 0xfe,0x1f, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x7c | VERTICAL LINE
0x00,0x00, 0x02,0x10, 0x02,0x10, 0x3e,0x1f, 0xfc,0x0f, 0xc0,0x00, 0xc0,0x00, 0x00,0x00, // 0x7d } RIGHT CURLY BRACKER
0x00,0x00, 0x80,0x01, 0xc0,0x00, 0xc0,0x00, 0x80,0x01, 0x80,0x01, 0xc0,0x00, 0x00,0x00, // 0x7e ~ TILDE
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x7f nezlomitelná mezera
0xfe,0xff, 0x02,0x80, 0x02,0x80, 0x03,0x80, 0x03,0x80, 0x02,0x80, 0x02,0x80, 0xfe,0xff, // 0x80 baterie vybitá
0xfe,0xff, 0x02,0xe0, 0x02,0xe0, 0x03,0xe0, 0x03,0xe0, 0x02,0xe0, 0x02,0xe0, 0xfe,0xff, // 0x81 baterie 20%
0xfe,0xff, 0x02,0xfc, 0x02,0xfc, 0x03,0xfc, 0x03,0xfc, 0x02,0xfc, 0x02,0xfc, 0xfe,0xff, // 0x82 baterie 40%
0xfe,0xff, 0x82,0xff, 0x82,0xff, 0x83,0xff, 0x83,0xff, 0x82,0xff, 0x82,0xff, 0xfe,0xff, // 0x83 baterie 60%
0xfe,0xff, 0xf2,0xff, 0xf2,0xff, 0xf3,0xff, 0xf3,0xff, 0xf2,0xff, 0xf2,0xff, 0xfe,0xff, // 0x84 baterie 80%
0xfe,0xff, 0xfe,0xff, 0xfe,0xff, 0xff,0xff, 0xff,0xff, 0xfe,0xff, 0xfe,0xff, 0xfe,0xff, // 0x85 baterie 100% nabitá
0xff,0x00, 0xff,0x00, 0x60,0x00, 0x30,0x02, 0x18,0x06, 0xfc,0x0f, 0x00,0x06, 0x00,0x02, // 0x86 blesk
0x20,0x00, 0x60,0x00, 0xff,0x00, 0x60,0x00, 0x20,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x87 šipka dolů
0x04,0x00, 0x06,0x00, 0xff,0x00, 0x06,0x00, 0x04,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x88 šipka nahoru
0x24,0x00, 0x66,0x00, 0xff,0x00, 0x66,0x00, 0x24,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x89 šipka nahoru i dolů
0x80,0x00, 0x80,0x02, 0x80,0x0a, 0xff,0x0a, 0xff,0x0a, 0x80,0x0a, 0x80,0x02, 0x80,0x00, // 0x8a zemnění
0xff,0xff, 0x41,0x88, 0x81,0x84, 0x01,0x83, 0x01,0x83, 0x81,0x84, 0x41,0x88, 0xff,0xff, // 0x8b unused
0xff,0xff, 0x41,0x88, 0x81,0x84, 0x01,0x83, 0x01,0x83, 0x81,0x84, 0x41,0x88, 0xff,0xff, // 0x8c unused
0xff,0xff, 0x41,0x88, 0x81,0x84, 0x01,0x83, 0x01,0x83, 0x81,0x84, 0x41,0x88, 0xff,0xff, // 0x8d unused
0xff,0xff, 0x41,0x88, 0x81,0x84, 0x01,0x83, 0x01,0x83, 0x81,0x84, 0x41,0x88, 0xff,0xff, // 0x8e unused
0xff,0xff, 0x41,0x88, 0x81,0x84, 0x01,0x83, 0x01,0x83, 0x81,0x84, 0x41,0x88, 0xff,0xff, // 0x8f unused
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0xe0,0x0f, 0xc0,0x07, 0x60,0x0c, 0x20,0x08, 0x00,0x00, // 0x90 malé alfa
0xf8,0x0f, 0xfc,0x0f, 0x04,0x00, 0x44,0x0c, 0xfc,0x08, 0xb8,0x07, 0x00,0x07, 0x00,0x00, // 0x91 malé beta
0xfc,0x0f, 0xfc,0x0f, 0x04,0x00, 0x04,0x00, 0x04,0x00, 0x0c,0x00, 0x0c,0x00, 0x00,0x00, // 0x92 velké gamma
0x20,0x00, 0xe0,0x0f, 0xe0,0x0f, 0x20,0x00, 0xe0,0x0f, 0xe0,0x0f, 0x20,0x00, 0x00,0x00, // 0x93 malé pí
0x0c,0x0c, 0x1c,0x0e, 0x34,0x0b, 0xe4,0x09, 0xc4,0x08, 0x0c,0x0c, 0x0c,0x0c, 0x00,0x00, // 0x94 velké sigma
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0xe0,0x0f, 0xe0,0x07, 0x20,0x00, 0x20,0x00, 0x00,0x00, // 0x95 malé sigma
0xe0,0x7f, 0xe0,0x7f, 0x00,0x08, 0x00,0x08, 0xe0,0x07, 0xe0,0x0f, 0x00,0x08, 0x00,0x00, // 0x96 malé mí
0x00,0x00, 0x20,0x00, 0x20,0x00, 0xe0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x00, 0x00,0x00, // 0x97 malé tau
0xf0,0x03, 0xf8,0x07, 0x08,0x04, 0xfc,0x0f, 0x08,0x04, 0xf8,0x07, 0xf0,0x03, 0x00,0x00, // 0x98 velké fí
0xf0,0x03, 0xf8,0x07, 0x4c,0x0c, 0x44,0x08, 0x4c,0x0c, 0xf8,0x07, 0xf0,0x03, 0x00,0x00, // 0x99 velké theta
0xf0,0x09, 0xf8,0x0f, 0x0c,0x0e, 0x04,0x00, 0x0c,0x0e, 0xf8,0x0f, 0xf0,0x09, 0x00,0x00, // 0x9a velké omega
0x00,0x00, 0x80,0x07, 0xc8,0x0f, 0x5c,0x08, 0x74,0x08, 0xe4,0x0f, 0x84,0x07, 0x00,0x00, // 0x9b malé delta
0xc0,0x01, 0xe0,0x03, 0x20,0x02, 0xe0,0x03, 0xe0,0x03, 0x20,0x02, 0xe0,0x03, 0xc0,0x01, // 0x9c nekonečno
0x80,0x07, 0xc0,0x0f, 0x00,0x08, 0x80,0x3f, 0x40,0x08, 0xc0,0x0f, 0x80,0x07, 0x00,0x00, // 0x9d malé fí
0xc0,0x06, 0xe0,0x0f, 0x20,0x09, 0x20,0x09, 0x20,0x08, 0x60,0x0c, 0x40,0x04, 0x00,0x00, // 0x9e malé epsilon
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0x9f unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xa0 nezlomitelná mezera
0xf8,0x0f, 0xfc,0x0f, 0x44,0x00, 0x44,0x00, 0x44,0x20, 0xfc,0x5f, 0xf8,0x0f, 0x00,0x00, // 0xa1 LATIN CAPITAL LETTER A WITH CEDILA Ą
0x01,0x00, 0x02,0x00, 0x02,0x00, 0x01,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xa2 BREVE oblouček
0x80,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x20,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, // 0xa3 LATIN CAPITAL LETTER L WITH STROKE
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xa4 valuta
0xfc,0x0f, 0xfc,0x0f, 0x00,0x08, 0x0c,0x08, 0x06,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x00, // 0xa5 měkké L
0x38,0x08, 0x7c,0x08, 0x44,0x08, 0x46,0x08, 0x45,0x08, 0xc4,0x0f, 0x84,0x07, 0x00,0x00, // 0xa6 S s čárkou
0x00,0x00, 0xcc,0x23, 0xfe,0x67, 0x32,0x44, 0x22,0x4c, 0xe6,0x7f, 0xc4,0x33, 0x00,0x00, // 0xa7 paragraf
0x00,0x00, 0x00,0x00, 0x02,0x00, 0x01,0x00, 0x00,0x00, 0x02,0x00, 0x01,0x00, 0x00,0x00, // 0xa8 přehláska
0x38,0x08, 0x7c,0x08, 0x45,0x08, 0x46,0x08, 0x45,0x08, 0xc4,0x0f, 0x84,0x07, 0x00,0x00, // 0xa9 Š ---
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xaa unused
0x04,0x00, 0x04,0x00, 0x04,0x00, 0xfc,0x0f, 0xfc,0x0f, 0x04,0x00, 0x04,0x00, 0x04,0x00, // 0xab Ť
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xac unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xad unused
0x04,0x0e, 0x04,0x0f, 0x85,0x09, 0xc6,0x08, 0x65,0x08, 0x3c,0x08, 0x1c,0x08, 0x00,0x00, // 0xae Ž
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xaf unused
0x00,0x00, 0x0c,0x00, 0x1e,0x00, 0x12,0x00, 0x1e,0x00, 0x0c,0x00, 0x00,0x00, 0x00,0x00, // 0xb0 stupeň
0x00,0x07, 0xa0,0x0f, 0xa0,0x08, 0xa0,0x08, 0xa0,0x28, 0xe0,0x5f, 0xc0,0x4f, 0x00,0x00, // 0xb1 ą
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb2 unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb3 unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb4 unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb5 unused
0xc0,0x08, 0xe0,0x09, 0x20,0x09, 0x28,0x09, 0x2c,0x09, 0x26,0x0f, 0x22,0x06, 0x00,0x00, // 0xb6 s s čárkou
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb7 unused
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xb8 unused
0xc2,0x08, 0xe6,0x09, 0x2c,0x09, 0x28,0x09, 0x2c,0x09, 0x26,0x0f, 0x22,0x06, 0x00,0x00, // 0xb9 š
0xc0,0x08, 0xe0,0x09, 0x20,0x29, 0x20,0x39, 0x20,0x09, 0x20,0x0f, 0x20,0x06, 0x00,0x00, // 0xba s s cedilou
0x00,0x00, 0x20,0x00, 0xfc,0x07, 0xfc,0x0f, 0x20,0x08, 0x26,0x08, 0x03,0x00, 0x00,0x00, // 0xbb ť
0x20,0x08, 0x20,0x0c, 0x20,0x0e, 0x28,0x0b, 0xac,0x09, 0xe6,0x08, 0x62,0x08, 0x00,0x00, // 0xbc z s čárkou
0x08,0x00, 0x0c,0x00, 0x06,0x00, 0x02,0x00, 0x08,0x00, 0x0c,0x00, 0x06,0x00, 0x02,0x00, // 0xbd uvozovky
0x20,0x08, 0x22,0x0c, 0x26,0x0e, 0x2c,0x0b, 0xac,0x09, 0xe6,0x08, 0x62,0x08, 0x00,0x00, // 0xbe ž
0x20,0x08, 0x20,0x0c, 0x20,0x0e, 0x2c,0x0b, 0xac,0x09, 0xe0,0x08, 0x60,0x08, 0x00,0x00, // 0xbf z s tečkou
0xfc,0x0f, 0xfc,0x0f, 0x44,0x00, 0x46,0x00, 0x47,0x00, 0xfd,0x0f, 0xb8,0x0f, 0x00,0x00, // 0xc0 R s čárkou
0xf0,0x0f, 0xf8,0x0f, 0x88,0x00, 0x8a,0x00, 0x8b,0x00, 0x89,0x00, 0xf8,0x0f, 0xf0,0x0f, // 0xc1 Á
0xf0,0x0f, 0xfa,0x0f, 0x8b,0x00, 0x89,0x00, 0x89,0x00, 0x8b,0x00, 0xfa,0x0f, 0xf0,0x0f, // 0xc2 Â
0xf0,0x0f, 0xf9,0x0f, 0x8b,0x00, 0x8a,0x00, 0x8a,0x00, 0x8b,0x00, 0xf9,0x0f, 0xf0,0x0f, // 0xc3 Ă
0xf0,0x0f, 0xfb,0x0f, 0x8b,0x00, 0x88,0x00, 0x88,0x00, 0x8b,0x00, 0xfb,0x0f, 0xf0,0x0f, // 0xc4 Ä
0xfa,0x0f, 0xfb,0x0f, 0x01,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x08, 0x00,0x00, // 0xc5 L s čárkou
0xf0,0x07, 0xf8,0x0f, 0x08,0x08, 0x0a,0x08, 0x0b,0x08, 0x09,0x08, 0x08,0x08, 0x00,0x00, // 0xc6 C s čárkou
0xf8,0x07, 0xfc,0x0f, 0x04,0x08, 0x04,0x28, 0x04,0x38, 0x04,0x08, 0x04,0x08, 0x00,0x00, // 0xc7 C s cedilou
0xf0,0x07, 0xf8,0x0f, 0x09,0x08, 0x0b,0x08, 0x0a,0x08, 0x0b,0x08, 0x09,0x08, 0x00,0x00, // 0xc8 Č
0xf0,0x07, 0xf8,0x0f, 0x88,0x08, 0x8a,0x08, 0x8b,0x08, 0x09,0x08, 0x08,0x08, 0x00,0x00, // 0xc9 É
0xf8,0x07, 0xfc,0x0f, 0x44,0x08, 0x44,0x38, 0x44,0x28, 0x04,0x08, 0x04,0x08, 0x00,0x00, // 0xca E s cedilou
0xf0,0x07, 0xf8,0x0f, 0x8b,0x08, 0x8b,0x08, 0x88,0x08, 0x0b,0x08, 0x0b,0x08, 0x00,0x00, // 0xcb Ë
0xf0,0x07, 0xf8,0x0f, 0x89,0x08, 0x8b,0x08, 0x8a,0x08, 0x0b,0x08, 0x09,0x08, 0x00,0x00, // 0xcc Ě
0x00,0x00, 0x00,0x00, 0x08,0x08, 0xfa,0x0f, 0xfb,0x0f, 0x09,0x08, 0x00,0x00, 0x00,0x00, // 0xcd Í
0x00,0x00, 0x02,0x00, 0x0b,0x08, 0xf9,0x0f, 0xf9,0x0f, 0x0b,0x08, 0x02,0x00, 0x00,0x00, // 0xce I s obráceným háčkem
0xf8,0x0f, 0xf9,0x0f, 0x0b,0x08, 0x0a,0x08, 0x0b,0x08, 0xf9,0x0f, 0xf0,0x07, 0x00,0x00, // 0xcf Ď
0x80,0x00, 0xf8,0x0f, 0xf8,0x0f, 0x88,0x08, 0x08,0x08, 0x08,0x08, 0xf8,0x0f, 0xf0,0x07, // 0xd0 Ð
0xf8,0x0f, 0xf8,0x0f, 0x60,0x00, 0x82,0x01, 0x03,0x06, 0xf9,0x0f, 0xf8,0x0f, 0x00,0x00, // 0xd1 N s čárkou
0xf8,0x0f, 0xf9,0x0f, 0x63,0x00, 0x82,0x01, 0x03,0x06, 0xf9,0x0f, 0xf8,0x0f, 0x00,0x00, // 0xd2 Ň
0xf0,0x07, 0xf8,0x0f, 0x08,0x08, 0x0a,0x08, 0x0b,0x08, 0xf9,0x0f, 0xf0,0x07, 0x00,0x00, // 0xd3 Ó
0xf0,0x07, 0xf8,0x0f, 0x08,0x08, 0x0a,0x08, 0x0b,0x08, 0xf9,0x0f, 0xf0,0x07, 0x00,0x00, // 0xd4 O s obráceným háčkem
0xf0,0x07, 0xfa,0x0f, 0x0b,0x08, 0x09,0x08, 0x0a,0x08, 0xfb,0x0f, 0xf1,0x07, 0x00,0x00, // 0xd5 O s dvěma čárkami
0xf0,0x07, 0xfb,0x0f, 0x0b,0x08, 0x08,0x08, 0x0b,0x08, 0xfb,0x0f, 0xf0,0x07, 0x00,0x00, // 0xd6 O s přehláskou
0x20,0x04, 0x60,0x06, 0xc0,0x03, 0x80,0x01, 0xc0,0x03, 0x60,0x06, 0x20,0x04, 0x00,0x00, // 0xd7 krát
0xfc,0x0f, 0xfd,0x0f, 0x47,0x00, 0x46,0x00, 0x47,0x00, 0xfd,0x0f, 0xb8,0x0f, 0x00,0x00, // 0xd8 Ř
0xf8,0x07, 0xf8,0x0f, 0x07,0x08, 0x05,0x08, 0x07,0x08, 0xf8,0x0f, 0xf8,0x07, 0x00,0x00, // 0xd9 Ů
0xf8,0x07, 0xf8,0x0f, 0x00,0x08, 0x02,0x08, 0x03,0x08, 0xf9,0x0f, 0xf8,0x07, 0x00,0x00, // 0xda Ú
0xf8,0x07, 0xfa,0x0f, 0x03,0x08, 0x01,0x08, 0x02,0x08, 0xfb,0x0f, 0xf9,0x07, 0x00,0x00, // 0xdb U s dvěma čárkami
0xf8,0x07, 0xfb,0x0f, 0x03,0x08, 0x00,0x08, 0x03,0x08, 0xfb,0x0f, 0xf8,0x07, 0x00,0x00, // 0xdc U s přehláskou
0x78,0x08, 0xf8,0x08, 0x80,0x08, 0x82,0x08, 0x83,0x08, 0xf9,0x0f, 0xf8,0x07, 0x00,0x00, // 0xdd Ý
0x04,0x00, 0x04,0x00, 0x04,0x00, 0xfc,0x5f, 0xfc,0x2f, 0x04,0x00, 0x04,0x00, 0x04,0x00, // 0xde T s cedilou
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // 0xdf unused
0xc0,0x0f, 0xe0,0x0f, 0x20,0x00, 0x28,0x00, 0x2c,0x00, 0x64,0x00, 0x60,0x00, 0x00,0x00, // 0xe0 ŕ
0x00,0x07, 0xa0,0x0f, 0xa8,0x08, 0xac,0x08, 0xa6,0x08, 0xe2,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xe1 á
0x00,0x07, 0xa8,0x0f, 0xac,0x08, 0xa6,0x08, 0xac,0x08, 0xe8,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xe2 â
0x00,0x07, 0xa6,0x0f, 0xae,0x08, 0xa8,0x08, 0xae,0x08, 0xe6,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xe3 ă
0x00,0x07, 0xac,0x0f, 0xac,0x08, 0xa0,0x08, 0xac,0x08, 0xec,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xe4 ä
0x00,0x00, 0x00,0x00, 0xfa,0x0f, 0xfb,0x1f, 0x01,0x10, 0x00,0x10, 0x00,0x00, 0x00,0x00, // 0xe5 ľ
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x28,0x08, 0x2c,0x08, 0x24,0x08, 0x20,0x08, 0x00,0x00, // 0xe6 ć
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x28, 0x20,0x38, 0x20,0x08, 0x20,0x08, 0x00,0x00, // 0xe7 ç
0xc0,0x07, 0xe4,0x0f, 0x2c,0x08, 0x28,0x08, 0x2c,0x08, 0x24,0x08, 0x20,0x08, 0x00,0x00, // 0xe8 č
0xc0,0x07, 0xe0,0x0f, 0x20,0x09, 0x28,0x09, 0x2c,0x09, 0xe4,0x09, 0xe0,0x09, 0x00,0x00, // 0xe9 é
0xc0,0x07, 0xe0,0x0f, 0x20,0x09, 0x20,0x39, 0x20,0x29, 0xe0,0x09, 0xe0,0x09, 0x00,0x00, // 0xea ę
0xc0,0x07, 0xec,0x0f, 0x2c,0x09, 0x20,0x09, 0x2c,0x09, 0xec,0x09, 0xe0,0x09, 0x00,0x00, // 0xeb ë
0xc0,0x07, 0xe4,0x0f, 0x2c,0x09, 0x28,0x09, 0x2c,0x09, 0xe4,0x09, 0xe0,0x09, 0x00,0x00, // 0xec ě
0x00,0x00, 0x00,0x00, 0x20,0x00, 0xe8,0x0f, 0xec,0x0f, 0x04,0x08, 0x00,0x00, 0x00,0x00, // 0xed í
0x00,0x00, 0x08,0x00, 0x2c,0x00, 0xe6,0x0f, 0xec,0x0f, 0x08,0x08, 0x00,0x00, 0x00,0x00, // 0xee î
0xc1,0x07, 0xe3,0x0f, 0x26,0x08, 0x23,0x08, 0x21,0x08, 0xfc,0x0f, 0xfc,0x0f, 0x00,0x00, // 0xef ď
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x20,0x08, 0x28,0x08, 0xfc,0x0f, 0xfc,0x0f, 0x08,0x00, // 0xf0 d přeškrtnuté
0xe0,0x0f, 0xe0,0x0f, 0x20,0x00, 0x28,0x00, 0x2c,0x00, 0xe4,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xf1 n s čárkou
0xe0,0x0f, 0xe4,0x0f, 0x2c,0x00, 0x28,0x00, 0x2c,0x00, 0xe4,0x0f, 0xc0,0x0f, 0x00,0x00, // 0xf2 ň
0xc0,0x07, 0xe0,0x0f, 0x20,0x08, 0x28,0x08, 0x2c,0x08, 0xe4,0x0f, 0xc0,0x07, 0x00,0x00, // 0xf3 ó
0xc0,0x07, 0xe8,0x0f, 0x2c,0x08, 0x26,0x08, 0x2c,0x08, 0xe8,0x0f, 0xc0,0x07, 0x00,0x00, // 0xf4 o s obráceným háčkem
0xc0,0x07, 0xe8,0x0f, 0x2c,0x08, 0x24,0x08, 0x28,0x08, 0xec,0x0f, 0xc4,0x07, 0x00,0x00, // 0xf5 o s dvěma čárkami
0xc0,0x07, 0xec,0x0f, 0x2c,0x08, 0x20,0x08, 0x2c,0x08, 0xec,0x0f, 0xc0,0x07, 0x00,0x00, // 0xf6 o s přehláskou
0x40,0x00, 0x40,0x00, 0x40,0x00, 0x58,0x03, 0x58,0x03, 0x40,0x00, 0x40,0x00, 0x40,0x00, // 0xf7 ÷ děleno
0xc0,0x0f, 0xe4,0x0f, 0x2c,0x00, 0x28,0x00, 0x2c,0x00, 0x64,0x00, 0x60,0x00, 0x00,0x00, // 0xf8 ř
0xe0,0x07, 0xe0,0x0f, 0x0e,0x08, 0x0a,0x08, 0x0e,0x08, 0xe0,0x0f, 0xe0,0x0f, 0x00,0x00, // 0xf9 ů
0xe0,0x07, 0xe0,0x0f, 0x00,0x08, 0x08,0x08, 0x0c,0x08, 0xe4,0x0f, 0xe0,0x0f, 0x00,0x00, // 0xfa ú
0xe0,0x07, 0xe8,0x0f, 0x0c,0x08, 0x04,0x08, 0x08,0x08, 0xec,0x0f, 0xe4,0x0f, 0x00,0x00, // 0xfb ű
0xe0,0x07, 0xec,0x0f, 0x0c,0x08, 0x00,0x08, 0x0c,0x08, 0xec,0x0f, 0xe0,0x0f, 0x00,0x00, // 0xfc ü
0xe0,0x47, 0xe0,0x4f, 0x00,0x48, 0x08,0x48, 0x0c,0x48, 0xe4,0x7f, 0xe0,0x3f, 0x00,0x00, // 0xfd ý
0x00,0x00, 0x20,0x00, 0xfc,0x27, 0xfc,0x2f, 0x20,0x38, 0x20,0x08, 0x00,0x00, 0x00,0x00, // 0xfe t s cedilou
0x00,0x00, 0x00,0x00, 0x06,0x00, 0x0f,0x00, 0x0f,0x00, 0x06,0x00, 0x00,0x00, 0x00,0x00, // 0xff tečka nahoře
};
#endif
font_spleen_8x5.h
/* Spleen font 8x5 */
#ifndef _inc_font_spleen_8x5
#define _inc_font_xpleen_8x5
/*
* Format
* <height>, <width>, <additional spacing per char>,
* <first ascii char>, <last ascii char>,
* <data>
*/
const uint8_t font_spleen_8x5[] =
{
8, 5, 1, 32, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, // 0x32 mezera
0x00, 0x00, 0x5F, 0x00, 0x00, // ! vykřičník
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7F, 0x14, 0x7F, 0x14, // #
0x44, 0x4A, 0xFF, 0x32, 0x00, // $
0xc6, 0x30, 0x0c, 0x63, 0x00, // %
0x30, 0x4e, 0x59, 0x26, 0x50, // &
0x00, 0x00, 0x07, 0x00, 0x00, // '
0x00, 0x3C, 0x42, 0x81, 0x00, // (
0x00, 0x81, 0x42, 0x3C, 0x00, // )
0x54, 0x38, 0x38, 0x54, 0x00, // *
0x10, 0x10, 0x7c, 0x10, 0x10, // +
0x00, 0x80, 0x60, 0x00, 0x00, // ,
0x10, 0x10, 0x10, 0x10, 0x00, // -
0x00, 0x00, 0x40, 0x00, 0x00, // .
0x20, 0x30, 0x0c, 0x03, 0x00, // /
0x3c, 0x52, 0x4a, 0x3c, 0x00, // 0
0x00, 0x44, 0x7e, 0x40, 0x00, // 1
0x64, 0x52, 0x52, 0x4c, 0x00, // 2
0x24, 0x42, 0x4a, 0x34, 0x00, // 3
0x1e, 0x10, 0x7c, 0x10, 0x00, // 4
0x4e, 0x4a, 0x4a, 0x32, 0x00, // 5
0x3C, 0x4A, 0x4a, 0x32, 0x00, // 6
0x06, 0x62, 0x12, 0x0e, 0x00, // 7
0x34, 0x4a, 0x4a, 0x34, 0x00, // 8
0x0c, 0x52, 0x52, 0x3c, 0x00, // 9
0x00, 0x00, 0x48, 0x00, 0x00, // :
0x00, 0x80, 0x68, 0x00, 0x00, // ;
0x00, 0x18, 0x24, 0x42, 0x00, // <
0x28, 0x28, 0x28, 0x28, 0x00, // =
0x00, 0x42, 0x24, 0x18, 0x00, // >
0x02, 0x51, 0x09, 0x06, 0x00, // ?
0x3c, 0x42, 0x5a, 0x5c, 0x00, // @
0x7C, 0x12, 0x12, 0x7c, 0x00, // A LATIN CAPITAL LETTER A
0x7e, 0x4a, 0x4a, 0x34, 0x00, // B LATIN CAPITAL LETTER B
0x3c, 0x42, 0x42, 0x42, 0x00, // C LATIN CAPITAL LETTER C
0x7e, 0x42, 0x42, 0x3c, 0x00, // D LATIN CAPITAL LETTER D
0x3c, 0x4a, 0x4a, 0x42, 0x00, // E LATIN CAPITAL LETTER E
0x7c, 0x0a, 0x0a, 0x02, 0x00, // F LATIN CAPITAL LETTER F
0x3c, 0x42, 0x4a, 0x7a, 0x00, // G LATIN CAPITAL LETTER G
0x7e, 0x08, 0x08, 0x7e, 0x00, // H LATIN CAPITAL LETTER H
0x00, 0x42, 0x7e, 0x42, 0x00, // I LATIN CAPITAL LETTER I
0x40, 0x42, 0x3e, 0x02, 0x00, // J LATIN CAPITAL LETTER J
0x7e, 0x08, 0x08, 0x76, 0x00, // K LATIN CAPITAL LETTER K
0x7e, 0x40, 0x40, 0x40, 0x00, // L LATIN CAPITAL LETTER L
0x7e, 0x0c, 0x0c, 0x7e, 0x00, // M LATIN CAPITAL LETTER M
0x7e, 0x0c, 0x30, 0x7e, 0x00, // N LATIN CAPITAL LETTER N
0x3c, 0x42, 0x42, 0x3c, 0x00, // O LATIN CAPITAL LETTER O
0x7e, 0x12, 0x12, 0x0c, 0x00, // P LATIN CAPITAL LETTER P
0x3c, 0x42, 0xc2, 0xbc, 0x00, // Q LATIN CAPITAL LETTER Q
0x7e, 0x12, 0x12, 0x6c, 0x00, // R LATIN CAPITAL LETTER R
0x44, 0x4a, 0x4a, 0x32, 0x00, // S LATIN CAPITAL LETTER S
0x02, 0x02, 0x7e, 0x02, 0x02, // T LATIN CAPITAL LETTER T
0x3e, 0x40, 0x40, 0x7e, 0x00, // U LATIN CAPITAL LETTER U
0x1e, 0x60, 0x60, 0x1e, 0x00, // V LATIN CAPITAL LETTER V
0x7e, 0x30, 0x30, 0x7e, 0x00, // W LATIN CAPITAL LETTER W
0x66, 0x18, 0x18, 0x66, 0x00, // X LATIN CAPITAL LETTER X
0x4e, 0x50, 0x50, 0x3e, 0x00, // Y LATIN CAPITAL LETTER Y
0x62, 0x52, 0x4a, 0x46, 0x00, // Z LATIN CAPITAL LETTER Z
0x00, 0xff, 0x81, 0x81, 0x00, // [
0x03, 0x0c, 0x30, 0xc0, 0x00, // "\"
0x00, 0x81, 0x81, 0xff, 0x00, // ]
0x08, 0x04, 0x02, 0x04, 0x08, // ^
0x80, 0x80, 0x80, 0x80, 0x00, // _ podtržítko
0x00, 0x01, 0x02, 0x08, 0x00, // `
0x20, 0x54, 0x54, 0x78, 0x00, // a LATIN SMALL LETTER a
0x7F, 0x44, 0x44, 0x38, 0x00, // b LATIN SMALL LETTER b
0x38, 0x44, 0x44, 0x44, 0x00, // c LATIN SMALL LETTER c
0x38, 0x44, 0x44, 0x7f, 0x00, // d LATIN SMALL LETTER d
0x38, 0x54, 0x54, 0x5c, 0x00, // e LATIN SMALL LETTER e
0x08, 0x7e, 0x09, 0x01, 0x00, // f LATIN SMALL LETTER f
0x98, 0xa4, 0xa4, 0x5c, 0x00, // g LATIN SMALL LETTER g
0x7F, 0x04, 0x04, 0x78, 0x00, // h LATIN SMALL LETTER h
0x00, 0x08, 0x7a, 0x40, 0x00, // i LATIN SMALL LETTER i
0x80, 0x80, 0x7a, 0x00, 0x00, // j LATIN SMALL LETTER j
0x7F, 0x10, 0x28, 0x44, 0x00, // k LATIN SMALL LETTER k
0x00, 0x3f, 0x40, 0x40, 0x00, // l LATIN SMALL LETTER l
0x7C, 0x18, 0x18, 0x7c, 0x00, // m LATIN SMALL LETTER m
0x7C, 0x04, 0x04, 0x78, 0x00, // n LATIN SMALL LETTER n
0x38, 0x44, 0x44, 0x38, 0x00, // o LATIN SMALL LETTER o
0xFC, 0x24, 0x24, 0x18, 0x00, // p LATIN SMALL LETTER p
0x18, 0x24, 0x24, 0xfc, 0x00, // q LATIN SMALL LETTER q
0x78, 0x04, 0x04, 0x0c, 0x00, // r LATIN SMALL LETTER r
0x48, 0x54, 0x54, 0x24, 0x00, // s LATIN SMALL LETTER s
0x04, 0x3f, 0x44, 0x40, 0x00, // t LATIN SMALL LETTER t
0x3C, 0x40, 0x40, 0x7c, 0x00, // u LATIN SMALL LETTER u
0x1C, 0x60, 0x60, 0x1c, 0x00, // v LATIN SMALL LETTER v
0x7C, 0x30, 0x30, 0x7c, 0x00, // w LATIN SMALL LETTER w
0x64, 0x18, 0x18, 0x64, 0x00, // x LATIN SMALL LETTER x
0x9C, 0xa0, 0xa0, 0x7c, 0x00, // y LATIN SMALL LETTER y
0x44, 0x64, 0x54, 0x4C, 0x00, // z LATIN SMALL LETTER z
0x18, 0x7e, 0x81, 0x81, 0x00, // { LEFT CURLY BRACKET
0x00, 0x00, 0xff, 0x00, 0x00, // | VERTICAL LINE
0x81, 0x81, 0x7e, 0x18, 0x00, // } RIGHT CURLY BRACKER
0x10, 0x08, 0x10, 0x10, 0x08, // ~ TILDE
0x00, 0x00, 0x00, 0x00, 0x00, // 0x7f nelomitelná mezera
0xfe, 0x83, 0x83, 0x83, 0xfe, // 0x80 baterie vybitá
0xfe, 0xc3, 0xc3, 0xc3, 0xfe, // 0x81 baterie 20%
0xfe, 0xe3, 0xe3, 0xe3, 0xfe, // 0x82 baterie 40%
0xfe, 0xf3, 0xf3, 0xf3, 0xfe, // 0x83 baterie 60%
0xfe, 0xfb, 0xfb, 0xfb, 0xfe, // 0x84 baterie 80%
0xfe, 0xff, 0xff, 0xff, 0xfe, // 0x85 baterie 100% nabitá
0x1f, 0x08, 0x44, 0xfe, 0x40, // 0x86 blesk
0x20, 0x60, 0xff, 0x60, 0x20, // 0x87 šipka dolů
0x04, 0x06, 0xff, 0x06, 0x04, // 0x88 šipka nahoru
0x24, 0x66, 0xff, 0x66, 0x24, // 0x89 šipka nahoru i dolů
0x60, 0x60, 0x7f, 0x60, 0x60, // 0x8a zemnění
0x00, 0x00, 0x00, 0x00, 0x00, // 0x8b unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x8c unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x8d unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x8e unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x8f unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x91 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x92 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x93 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x94 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x95 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x96 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x97 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x99 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9a unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9b unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9c unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9d unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9e unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0x9f unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 nezlomitelná mezera
0x7c, 0x12, 0x12, 0x7c, 0x80, // 0xa1 LATIN CAPITAL LETTER A WITH
0x01, 0x02, 0x02, 0x01, 0x00, // 0xa2 BREVE oblouček
0x10, 0x7e, 0x48, 0x40, 0x40, // 0xa3 LATIN CAPITAL LETTER L WITH STROKE
0x00, 0x00, 0x00, 0x00, 0x00, // 0xa4 valuta
0x7e, 0x42, 0x41, 0x40, 0x00, // 0xa5 měkké L
0x44, 0x4a, 0x4a, 0x33, 0x00, // 0xa6 S s čárkou
0x80, 0xb6, 0x49, 0x31, 0x00, // 0xa7 paragraf
0x00, 0x01, 0x00, 0x01, 0x00, // 0xa8 přehláska
0x44, 0x4b, 0x4a, 0x33, 0x00, // 0xa9 Š ---
0x00, 0x00, 0x00, 0x00, 0x00, // 0xaa unused
0x04, 0x05, 0x7e, 0x05, 0x04, // 0xab Ť
0x00, 0x00, 0x00, 0x00, 0x00, // 0xac unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xad unused
0x62, 0x73, 0x5a, 0x4f, 0x46, // 0xae Ž
0x00, 0x00, 0x00, 0x00, 0x00, // 0xaf unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb1 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb2 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb3 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb4 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb5 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb6 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb7 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 unused
0x48, 0x55, 0x56, 0x25, 0x00, // 0xb9 š
0x00, 0x00, 0x00, 0x00, 0x00, // 0xba unused
0x04, 0x3f, 0x44, 0x40, 0x03, // 0xbb ť
0x00, 0x00, 0x00, 0x00, 0x00, // 0xbc unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xbd unused
0x45, 0x66, 0x56, 0x4d, 0x00, // 0xbe ž
0x00, 0x00, 0x00, 0x00, 0x00, // 0xbf unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 unused
0x7c, 0x12, 0x12, 0x7e, 0x01, // 0xc1 Á
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc2 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc3 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc4 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc5 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc6 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xc7 unused
0x3c, 0x43, 0x42, 0x43, 0x00, // 0xc8 Č
0x7e, 0x4a, 0x4b, 0x42, 0x00, // 0xc9 É
0x00, 0x00, 0x00, 0x00, 0x00, // 0xca unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xcb unused
0x7e, 0x4b, 0x4a, 0x43, 0x00, // 0xcc Ě
0x00, 0x44, 0x7c, 0x46, 0x01, // 0xcd Í
0x00, 0x00, 0x00, 0x00, 0x00, // 0xce unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xcf unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xd1 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xd2 unused
0x7e, 0x0d, 0x32, 0x7d, 0x00, // 0xd3 Ň
0x3c, 0x42, 0x42, 0x3d, 0x00, // 0xd4 Ó
0x00, 0x00, 0x00, 0x00, 0x00, // 0xd5 krát
0x00, 0x00, 0x00, 0x00, 0x00, // 0xd6 unused
0x44, 0x28, 0x10, 0x28, 0x44, // 0xd7 krát
0x7e, 0x13, 0x12, 0x6d, 0x00, // 0xd8 Ř
0x3e, 0x43, 0x43, 0x7e, 0x00, // 0xd9 Ů
0x3e, 0x40, 0x42, 0x7d, 0x00, // 0xda Ú
0x00, 0x00, 0x00, 0x00, 0x00, // 0xdb unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xdc unused
0x4e, 0x50, 0x52, 0x3d, 0x00, // 0xdd Ý
0x00, 0x00, 0x00, 0x00, 0x00, // 0xde unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xdf unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 unused
0x20, 0x54, 0x56, 0x79, 0x00, // 0xe1 á
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe2 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe3 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe4 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe5 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe6 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xe7 unused
0x38, 0x45, 0x46, 0x45, 0x00, // 0xe8 č
0x38, 0x54, 0x56, 0x5d, 0x00, // 0xe9 é
0x00, 0x00, 0x00, 0x00, 0x00, // 0xea unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xeb unused
0x38, 0x55, 0x56, 0x5d, 0x00, // 0xec ě
0x00, 0x40, 0x78, 0x42, 0x01, // 0xed í
0x00, 0x00, 0x00, 0x00, 0x00, // 0xee unused
0x38, 0x44, 0x44, 0x7f, 0x03, // 0xef ď
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf1 unused
0x7d, 0x06, 0x05, 0x78, 0x00, // 0xf2 ň
0x38, 0x44, 0x46, 0x39, 0x00, // 0xf3 ó
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf4 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf5 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf6 unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xf7 unused
0x78, 0x05, 0x06, 0x0d, 0x00, // 0xf8 ř
0x3c, 0x43, 0x43, 0x7c, 0x00, // 0xf9 ů
0x3c, 0x40, 0x42, 0x7d, 0x00, // 0xfa ú
0x00, 0x00, 0x00, 0x00, 0x00, // 0xfb unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xfc unused
0x4e, 0x50, 0x52, 0x3d, 0x00, // 0xfd ý
0x00, 0x00, 0x00, 0x00, 0x00, // 0xfe unused
0x00, 0x00, 0x00, 0x00, 0x00, // 0xff unused
};
#endif
makefsdata.py
#!/usr/bin/python3
# This script is by @rspeir on GitHub:
# https://github.com/krzmaz/pico-w-webserver-example/pull/1/files/4b3e78351dd236f213da9bebbb20df690d470476#diff-e675c4a367e382db6f9ba61833a58c62029d8c71c3156a9f238b612b69de279d
# Renamed output to avoid linking incorrect file
import os
import binascii
#Create file to write output into
output = open('htmldata.c', 'w')
#Traverse directory, generate list of files
files = list()
os.chdir('./html_files')
for(dirpath, dirnames, filenames) in os.walk('.'):
files += [os.path.join(dirpath, file) for file in filenames]
filenames = list()
varnames = list()
#Generate appropriate HTTP headers
for file in files:
if '404' in file:
header = "HTTP/1.0 404 File not found\r\n"
else:
header = "HTTP/1.0 200 OK\r\n"
header += "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"
if '.html' in file:
header += "Content-type: text/html\r\n"
elif '.shtml' in file:
header += "Content-type: text/html\r\n"
elif '.jpg' in file:
header += "Content-type: image/jpeg\r\n"
elif '.gif' in file:
header += "Content-type: image/gif\r\n"
elif '.png' in file:
header += "Content-type: image/png\r\n"
elif '.class' in file:
header += "Content-type: application/octet-stream\r\n"
elif '.js' in file:
header += "Content-type: text/javascript\r\n"
elif '.css' in file:
header += "Content-type: text/css\r\n"
elif '.svg' in file:
header += "Content-type: image/svg+xml\r\n"
else:
header += "Content-type: text/plain\r\n"
header += "\r\n"
fvar = file[1:] #remove leading dot in filename
fvar = fvar.replace('/', '_') #replace *nix path separator with underscore
fvar = fvar.replace('\\', '_') #replace DOS path separator with underscore
fvar = fvar.replace('.', '_') #replace file extension dot with underscore
output.write("static const unsigned char data{}[] = {{\n".format(fvar))
output.write("\t/* {} */\n\t".format(file))
#first set of hex data encodes the filename
b = bytes(file[1:].replace('\\', '/'), 'utf-8') #change DOS path separator to forward slash
for byte in binascii.hexlify(b, b' ', 1).split():
output.write("0x{}, ".format(byte.decode()))
output.write("0,\n\t")
#second set of hex data is the HTTP header/mime type we generated above
b = bytes(header, 'utf-8')
count = 0
for byte in binascii.hexlify(b, b' ', 1).split():
output.write("0x{}, ".format(byte.decode()))
count = count + 1
if(count == 10):
output.write("\n\t")
count = 0
output.write("\n\t")
#finally, dump raw hex data from files
with open(file, 'rb') as f:
count = 0
while(byte := f.read(1)):
byte = binascii.hexlify(byte)
output.write("0x{}, ".format(byte.decode()))
count = count + 1
if(count == 10):
output.write("\n\t")
count = 0
output.write("};\n\n")
filenames.append(file[1:])
varnames.append(fvar)
for i in range(len(filenames)):
prevfile = "NULL"
if(i > 0):
prevfile = "file" + varnames[i-1]
output.write("const struct fsdata_file file{0}[] = {{{{ {1}, data{2}, ".format(varnames[i], prevfile, varnames[i]))
output.write("data{} + {}, ".format(varnames[i], len(filenames[i]) + 1))
output.write("sizeof(data{}) - {}, ".format(varnames[i], len(filenames[i]) + 1))
output.write("FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT}};\n")
output.write("\n#define FS_ROOT file{}\n".format(varnames[-1]))
output.write("#define FS_NUMFILES {}\n".format(len(filenames)))
Sestavení projektu
mkdir automaticke_zalevani
cd automaticke_zalevani
## sem nakopírujte všechny soubory
mkdir build
cd build
cmake .. #(1)
make -j8
| 1 | cmake se používá při vytváření anebo obnovení html_stránek do webu. |
Přednastavení konfigurace Wifi (samostatný projekt)
nastaveni/CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(PICO_BOARD pico_w)
set (CMAKE_C_STANDARD 11)
set (CMAKE_CXX_STANDARD 17)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
set(PROJECT_NAME picow_persistent_write)
project(${PROJECT_NAME} C CXX ASM)
pico_sdk_init()
add_executable(${PROJECT_NAME}
PersistentStorage.c
)
# nastaveni vyhrazeneho mista ve XIP flash pro konfiguracni data
pico_set_linker_script(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_custom.ld)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries( ${PROJECT_NAME}
pico_stdlib
pico_cyw43_arch_lwip_threadsafe_background
hardware_flash
hardware_sync
)
# volby pro linker
target_link_options( ${PROJECT_NAME} PRIVATE -Xlinker --print-memory-usage)
pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_enable_stdio_uart(${PROJECT_NAME} 0)
pico_add_extra_outputs(${PROJECT_NAME})
nastaveni/memmap_custom.ld
/* Based on GCC ARM embedded samples.
Defines the following symbols for use by code:
__exidx_start
__exidx_end
__etext
__data_start__
__preinit_array_start
__preinit_array_end
__init_array_start
__init_array_end
__fini_array_start
__fini_array_end
__data_end__
__bss_start__
__bss_end__
__end__
end
__HeapLimit
__StackLimit
__StackTop
__stack (== StackTop)
*/
__PERSISTENT_STORAGE_LEN = 16k ;
MEMORY
{
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k - __PERSISTENT_STORAGE_LEN
FLASH_PERSISTENT(rw) : ORIGIN = 0x10000000 + (2048k - __PERSISTENT_STORAGE_LEN) , LENGTH = __PERSISTENT_STORAGE_LEN
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
}
ENTRY(_entry_point)
SECTIONS
{
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
and checksummed. It is usually built by the boot_stage2 target
in the Raspberry Pi Pico SDK
*/
.flash_begin : {
__flash_binary_start = .;
} > FLASH
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > FLASH
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
/* The second stage will always enter the image at the start of .text.
The debugger will use the ELF entry point, which is the _entry_point
symbol if present, otherwise defaults to start of .text.
This can be used to transfer control back to the bootrom on debugger
launches only, to perform proper flash setup.
*/
.text : {
__logical_binary_start = .;
KEEP (*(.vectors))
KEEP (*(.binary_info_header))
__binary_info_header_end = .;
KEEP (*(.reset))
/* TODO revisit this now memset/memcpy/float in ROM */
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
* FLASH ... we will include any thing excluded here in .data below by default */
*(.init)
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
*(.fini)
/* Pull all c'tors into .text */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* Followed by destructors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.eh_frame*)
. = ALIGN(4);
} > FLASH
.rodata : {
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
. = ALIGN(4);
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
. = ALIGN(4);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* Machine inspectable binary information */
. = ALIGN(4);
__binary_info_start = .;
.binary_info :
{
KEEP(*(.binary_info.keep.*))
*(.binary_info.*)
} > FLASH
__binary_info_end = .;
. = ALIGN(4);
/* End of .text-like segments */
__etext = .;
.section_persisitent : {
"ADDR_PERSISTENT" = .;
} > FLASH_PERSISTENT
.ram_vector_table (COPY): {
*(.ram_vector_table)
} > RAM
.data : {
__data_start__ = .;
*(vtable)
*(.time_critical*)
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
*(.text*)
. = ALIGN(4);
*(.rodata*)
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
*(.after_data.*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__mutex_array_start = .);
KEEP(*(SORT(.mutex_array.*)))
KEEP(*(.mutex_array))
PROVIDE_HIDDEN (__mutex_array_end = .);
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH
.uninitialized_data (COPY): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
*(.scratch_x.*)
. = ALIGN(4);
__scratch_x_end__ = .;
} > SCRATCH_X AT > FLASH
__scratch_x_source__ = LOADADDR(.scratch_x);
.scratch_y : {
__scratch_y_start__ = .;
*(.scratch_y.*)
. = ALIGN(4);
__scratch_y_end__ = .;
} > SCRATCH_Y AT > FLASH
__scratch_y_source__ = LOADADDR(.scratch_y);
.bss : {
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack*_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later
*
* stack1 section may be empty/missing if platform_launch_core1 is not used */
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
{
*(.stack*)
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
} > FLASH
/* stack limit is poorly named, but historically is maximum heap ptr */
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
/* todo assert on extra code */
}
nastaveni/PersistentStorage.c
/* Ukládání dat Wifi připojení do FLASH paměti Pica
* (c) Jirka Chráska 2025; <jirka@lixis.cz>
*
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "flash_utils.h"
#include "hardware/flash.h"
#include "hardware/sync.h"
#include <string.h>
const uint8_t *flash_target_content;
#define MOJE_VELIKOST 4*FLASH_SECTOR_SIZE
#define RECORD_SIZE 128
char data[MOJE_VELIKOST] = {0};
// tiskne buffer jako hexadecimální čísla
void print_buf(const uint8_t *buf, size_t len)
{
for (size_t i = 0; i < len; ++i) {
printf("%02x", buf[i]);
if (i % 16 == 15)
printf("\n");
else
printf(" ");
}
}
// tiskne buffer jako znaky
void print_chars(const uint8_t *buf, size_t len)
{
for (size_t i = 0; i < len; ++i) {
printf("%c", buf[i]);
if (i % 16 == 15)
printf("\n");
else
printf(" ");
}
}
int main()
{
flash_target_content = (const uint8_t *) getAddressPersistent();
uint32_t kam = PICO_FLASH_SIZE_BYTES - MOJE_VELIKOST;
stdio_init_all();
sleep_ms(1500);
printf("Zápis dat dat na XIP flash...\nStiskni klavesu.\n");
getchar();
// konfigurace SSID, PASS, AUTH, IPv6, IPv4
// každý záznam (record) má 128 byte
char *record1 = &data[0*RECORD_SIZE];
sprintf(record1,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "chorche", '\0', "Kt37Oe10UB9;", '\0', "WPA2_MIXED_PSK",'\0', "y",'\0', "y");
char *record2 = &data[1*RECORD_SIZE];
sprintf(record2,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "chorche5", '\0', "Krabice17sBotama19", '\0', "WPA2_MIXED_PSK", '\0', "y", '\0', "y");
char *record3 = &data[2*RECORD_SIZE];
sprintf(record3,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "chorche6", '\0', "Krabice17sBotama19.", '\0', "WPA_TKIP_PSK", '\0', "y", '\0', "y");
char *record4 = &data[3*RECORD_SIZE];
sprintf(record4,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "Repeater_663D4C", '\0', "hesloneniveslo2931", '\0', "WPA2_MIXED_PSK", '\0', "y", '\0', "y");
char *record5 = &data[4*RECORD_SIZE];
sprintf(record5,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "sspvc-ucitel", '\0', "kantorIdeal", '\0', "WPA_MIXED_PSK", '\0', "y", '\0', "y");
char *record6 = &data[5*RECORD_SIZE];
sprintf(record6,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "sspvc", '\0', "", '\0', "WPA2_MIXED_PSK", '\0', "n", '\0', "y");
char *record7 = &data[6*RECORD_SIZE];
sprintf(record7,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "chorche3", '\0', "Krabice17sBotama19", '\0', "WPA_MIXED_PSK", '\0', "y", '\0', "y");
char *record8 = &data[7*RECORD_SIZE];
sprintf(record8,"SSID:%s%cPASS:%s%cAUTH:%s%cIPv6:%s%cIPv4:%s", "Internet_5C31_EXT", '\0', "Mi514laN", '\0', "WPA2_MIXED_PSK", '\0', "n", '\0', "y");
printf("\nZapis do flashe.\n");
printf("FLASH_MEM=%p FLASH_PAGE_SIZE=%d, FLASH_SECTOR_SIZE=%d, XIP_BASE=0x%p, kam=0x%x\n",getAddressPersistent(), FLASH_PAGE_SIZE, FLASH_SECTOR_SIZE, XIP_BASE, kam );
sleep_ms(5000);
printf("Erasing %d bytes of flash\n", MOJE_VELIKOST);
printf("Writing %d bytes to flash\n", FLASH_PAGE_SIZE*4);
// uložíme a zakážeme přerušení
uint32_t ints = save_and_disable_interrupts();
// vymažeme sektory flashe (4*4096 bytů )
flash_range_erase(kam,MOJE_VELIKOST);
// zapíšeme data do flashe
flash_range_program(kam, data, FLASH_PAGE_SIZE*4);
// obnovíme přerušení
restore_interrupts(ints);
// Přečteme, co jsme zapsali
printf("Uložená síť 1: \"%s\"\n", (char *) flash_target_content+(0*128));
print_chars(flash_target_content+(0*128), 128);
printf("Uložená síť 2: \"%s\"\n", (char *) flash_target_content+(1*128));
print_chars(flash_target_content+(1*128), 128);
printf("Uložená síť 3: \"%s\"\n", (char *) flash_target_content+(2*128));
print_chars(flash_target_content+(2*128), 128);
printf("Uložená síť 4: \"%s\"\n", (char *) flash_target_content+(3*128));
print_chars(flash_target_content+(3*128), 128);
printf("Uložená síť 5: \"%s\"\n", (char *) flash_target_content+(4*128));
print_chars(flash_target_content+(4*128), 128);
printf("Uložená síť 6: \"%s\"\n", (char *) flash_target_content+(5*128));
print_chars(flash_target_content+(5*128), 128);
printf("Uložená síť 7: \"%s\"\n", (char *) flash_target_content+(6*128));
print_chars(flash_target_content+(6*128), 128);
printf("Uložená síť 8: \"%s\"\n", (char *) flash_target_content+(7*128));
print_chars(flash_target_content+(7*128), 128);
sleep_ms(2000);
return 0;
}
nastaveni/flash_utils.h
#include <stdint.h>
inline uint32_t *getAddressPersistent()
{
extern uint32_t ADDR_PERSISTENT[];
return ADDR_PERSISTENT;
}
nastaveni/lwipopts.h
#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H
#define _LWIPOPTS_EXAMPLE_COMMONH_H
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
// allow override in some examples
#ifndef NO_SYS
#define NO_SYS 1
#endif
// allow override in some examples
#ifndef LWIP_SOCKET
#define LWIP_SOCKET 0
#endif
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 4000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#endif /* __LWIPOPTS_H__ */




