├── main ├── www │ ├── .gitignore │ ├── compress_pages.sh │ ├── style.css │ └── script.js ├── include │ ├── scut.h │ ├── app_sntp.h │ ├── app_lcd.h │ ├── app_httpd.h │ ├── idf_version.h │ ├── app_wifi.h │ ├── app_illuminator.h │ ├── app_settings.h │ └── app_camera.h ├── component.mk ├── CMakeLists.txt ├── scut.c ├── fonts │ ├── fonts.h │ ├── Picopixel.h │ ├── Tiny3x3a2pt7b.h │ ├── Org_01.h │ ├── FreeMono9pt7b.h │ ├── FreeMonoOblique9pt7b.h │ ├── FreeMonoBold9pt7b.h │ ├── FreeSerif9pt7b.h │ ├── FreeSans9pt7b.h │ ├── FreeSerifBold9pt7b.h │ ├── FreeSerifItalic9pt7b.h │ ├── FreeMonoBoldOblique9pt7b.h │ └── FreeSansBold9pt7b.h ├── app_sntp.c ├── app_illuminator.c ├── app_main.c ├── app_camera.c ├── app_lcd.c ├── app_settings.c ├── Kconfig.projbuild └── app_wifi.c ├── data └── fonts.bin ├── images └── screenshot.png ├── .gitignore ├── Makefile ├── partitions.csv ├── CMakeLists.txt ├── .gitmodules ├── notes ├── scripts ├── backup_font_partition.py └── restore_font_partition.py ├── sdkconfig.defaults ├── README.md └── .github └── workflows └── build.yml /main/www/.gitignore: -------------------------------------------------------------------------------- 1 | *.gz 2 | -------------------------------------------------------------------------------- /data/fonts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkeevil/esp32-cam/HEAD/data/fonts.bin -------------------------------------------------------------------------------- /images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkeevil/esp32-cam/HEAD/images/screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | sdkconfig 3 | sdkconfig.old 4 | .DS_Store 5 | .vscode 6 | main/www/.idea/ 7 | *.swp 8 | -------------------------------------------------------------------------------- /main/include/scut.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "esp_log.h" 4 | #include "esp_system.h" 5 | esp_err_t scut (char * dst, char * src, size_t dst_size); 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := esp32-cam 7 | 8 | include $(IDF_PATH)/make/project.mk -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # Espressif ESP32 Partition Table 2 | # Name, Type, SubType, Offset, Size 3 | factory, app, factory, 0x020000, 3520K 4 | fonts, data, nvs, 0x390000, 256K 5 | nvs, data, nvs, 0x3D0000, 16K 6 | -------------------------------------------------------------------------------- /main/include/app_sntp.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_SNTP_H_ 2 | #define _APP_SNTP_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void app_sntp_startup(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /main/include/app_lcd.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_LCD_H_ 2 | #define _APP_LCD_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void app_lcd_startup(); 9 | void app_lcd_shutdown(); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /main/include/app_httpd.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _APP_HTTPD_H_ 3 | #define _APP_HTTPD_H_ 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | extern float avg_fps; 10 | 11 | void app_httpd_startup(); 12 | void app_httpd_shutdown(); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | 6 | set(EXTRA_COMPONENT_DIRS components) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(esp32-cam) 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/esp32-camera"] 2 | path = components/esp32-camera 3 | url = https://github.com/espressif/esp32-camera.git 4 | branch = master 5 | 6 | [submodule "components/esp-idf-ssd1306"] 7 | path = components/esp-idf-ssd1306 8 | url = https://github.com/bkeevil/esp-idf-ssd1306.git 9 | branch = development 10 | -------------------------------------------------------------------------------- /notes: -------------------------------------------------------------------------------- 1 | to make "allocate in psram" work go to Component config -> ESP32 specific -> SPI ram config -> SPI RAM ACCESS METHOD -> using heap_caps_malloc 2 | 3 | 4 | dhcp hostame is too long ! :D 5 | po zadani retezce ve web ui a kliknuti na save se neulozi posledni ve kterem je prave focus pokud byl zmenen 6 | mezera v user passwordu udela bordel 7 | 8 | 9 | -------------------------------------------------------------------------------- /main/include/idf_version.h: -------------------------------------------------------------------------------- 1 | #if !defined(__IDF_VERSION__H__) 2 | #define __IDF_VERSION__H__ 3 | 4 | #include 5 | 6 | #if ESP_IDF_VERSION_MAJOR < 4 7 | #error esp-idf version must be 4.x 8 | #endif 9 | 10 | #if ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION_MINOR < 1 11 | #define __USE_LWIP_IP_4_ADDR 12 | #define __USE_TCP_ADAPTOR 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /main/include/app_wifi.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_WIFI_H_ 2 | #define _APP_WIFI_H_ 3 | 4 | #include "freertos/event_groups.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define WIFI_CONNECTED_BIT BIT0 // Event group bit is set high while connected 11 | #define WIFI_SOFTAP_BIT BIT1 12 | 13 | int wifi_connection_count(); 14 | int wifi_get_rssi(); 15 | float wifi_get_tx_power(); 16 | 17 | void app_wifi_startup(); 18 | void app_wifi_shutdown(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif -------------------------------------------------------------------------------- /main/www/compress_pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for file in `ls *.html`; do 3 | echo "Compressing: $file" 4 | cp "$file" "copy_$file" && \ 5 | gzip -f "$file" && \ 6 | mv "copy_$file" "$file" 7 | done 8 | for file in `ls *.css`; do 9 | echo "Compressing: $file" 10 | cp "$file" "copy_$file" && \ 11 | gzip -f "$file" && \ 12 | mv "copy_$file" "$file" 13 | done 14 | for file in `ls *.js`; do 15 | echo "Compressing: $file" 16 | cp "$file" "copy_$file" && \ 17 | gzip -f "$file" && \ 18 | mv "copy_$file" "$file" 19 | done -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main Makefile. This is basically the same as a component makefile. 3 | # 4 | # This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, 5 | # this will take the sources in the src/ directory, compile them and link them into 6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, 7 | # please read the SDK documents if you need to do this. 8 | # 9 | COMPONENT_EMBED_FILES := www/index.html.gz 10 | COMPONENT_EMBED_FILES += www/style.css.gz 11 | COMPONENT_EMBED_FILES += www/script.js.gz -------------------------------------------------------------------------------- /main/include/app_illuminator.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_ILLUMINATOR_H_ 2 | #define _APP_ILLUMINATOR_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #ifdef CONFIG_LED_ILLUMINATOR_ENABLED 9 | #ifdef CONFIG_LED_LEDC_LOW_SPEED_MODE 10 | #define CONFIG_LED_LEDC_SPEED_MODE LEDC_LOW_SPEED_MODE 11 | #else 12 | #define CONFIG_LED_LEDC_SPEED_MODE LEDC_HIGH_SPEED_MODE 13 | #endif 14 | 15 | void app_illuminator_startup(); 16 | void app_illuminator_shutdown(); 17 | void app_illuminator_set_led_intensity(uint8_t duty); 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register( 2 | SRCS "app_main.c" 3 | "app_settings.c" 4 | "app_illuminator.c" 5 | "app_camera.c" 6 | "app_wifi.c" 7 | "app_fonts.c" 8 | "app_httpd.c" 9 | "app_lcd.c" 10 | "app_sntp.c" 11 | "scut.c" 12 | REQUIRES esp32-camera 13 | esp-idf-ssd1306 14 | mdns 15 | nvs_flash 16 | esp_http_server 17 | INCLUDE_DIRS "include" 18 | "fonts" 19 | EMBED_FILES "www/index.html.gz" 20 | "www/style.css.gz" 21 | "www/script.js.gz" 22 | ) 23 | -------------------------------------------------------------------------------- /main/scut.c: -------------------------------------------------------------------------------- 1 | #include "scut.h" 2 | 3 | static const char TAG[] = "scut"; 4 | esp_err_t scut (char * dst, char * src, size_t n) { 5 | //sizeof (dst) must be at least n 6 | //clears n bytes in destination using null-termination character 7 | //truncate src string to (n - 1) characters by copying (n- 1) characters from src to dst 8 | //then there is no need to add null term char because we cleared n and copied 1 char less than n 9 | memset(dst, '\0', n); //clear n bytes with nullterms 10 | 11 | if (n < 2) { 12 | //thats an error 13 | ESP_LOGI(TAG, "dst size < 2 makes no sense"); 14 | return ESP_FAIL; 15 | } 16 | 17 | memcpy(dst, src, n - 1); 18 | return ESP_OK; 19 | } 20 | -------------------------------------------------------------------------------- /scripts/backup_font_partition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import os 5 | 6 | idf_path = os.environ["IDF_PATH"] # get value of IDF_PATH from environment 7 | parttool_dir = os.path.join(idf_path, "components", "partition_table") # parttool.py lives in $IDF_PATH/components/partition_table 8 | 9 | sys.path.append(parttool_dir) # this enables Python to find parttool module 10 | from parttool import * # import all names inside parttool module 11 | 12 | # Create a partool.py target device connected on serial port /dev/ttyUSB1 13 | target = ParttoolTarget("/dev/ttyUSB0") 14 | 15 | print("Backing up fonts partition to fonts.bin...") 16 | 17 | target.read_partition(PartitionName("fonts"), "fonts.bin") 18 | 19 | print("Done"); 20 | -------------------------------------------------------------------------------- /scripts/restore_font_partition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import os 5 | 6 | idf_path = os.environ["IDF_PATH"] # get value of IDF_PATH from environment 7 | parttool_dir = os.path.join(idf_path, "components", "partition_table") # parttool.py lives in $IDF_PATH/components/partition_table 8 | 9 | sys.path.append(parttool_dir) # this enables Python to find parttool module 10 | from parttool import * # import all names inside parttool module 11 | 12 | # Create a partool.py target device connected on serial port /dev/ttyUSB1 13 | target = ParttoolTarget("/dev/ttyUSB0") 14 | 15 | print("Restoring fonts partition from data/fonts.bin..") 16 | 17 | target.write_partition(PartitionName("fonts"), "../data/fonts.bin") 18 | 19 | print("Done"); 20 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # pin camera and WiFi stack to a specific core for performance and reliability 2 | CONFIG_CAMERA_CORE1=y 3 | CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y 4 | 5 | # increase CPU frequency for performance 6 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 7 | 8 | # the code requires SPI RAM 9 | CONFIG_ESP32_SPIRAM_SUPPORT=y 10 | 11 | # use SPI RAM when malloc(), otherwise WiFi stack and httpd tasks fail with 12 | # ESP_ERR_NO_MEM 13 | CONFIG_SPIRAM_USE_MALLOC=y 14 | 15 | # the code requires custom partition table and more than 4MB flash 16 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 17 | CONFIG_PARTITION_TABLE_CUSTOM=y 18 | CONFIG_PARTITION_TABLE_OFFSET=0x18000 19 | 20 | # esp32-camera uses rtc_gpio_desc in rtc_io_desc_t, instead of rtc_io_desc 21 | CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC=y 22 | -------------------------------------------------------------------------------- /main/fonts/fonts.h: -------------------------------------------------------------------------------- 1 | #ifndef _GFXFONT_H_ 2 | #define _GFXFONT_H_ 3 | 4 | /// Font data stored PER GLYPH 5 | typedef struct { 6 | uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap 7 | uint8_t width; ///< Bitmap dimensions in pixels 8 | uint8_t height; ///< Bitmap dimensions in pixels 9 | uint8_t xAdvance; ///< Distance to advance cursor (x axis) 10 | int8_t xOffset; ///< X dist from cursor pos to UL corner 11 | int8_t yOffset; ///< Y dist from cursor pos to UL corner 12 | } GFXglyph; 13 | 14 | /// Data stored for FONT AS A WHOLE 15 | typedef struct { 16 | uint8_t *bitmap; ///< Glyph bitmaps, concatenated 17 | GFXglyph *glyph; ///< Glyph array 18 | uint8_t first; ///< ASCII extents (first char) 19 | uint8_t last; ///< ASCII extents (last char) 20 | uint8_t yAdvance; ///< Newline distance (y axis) 21 | } GFXfont; 22 | 23 | #endif // _GFXFONT_H_ -------------------------------------------------------------------------------- /main/app_sntp.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_SNTP_ENABLED 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "sdkconfig.h" 11 | #include "esp_log.h" 12 | #include "app_settings.h" 13 | #include "app_wifi.h" 14 | #include "esp_sntp.h" 15 | 16 | 17 | static const char *TAG = "sntp"; 18 | extern EventGroupHandle_t event_group; 19 | 20 | void time_sync_ notification_cb(struct timeval *tv) { 21 | ESP_LOGI(TAG, "Notification of a time synchronization event"); 22 | } 23 | 24 | void app_sntp_startup() { 25 | time_t now = 0 26 | struct tm timeinfo = { 0 }; 27 | 28 | ESP_LOGI(TAG, "Initializing SNTP"); 29 | sntp_setoperatingmode(SNTP_OPMODE_POLL); 30 | sntp_setservername(0, settings.ntp_server); 31 | sntp_set_time_sync_notification_cb(time_sync_notification_cb); 32 | sntp_init(); 33 | // wait for time to be set 34 | int retry = 0; 35 | const int retry_count = 3; 36 | while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) { 37 | ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); 38 | vTaskDelay(2000 / portTICK_PERIOD_MS); 39 | } 40 | char strftime_buf[64]; 41 | setenv("TZ", settings.timezone, 1); 42 | tzset(); 43 | ESP_LOGI(TAG, "Timezone set to %s",settings.timezone); 44 | time(&now); 45 | localtime_r(&now, &timeinfo); 46 | strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); 47 | ESP_LOGI(TAG, "The current date/time is: %s", strftime_buf); 48 | return; 49 | } 50 | 51 | #endif -------------------------------------------------------------------------------- /main/include/app_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef APP_SETTINGS_H_ 2 | #define APP_SETTINGS_H_ 3 | 4 | #include "idf_version.h" 5 | 6 | #if defined(__USE_LWIP_IP_4_ADDR) 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | //lengths in characters WO null term 13 | #define LEN_WIFI_SSID 31 14 | #define LEN_WIFI_PASSWORD 63 15 | #define LEN_HOSTNAME 32 16 | #define LEN_HTTP_USER 16 17 | #define LEN_HTTP_PASSWORD 16 18 | #ifdef CONFIG_MDNS_ENABLED 19 | #define LEN_MDNS_INSTANCE 32 20 | #endif 21 | #ifdef CONFIG_SNTP_ENABLED 22 | #define LEN_NTP_SERVER 32 23 | #define LEN_TIMEZONE 32 24 | #endif 25 | 26 | struct app_settings_t { 27 | int size; 28 | char wifi_ssid[LEN_WIFI_SSID + 1]; 29 | char wifi_password[LEN_WIFI_PASSWORD + 1]; 30 | char hostname[LEN_HOSTNAME + 1]; 31 | #ifdef CONFIG_MDNS_ENABLED 32 | char mdns_instance[LEN_MDNS_INSTANCE + 1]; 33 | #endif 34 | #ifdef CONFIG_SNTP_ENABLED 35 | char ntp_server[LEN_NTP_SERVER + 1]; 36 | char timezone[LEN_TIMEZONE + 1]; 37 | #endif 38 | bool dhcp; 39 | uint8_t fps; 40 | bool http_auth; 41 | char http_user[LEN_HTTP_USER + 1]; 42 | char http_password[LEN_HTTP_PASSWORD + 1]; 43 | #if defined(__USE_LWIP_IP_4_ADDR) 44 | ip4_addr_t ip; 45 | ip4_addr_t netmask; 46 | ip4_addr_t gateway; 47 | ip4_addr_t dns1; 48 | ip4_addr_t dns2; 49 | #else 50 | esp_ip4_addr_t ip; 51 | esp_ip4_addr_t netmask; 52 | esp_ip4_addr_t gateway; 53 | esp_ip4_addr_t dns1; 54 | esp_ip4_addr_t dns2; 55 | #endif 56 | } settings; 57 | 58 | void app_settings_save(); 59 | void app_settings_reset(); 60 | void app_settings_startup(); 61 | void app_settings_shutdown(); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /main/app_illuminator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "driver/ledc.h" 5 | #include "esp_log.h" 6 | #include "sdkconfig.h" 7 | #include "app_illuminator.h" 8 | 9 | #ifdef CONFIG_LED_ILLUMINATOR_ENABLED 10 | 11 | static const char *TAG = "Illuminator"; 12 | 13 | void app_illuminator_startup() { 14 | gpio_set_direction(CONFIG_LED_LEDC_PIN,GPIO_MODE_OUTPUT); 15 | ledc_timer_config_t ledc_timer = { 16 | .duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty 17 | .freq_hz = 1000, // frequency of PWM signal 18 | .speed_mode = LEDC_LOW_SPEED_MODE, // timer mode 19 | .timer_num = CONFIG_LED_LEDC_TIMER // timer index 20 | }; 21 | ledc_channel_config_t ledc_channel = { 22 | .channel = CONFIG_LED_LEDC_CHANNEL, 23 | .duty = 0, 24 | .gpio_num = CONFIG_LED_LEDC_PIN, 25 | .speed_mode = LEDC_LOW_SPEED_MODE, 26 | .hpoint = 0, 27 | .timer_sel = CONFIG_LED_LEDC_TIMER 28 | }; 29 | #ifdef CONFIG_LED_LEDC_HIGH_SPEED_MODE 30 | ledc_timer.speed_mode = ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE; 31 | #endif 32 | switch (ledc_timer_config(&ledc_timer)) { 33 | case ESP_ERR_INVALID_ARG: ESP_LOGE(TAG, "ledc_timer_config() parameter error"); break; 34 | case ESP_FAIL: ESP_LOGE(TAG, "ledc_timer_config() Can not find a proper pre-divider number base on the given frequency and the current duty_resolution"); break; 35 | case ESP_OK: if (ledc_channel_config(&ledc_channel) == ESP_ERR_INVALID_ARG) { 36 | ESP_LOGE(TAG, "ledc_channel_config() parameter error"); 37 | } 38 | break; 39 | default: break; 40 | } 41 | } 42 | 43 | void app_illuminator_shutdown() { 44 | ledc_stop(LEDC_LOW_SPEED_MODE,CONFIG_LED_LEDC_CHANNEL,0); 45 | } 46 | 47 | void app_illuminator_set_led_intensity(uint8_t duty) { // Turn LED On or Off 48 | uint8_t _duty = CONFIG_LED_MAX_INTENSITY; 49 | if (duty < _duty) _duty = duty; 50 | 51 | ledc_set_duty(CONFIG_LED_LEDC_SPEED_MODE, CONFIG_LED_LEDC_CHANNEL, _duty); 52 | ledc_update_duty(CONFIG_LED_LEDC_SPEED_MODE, CONFIG_LED_LEDC_CHANNEL); 53 | ESP_LOGI(TAG, "Set LED intensity to %d", _duty); 54 | } 55 | #endif -------------------------------------------------------------------------------- /main/app_main.c: -------------------------------------------------------------------------------- 1 | #include "freertos/FreeRTOS.h" 2 | #include "freertos/event_groups.h" 3 | #include "esp_event.h" 4 | #include "esp_system.h" 5 | #include "esp_log.h" 6 | #include "nvs_flash.h" 7 | #include "sdkconfig.h" 8 | #include "app_settings.h" 9 | #include "app_wifi.h" 10 | #include "app_camera.h" 11 | #include "app_httpd.h" 12 | #include "app_lcd.h" 13 | #ifdef CONFIG_MDNS_ENABLED 14 | #include "mdns.h" 15 | #endif 16 | #ifdef CONFIG_SNTP_ENABLED 17 | //#include "app_sntp.h" 18 | #endif 19 | 20 | EventGroupHandle_t event_group; 21 | 22 | void app_shutdown() { 23 | app_settings_shutdown(); 24 | #ifdef CONFIG_USE_SSD1306_LCD_DRIVER 25 | app_lcd_shutdown(); 26 | #endif 27 | #ifdef CONFIG_LED_ILLUMINATOR_ENABLED 28 | app_illuminator_shutdown(); 29 | #endif 30 | #ifdef CONFIG_MDNS_ENABLED 31 | mdns_free(); 32 | #endif 33 | app_httpd_shutdown(); 34 | app_wifi_shutdown(); 35 | app_camera_shutdown(); 36 | } 37 | 38 | void app_main() 39 | { 40 | EventBits_t uxBits; 41 | 42 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 43 | event_group = xEventGroupCreate(); 44 | 45 | app_settings_startup(); 46 | // app_settings_reset(); 47 | // app_settings_save(); 48 | 49 | app_camera_startup(); 50 | #ifdef CONFIG_LED_ILLUMINATOR_ENABLED 51 | app_illuminator_startup(); 52 | #endif 53 | app_wifi_startup(); 54 | 55 | for (;;) { 56 | uxBits = xEventGroupWaitBits(event_group,WIFI_CONNECTED_BIT | WIFI_SOFTAP_BIT,pdFALSE,pdFALSE,500 / portTICK_PERIOD_MS); 57 | if (uxBits > 0) { 58 | #ifdef CONFIG_SNTP_ENABLED 59 | //app_sntp_startup(); 60 | #endif 61 | #ifdef CONFIG_MDNS_ENABLED 62 | ESP_ERROR_CHECK(mdns_init()); 63 | ESP_ERROR_CHECK(mdns_hostname_set(settings.hostname)); 64 | ESP_ERROR_CHECK(mdns_instance_name_set(settings.mdns_instance)); 65 | mdns_txt_item_t serviceTxtData[1] = { {"path","/"} }; 66 | ESP_ERROR_CHECK( mdns_service_add(settings.mdns_instance, "_http", "_tcp", 80, serviceTxtData, 1) ); 67 | #endif 68 | app_httpd_startup(); 69 | #ifdef CONFIG_USE_SSD1306_LCD_DRIVER 70 | app_lcd_startup(); 71 | #endif 72 | return; 73 | } 74 | } 75 | esp_register_shutdown_handler(&app_shutdown); 76 | } 77 | -------------------------------------------------------------------------------- /main/app_camera.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "esp_system.h" 5 | #include "esp_camera.h" 6 | #include "esp_log.h" 7 | #include "sdkconfig.h" 8 | #include "app_settings.h" 9 | #include "app_camera.h" 10 | 11 | static const char *TAG = "Camera"; 12 | 13 | void app_camera_reset_defaults() { 14 | sensor_t *s = esp_camera_sensor_get(); 15 | if (s != NULL) { 16 | s->set_framesize(s,FRAMESIZE_CIF); 17 | s->set_quality(s,14); 18 | s->set_brightness(s,0); 19 | s->set_contrast(s,0); 20 | s->set_saturation(s,0); 21 | s->set_sharpness(s,0); 22 | s->set_denoise(s,1); 23 | s->set_special_effect(s,0); 24 | s->set_wb_mode(s,0); 25 | s->set_whitebal(s,1); 26 | s->set_awb_gain(s,1); 27 | s->set_exposure_ctrl(s,1); 28 | s->set_aec2(s,1); 29 | s->set_ae_level(s,1); 30 | s->set_aec_value(s,600); 31 | s->set_gain_ctrl(s,1); 32 | s->set_agc_gain(s,15); 33 | s->set_gainceiling(s,GAINCEILING_16X); 34 | s->set_bpc(s,1); 35 | s->set_wpc(s,1); 36 | s->set_raw_gma(s,0); 37 | s->set_lenc(s,1); 38 | s->set_hmirror(s,0); 39 | s->set_vflip(s,0); 40 | s->set_dcw(s,0); 41 | s->set_colorbar(s,0); 42 | } 43 | } 44 | 45 | void app_camera_startup() { 46 | camera_config_t config; 47 | 48 | config.ledc_channel = LEDC_CHANNEL_0; 49 | config.ledc_timer = LEDC_TIMER_0; 50 | config.pin_d0 = Y2_GPIO_NUM; 51 | config.pin_d1 = Y3_GPIO_NUM; 52 | config.pin_d2 = Y4_GPIO_NUM; 53 | config.pin_d3 = Y5_GPIO_NUM; 54 | config.pin_d4 = Y6_GPIO_NUM; 55 | config.pin_d5 = Y7_GPIO_NUM; 56 | config.pin_d6 = Y8_GPIO_NUM; 57 | config.pin_d7 = Y9_GPIO_NUM; 58 | config.pin_xclk = XCLK_GPIO_NUM; 59 | config.pin_pclk = PCLK_GPIO_NUM; 60 | config.pin_vsync = VSYNC_GPIO_NUM; 61 | config.pin_href = HREF_GPIO_NUM; 62 | config.pin_sscb_sda = SIOD_GPIO_NUM; 63 | config.pin_sscb_scl = SIOC_GPIO_NUM; 64 | config.pin_pwdn = PWDN_GPIO_NUM; 65 | config.pin_reset = RESET_GPIO_NUM; 66 | config.xclk_freq_hz = 20000000; 67 | config.pixel_format = PIXFORMAT_JPEG; 68 | config.frame_size = FRAMESIZE_UXGA; //temporary set highest resolution 69 | config.jpeg_quality = 10; //and best quality 70 | config.fb_count = 2; //2 buffers, because esp_camera_init calculates fb size from these values 71 | // check if ^^ will work wo PSRAM - I dont think so 72 | 73 | esp_err_t err = esp_camera_init(&config); 74 | if (err != ESP_OK) { 75 | ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); 76 | return; 77 | } 78 | 79 | app_camera_reset_defaults(); 80 | esp_camera_load_from_nvs("camera"); 81 | } 82 | 83 | void app_camera_shutdown() { 84 | esp_camera_deinit(); 85 | ESP_LOGI(TAG,"Camera deinitialized"); 86 | } 87 | -------------------------------------------------------------------------------- /main/app_lcd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | #include "sdkconfig.h" 8 | #include "esp_log.h" 9 | #include "app_settings.h" 10 | #include "app_wifi.h" 11 | #include "app_httpd.h" 12 | #include "idf_version.h" 13 | #if defined(__USE_LWIP_IP_4_ADDR) 14 | #include 15 | #else 16 | #include 17 | #endif 18 | #include "ssd1306.h" 19 | 20 | /*#define OLED_ADDRESS 0x3c 21 | #define I2C_SDA 14 22 | #define I2C_SCL 13*/ 23 | 24 | static const char *TAG = "LCD"; 25 | 26 | static TaskHandle_t xUpdateLCDTaskHandle = NULL; 27 | 28 | SSD1306_t lcd; 29 | 30 | char lineChar[24]; 31 | 32 | void app_update_lcd_task (void * pvParameters) { 33 | int rssi; 34 | 35 | for (;;) { 36 | ssd1306_clear_screen(&lcd, false); 37 | ssd1306_contrast(&lcd, 0xff); 38 | #if defined(__USE_LWIP_IP_4_ADDR) 39 | ip4addr_ntoa_r(&settings.ip,lineChar,24); 40 | #else 41 | esp_ip4addr_ntoa(&settings.ip,lineChar,24); 42 | #endif 43 | ssd1306_display_text(&lcd,0, lineChar, strlen(lineChar), false); 44 | ssd1306_display_text(&lcd,1, settings.wifi_ssid, strlen(settings.wifi_ssid), false); 45 | rssi = 2 * (wifi_get_rssi() + 100); 46 | sprintf(lineChar,"RSSI: %d%%",rssi); 47 | ssd1306_display_text(&lcd, 2, lineChar, strlen(lineChar), false); 48 | sprintf(lineChar,"FPS: %.1f",avg_fps); 49 | ssd1306_display_text(&lcd,3, lineChar, strlen(lineChar), false); 50 | vTaskDelay(1000 / portTICK_PERIOD_MS); 51 | } 52 | } 53 | 54 | void app_lcd_startup() { 55 | ESP_LOGI(TAG, "Starting up LCD Driver"); 56 | #if CONFIG_I2C_INTERFACE 57 | ESP_LOGI(TAG, "INTERFACE is i2c"); 58 | ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO); 59 | ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO); 60 | ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO); 61 | i2c_master_init(CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO); 62 | #if CONFIG_SSD1306_128x64 63 | ESP_LOGI(TAG, "Panel is 128x64"); 64 | i2c_init(&lcd, 128, 64, 0x3C); 65 | #endif // CONFIG_SSD1306_128x64 66 | #if CONFIG_SSD1306_128x32 67 | ESP_LOGI(TAG, "Panel is 128x32"); 68 | i2c_init(&lcd, 128, 32, 0x3C); 69 | #endif // CONFIG_SSD1306_128x32 70 | #endif // CONFIG_I2C_INTERFACE 71 | 72 | #if CONFIG_SPI_INTERFACE 73 | ESP_LOGI(TAG, "INTERFACE is SPI"); 74 | ESP_LOGI(TAG, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO); 75 | ESP_LOGI(TAG, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO); 76 | ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO); 77 | spi_master_init(&lcd, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO); 78 | spi_init(&lcd, 128, 64); 79 | #endif // CONFIG_SPI_INTERFACE 80 | 81 | ssd1306_clear_screen(&lcd, false); 82 | ssd1306_contrast(&lcd, 0xff); 83 | 84 | xTaskCreate(app_update_lcd_task, "LCD", 2048, NULL, tskIDLE_PRIORITY, &xUpdateLCDTaskHandle ); 85 | } 86 | 87 | void app_lcd_shutdown() { 88 | ESP_LOGI(TAG, "Shutting down lcd driver"); 89 | ssd1306_clear_screen(&lcd, false); 90 | ssd1306_contrast(&lcd, 0xff); 91 | vTaskDelete(xUpdateLCDTaskHandle); 92 | } 93 | -------------------------------------------------------------------------------- /main/include/app_camera.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_CAMERA_H_ 2 | #define _APP_CAMERA_H_ 3 | 4 | #if CONFIG_CAMERA_MODEL_WROVER_KIT 5 | #define PWDN_GPIO_NUM -1 6 | #define RESET_GPIO_NUM -1 7 | #define XCLK_GPIO_NUM 21 8 | #define SIOD_GPIO_NUM 26 9 | #define SIOC_GPIO_NUM 27 10 | 11 | #define Y9_GPIO_NUM 35 12 | #define Y8_GPIO_NUM 34 13 | #define Y7_GPIO_NUM 39 14 | #define Y6_GPIO_NUM 36 15 | #define Y5_GPIO_NUM 19 16 | #define Y4_GPIO_NUM 18 17 | #define Y3_GPIO_NUM 5 18 | #define Y2_GPIO_NUM 4 19 | #define VSYNC_GPIO_NUM 25 20 | #define HREF_GPIO_NUM 23 21 | #define PCLK_GPIO_NUM 22 22 | 23 | #elif CONFIG_CAMERA_MODEL_ESP_EYE 24 | #define PWDN_GPIO_NUM -1 25 | #define RESET_GPIO_NUM -1 26 | #define XCLK_GPIO_NUM 4 27 | #define SIOD_GPIO_NUM 18 28 | #define SIOC_GPIO_NUM 23 29 | 30 | #define Y9_GPIO_NUM 36 31 | #define Y8_GPIO_NUM 37 32 | #define Y7_GPIO_NUM 38 33 | #define Y6_GPIO_NUM 39 34 | #define Y5_GPIO_NUM 35 35 | #define Y4_GPIO_NUM 14 36 | #define Y3_GPIO_NUM 13 37 | #define Y2_GPIO_NUM 34 38 | #define VSYNC_GPIO_NUM 5 39 | #define HREF_GPIO_NUM 27 40 | #define PCLK_GPIO_NUM 25 41 | 42 | #elif CONFIG_CAMERA_MODEL_M5STACK_PSRAM 43 | #define PWDN_GPIO_NUM -1 44 | #define RESET_GPIO_NUM 15 45 | #define XCLK_GPIO_NUM 27 46 | #define SIOD_GPIO_NUM 25 47 | #define SIOC_GPIO_NUM 23 48 | 49 | #define Y9_GPIO_NUM 19 50 | #define Y8_GPIO_NUM 36 51 | #define Y7_GPIO_NUM 18 52 | #define Y6_GPIO_NUM 39 53 | #define Y5_GPIO_NUM 5 54 | #define Y4_GPIO_NUM 34 55 | #define Y3_GPIO_NUM 35 56 | #define Y2_GPIO_NUM 32 57 | #define VSYNC_GPIO_NUM 22 58 | #define HREF_GPIO_NUM 26 59 | #define PCLK_GPIO_NUM 21 60 | 61 | #elif CONFIG_CAMERA_MODEL_M5STACK_WIDE 62 | #define PWDN_GPIO_NUM -1 63 | #define RESET_GPIO_NUM 15 64 | #define XCLK_GPIO_NUM 27 65 | #define SIOD_GPIO_NUM 22 66 | #define SIOC_GPIO_NUM 23 67 | 68 | #define Y9_GPIO_NUM 19 69 | #define Y8_GPIO_NUM 36 70 | #define Y7_GPIO_NUM 18 71 | #define Y6_GPIO_NUM 39 72 | #define Y5_GPIO_NUM 5 73 | #define Y4_GPIO_NUM 34 74 | #define Y3_GPIO_NUM 35 75 | #define Y2_GPIO_NUM 32 76 | #define VSYNC_GPIO_NUM 25 77 | #define HREF_GPIO_NUM 26 78 | #define PCLK_GPIO_NUM 21 79 | 80 | #elif CONFIG_CAMERA_MODEL_AI_THINKER 81 | #define PWDN_GPIO_NUM 32 82 | #define RESET_GPIO_NUM -1 83 | #define XCLK_GPIO_NUM 0 84 | #define SIOD_GPIO_NUM 26 85 | #define SIOC_GPIO_NUM 27 86 | 87 | #define Y9_GPIO_NUM 35 88 | #define Y8_GPIO_NUM 34 89 | #define Y7_GPIO_NUM 39 90 | #define Y6_GPIO_NUM 36 91 | #define Y5_GPIO_NUM 21 92 | #define Y4_GPIO_NUM 19 93 | #define Y3_GPIO_NUM 18 94 | #define Y2_GPIO_NUM 5 95 | #define VSYNC_GPIO_NUM 25 96 | #define HREF_GPIO_NUM 23 97 | #define PCLK_GPIO_NUM 22 98 | 99 | #elif CONFIG_CAMERA_MODEL_TJOURNAL 100 | #define PWDN_GPIO_NUM -1 101 | #define RESET_GPIO_NUM 15 102 | #define XCLK_GPIO_NUM 27 103 | #define SIOD_GPIO_NUM 25 104 | #define SIOC_GPIO_NUM 23 105 | 106 | #define Y9_GPIO_NUM 19 107 | #define Y8_GPIO_NUM 36 108 | #define Y7_GPIO_NUM 18 109 | #define Y6_GPIO_NUM 39 110 | #define Y5_GPIO_NUM 5 111 | #define Y4_GPIO_NUM 34 112 | #define Y3_GPIO_NUM 35 113 | #define Y2_GPIO_NUM 17 114 | 115 | #define VSYNC_GPIO_NUM 22 116 | #define HREF_GPIO_NUM 26 117 | #define PCLK_GPIO_NUM 21 118 | 119 | #elif CONFIG_CAMERA_MODEL_CUSTOM 120 | #define PWDN_GPIO_NUM CONFIG_CAMERA_PIN_PWDN 121 | #define RESET_GPIO_NUM CONFIG_CAMERA_PIN_RESET 122 | #define XCLK_GPIO_NUM CONFIG_CAMERA_PIN_XCLK 123 | #define SIOD_GPIO_NUM CONFIG_CAMERA_PIN_SIOD 124 | #define SIOC_GPIO_NUM CONFIG_CAMERA_PIN_SIOC 125 | 126 | #define Y9_GPIO_NUM CONFIG_CAMERA_PIN_Y9 127 | #define Y8_GPIO_NUM CONFIG_CAMERA_PIN_Y8 128 | #define Y7_GPIO_NUM CONFIG_CAMERA_PIN_Y7 129 | #define Y6_GPIO_NUM CONFIG_CAMERA_PIN_Y6 130 | #define Y5_GPIO_NUM CONFIG_CAMERA_PIN_Y5 131 | #define Y4_GPIO_NUM CONFIG_CAMERA_PIN_Y4 132 | #define Y3_GPIO_NUM CONFIG_CAMERA_PIN_Y3 133 | #define Y2_GPIO_NUM CONFIG_CAMERA_PIN_Y2 134 | #define VSYNC_GPIO_NUM CONFIG_CAMERA_PIN_VSYNC 135 | #define HREF_GPIO_NUM CONFIG_CAMERA_PIN_HREF 136 | #define PCLK_GPIO_NUM CONFIG_CAMERA_PIN_PCLK 137 | #endif 138 | 139 | #ifdef __cplusplus 140 | extern "C" { 141 | #endif 142 | 143 | #ifdef CONFIG_LED_ILLUMINATOR_ENABLED 144 | void app_illuminator_startup(); 145 | void app_illuminator_shutdown(); 146 | #endif 147 | 148 | void app_camera_startup(); 149 | void app_camera_reset(); 150 | void app_camera_shutdown(); 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif -------------------------------------------------------------------------------- /main/app_settings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "esp_log.h" 6 | #include "nvs_flash.h" 7 | #include "nvs.h" 8 | #include "sdkconfig.h" 9 | 10 | #include "idf_version.h" 11 | #if defined(__USE_TCP_ADAPTOR) 12 | #include 13 | #else 14 | #include 15 | #endif 16 | //#include "ssd1306.h" 17 | #include "app_settings.h" 18 | #include "scut.h" 19 | 20 | static const char* TAG = "settings"; 21 | static const char* NVS_KEY = "settings"; 22 | 23 | static void log_settings() { 24 | ESP_LOGI(TAG, " hostname=%s", settings.hostname); 25 | ESP_LOGI(TAG, " wifi_ssid=%s", settings.wifi_ssid); 26 | ESP_LOGI(TAG, " wifi_password=%s", settings.wifi_password); 27 | #ifdef CONFIG_MDNS_ENABLED 28 | ESP_LOGI(TAG, " mdns_instance=%s", settings.mdns_instance); 29 | #endif 30 | #ifdef CONFIG_SNTP_ENABLED 31 | ESP_LOGI(TAG, " ntp_server=%s",settings.ntp_server); 32 | ESP_LOGI(TAG, " timezone=%s",settings.timezone); 33 | #endif 34 | ESP_LOGI(TAG, " dhcp=%u", settings.dhcp); 35 | ESP_LOGI(TAG, " ip=" IPSTR, IP2STR(&settings.ip)); 36 | ESP_LOGI(TAG, " netmask=" IPSTR, IP2STR(&settings.netmask)); 37 | ESP_LOGI(TAG, " gateway=" IPSTR, IP2STR(&settings.gateway)); 38 | ESP_LOGI(TAG, " dns1=" IPSTR, IP2STR(&settings.dns1)); 39 | ESP_LOGI(TAG, " dns2=" IPSTR, IP2STR(&settings.dns2)); 40 | ESP_LOGI(TAG, " fps=%u", settings.fps); 41 | ESP_LOGI(TAG, " auth=%u", settings.http_auth); 42 | ESP_LOGI(TAG, " http_user=%s", settings.http_user); 43 | ESP_LOGI(TAG, " http_password=%s", settings.http_password); 44 | } 45 | 46 | void app_settings_reset() { 47 | nvs_handle_t handle; 48 | 49 | ESP_LOGI(TAG,"Erasing all settings from NVS"); 50 | if (nvs_open(NVS_KEY,NVS_READWRITE,&handle) == ESP_OK) { 51 | nvs_erase_all(handle); 52 | nvs_close(handle); 53 | } 54 | ESP_LOGI(TAG,"Restoring default settings"); 55 | memset(&settings,0,sizeof(settings)); 56 | scut(settings.wifi_ssid, CONFIG_ESP_WIFI_SSID, (((sizeof(settings.wifi_ssid)) >= (sizeof(CONFIG_ESP_WIFI_SSID))) ? (sizeof(CONFIG_ESP_WIFI_SSID)) : (sizeof(settings.wifi_ssid)))); 57 | scut(settings.wifi_password, CONFIG_ESP_WIFI_PASSWORD, (((sizeof(settings.wifi_password)) >= (sizeof(CONFIG_ESP_WIFI_PASSWORD))) ? (sizeof(CONFIG_ESP_WIFI_PASSWORD)) : (sizeof(settings.wifi_password)))); 58 | scut(settings.hostname, CONFIG_LWIP_LOCAL_HOSTNAME, (((sizeof(settings.hostname)) >= (sizeof(CONFIG_LWIP_LOCAL_HOSTNAME))) ? (sizeof(CONFIG_LWIP_LOCAL_HOSTNAME)) : (sizeof(settings.hostname)))); 59 | #ifdef CONFIG_MDNS_ENABLED 60 | scut(settings.mdns_instance, CONFIG_MDNS_INSTANCE, (((sizeof(settings.mdns_instance)) >= (sizeof(CONFIG_MDNS_INSTANCE))) ? (sizeof(CONFIG_MDNS_INSTANCE)) : (sizeof(settings.mdns_instance)))); 61 | #endif 62 | #ifdef CONFIG_SNTP_ENABLED 63 | scut(settings.ntp_server, CONFIG_NTP_SERVER, (((sizeof(settings.ntp_server)) >= (sizeof(CONFIG_NTP_SERVER))) ? (sizeof(CONFIG_NTP_SERVER)) : (sizeof(settings.ntp_server)))); 64 | scut(settings.timezone, CONFIG_TIMEZONE, (((sizeof(settings.timezone)) >= (sizeof(CONFIG_TIMEZONE))) ? (sizeof(CONFIG_TIMEZONE)) : (sizeof(settings.timezone)))); 65 | #endif 66 | settings.dhcp = true; 67 | settings.fps = 0; 68 | #ifdef CONFIG_DEF_HTTP_AUTH_ENABLED 69 | settings.http_auth = true; 70 | scut(settings.http_user, CONFIG_DEF_HTTP_USER, (((sizeof(settings.http_user)) >= (sizeof(CONFIG_DEF_HTTP_USER))) ? (sizeof(CONFIG_DEF_HTTP_USER)) : (sizeof(settings.http_user)))); 71 | scut(settings.http_password, CONFIG_DEF_HTTP_PASSWORD, (((sizeof(settings.http_password)) >= (sizeof(CONFIG_DEF_HTTP_PASSWORD))) ? (sizeof(CONFIG_DEF_HTTP_PASSWORD)) : (sizeof(settings.http_password)))); 72 | #else 73 | settings.http_auth = false; 74 | #endif 75 | } 76 | 77 | void app_settings_save() { 78 | nvs_handle_t handle; 79 | esp_err_t ret; 80 | 81 | ret = nvs_open(NVS_KEY,NVS_READWRITE,&handle); 82 | if (ret == ESP_OK) { 83 | settings.size = sizeof(settings); 84 | ret = nvs_set_blob(handle,"settings",&settings,sizeof(settings)); 85 | if (ret == ESP_OK) { 86 | nvs_commit(handle); 87 | ESP_LOGI(TAG,"Saved settings to NVS"); 88 | log_settings(); 89 | } else { 90 | ESP_LOGE(TAG,"Error (%d) saving settings to NVS",ret); 91 | } 92 | nvs_close(handle); 93 | } else { 94 | ESP_LOGE(TAG,"Error (%d) opening settings",ret); 95 | } 96 | } 97 | 98 | void app_settings_startup() { 99 | nvs_handle_t handle; 100 | 101 | esp_err_t ret = nvs_flash_init(); 102 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 103 | ESP_ERROR_CHECK(nvs_flash_erase()); 104 | ret = nvs_flash_init(); 105 | } 106 | ESP_ERROR_CHECK(ret); 107 | 108 | ESP_LOGI(TAG,"NVS Flash Init"); 109 | 110 | ret = nvs_open(NVS_KEY,NVS_READONLY,&handle); 111 | if (ret == ESP_OK) { 112 | size_t size = sizeof(settings); 113 | ret = nvs_get_blob(handle,"settings",&settings,&size); 114 | if (ret == ESP_OK) { 115 | if (settings.size == sizeof(settings)) { 116 | ESP_LOGI(TAG,"Settings loaded from NVS"); 117 | log_settings(); 118 | } else { 119 | app_settings_reset(); 120 | app_settings_save(); 121 | } 122 | } else { 123 | app_settings_reset(); 124 | app_settings_save(); 125 | } 126 | nvs_close(handle); 127 | } else { 128 | app_settings_reset(); 129 | app_settings_save(); 130 | } 131 | } 132 | 133 | void app_settings_shutdown() { 134 | app_settings_save(); 135 | nvs_flash_deinit(); 136 | } 137 | -------------------------------------------------------------------------------- /main/fonts/Picopixel.h: -------------------------------------------------------------------------------- 1 | // Picopixel by Sebastian Weber. A tiny font 2 | // with all characters within a 6 pixel height. 3 | 4 | const uint8_t PicopixelBitmaps[] = { 5 | 0xE8, 0xB4, 0x57, 0xD5, 0xF5, 0x00, 0x4E, 0x3E, 0x80, 0xA5, 0x4A, 0x4A, 6 | 0x5A, 0x50, 0xC0, 0x6A, 0x40, 0x95, 0x80, 0xAA, 0x80, 0x5D, 0x00, 0x60, 7 | 0xE0, 0x80, 0x25, 0x48, 0x56, 0xD4, 0x75, 0x40, 0xC5, 0x4E, 0xC5, 0x1C, 8 | 0x97, 0x92, 0xF3, 0x1C, 0x53, 0x54, 0xE5, 0x48, 0x55, 0x54, 0x55, 0x94, 9 | 0xA0, 0x46, 0x64, 0xE3, 0x80, 0x98, 0xC5, 0x04, 0x56, 0xC6, 0x57, 0xDA, 10 | 0xD7, 0x5C, 0x72, 0x46, 0xD6, 0xDC, 0xF3, 0xCE, 0xF3, 0x48, 0x72, 0xD4, 11 | 0xB7, 0xDA, 0xF8, 0x24, 0xD4, 0xBB, 0x5A, 0x92, 0x4E, 0x8E, 0xEB, 0x58, 12 | 0x80, 0x9D, 0xB9, 0x90, 0x56, 0xD4, 0xD7, 0x48, 0x56, 0xD4, 0x40, 0xD7, 13 | 0x5A, 0x71, 0x1C, 0xE9, 0x24, 0xB6, 0xD4, 0xB6, 0xA4, 0x8C, 0x6B, 0x55, 14 | 0x00, 0xB5, 0x5A, 0xB5, 0x24, 0xE5, 0x4E, 0xEA, 0xC0, 0x91, 0x12, 0xD5, 15 | 0xC0, 0x54, 0xF0, 0x90, 0xC7, 0xF0, 0x93, 0x5E, 0x71, 0x80, 0x25, 0xDE, 16 | 0x5E, 0x30, 0x6E, 0x80, 0x77, 0x9C, 0x93, 0x5A, 0xB8, 0x45, 0x60, 0x92, 17 | 0xEA, 0xAA, 0x40, 0xD5, 0x6A, 0xD6, 0x80, 0x55, 0x00, 0xD7, 0x40, 0x75, 18 | 0x90, 0xE8, 0x71, 0xE0, 0xBA, 0x40, 0xB5, 0x80, 0xB5, 0x00, 0x8D, 0x54, 19 | 0xAA, 0x80, 0xAC, 0xE0, 0xE5, 0x70, 0x6A, 0x26, 0xFC, 0xC8, 0xAC, 0x5A }; 20 | 21 | const GFXglyph PicopixelGlyphs[] = { 22 | { 0, 0, 0, 2, 0, 1 }, // 0x20 ' ' 23 | { 0, 1, 5, 2, 0, -4 }, // 0x21 '!' 24 | { 1, 3, 2, 4, 0, -4 }, // 0x22 '"' 25 | { 2, 5, 5, 6, 0, -4 }, // 0x23 '#' 26 | { 6, 3, 6, 4, 0, -4 }, // 0x24 '$' 27 | { 9, 3, 5, 4, 0, -4 }, // 0x25 '%' 28 | { 11, 4, 5, 5, 0, -4 }, // 0x26 '&' 29 | { 14, 1, 2, 2, 0, -4 }, // 0x27 ''' 30 | { 15, 2, 5, 3, 0, -4 }, // 0x28 '(' 31 | { 17, 2, 5, 3, 0, -4 }, // 0x29 ')' 32 | { 19, 3, 3, 4, 0, -3 }, // 0x2A '*' 33 | { 21, 3, 3, 4, 0, -3 }, // 0x2B '+' 34 | { 23, 2, 2, 3, 0, 0 }, // 0x2C ',' 35 | { 24, 3, 1, 4, 0, -2 }, // 0x2D '-' 36 | { 25, 1, 1, 2, 0, 0 }, // 0x2E '.' 37 | { 26, 3, 5, 4, 0, -4 }, // 0x2F '/' 38 | { 28, 3, 5, 4, 0, -4 }, // 0x30 '0' 39 | { 30, 2, 5, 3, 0, -4 }, // 0x31 '1' 40 | { 32, 3, 5, 4, 0, -4 }, // 0x32 '2' 41 | { 34, 3, 5, 4, 0, -4 }, // 0x33 '3' 42 | { 36, 3, 5, 4, 0, -4 }, // 0x34 '4' 43 | { 38, 3, 5, 4, 0, -4 }, // 0x35 '5' 44 | { 40, 3, 5, 4, 0, -4 }, // 0x36 '6' 45 | { 42, 3, 5, 4, 0, -4 }, // 0x37 '7' 46 | { 44, 3, 5, 4, 0, -4 }, // 0x38 '8' 47 | { 46, 3, 5, 4, 0, -4 }, // 0x39 '9' 48 | { 48, 1, 3, 2, 0, -3 }, // 0x3A ':' 49 | { 49, 2, 4, 3, 0, -3 }, // 0x3B ';' 50 | { 50, 2, 3, 3, 0, -3 }, // 0x3C '<' 51 | { 51, 3, 3, 4, 0, -3 }, // 0x3D '=' 52 | { 53, 2, 3, 3, 0, -3 }, // 0x3E '>' 53 | { 54, 3, 5, 4, 0, -4 }, // 0x3F '?' 54 | { 56, 3, 5, 4, 0, -4 }, // 0x40 '@' 55 | { 58, 3, 5, 4, 0, -4 }, // 0x41 'A' 56 | { 60, 3, 5, 4, 0, -4 }, // 0x42 'B' 57 | { 62, 3, 5, 4, 0, -4 }, // 0x43 'C' 58 | { 64, 3, 5, 4, 0, -4 }, // 0x44 'D' 59 | { 66, 3, 5, 4, 0, -4 }, // 0x45 'E' 60 | { 68, 3, 5, 4, 0, -4 }, // 0x46 'F' 61 | { 70, 3, 5, 4, 0, -4 }, // 0x47 'G' 62 | { 72, 3, 5, 4, 0, -4 }, // 0x48 'H' 63 | { 74, 1, 5, 2, 0, -4 }, // 0x49 'I' 64 | { 75, 3, 5, 4, 0, -4 }, // 0x4A 'J' 65 | { 77, 3, 5, 4, 0, -4 }, // 0x4B 'K' 66 | { 79, 3, 5, 4, 0, -4 }, // 0x4C 'L' 67 | { 81, 5, 5, 6, 0, -4 }, // 0x4D 'M' 68 | { 85, 4, 5, 5, 0, -4 }, // 0x4E 'N' 69 | { 88, 3, 5, 4, 0, -4 }, // 0x4F 'O' 70 | { 90, 3, 5, 4, 0, -4 }, // 0x50 'P' 71 | { 92, 3, 6, 4, 0, -4 }, // 0x51 'Q' 72 | { 95, 3, 5, 4, 0, -4 }, // 0x52 'R' 73 | { 97, 3, 5, 4, 0, -4 }, // 0x53 'S' 74 | { 99, 3, 5, 4, 0, -4 }, // 0x54 'T' 75 | { 101, 3, 5, 4, 0, -4 }, // 0x55 'U' 76 | { 103, 3, 5, 4, 0, -4 }, // 0x56 'V' 77 | { 105, 5, 5, 6, 0, -4 }, // 0x57 'W' 78 | { 109, 3, 5, 4, 0, -4 }, // 0x58 'X' 79 | { 111, 3, 5, 4, 0, -4 }, // 0x59 'Y' 80 | { 113, 3, 5, 4, 0, -4 }, // 0x5A 'Z' 81 | { 115, 2, 5, 3, 0, -4 }, // 0x5B '[' 82 | { 117, 3, 5, 4, 0, -4 }, // 0x5C '\' 83 | { 119, 2, 5, 3, 0, -4 }, // 0x5D ']' 84 | { 121, 3, 2, 4, 0, -4 }, // 0x5E '^' 85 | { 122, 4, 1, 4, 0, 1 }, // 0x5F '_' 86 | { 123, 2, 2, 3, 0, -4 }, // 0x60 '`' 87 | { 124, 3, 4, 4, 0, -3 }, // 0x61 'a' 88 | { 126, 3, 5, 4, 0, -4 }, // 0x62 'b' 89 | { 128, 3, 3, 4, 0, -2 }, // 0x63 'c' 90 | { 130, 3, 5, 4, 0, -4 }, // 0x64 'd' 91 | { 132, 3, 4, 4, 0, -3 }, // 0x65 'e' 92 | { 134, 2, 5, 3, 0, -4 }, // 0x66 'f' 93 | { 136, 3, 5, 4, 0, -3 }, // 0x67 'g' 94 | { 138, 3, 5, 4, 0, -4 }, // 0x68 'h' 95 | { 140, 1, 5, 2, 0, -4 }, // 0x69 'i' 96 | { 141, 2, 6, 3, 0, -4 }, // 0x6A 'j' 97 | { 143, 3, 5, 4, 0, -4 }, // 0x6B 'k' 98 | { 145, 2, 5, 3, 0, -4 }, // 0x6C 'l' 99 | { 147, 5, 3, 6, 0, -2 }, // 0x6D 'm' 100 | { 149, 3, 3, 4, 0, -2 }, // 0x6E 'n' 101 | { 151, 3, 3, 4, 0, -2 }, // 0x6F 'o' 102 | { 153, 3, 4, 4, 0, -2 }, // 0x70 'p' 103 | { 155, 3, 4, 4, 0, -2 }, // 0x71 'q' 104 | { 157, 2, 3, 3, 0, -2 }, // 0x72 'r' 105 | { 158, 3, 4, 4, 0, -3 }, // 0x73 's' 106 | { 160, 2, 5, 3, 0, -4 }, // 0x74 't' 107 | { 162, 3, 3, 4, 0, -2 }, // 0x75 'u' 108 | { 164, 3, 3, 4, 0, -2 }, // 0x76 'v' 109 | { 166, 5, 3, 6, 0, -2 }, // 0x77 'w' 110 | { 168, 3, 3, 4, 0, -2 }, // 0x78 'x' 111 | { 170, 3, 4, 4, 0, -2 }, // 0x79 'y' 112 | { 172, 3, 4, 4, 0, -3 }, // 0x7A 'z' 113 | { 174, 3, 5, 4, 0, -4 }, // 0x7B '{' 114 | { 176, 1, 6, 2, 0, -4 }, // 0x7C '|' 115 | { 177, 3, 5, 4, 0, -4 }, // 0x7D '}' 116 | { 179, 4, 2, 5, 0, -3 } }; // 0x7E '~' 117 | 118 | const GFXfont Picopixel = { 119 | (uint8_t *)PicopixelBitmaps, 120 | (GFXglyph *)PicopixelGlyphs, 121 | 0x20, 0x7E, 7 }; 122 | 123 | // Approx. 852 bytes 124 | -------------------------------------------------------------------------------- /main/fonts/Tiny3x3a2pt7b.h: -------------------------------------------------------------------------------- 1 | /** 2 | ** The FontStruction “Tiny3x3a” 3 | ** (https://fontstruct.com/fontstructions/show/670512) by “Michaelangel007” is 4 | ** licensed under a Creative Commons Attribution Non-commercial Share Alike license 5 | ** (http://creativecommons.org/licenses/by-nc-sa/3.0/). 6 | ** “Tiny3x3a” was originally cloned (copied) from the FontStruction 7 | ** “CHECKER” (https://fontstruct.com/fontstructions/show/2391) by Wolf grant 8 | ** Grant, which is licensed under a Creative Commons Attribution Non-commercial 9 | ** Share Alike license (http://creativecommons.org/licenses/by-nc-sa/3.0/). 10 | * 11 | * Converted by eadmaster with fontconvert 12 | **/ 13 | 14 | const uint8_t Tiny3x3a2pt7bBitmaps[] = { 15 | 0xC0, 0xB4, 0xBF, 0x80, 0x6B, 0x00, 0xDD, 0x80, 0x59, 0x80, 0x80, 0x64, 16 | 0x98, 0xF0, 0x5D, 0x00, 0xC0, 0xE0, 0x80, 0x2A, 0x00, 0x55, 0x00, 0x94, 17 | 0xC9, 0x80, 0xEF, 0x80, 0xBC, 0x80, 0x6B, 0x00, 0x9F, 0x80, 0xE4, 0x80, 18 | 0x7F, 0x00, 0xFC, 0x80, 0xA0, 0x58, 0x64, 0xE3, 0x80, 0x98, 0xD8, 0xD8, 19 | 0x80, 0x5E, 0x80, 0xDF, 0x80, 0x71, 0x80, 0xD7, 0x00, 0xFB, 0x80, 0xFA, 20 | 0x00, 0xD7, 0x80, 0xBE, 0x80, 0xE0, 0x27, 0x00, 0xBA, 0x80, 0x93, 0x80, 21 | 0xFE, 0x80, 0xF6, 0x80, 0xF7, 0x80, 0xFE, 0x00, 0xF7, 0x00, 0xDE, 0x80, 22 | 0x6B, 0x00, 0xE9, 0x00, 0xB7, 0x80, 0xB5, 0x00, 0xBF, 0x80, 0xAA, 0x80, 23 | 0xA9, 0x00, 0xEB, 0x80, 0xEC, 0x88, 0x80, 0xDC, 0x54, 0xE0, 0x90, 0x70, 24 | 0xBC, 0xF0, 0x7C, 0xB0, 0x68, 0xFC, 0xBC, 0xC0, 0x58, 0x9A, 0x80, 0xA4, 25 | 0xDC, 0xD4, 0xF0, 0xF8, 0xF4, 0xE0, 0x60, 0x59, 0x80, 0xBC, 0xA8, 0xEC, 26 | 0xF0, 0xAC, 0x80, 0x90, 0x79, 0x80, 0xF0, 0xCF, 0x00, 0x78 }; 27 | 28 | const GFXglyph Tiny3x3a2pt7bGlyphs[] = { 29 | { 0, 0, 0, 4, 0, 1 }, // 0x20 ' ' 30 | { 0, 1, 2, 3, 1, -2 }, // 0x21 '!' 31 | { 1, 3, 2, 4, 0, -2 }, // 0x22 '"' 32 | { 2, 3, 3, 4, 0, -2 }, // 0x23 '#' 33 | { 4, 3, 3, 4, 0, -2 }, // 0x24 '$' 34 | { 6, 3, 3, 4, 0, -2 }, // 0x25 '%' 35 | { 8, 3, 3, 4, 0, -2 }, // 0x26 '&' 36 | { 10, 1, 1, 3, 1, -2 }, // 0x27 ''' 37 | { 11, 2, 3, 3, 0, -2 }, // 0x28 '(' 38 | { 12, 2, 3, 4, 1, -2 }, // 0x29 ')' 39 | { 13, 2, 2, 4, 1, -2 }, // 0x2A '*' 40 | { 14, 3, 3, 4, 0, -2 }, // 0x2B '+' 41 | { 16, 1, 2, 2, 0, 0 }, // 0x2C ',' 42 | { 17, 3, 1, 4, 0, -1 }, // 0x2D '-' 43 | { 18, 1, 1, 2, 0, 0 }, // 0x2E '.' 44 | { 19, 3, 3, 4, 0, -2 }, // 0x2F '/' 45 | { 21, 3, 3, 4, 0, -2 }, // 0x30 '0' 46 | { 23, 2, 3, 3, 0, -2 }, // 0x31 '1' 47 | { 24, 3, 3, 4, 0, -2 }, // 0x32 '2' 48 | { 26, 3, 3, 4, 0, -2 }, // 0x33 '3' 49 | { 28, 3, 3, 4, 0, -2 }, // 0x34 '4' 50 | { 30, 3, 3, 4, 0, -2 }, // 0x35 '5' 51 | { 32, 3, 3, 4, 0, -2 }, // 0x36 '6' 52 | { 34, 3, 3, 4, 0, -2 }, // 0x37 '7' 53 | { 36, 3, 3, 4, 0, -2 }, // 0x38 '8' 54 | { 38, 3, 3, 4, 0, -2 }, // 0x39 '9' 55 | { 40, 1, 3, 3, 1, -2 }, // 0x3A ':' 56 | { 41, 2, 3, 3, 0, -1 }, // 0x3B ';' 57 | { 42, 2, 3, 3, 0, -2 }, // 0x3C '<' 58 | { 43, 3, 3, 4, 0, -2 }, // 0x3D '=' 59 | { 45, 2, 3, 4, 1, -2 }, // 0x3E '>' 60 | { 46, 2, 3, 4, 1, -2 }, // 0x3F '?' 61 | { 47, 3, 3, 4, 0, -2 }, // 0x40 '@' 62 | { 49, 3, 3, 4, 0, -2 }, // 0x41 'A' 63 | { 51, 3, 3, 4, 0, -2 }, // 0x42 'B' 64 | { 53, 3, 3, 4, 0, -2 }, // 0x43 'C' 65 | { 55, 3, 3, 4, 0, -2 }, // 0x44 'D' 66 | { 57, 3, 3, 4, 0, -2 }, // 0x45 'E' 67 | { 59, 3, 3, 4, 0, -2 }, // 0x46 'F' 68 | { 61, 3, 3, 4, 0, -2 }, // 0x47 'G' 69 | { 63, 3, 3, 4, 0, -2 }, // 0x48 'H' 70 | { 65, 1, 3, 3, 1, -2 }, // 0x49 'I' 71 | { 66, 3, 3, 4, 0, -2 }, // 0x4A 'J' 72 | { 68, 3, 3, 4, 0, -2 }, // 0x4B 'K' 73 | { 70, 3, 3, 4, 0, -2 }, // 0x4C 'L' 74 | { 72, 3, 3, 4, 0, -2 }, // 0x4D 'M' 75 | { 74, 3, 3, 4, 0, -2 }, // 0x4E 'N' 76 | { 76, 3, 3, 4, 0, -2 }, // 0x4F 'O' 77 | { 78, 3, 3, 4, 0, -2 }, // 0x50 'P' 78 | { 80, 3, 3, 4, 0, -2 }, // 0x51 'Q' 79 | { 82, 3, 3, 4, 0, -2 }, // 0x52 'R' 80 | { 84, 3, 3, 4, 0, -2 }, // 0x53 'S' 81 | { 86, 3, 3, 4, 0, -2 }, // 0x54 'T' 82 | { 88, 3, 3, 4, 0, -2 }, // 0x55 'U' 83 | { 90, 3, 3, 4, 0, -2 }, // 0x56 'V' 84 | { 92, 3, 3, 4, 0, -2 }, // 0x57 'W' 85 | { 94, 3, 3, 4, 0, -2 }, // 0x58 'X' 86 | { 96, 3, 3, 4, 0, -2 }, // 0x59 'Y' 87 | { 98, 3, 3, 4, 0, -2 }, // 0x5A 'Z' 88 | { 100, 2, 3, 3, 0, -2 }, // 0x5B '[' 89 | { 101, 3, 3, 4, 0, -2 }, // 0x5C '\' 90 | { 103, 2, 3, 4, 1, -2 }, // 0x5D ']' 91 | { 104, 3, 2, 4, 0, -2 }, // 0x5E '^' 92 | { 105, 3, 1, 4, 0, 0 }, // 0x5F '_' 93 | { 106, 2, 2, 3, 0, -2 }, // 0x60 '`' 94 | { 107, 2, 2, 3, 0, -1 }, // 0x61 'a' 95 | { 108, 2, 3, 3, 0, -2 }, // 0x62 'b' 96 | { 109, 2, 2, 3, 0, -1 }, // 0x63 'c' 97 | { 110, 2, 3, 3, 0, -2 }, // 0x64 'd' 98 | { 111, 2, 2, 3, 0, -1 }, // 0x65 'e' 99 | { 112, 2, 3, 3, 0, -2 }, // 0x66 'f' 100 | { 113, 2, 3, 3, 0, -1 }, // 0x67 'g' 101 | { 114, 2, 3, 3, 0, -2 }, // 0x68 'h' 102 | { 115, 1, 2, 2, 0, -1 }, // 0x69 'i' 103 | { 116, 2, 3, 3, 0, -1 }, // 0x6A 'j' 104 | { 117, 3, 3, 4, 0, -2 }, // 0x6B 'k' 105 | { 119, 2, 3, 3, 0, -2 }, // 0x6C 'l' 106 | { 120, 3, 2, 4, 0, -1 }, // 0x6D 'm' 107 | { 121, 3, 2, 4, 0, -1 }, // 0x6E 'n' 108 | { 122, 2, 2, 3, 0, -1 }, // 0x6F 'o' 109 | { 123, 2, 3, 3, 0, -1 }, // 0x70 'p' 110 | { 124, 2, 3, 3, 0, -1 }, // 0x71 'q' 111 | { 125, 2, 2, 3, 0, -1 }, // 0x72 'r' 112 | { 126, 2, 2, 3, 0, -1 }, // 0x73 's' 113 | { 127, 3, 3, 4, 0, -2 }, // 0x74 't' 114 | { 129, 3, 2, 4, 0, -1 }, // 0x75 'u' 115 | { 130, 3, 2, 4, 0, -1 }, // 0x76 'v' 116 | { 131, 3, 2, 4, 0, -1 }, // 0x77 'w' 117 | { 132, 2, 2, 3, 0, -1 }, // 0x78 'x' 118 | { 133, 3, 3, 4, 0, -1 }, // 0x79 'y' 119 | { 135, 2, 2, 3, 0, -1 }, // 0x7A 'z' 120 | { 136, 3, 3, 4, 0, -2 }, // 0x7B '{' 121 | { 138, 1, 4, 3, 1, -2 }, // 0x7C '|' 122 | { 139, 3, 3, 4, 0, -2 }, // 0x7D '}' 123 | { 141, 3, 2, 4, 0, -2 } }; // 0x7E '~' 124 | 125 | const GFXfont Tiny3x3a2pt7b = { 126 | (uint8_t *)Tiny3x3a2pt7bBitmaps, 127 | (GFXglyph *)Tiny3x3a2pt7bGlyphs, 128 | 0x20, 0x7E, 4 }; 129 | 130 | // Approx. 814 bytes 131 | -------------------------------------------------------------------------------- /main/www/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial,Helvetica,sans-serif; 3 | background: #181818; 4 | color: #EFEFEF; 5 | font-size: 16px 6 | } 7 | 8 | section#main { 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | 13 | section#header { 14 | min-width: 342px; 15 | background-color: #363636; 16 | margin-bottom: 6px; 17 | padding: 4px 12px; 18 | display: flex; 19 | flex-wrap: wrap; 20 | border-radius: 4px; 21 | justify-content: space-between; 22 | } 23 | 24 | section#content { 25 | display: flex; 26 | flex-wrap: wrap; 27 | align-items: stretch 28 | } 29 | 30 | section#sidebar { 31 | display: flex; 32 | flex-direction: column; 33 | } 34 | 35 | nav#maintoolbar { 36 | display: flex; 37 | flex-wrap: nowrap; 38 | justify-content: flex-end; 39 | } 40 | 41 | nav#sidetoolbar { 42 | display: flex; 43 | flex-direction: column; 44 | } 45 | 46 | nav.menu { 47 | display: none; 48 | flex-direction: column; 49 | flex-wrap: nowrap; 50 | min-width: 350px; 51 | background: #363636; 52 | padding: 8px; 53 | border-radius: 4px; 54 | margin-top: -10px; 55 | margin-right: 10px; 56 | margin-bottom: 10px; 57 | } 58 | 59 | figure { 60 | padding: 0px; 61 | margin: 0; 62 | -webkit-margin-before: 0; 63 | margin-block-start: 0; 64 | -webkit-margin-after: 0; 65 | margin-block-end: 0; 66 | -webkit-margin-start: 0; 67 | margin-inline-start: 0; 68 | -webkit-margin-end: 0; 69 | margin-inline-end: 0 70 | } 71 | 72 | figure img { 73 | display: block; 74 | width: 100%; 75 | height: auto; 76 | border-radius: 4px; 77 | margin-top: 8px; 78 | } 79 | 80 | @media (min-width: 800px) and (orientation:landscape) { 81 | section#content { 82 | display:flex; 83 | flex-wrap: nowrap; 84 | align-items: stretch 85 | } 86 | 87 | figure img { 88 | display: block; 89 | max-width: 100%; 90 | max-height: calc(100vh - 40px); 91 | width: auto; 92 | height: auto 93 | } 94 | 95 | figure { 96 | padding: 0 0 0 0px; 97 | margin: 0; 98 | -webkit-margin-before: 0; 99 | margin-block-start: 0; 100 | -webkit-margin-after: 0; 101 | margin-block-end: 0; 102 | -webkit-margin-start: 0; 103 | margin-inline-start: 0; 104 | -webkit-margin-end: 0; 105 | margin-inline-end: 0 106 | } 107 | } 108 | 109 | .settings-label { 110 | height: 36px; 111 | } 112 | 113 | .nav-toggle { 114 | cursor: pointer; 115 | display: block; 116 | } 117 | 118 | .nav-toggle-cb { 119 | height: 12px; 120 | display: none; 121 | outline: 0; 122 | opacity: 0; 123 | width: 0; 124 | } 125 | 126 | #nav-toggle-basic-cb:checked+#basic-menu, 127 | #nav-toggle-network-cb:checked+#network-menu, 128 | #nav-toggle-adv-cb:checked+#adv-menu { 129 | display: flex; 130 | } 131 | 132 | .input-group { 133 | display: flex; 134 | flex-wrap: nowrap; 135 | line-height: 22px; 136 | margin: 5px 0 137 | } 138 | 139 | .input-group>label { 140 | display: inline-block; 141 | padding-right: 10px; 142 | min-width: 38% 143 | } 144 | 145 | .input-group>output { 146 | min-width: 25px; 147 | padding: 0 5px; 148 | } 149 | 150 | .input-group input,.input-group select { 151 | flex-grow: 1 152 | } 153 | 154 | .range-max,.range-min { 155 | display: inline-block; 156 | padding: 0 5px 157 | } 158 | 159 | button, .button { 160 | display: block; 161 | margin: 5px; 162 | padding: 8px 12px; 163 | border: 0; 164 | line-height: 16px; 165 | cursor: pointer; 166 | color: #fff; 167 | background: #3034ff; 168 | border-radius: 5px; 169 | font-size: 16px; 170 | outline: 0 171 | } 172 | 173 | button:hover { 174 | background: #494dff 175 | } 176 | 177 | button:active { 178 | background: #1c21f2 179 | } 180 | 181 | button.disabled { 182 | cursor: default; 183 | background: #a0a0a0 184 | } 185 | 186 | input[type=range] { 187 | -webkit-appearance: none; 188 | width: 100%; 189 | height: 22px; 190 | background: #363636; 191 | cursor: pointer; 192 | margin: 0 193 | } 194 | 195 | input[type=range]:focus { 196 | outline: 0 197 | } 198 | 199 | input[type=range]::-webkit-slider-runnable-track { 200 | width: 100%; 201 | height: 2px; 202 | cursor: pointer; 203 | background: #EFEFEF; 204 | border-radius: 0; 205 | border: 0 solid #EFEFEF 206 | } 207 | 208 | input[type=range]::-webkit-slider-thumb { 209 | border: 1px solid rgba(0,0,30,0); 210 | height: 22px; 211 | width: 22px; 212 | border-radius: 50px; 213 | background: #3034ff; 214 | cursor: pointer; 215 | -webkit-appearance: none; 216 | margin-top: -11.5px 217 | } 218 | 219 | input[type=range]:focus::-webkit-slider-runnable-track { 220 | background: #EFEFEF 221 | } 222 | 223 | input[type=range]::-moz-range-track { 224 | width: 100%; 225 | height: 2px; 226 | cursor: pointer; 227 | background: #EFEFEF; 228 | border-radius: 0; 229 | border: 0 solid #EFEFEF 230 | } 231 | 232 | input[type=range]::-moz-range-thumb { 233 | border: 1px solid rgba(0,0,30,0); 234 | height: 22px; 235 | width: 22px; 236 | border-radius: 50px; 237 | background: #3034ff; 238 | cursor: pointer 239 | } 240 | 241 | input[type=range]::-ms-track { 242 | width: 100%; 243 | height: 2px; 244 | cursor: pointer; 245 | background: 0 0; 246 | border-color: transparent; 247 | color: transparent 248 | } 249 | 250 | input[type=range]::-ms-fill-lower { 251 | background: #EFEFEF; 252 | border: 0 solid #EFEFEF; 253 | border-radius: 0 254 | } 255 | 256 | input[type=range]::-ms-fill-upper { 257 | background: #EFEFEF; 258 | border: 0 solid #EFEFEF; 259 | border-radius: 0 260 | } 261 | 262 | input[type=range]::-ms-thumb { 263 | border: 1px solid rgba(0,0,30,0); 264 | height: 22px; 265 | width: 22px; 266 | border-radius: 50px; 267 | background: #3034ff; 268 | cursor: pointer; 269 | height: 2px 270 | } 271 | 272 | input[type=range]:focus::-ms-fill-lower { 273 | background: #EFEFEF 274 | } 275 | 276 | input[type=range]:focus::-ms-fill-upper { 277 | background: #363636 278 | } 279 | 280 | input[type=text], input[type=password] { 281 | border: 1px solid #363636; 282 | font-size: 14px; 283 | height: 20px; 284 | width: 20px; /* ??? */ 285 | margin: 1px; 286 | outline: 0; 287 | border-radius: 5px 288 | } 289 | 290 | .inline-button { 291 | line-height: 20px; 292 | margin: 2px; 293 | padding: 1px 4px 2px 4px; 294 | } 295 | 296 | .switch { 297 | display: block; 298 | position: relative; 299 | line-height: 22px; 300 | font-size: 16px; 301 | height: 22px 302 | } 303 | 304 | .switch input { 305 | outline: 0; 306 | opacity: 0; 307 | width: 0; 308 | height: 0 309 | } 310 | 311 | .slider { 312 | width: 50px; 313 | height: 22px; 314 | border-radius: 22px; 315 | cursor: pointer; 316 | background-color: grey 317 | } 318 | 319 | .slider,.slider:before { 320 | display: inline-block; 321 | transition: .4s 322 | } 323 | 324 | .slider:before { 325 | position: relative; 326 | content: ""; 327 | border-radius: 50%; 328 | height: 16px; 329 | width: 16px; 330 | left: 4px; 331 | top: 3px; 332 | background-color: #fff 333 | } 334 | 335 | input:checked+.slider { 336 | background-color: #3034ff 337 | } 338 | 339 | input:checked+.slider:before { 340 | -webkit-transform: translateX(26px); 341 | transform: translateX(26px) 342 | } 343 | 344 | select { 345 | border: 1px solid #363636; 346 | font-size: 14px; 347 | height: 22px; 348 | outline: 0; 349 | border-radius: 5px 350 | } 351 | 352 | .image-container { 353 | position: relative; 354 | min-width: 160px 355 | } 356 | 357 | .hidden { 358 | display: none 359 | } -------------------------------------------------------------------------------- /main/fonts/Org_01.h: -------------------------------------------------------------------------------- 1 | // Org_v01 by Orgdot (www.orgdot.com/aliasfonts). A tiny, 2 | // stylized font with all characters within a 6 pixel height. 3 | 4 | const uint8_t Org_01Bitmaps[] = { 5 | 0xE8, 0xA0, 0x57, 0xD5, 0xF5, 0x00, 0xFD, 0x3E, 0x5F, 0x80, 0x88, 0x88, 6 | 0x88, 0x80, 0xF4, 0xBF, 0x2E, 0x80, 0x80, 0x6A, 0x40, 0x95, 0x80, 0xAA, 7 | 0x80, 0x5D, 0x00, 0xC0, 0xF0, 0x80, 0x08, 0x88, 0x88, 0x00, 0xFC, 0x63, 8 | 0x1F, 0x80, 0xF8, 0xF8, 0x7F, 0x0F, 0x80, 0xF8, 0x7E, 0x1F, 0x80, 0x8C, 9 | 0x7E, 0x10, 0x80, 0xFC, 0x3E, 0x1F, 0x80, 0xFC, 0x3F, 0x1F, 0x80, 0xF8, 10 | 0x42, 0x10, 0x80, 0xFC, 0x7F, 0x1F, 0x80, 0xFC, 0x7E, 0x1F, 0x80, 0x90, 11 | 0xB0, 0x2A, 0x22, 0xF0, 0xF0, 0x88, 0xA8, 0xF8, 0x4E, 0x02, 0x00, 0xFD, 12 | 0x6F, 0x0F, 0x80, 0xFC, 0x7F, 0x18, 0x80, 0xF4, 0x7D, 0x1F, 0x00, 0xFC, 13 | 0x21, 0x0F, 0x80, 0xF4, 0x63, 0x1F, 0x00, 0xFC, 0x3F, 0x0F, 0x80, 0xFC, 14 | 0x3F, 0x08, 0x00, 0xFC, 0x2F, 0x1F, 0x80, 0x8C, 0x7F, 0x18, 0x80, 0xF9, 15 | 0x08, 0x4F, 0x80, 0x78, 0x85, 0x2F, 0x80, 0x8D, 0xB1, 0x68, 0x80, 0x84, 16 | 0x21, 0x0F, 0x80, 0xFD, 0x6B, 0x5A, 0x80, 0xFC, 0x63, 0x18, 0x80, 0xFC, 17 | 0x63, 0x1F, 0x80, 0xFC, 0x7F, 0x08, 0x00, 0xFC, 0x63, 0x3F, 0x80, 0xFC, 18 | 0x7F, 0x29, 0x00, 0xFC, 0x3E, 0x1F, 0x80, 0xF9, 0x08, 0x42, 0x00, 0x8C, 19 | 0x63, 0x1F, 0x80, 0x8C, 0x62, 0xA2, 0x00, 0xAD, 0x6B, 0x5F, 0x80, 0x8A, 20 | 0x88, 0xA8, 0x80, 0x8C, 0x54, 0x42, 0x00, 0xF8, 0x7F, 0x0F, 0x80, 0xEA, 21 | 0xC0, 0x82, 0x08, 0x20, 0x80, 0xD5, 0xC0, 0x54, 0xF8, 0x80, 0xF1, 0xFF, 22 | 0x8F, 0x99, 0xF0, 0xF8, 0x8F, 0x1F, 0x99, 0xF0, 0xFF, 0x8F, 0x6B, 0xA4, 23 | 0xF9, 0x9F, 0x10, 0x8F, 0x99, 0x90, 0xF0, 0x55, 0xC0, 0x8A, 0xF9, 0x90, 24 | 0xF8, 0xFD, 0x63, 0x10, 0xF9, 0x99, 0xF9, 0x9F, 0xF9, 0x9F, 0x80, 0xF9, 25 | 0x9F, 0x20, 0xF8, 0x88, 0x47, 0x1F, 0x27, 0xC8, 0x42, 0x00, 0x99, 0x9F, 26 | 0x99, 0x97, 0x8C, 0x6B, 0xF0, 0x96, 0x69, 0x99, 0x9F, 0x10, 0x2E, 0x8F, 27 | 0x2B, 0x22, 0xF8, 0x89, 0xA8, 0x0F, 0xE0 }; 28 | 29 | const GFXglyph Org_01Glyphs[] = { 30 | { 0, 0, 0, 6, 0, 1 }, // 0x20 ' ' 31 | { 0, 1, 5, 2, 0, -4 }, // 0x21 '!' 32 | { 1, 3, 1, 4, 0, -4 }, // 0x22 '"' 33 | { 2, 5, 5, 6, 0, -4 }, // 0x23 '#' 34 | { 6, 5, 5, 6, 0, -4 }, // 0x24 '$' 35 | { 10, 5, 5, 6, 0, -4 }, // 0x25 '%' 36 | { 14, 5, 5, 6, 0, -4 }, // 0x26 '&' 37 | { 18, 1, 1, 2, 0, -4 }, // 0x27 ''' 38 | { 19, 2, 5, 3, 0, -4 }, // 0x28 '(' 39 | { 21, 2, 5, 3, 0, -4 }, // 0x29 ')' 40 | { 23, 3, 3, 4, 0, -3 }, // 0x2A '*' 41 | { 25, 3, 3, 4, 0, -3 }, // 0x2B '+' 42 | { 27, 1, 2, 2, 0, 0 }, // 0x2C ',' 43 | { 28, 4, 1, 5, 0, -2 }, // 0x2D '-' 44 | { 29, 1, 1, 2, 0, 0 }, // 0x2E '.' 45 | { 30, 5, 5, 6, 0, -4 }, // 0x2F '/' 46 | { 34, 5, 5, 6, 0, -4 }, // 0x30 '0' 47 | { 38, 1, 5, 2, 0, -4 }, // 0x31 '1' 48 | { 39, 5, 5, 6, 0, -4 }, // 0x32 '2' 49 | { 43, 5, 5, 6, 0, -4 }, // 0x33 '3' 50 | { 47, 5, 5, 6, 0, -4 }, // 0x34 '4' 51 | { 51, 5, 5, 6, 0, -4 }, // 0x35 '5' 52 | { 55, 5, 5, 6, 0, -4 }, // 0x36 '6' 53 | { 59, 5, 5, 6, 0, -4 }, // 0x37 '7' 54 | { 63, 5, 5, 6, 0, -4 }, // 0x38 '8' 55 | { 67, 5, 5, 6, 0, -4 }, // 0x39 '9' 56 | { 71, 1, 4, 2, 0, -3 }, // 0x3A ':' 57 | { 72, 1, 4, 2, 0, -3 }, // 0x3B ';' 58 | { 73, 3, 5, 4, 0, -4 }, // 0x3C '<' 59 | { 75, 4, 3, 5, 0, -3 }, // 0x3D '=' 60 | { 77, 3, 5, 4, 0, -4 }, // 0x3E '>' 61 | { 79, 5, 5, 6, 0, -4 }, // 0x3F '?' 62 | { 83, 5, 5, 6, 0, -4 }, // 0x40 '@' 63 | { 87, 5, 5, 6, 0, -4 }, // 0x41 'A' 64 | { 91, 5, 5, 6, 0, -4 }, // 0x42 'B' 65 | { 95, 5, 5, 6, 0, -4 }, // 0x43 'C' 66 | { 99, 5, 5, 6, 0, -4 }, // 0x44 'D' 67 | { 103, 5, 5, 6, 0, -4 }, // 0x45 'E' 68 | { 107, 5, 5, 6, 0, -4 }, // 0x46 'F' 69 | { 111, 5, 5, 6, 0, -4 }, // 0x47 'G' 70 | { 115, 5, 5, 6, 0, -4 }, // 0x48 'H' 71 | { 119, 5, 5, 6, 0, -4 }, // 0x49 'I' 72 | { 123, 5, 5, 6, 0, -4 }, // 0x4A 'J' 73 | { 127, 5, 5, 6, 0, -4 }, // 0x4B 'K' 74 | { 131, 5, 5, 6, 0, -4 }, // 0x4C 'L' 75 | { 135, 5, 5, 6, 0, -4 }, // 0x4D 'M' 76 | { 139, 5, 5, 6, 0, -4 }, // 0x4E 'N' 77 | { 143, 5, 5, 6, 0, -4 }, // 0x4F 'O' 78 | { 147, 5, 5, 6, 0, -4 }, // 0x50 'P' 79 | { 151, 5, 5, 6, 0, -4 }, // 0x51 'Q' 80 | { 155, 5, 5, 6, 0, -4 }, // 0x52 'R' 81 | { 159, 5, 5, 6, 0, -4 }, // 0x53 'S' 82 | { 163, 5, 5, 6, 0, -4 }, // 0x54 'T' 83 | { 167, 5, 5, 6, 0, -4 }, // 0x55 'U' 84 | { 171, 5, 5, 6, 0, -4 }, // 0x56 'V' 85 | { 175, 5, 5, 6, 0, -4 }, // 0x57 'W' 86 | { 179, 5, 5, 6, 0, -4 }, // 0x58 'X' 87 | { 183, 5, 5, 6, 0, -4 }, // 0x59 'Y' 88 | { 187, 5, 5, 6, 0, -4 }, // 0x5A 'Z' 89 | { 191, 2, 5, 3, 0, -4 }, // 0x5B '[' 90 | { 193, 5, 5, 6, 0, -4 }, // 0x5C '\' 91 | { 197, 2, 5, 3, 0, -4 }, // 0x5D ']' 92 | { 199, 3, 2, 4, 0, -4 }, // 0x5E '^' 93 | { 200, 5, 1, 6, 0, 1 }, // 0x5F '_' 94 | { 201, 1, 1, 2, 0, -4 }, // 0x60 '`' 95 | { 202, 4, 4, 5, 0, -3 }, // 0x61 'a' 96 | { 204, 4, 5, 5, 0, -4 }, // 0x62 'b' 97 | { 207, 4, 4, 5, 0, -3 }, // 0x63 'c' 98 | { 209, 4, 5, 5, 0, -4 }, // 0x64 'd' 99 | { 212, 4, 4, 5, 0, -3 }, // 0x65 'e' 100 | { 214, 3, 5, 4, 0, -4 }, // 0x66 'f' 101 | { 216, 4, 5, 5, 0, -3 }, // 0x67 'g' 102 | { 219, 4, 5, 5, 0, -4 }, // 0x68 'h' 103 | { 222, 1, 4, 2, 0, -3 }, // 0x69 'i' 104 | { 223, 2, 5, 3, 0, -3 }, // 0x6A 'j' 105 | { 225, 4, 5, 5, 0, -4 }, // 0x6B 'k' 106 | { 228, 1, 5, 2, 0, -4 }, // 0x6C 'l' 107 | { 229, 5, 4, 6, 0, -3 }, // 0x6D 'm' 108 | { 232, 4, 4, 5, 0, -3 }, // 0x6E 'n' 109 | { 234, 4, 4, 5, 0, -3 }, // 0x6F 'o' 110 | { 236, 4, 5, 5, 0, -3 }, // 0x70 'p' 111 | { 239, 4, 5, 5, 0, -3 }, // 0x71 'q' 112 | { 242, 4, 4, 5, 0, -3 }, // 0x72 'r' 113 | { 244, 4, 4, 5, 0, -3 }, // 0x73 's' 114 | { 246, 5, 5, 6, 0, -4 }, // 0x74 't' 115 | { 250, 4, 4, 5, 0, -3 }, // 0x75 'u' 116 | { 252, 4, 4, 5, 0, -3 }, // 0x76 'v' 117 | { 254, 5, 4, 6, 0, -3 }, // 0x77 'w' 118 | { 257, 4, 4, 5, 0, -3 }, // 0x78 'x' 119 | { 259, 4, 5, 5, 0, -3 }, // 0x79 'y' 120 | { 262, 4, 4, 5, 0, -3 }, // 0x7A 'z' 121 | { 264, 3, 5, 4, 0, -4 }, // 0x7B '{' 122 | { 266, 1, 5, 2, 0, -4 }, // 0x7C '|' 123 | { 267, 3, 5, 4, 0, -4 }, // 0x7D '}' 124 | { 269, 5, 3, 6, 0, -3 } }; // 0x7E '~' 125 | 126 | const GFXfont Org_01 = { 127 | (uint8_t *)Org_01Bitmaps, 128 | (GFXglyph *)Org_01Glyphs, 129 | 0x20, 0x7E, 7 }; 130 | 131 | // Approx. 943 bytes 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-CAM 2 | 3 | The goal of this project is to create a functional webcam firmware for ESP32 based camera boards with OV2640 modules using the ESP-IDF framework. Such modules often come with optional components like high power LED "flash", an OLED display, or a motion detector. This project will incorporate compile time support for optional libraries to support these components. 4 | 5 | ![Screenshot Image](/images/screenshot.png "Screenshot") 6 | 7 | This project was originally forked from one of the example programs for the ESP-WHO face recognition framework by Espressif. The face detection and recognition code has been removed to provide more resources for other features and to eliminate a dependency on external SPI RAM. In its place I have added: 8 | 9 | * An improved web interface 10 | * The ability to modify wifi and network settings from the web interface 11 | * Persistent storage of camera and other settings in NVS 12 | * An SSD1306 display driver and code to outputs pertinent information about the wifi connection and frame rate 13 | * An LED Illuminator driver to control the intensity of an LED flash 14 | * An mDNS server to announce camera services to the local network 15 | * Implement the NTP client and RTC for date/time 16 | 17 | The resources available on the ESP32 to support cameras are very limited and users should not expect to see anything like the full resolutions and frame rates the OV2640 is capable of. 18 | 19 | ## Status 20 | 21 | I am no longer actively maintaining this project but continue to process pull requests. If anyone is enthusiastic about taking over this project then please contact me at me@bondkeevil.ca 22 | 23 | ## License 24 | 25 | Espressif originally released their source code under the MIT license. I will release my contributions to this source code under the same license: 26 | 27 | ESPRESSIF MIT License 28 | 29 | Copyright (c) 2018 30 | 31 | Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, 32 | it is free of charge, to any person obtaining a copy of this software and associated 33 | documentation files (the "Software"), to deal in the Software without restriction, including 34 | without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 35 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished 36 | to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all copies or 39 | substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 43 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 44 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 45 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 46 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 47 | 48 | ## Installation 49 | 50 | The source code requires the [installation of the ESP-IDF toolchain and development framework](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html) 51 | 52 | **The source code works with the release/v4.0 branch.** 53 | 54 | Once that is done, create a folder for your projects and set the path and environment variables of your shell: 55 | 56 | ``` 57 | cd /home/username/esp/esp-idf 58 | . ./export.sh 59 | cd .. 60 | mkdir myprojects 61 | cd myprojects 62 | ``` 63 | 64 | clone the repository using the recursive option: 65 | 66 | ``` 67 | git clone --recursive https://github.com/bkeevil/esp32-cam.git 68 | cd esp32-cam 69 | ``` 70 | 71 | Compress the stylesheet, html and javascript pages in main/www 72 | 73 | ``` 74 | cd main/www 75 | ./compress_pages.sh 76 | cd ../.. 77 | ``` 78 | 79 | To configure the source code you first need to run `idf.py menuconfig` from the root of the source tree. This will bring up an ncurses based repository editor. 80 | 81 | Important settings are: 82 | 83 | - Select a USB port for uploading the firmware under *Serial Flasher Config -> Default serial port* 84 | - Select what board you are using under *Camera Web Server -> Camera Pins* 85 | - If your board has an LED flash, enable it under *Camera Web Server -> LED Illuminator* 86 | - You can select default wifi settings under *Camera Web Server -> Wifi Settings* 87 | - If your board has an SSD1306 based OLED display, enable it under *Component Config -> SSD1306 Configuration* and select pins for SDA and SCL 88 | - To use additional external SPI RAM that may be on your board, enable it using *Component Config -> ESP32 Specific -> Support for external, SPI-connected RAM* 89 | - To enable font overlays, under *Font Configuration* check *Store Font Partition* (Uses approximately 240K of flash) 90 | - Enable NTP and select a default NTP server and timezone under *NTP configuration* 91 | 92 | When your settings are complete, save them and exit. 93 | 94 | If needed, clean your build directory with `idf.py fullclean` 95 | 96 | Compile the source code by executing `idf.py build` 97 | 98 | Flash the binary file to your ESP32 module using `idf.py flash` 99 | 100 | Monitor the debug serial output by running `idf.py monitor` 101 | 102 | ### Upgrade Notes 103 | 104 | I moved the offset of the partition table in flash from 8000 to 18000. If you get the error message "Detected overlap at address: 0x8000 for file: partition_table/partition-table.bin" then check the following line in `sdkconfig` and `sdkconfig.defaults` 105 | 106 | ``` 107 | CONFIG_PARTITION_TABLE_OFFSET=0x18000 108 | ``` 109 | 110 | ### Windows 10 Installation Notes 111 | 112 | Instead of using make xxxx commands, you have to use idf.py xxxx commands. For example: 113 | 114 | ``` 115 | idf.py build 116 | idf.py menuconfig 117 | idf.py app 118 | idf.py -p Portname app-flash 119 | ``` 120 | 121 | Start ESP-IDF Command Prompt from Windows Start Menu to have idf.py available automatically. 122 | 123 | To further simplify the build process, create a build-windows-defaultcomport file (without any extension) with your devices COM port, e.g. COM15, then from within the ESP-IFD prompt run the build script. 124 | ``` 125 | echo COM15 > build-windows-defaultcomport 126 | powershell.exe .\build-windows.ps1 127 | ``` 128 | 129 | ## First Run 130 | 131 | When the firmware first starts up, it will try to establish a wifi connection in the following order: 132 | 133 | 1. Establish a connection using the SSID and password stored in non-volatile storage (nvs) 134 | 2. Establish a connection using the default STA SSID and password provided by `make menuconfig` 135 | 3. After five failed attempts at starting in station (STA) mode, it will fall back to SoftAP mode and act as a wifi access point 136 | 137 | To connect to the access point, point a browser to 192.168.4.1. There is no username or password. 138 | 139 | From the web interface, select a Wifi SSID and password and optionally specify a static IP address and other network settings. Reboot the device for the settings to take effect. 140 | 141 | ## Web Camera URLS 142 | 143 | Picture: http://IP/capture 144 | 145 | Stream: http://IP:81/stream 146 | 147 | Control LED: http://IP/control?var=led_intensity&val=[0...255] 148 | 149 | ## Notes 150 | 151 | - Although the ESP32-Camera driver provides support for the OV3660 sensor, it is not supported by this firmware due to the unavailability of these sensors on the market for testing purposes. 152 | - The esp_restart() function used by the web interface for a software reboot does not work on my boards. You might have to unplug the device to force a hardware restart. 153 | 154 | ## Contributions 155 | 156 | Developer contributions that further the goals of this project are most welcome. 157 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build 3 | on: 4 | - pull_request 5 | - push 6 | jobs: 7 | 8 | # XXX create multiple jobs for major versions 9 | # 10 | # for those who want to _refactor_ the jobs: 11 | # 12 | # in the previous CI implementation, all builds share a single build 13 | # process. that way, you can remove duplications. however, every time a 14 | # version changes the build process, the change affects all other build 15 | # processes. I am tired of tracking changes and workarounds in the build 16 | # process. the result is many `if`s. assuming major version does not change 17 | # (a lot) its build process, creating multiple jobs, and using matrix is the 18 | # only sane way. as GitHub Actions does not support reusable steps, there 19 | # are many duplications. but no need to modify the entire build process to 20 | # adopt changes in master. 21 | build_esp32_v4_x: 22 | runs-on: ubuntu-latest 23 | strategy: 24 | matrix: 25 | build_method: 26 | - idf 27 | - make 28 | branch: 29 | - master 30 | - v4.1 31 | - v4.0.1 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v2 35 | with: 36 | submodules: true 37 | 38 | - name: Install python 39 | uses: actions/setup-python@v2 40 | with: 41 | 42 | # XXX install python 3.8 because the official python package 43 | # segfaults when installing modules in the runner. 44 | # 45 | # 2020-09-03T02:29:58.2517141Z Successfully installed cffi-1.14.2 cryptography-3.1 future-0.18.2 pycparser-2.20 pyparsing-2.3.1 pyserial-3.4 setuptools-50.1.0 six-1.15.0 46 | # 2020-09-03T02:30:09.0409148Z /home/runner/work/_temp/66c91304-eef8-456d-84a1-7299428a62f7.sh: line 5: 4140 Segmentation fault (core dumped) python3 -m pip install --user -r ${IDF_PATH}/requirements.txt 47 | # 2020-09-03T02:30:09.0414254Z ##[error]Process completed with exit code 139. 48 | # 49 | # possibly related issue: 50 | # https://github.com/actions/virtual-environments/issues/159 51 | python-version: 3.8 52 | 53 | - name: Install dependencies 54 | run: | 55 | sudo apt-get install \ 56 | bison \ 57 | ccache \ 58 | flex \ 59 | gcc \ 60 | git \ 61 | gperf \ 62 | libffi-dev \ 63 | libncurses-dev \ 64 | libssl-dev \ 65 | make \ 66 | wget 67 | 68 | - name: Set environment variables 69 | id: set_env 70 | run: | 71 | SDK_NAME="esp-idf" 72 | GCC_PREFIX="xtensa-esp32-elf" 73 | GCC_FILE="${GCC_PREFIX}-gcc" 74 | # /home/runner/.espressif/tools/xtensa-esp32-elf/esp-2020r2-8.2.0/xtensa-esp32-elf/bin 75 | TOOLCHAIN_DIR="${HOME}/.espressif/tools" 76 | case "${{ matrix.branch }}" in 77 | v4.0.1) 78 | TOOLCHAIN_VERSION="esp-2019r2-8.2.0" 79 | ;; 80 | v4.1*) 81 | TOOLCHAIN_VERSION="esp-2020r2-8.2.0" 82 | ;; 83 | master) 84 | TOOLCHAIN_VERSION="esp-2020r3-8.4.0" 85 | ;; 86 | esac 87 | REPO_DIR=`pwd` 88 | EXAMPLE_DIR="${REPO_DIR}" 89 | DISTFILE_DIR="${HOME}/distfiles" 90 | __PROJECT_PATH=`pwd` 91 | 92 | # XXX actions/checkout does not allow to checkout a repository other 93 | # than under __PROJECT_PATH 94 | IDF_PATH="${__PROJECT_PATH}/idf" 95 | 96 | echo "::set-env name=IDF_PATH::${IDF_PATH}" 97 | 98 | # XXX prefix all the environment variables with `__PROJECT_` to avoid pollution 99 | echo "::set-env name=__PROJECT_EXAMPLE_DIR::${EXAMPLE_DIR}" 100 | echo "::set-env name=__PROJECT_GCC_FILE::${GCC_FILE}" 101 | echo "::set-env name=__PROJECT_GCC_PREFIX::${GCC_PREFIX}" 102 | echo "::set-env name=__PROJECT_SDK_NAME::${SDK_NAME}" 103 | echo "::set-env name=__PROJECT_TOOLCHAIN_FILE::${TOOLCHAIN_FILE}" 104 | echo "::set-env name=__PROJECT_TOOLCHAIN_DIR::${TOOLCHAIN_DIR}" 105 | echo "::set-env name=__PROJECT_TOOLCHAIN_VERSION::${TOOLCHAIN_VERSION}" 106 | echo "::set-env name=__PROJECT_DISTFILE_DIR::${DISTFILE_DIR}" 107 | echo "::set-env name=__PROJECT_PATH::${__PROJECT_PATH}" 108 | echo "::set-env name=__PROJECT_BUILD_COMMAND::${__PROJECT_BUILD_COMMAND}" 109 | echo "::set-env name=__PROJECT_BUILD_COMMAND_ARG::${__PROJECT_BUILD_COMMAND_ARG}" 110 | 111 | - name: Checkout the SDK 112 | uses: actions/checkout@v2 113 | with: 114 | repository: espressif/esp-idf 115 | path: idf 116 | submodules: recursive 117 | ref: ${{ matrix.branch }} 118 | 119 | - name: Fixup the SDK 120 | run: | 121 | 122 | # XXX workaround removed option, --no-site-packages, from virtualenv. should 123 | # be removed when the following commit is merged 124 | # https://github.com/espressif/esp-idf/commit/7a18f02acd7005f7c56e62175a8d1968a1a9019d 125 | sed -i -e "s/'--no-site-packages',//" ${IDF_PATH}/tools/idf_tools.py 126 | 127 | # XXX remove some modules 128 | # gdbgui cannot be installed successfully with python 3.8 129 | sed -i -e "s/^gdbgui.*//" -e "s/^pygdbmi.*//" ${IDF_PATH}/requirements.txt 130 | 131 | - name: Install python requirements 132 | run: | 133 | cd "${IDF_PATH}" 134 | ./install.sh 135 | 136 | - name: Compress HTML assets 137 | run: | 138 | cd main/www 139 | bash ./compress_pages.sh 140 | 141 | - name: Build (idf.py) 142 | if: ${{ matrix.build_method == 'idf' }} 143 | run: | 144 | IGNORE_FILE="travis-ignore" 145 | . ${IDF_PATH}/export.sh 146 | 147 | # XXX share cache between examples. 148 | # see "Compiling In Different Directories" in ccache(1) 149 | # | | 4.0.1 | master | 150 | # |----------------------------------------|---------|---------| 151 | # | without ccache | 33m 42s | 50m 27s | 152 | # | CCACHE_BASEDIR and CCACHE_NOHASHDIR | 10m 41s | 16m 38s | 153 | export CCACHE_BASEDIR="${__PROJECT_EXAMPLE_DIR}" 154 | export CCACHE_NOHASHDIR=true 155 | 156 | cd "${__PROJECT_EXAMPLE_DIR}" 157 | idf.py --ccache build 158 | 159 | - name: Setup ccache (make) 160 | 161 | # XXX ccache needs to be configured here 162 | # unlike idf.py, esp-idf does nothing to setup ccache for make. 163 | # IDF_CCACHE_ENABLE does not work either. 164 | if: ${{ matrix.build_method == 'make' }} 165 | run: | 166 | ccache --version 167 | GCC_BIN_DIR="${__PROJECT_TOOLCHAIN_DIR}/${__PROJECT_GCC_PREFIX}/${__PROJECT_TOOLCHAIN_VERSION}/${__PROJECT_GCC_PREFIX}/bin" 168 | CCACHE_BIN_DIR="${HOME}/ccache_bin" 169 | mkdir -p "${CCACHE_BIN_DIR}" 170 | (cd "${CCACHE_BIN_DIR}" && ln -s /usr/bin/ccache "${__PROJECT_GCC_FILE}") 171 | export PATH="${CCACHE_BIN_DIR}:$PATH:${GCC_BIN_DIR}" 172 | ${CCACHE_BIN_DIR}/${__PROJECT_GCC_FILE} --version 173 | echo "::set-env name=PATH::${PATH}" 174 | echo "::set-env name=CCACHE_BASEDIR::${__PROJECT_EXAMPLE_DIR}" 175 | echo "::set-env name=CCACHE_NOHASHDIR::true" 176 | 177 | - name: Build (make) 178 | if: ${{ matrix.build_method == 'make' }} 179 | run: | 180 | export TERM="xterm-256color" 181 | IGNORE_FILE="travis-ignore" 182 | . ${IDF_PATH}/export.sh 183 | 184 | make -C "${__PROJECT_EXAMPLE_DIR}" defconfig 185 | make -C "${__PROJECT_EXAMPLE_DIR}" 186 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Camera Web Server" 2 | 3 | menu "WiFi Settings" 4 | config ESP_WIFI_SSID 5 | string "WiFi STA SSID" 6 | default "" 7 | help 8 | WiFi SSID (network name) to connect to or empty for Off. 9 | 10 | config ESP_WIFI_PASSWORD 11 | string "WiFi STA Password" 12 | default "" 13 | help 14 | WiFi Password if WEP/WPA/WPA2 or empty if Open. 15 | 16 | config ESP_MAXIMUM_RETRY 17 | int "Maximum retry" 18 | default 5 19 | help 20 | Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. 21 | 22 | config ESP_WIFI_AP_SSID 23 | string "WiFi AP SSID" 24 | default "ESP32-Camera" 25 | help 26 | AP SSID (network name) to create or empty for Off. 27 | 28 | config ESP_WIFI_AP_PASSWORD 29 | string "WiFi AP Password" 30 | default "" 31 | help 32 | AP password for WPA2 or empty for Open. 33 | 34 | config SERVER_IP 35 | string "WiFi AP IP Address" 36 | default "192.168.4.1" 37 | help 38 | IP address that the ESP will assign to it's AP interface. You can use this IP to connect to the camera after flashing. 39 | 40 | config LWIP_LOCAL_HOSTNAME 41 | string "Local hostname" 42 | default "espressif" 43 | help 44 | The hostname under which the camera will accesible in the local network. 45 | 46 | endmenu 47 | 48 | menu "Authentication" 49 | config DEF_HTTP_AUTH_ENABLED 50 | bool "Authentication required" 51 | default y 52 | help 53 | Enable or disable authentication 54 | 55 | config DEF_HTTP_USER 56 | string "Username" 57 | default "buger" 58 | help 59 | Username for authentication - max 15 characters 60 | 61 | config DEF_HTTP_PASSWORD 62 | string "Password" 63 | default "wannaSEE" 64 | help 65 | Password for authentication - max 15 characters 66 | endmenu 67 | 68 | menu "mDNS Settings" 69 | config MDNS_ENABLED 70 | bool "mDNS Enabled" 71 | default y 72 | help 73 | Should mDNS be used 74 | 75 | config MDNS_INSTANCE 76 | depends on MDNS_ENABLED 77 | string "mDNS Instance Name" 78 | default "ESP32 Camera Web Server" 79 | help 80 | mDNS Instance Name to use 81 | endmenu 82 | 83 | 84 | menu "SNTP Configuration" 85 | 86 | config SNTP_ENABLED 87 | bool "Enable SNTP Time Synchronization" 88 | default y 89 | help 90 | Enable SNTP Time Synchronization. 91 | 92 | config NTP_SERVER 93 | depends on SNTP_ENABLED 94 | string "NTP Server" 95 | default "pool.ntp.org" 96 | help 97 | Choose a default ntp server. 98 | 99 | config TIMEZONE 100 | depends on SNTP_ENABLED 101 | string "Timezone" 102 | default "" 103 | help 104 | For help see: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html 105 | 106 | endmenu 107 | 108 | menu "LED Illuminator" 109 | config LED_ILLUMINATOR_ENABLED 110 | bool "LED Illuminator Enabled" 111 | default n 112 | help 113 | Enable an LED Flash or IR Illuminator 114 | 115 | config LED_LEDC_PIN 116 | depends on LED_ILLUMINATOR_ENABLED 117 | int "LED Illuminator GPIO Pin" 118 | range 0 33 119 | default 4 120 | help 121 | Set a pin to illuminate an onboard LED or IR Illuminator when streaming or taking snapshots. 122 | 123 | config LED_MAX_INTENSITY 124 | depends on LED_ILLUMINATOR_ENABLED 125 | int "LED Maximum Intensity (0-255)" 126 | range 0 255 127 | default 255 128 | help 129 | Limit the maximum intensity of the LED while streaming to prevent overheating (0-255). 130 | 131 | choice LED_LEDC_SPEED_MODE 132 | depends on LED_ILLUMINATOR_ENABLED 133 | bool "Select LEDC Timer Speed Mode" 134 | default LED_LEDC_LOW_SPEED_MODE 135 | help 136 | Select a speed mode for the LEDC channel 137 | 138 | config LED_LEDC_LOW_SPEED_MODE 139 | bool "LOW_SPEED_MODE" 140 | config LED_LEDC_HIGH_SPEED_MODE 141 | bool "HIGH_SPEED_MODE" 142 | endchoice 143 | 144 | config LED_LEDC_TIMER 145 | depends on LED_ILLUMINATOR_ENABLED 146 | int "LEDC Timer" 147 | range 0 3 148 | default 1 149 | help 150 | Select the LEDC Timer (0-3) 151 | 152 | config LED_LEDC_CHANNEL 153 | depends on LED_ILLUMINATOR_ENABLED 154 | int "LEDC Channel" 155 | range 0 7 156 | default 1 157 | help 158 | Select the LEDC Channel (0-7) 159 | endmenu 160 | 161 | menu "Camera Pins" 162 | choice CAMERA_MODEL 163 | bool "Select Camera Pinout" 164 | default CAMERA_MODEL_WROVER_KIT 165 | help 166 | Select Camera Pinout. 167 | 168 | config CAMERA_MODEL_WROVER_KIT 169 | bool "WROVER-KIT With OV2640 Module" 170 | config CAMERA_MODEL_ESP_EYE 171 | bool "ESP_EYE DevKit" 172 | config CAMERA_MODEL_M5STACK_PSRAM 173 | bool "M5Stack Camera With PSRAM" 174 | config CAMERA_MODEL_M5STACK_WIDE 175 | bool "M5Stack Camera F (Wide)" 176 | config CAMERA_MODEL_AI_THINKER 177 | bool "ESP32-CAM by AI-Thinker" 178 | config CAMERA_MODEL_TJOURNAL 179 | bool "TTGO T-Journal" 180 | config CAMERA_MODEL_CUSTOM 181 | bool "Custom Camera Pinout" 182 | endchoice 183 | 184 | config CAMERA_PIN_PWDN 185 | depends on CAMERA_MODEL_CUSTOM 186 | int "Power Down pin" 187 | range -1 33 188 | default -1 189 | help 190 | Select Power Down pin or -1 for unmanaged. 191 | 192 | config CAMERA_PIN_RESET 193 | depends on CAMERA_MODEL_CUSTOM 194 | int "Reset pin" 195 | range -1 33 196 | default -1 197 | help 198 | Select Camera Reset pin or -1 for software reset. 199 | 200 | config CAMERA_PIN_XCLK 201 | depends on CAMERA_MODEL_CUSTOM 202 | int "XCLK pin" 203 | range 0 33 204 | default 21 205 | help 206 | Select Camera XCLK pin. 207 | 208 | config CAMERA_PIN_SIOD 209 | depends on CAMERA_MODEL_CUSTOM 210 | int "SIOD pin" 211 | range 0 33 212 | default 26 213 | help 214 | Select Camera SIOD pin. 215 | 216 | config CAMERA_PIN_SIOC 217 | depends on CAMERA_MODEL_CUSTOM 218 | int "SIOC pin" 219 | range 0 33 220 | default 27 221 | help 222 | Select Camera SIOC pin. 223 | 224 | config CAMERA_PIN_VSYNC 225 | depends on CAMERA_MODEL_CUSTOM 226 | int "VSYNC pin" 227 | range 0 39 228 | default 25 229 | help 230 | Select Camera VSYNC pin. 231 | 232 | config CAMERA_PIN_HREF 233 | depends on CAMERA_MODEL_CUSTOM 234 | int "HREF pin" 235 | range 0 39 236 | default 23 237 | help 238 | Select Camera HREF pin. 239 | 240 | config CAMERA_PIN_PCLK 241 | depends on CAMERA_MODEL_CUSTOM 242 | int "PCLK pin" 243 | range 0 39 244 | default 25 245 | help 246 | Select Camera PCLK pin. 247 | 248 | config CAMERA_PIN_Y2 249 | depends on CAMERA_MODEL_CUSTOM 250 | int "Y2 pin" 251 | range 0 39 252 | default 4 253 | help 254 | Select Camera Y2 pin. 255 | 256 | config CAMERA_PIN_Y3 257 | depends on CAMERA_MODEL_CUSTOM 258 | int "Y3 pin" 259 | range 0 39 260 | default 5 261 | help 262 | Select Camera Y3 pin. 263 | 264 | config CAMERA_PIN_Y4 265 | depends on CAMERA_MODEL_CUSTOM 266 | int "Y4 pin" 267 | range 0 39 268 | default 18 269 | help 270 | Select Camera Y4 pin. 271 | 272 | config CAMERA_PIN_Y5 273 | depends on CAMERA_MODEL_CUSTOM 274 | int "Y5 pin" 275 | range 0 39 276 | default 19 277 | help 278 | Select Camera Y5 pin. 279 | 280 | config CAMERA_PIN_Y6 281 | depends on CAMERA_MODEL_CUSTOM 282 | int "Y6 pin" 283 | range 0 39 284 | default 36 285 | help 286 | Select Camera Y6 pin. 287 | 288 | config CAMERA_PIN_Y7 289 | depends on CAMERA_MODEL_CUSTOM 290 | int "Y7 pin" 291 | range 0 39 292 | default 39 293 | help 294 | Select Camera Y7 pin. 295 | 296 | config CAMERA_PIN_Y8 297 | depends on CAMERA_MODEL_CUSTOM 298 | int "Y8 pin" 299 | range 0 39 300 | default 34 301 | help 302 | Select Camera Y8 pin. 303 | 304 | config CAMERA_PIN_Y9 305 | depends on CAMERA_MODEL_CUSTOM 306 | int "Y9 pin" 307 | range 0 39 308 | default 35 309 | help 310 | Select Camera Y9 pin. 311 | 312 | endmenu 313 | 314 | endmenu 315 | 316 | menu "Font Configuration" 317 | 318 | config STORE_FONT_PARTITION 319 | bool "Store Font Partition" 320 | default n 321 | help 322 | Set to True to erase and rewrite the font partition. This causes all selected fonts to be loaded into memory and written out to a partition. This option is meant for exporting a font partition image containing specific fonts. 323 | 324 | endmenu 325 | -------------------------------------------------------------------------------- /main/app_wifi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include "freertos/event_groups.h" 5 | #include "esp_system.h" 6 | #include "esp_wifi.h" 7 | #include "esp_event.h" 8 | #include "esp_log.h" 9 | #include "lwip/sys.h" 10 | #include "lwip/err.h" 11 | #include "lwip/dns.h" 12 | #include "nvs_flash.h" 13 | #include "sdkconfig.h" 14 | #include "app_settings.h" 15 | #include "app_wifi.h" 16 | 17 | #include "idf_version.h" 18 | #if defined(__USE_TCP_ADAPTOR) 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | static const char *TAG = "wifi station"; 25 | 26 | extern EventGroupHandle_t event_group; 27 | 28 | static int s_retry_num = 0; 29 | 30 | static char *wifi_authmode_to_str(wifi_auth_mode_t mode) { 31 | switch(mode) { 32 | case WIFI_AUTH_OPEN: 33 | return "Open"; 34 | case WIFI_AUTH_WEP: 35 | return "WEP"; 36 | case WIFI_AUTH_WPA_PSK: 37 | return "WPA"; 38 | case WIFI_AUTH_WPA2_PSK: 39 | return "WPA2"; 40 | case WIFI_AUTH_WPA_WPA2_PSK: 41 | return "WPA_WPA2"; 42 | case WIFI_AUTH_WPA2_ENTERPRISE: 43 | return "WPA2 Enterprise"; 44 | default: 45 | return "Unknown"; 46 | } 47 | } 48 | 49 | float wifi_get_tx_power() { 50 | int8_t tx_power; 51 | ESP_ERROR_CHECK(esp_wifi_get_max_tx_power(&tx_power)); 52 | return tx_power * 0.25; 53 | } 54 | 55 | int wifi_get_rssi() { 56 | wifi_ap_record_t apinfo; 57 | 58 | ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(&apinfo)); 59 | return apinfo.rssi; 60 | } 61 | 62 | int wifi_connection_count() { 63 | wifi_sta_list_t list; 64 | if (esp_wifi_ap_get_sta_list(&list) == ESP_OK) { 65 | return list.num; 66 | } else { 67 | return 0; 68 | } 69 | } 70 | 71 | static void wifi_dump_ap_info() { 72 | wifi_ap_record_t apinfo; 73 | int8_t tx_power; 74 | 75 | ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(&apinfo)); 76 | ESP_ERROR_CHECK(esp_wifi_get_max_tx_power(&tx_power)); 77 | ESP_LOGI(TAG,"Primary Channel: %d",apinfo.primary); 78 | ESP_LOGI(TAG,"Secondary Channel: %d",apinfo.second); 79 | ESP_LOGI(TAG,"RSSI: %d",apinfo.rssi); 80 | ESP_LOGI(TAG,"Auth Mode: %s",wifi_authmode_to_str(apinfo.authmode)); 81 | ESP_LOGI(TAG,"Country Code: %s",apinfo.country.cc); 82 | ESP_LOGI(TAG,"Transmit Power: %3.1f dBm",tx_power * 0.25); 83 | ESP_LOGI(TAG,"Phy Mode: 11%s%s%s %s",apinfo.phy_11b ? "B" : "",apinfo.phy_11g ? "G" : "", apinfo.phy_11n ? "N" : "", apinfo.phy_lr ? "LR" : ""); 84 | } 85 | 86 | void wifi_init_softap() 87 | { 88 | if (strcmp(CONFIG_SERVER_IP, "192.168.4.1")) 89 | { 90 | int a, b, c, d; 91 | sscanf(CONFIG_SERVER_IP, "%d.%d.%d.%d", &a, &b, &c, &d); 92 | tcpip_adapter_ip_info_t ip_info; 93 | IP4_ADDR(&ip_info.ip, a, b, c, d); 94 | IP4_ADDR(&ip_info.gw, a, b, c, d); 95 | IP4_ADDR(&ip_info.netmask, 255, 255, 255, 0); 96 | ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(WIFI_IF_AP)); 97 | ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(WIFI_IF_AP, &ip_info)); 98 | ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(WIFI_IF_AP)); 99 | } 100 | wifi_config_t wifi_config; 101 | memset(&wifi_config, 0, sizeof(wifi_config_t)); 102 | strncpy((char*)wifi_config.ap.ssid, CONFIG_ESP_WIFI_AP_SSID, sizeof(wifi_config.ap.ssid)); // whhhyy??? snprintf((char*)wifi_config.ap.ssid, 32, "%s", CONFIG_ESP_WIFI_AP_SSID); 103 | //not needed wifi_config.ap.ssid_len = strlen((char*)wifi_config.ap.ssid); 104 | strncpy((char*)wifi_config.ap.password, CONFIG_ESP_WIFI_AP_PASSWORD, sizeof(wifi_config.ap.password)); //why ???snprintf((char*)wifi_config.ap.password, 64, "%s", CONFIG_ESP_WIFI_AP_PASSWORD); 105 | wifi_config.ap.max_connection = 1; 106 | wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; 107 | if (strlen(CONFIG_ESP_WIFI_AP_PASSWORD) == 0) { 108 | wifi_config.ap.authmode = WIFI_AUTH_OPEN; 109 | } 110 | 111 | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); 112 | xEventGroupSetBits(event_group, WIFI_SOFTAP_BIT); 113 | ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s", 114 | CONFIG_ESP_WIFI_AP_SSID, CONFIG_ESP_WIFI_AP_PASSWORD); 115 | } 116 | 117 | static void wifi_init_sta(void) { 118 | wifi_config_t wifi_config; 119 | memset(&wifi_config, 0, sizeof(wifi_config_t)); 120 | snprintf((char*)wifi_config.sta.ssid, 32, "%s", settings.wifi_ssid); 121 | snprintf((char*)wifi_config.sta.password, 64, "%s", settings.wifi_password); 122 | ESP_LOGI(TAG, "Connecting to AP SSID:%s password:%s", 123 | wifi_config.sta.ssid, wifi_config.sta.password); 124 | 125 | wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; 126 | 127 | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); 128 | 129 | ESP_LOGI(TAG, "wifi_init_sta finished."); 130 | ESP_LOGI(TAG, "connecting to ap SSID:%s password:%s", 131 | wifi_config.sta.ssid, wifi_config.sta.password); 132 | } 133 | 134 | static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) 135 | { 136 | if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) { 137 | wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; 138 | ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", 139 | MAC2STR(event->mac), event->aid); 140 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) { 141 | wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; 142 | ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", 143 | MAC2STR(event->mac), event->aid); 144 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { 145 | esp_wifi_connect(); 146 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { 147 | wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data; 148 | ESP_LOGW(TAG,"Station disconnected (reason=%d)",event->reason); 149 | if (s_retry_num ip_info.ip; 165 | ESP_LOGI(TAG, "got ip:" IPSTR "\n", IP2STR(&settings.ip)); 166 | s_retry_num = 0; 167 | xEventGroupSetBits(event_group, WIFI_CONNECTED_BIT); 168 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { 169 | wifi_dump_ap_info(); 170 | } 171 | } 172 | 173 | void app_wifi_startup() { 174 | 175 | #if defined(__USE_TCP_ADAPTOR) 176 | tcpip_adapter_init(); 177 | tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,settings.hostname); 178 | tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP,settings.hostname); 179 | 180 | #else 181 | esp_netif_t *if_sta; 182 | esp_netif_t *if_ap; 183 | ESP_ERROR_CHECK(esp_netif_init()); 184 | if_sta = esp_netif_create_default_wifi_sta(); 185 | if_ap = esp_netif_create_default_wifi_ap(); 186 | esp_netif_set_hostname(if_sta,settings.hostname); 187 | esp_netif_set_hostname(if_ap,settings.hostname); 188 | #endif 189 | 190 | if (!settings.dhcp) { 191 | #if defined(__USE_TCP_ADAPTOR) 192 | tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); 193 | tcpip_adapter_ip_info_t info; 194 | #else 195 | esp_netif_dhcpc_stop(if_sta); 196 | esp_netif_ip_info_t info; 197 | #endif 198 | info.ip.addr = settings.ip.addr; 199 | info.gw.addr = settings.gateway.addr; 200 | info.netmask.addr = settings.netmask.addr; 201 | #if defined(__USE_TCP_ADAPTOR) 202 | tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); 203 | #else 204 | esp_netif_set_ip_info(if_sta, &info); 205 | #endif 206 | dns_setserver(1, (const ip_addr_t *)&settings.dns1); 207 | dns_setserver(2, (const ip_addr_t *)&settings.dns2); 208 | } 209 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 210 | 211 | ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); 212 | ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); 213 | //ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &event_handler, NULL)); 214 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 215 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 216 | 217 | wifi_init_sta(); 218 | ESP_ERROR_CHECK(esp_wifi_start()); 219 | wifi_country_t wifi_country = { 220 | .cc = "", 221 | .schan = 1, 222 | .nchan = 13, 223 | .max_tx_power = 78, 224 | .policy = WIFI_COUNTRY_POLICY_AUTO 225 | }; 226 | ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); 227 | // ESP_ERROR_CHECK(esp_wifi_set_max_tx_power(78)); 228 | } 229 | 230 | void app_wifi_shutdown() { 231 | esp_wifi_disconnect(); 232 | esp_wifi_stop(); 233 | esp_wifi_deinit(); 234 | } 235 | -------------------------------------------------------------------------------- /main/fonts/FreeMono9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeMono9pt7bBitmaps[] = { 2 | 0xAA, 0xA8, 0x0C, 0xED, 0x24, 0x92, 0x48, 0x24, 0x48, 0x91, 0x2F, 0xE4, 3 | 0x89, 0x7F, 0x28, 0x51, 0x22, 0x40, 0x08, 0x3E, 0x62, 0x40, 0x30, 0x0E, 4 | 0x01, 0x81, 0xC3, 0xBE, 0x08, 0x08, 0x71, 0x12, 0x23, 0x80, 0x23, 0xB8, 5 | 0x0E, 0x22, 0x44, 0x70, 0x38, 0x81, 0x02, 0x06, 0x1A, 0x65, 0x46, 0xC8, 6 | 0xEC, 0xE9, 0x24, 0x5A, 0xAA, 0xA9, 0x40, 0xA9, 0x55, 0x5A, 0x80, 0x10, 7 | 0x22, 0x4B, 0xE3, 0x05, 0x11, 0x00, 0x10, 0x20, 0x47, 0xF1, 0x02, 0x04, 8 | 0x00, 0x6B, 0x48, 0xFF, 0x00, 0xF0, 0x02, 0x08, 0x10, 0x60, 0x81, 0x04, 9 | 0x08, 0x20, 0x41, 0x02, 0x08, 0x00, 0x38, 0x8A, 0x0C, 0x18, 0x30, 0x60, 10 | 0xC1, 0x82, 0x88, 0xE0, 0x27, 0x28, 0x42, 0x10, 0x84, 0x21, 0x3E, 0x38, 11 | 0x8A, 0x08, 0x10, 0x20, 0x82, 0x08, 0x61, 0x03, 0xF8, 0x7C, 0x06, 0x02, 12 | 0x02, 0x1C, 0x06, 0x01, 0x01, 0x01, 0x42, 0x3C, 0x18, 0xA2, 0x92, 0x8A, 13 | 0x28, 0xBF, 0x08, 0x21, 0xC0, 0x7C, 0x81, 0x03, 0xE4, 0x40, 0x40, 0x81, 14 | 0x03, 0x88, 0xE0, 0x1E, 0x41, 0x04, 0x0B, 0x98, 0xB0, 0xC1, 0xC2, 0x88, 15 | 0xE0, 0xFE, 0x04, 0x08, 0x20, 0x40, 0x82, 0x04, 0x08, 0x20, 0x40, 0x38, 16 | 0x8A, 0x0C, 0x14, 0x47, 0x11, 0x41, 0x83, 0x8C, 0xE0, 0x38, 0x8A, 0x1C, 17 | 0x18, 0x68, 0xCE, 0x81, 0x04, 0x13, 0xC0, 0xF0, 0x0F, 0x6C, 0x00, 0xD2, 18 | 0xD2, 0x00, 0x03, 0x04, 0x18, 0x60, 0x60, 0x18, 0x04, 0x03, 0xFF, 0x80, 19 | 0x00, 0x1F, 0xF0, 0x40, 0x18, 0x03, 0x00, 0x60, 0x20, 0x60, 0xC0, 0x80, 20 | 0x3D, 0x84, 0x08, 0x30, 0xC2, 0x00, 0x00, 0x00, 0x30, 0x3C, 0x46, 0x82, 21 | 0x8E, 0xB2, 0xA2, 0xA2, 0x9F, 0x80, 0x80, 0x40, 0x3C, 0x3C, 0x01, 0x40, 22 | 0x28, 0x09, 0x01, 0x10, 0x42, 0x0F, 0xC1, 0x04, 0x40, 0x9E, 0x3C, 0xFE, 23 | 0x21, 0x90, 0x48, 0x67, 0xE2, 0x09, 0x02, 0x81, 0x41, 0xFF, 0x80, 0x3E, 24 | 0xB0, 0xF0, 0x30, 0x08, 0x04, 0x02, 0x00, 0x80, 0x60, 0x8F, 0x80, 0xFE, 25 | 0x21, 0x90, 0x68, 0x14, 0x0A, 0x05, 0x02, 0x83, 0x43, 0x7F, 0x00, 0xFF, 26 | 0x20, 0x90, 0x08, 0x87, 0xC2, 0x21, 0x00, 0x81, 0x40, 0xFF, 0xC0, 0xFF, 27 | 0xA0, 0x50, 0x08, 0x87, 0xC2, 0x21, 0x00, 0x80, 0x40, 0x78, 0x00, 0x1E, 28 | 0x98, 0x6C, 0x0A, 0x00, 0x80, 0x20, 0xF8, 0x0B, 0x02, 0x60, 0x87, 0xC0, 29 | 0xE3, 0xA0, 0x90, 0x48, 0x27, 0xF2, 0x09, 0x04, 0x82, 0x41, 0x71, 0xC0, 30 | 0xF9, 0x08, 0x42, 0x10, 0x84, 0x27, 0xC0, 0x1F, 0x02, 0x02, 0x02, 0x02, 31 | 0x02, 0x82, 0x82, 0xC6, 0x78, 0xE3, 0xA1, 0x11, 0x09, 0x05, 0x83, 0x21, 32 | 0x08, 0x84, 0x41, 0x70, 0xC0, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 33 | 0x41, 0x41, 0xFF, 0xE0, 0xEC, 0x19, 0x45, 0x28, 0xA4, 0xA4, 0x94, 0x91, 34 | 0x12, 0x02, 0x40, 0x5C, 0x1C, 0xC3, 0xB0, 0x94, 0x4A, 0x24, 0x92, 0x49, 35 | 0x14, 0x8A, 0x43, 0x70, 0x80, 0x1E, 0x31, 0x90, 0x50, 0x18, 0x0C, 0x06, 36 | 0x02, 0x82, 0x63, 0x0F, 0x00, 0xFE, 0x43, 0x41, 0x41, 0x42, 0x7C, 0x40, 37 | 0x40, 0x40, 0xF0, 0x1C, 0x31, 0x90, 0x50, 0x18, 0x0C, 0x06, 0x02, 0x82, 38 | 0x63, 0x1F, 0x04, 0x07, 0x92, 0x30, 0xFE, 0x21, 0x90, 0x48, 0x24, 0x23, 39 | 0xE1, 0x10, 0x84, 0x41, 0x70, 0xC0, 0x3A, 0xCD, 0x0A, 0x03, 0x01, 0x80, 40 | 0xC1, 0xC7, 0x78, 0xFF, 0xC4, 0x62, 0x21, 0x00, 0x80, 0x40, 0x20, 0x10, 41 | 0x08, 0x1F, 0x00, 0xE3, 0xA0, 0x90, 0x48, 0x24, 0x12, 0x09, 0x04, 0x82, 42 | 0x22, 0x0E, 0x00, 0xF1, 0xE8, 0x10, 0x82, 0x10, 0x42, 0x10, 0x22, 0x04, 43 | 0x80, 0x50, 0x0C, 0x00, 0x80, 0xF1, 0xE8, 0x09, 0x11, 0x25, 0x44, 0xA8, 44 | 0x55, 0x0C, 0xA1, 0x8C, 0x31, 0x84, 0x30, 0xE3, 0xA0, 0x88, 0x82, 0x80, 45 | 0x80, 0xC0, 0x90, 0x44, 0x41, 0x71, 0xC0, 0xE3, 0xA0, 0x88, 0x82, 0x81, 46 | 0x40, 0x40, 0x20, 0x10, 0x08, 0x1F, 0x00, 0xFD, 0x0A, 0x20, 0x81, 0x04, 47 | 0x10, 0x21, 0x83, 0xFC, 0xEA, 0xAA, 0xAA, 0xC0, 0x80, 0x81, 0x03, 0x02, 48 | 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0xD5, 0x55, 0x55, 0xC0, 49 | 0x10, 0x51, 0x22, 0x28, 0x20, 0xFF, 0xE0, 0x88, 0x80, 0x7E, 0x00, 0x80, 50 | 0x47, 0xEC, 0x14, 0x0A, 0x0C, 0xFB, 0xC0, 0x20, 0x10, 0x0B, 0xC6, 0x12, 51 | 0x05, 0x02, 0x81, 0x40, 0xB0, 0xB7, 0x80, 0x3A, 0x8E, 0x0C, 0x08, 0x10, 52 | 0x10, 0x9E, 0x03, 0x00, 0x80, 0x47, 0xA4, 0x34, 0x0A, 0x05, 0x02, 0x81, 53 | 0x21, 0x8F, 0x60, 0x3C, 0x43, 0x81, 0xFF, 0x80, 0x80, 0x61, 0x3E, 0x3D, 54 | 0x04, 0x3E, 0x41, 0x04, 0x10, 0x41, 0x0F, 0x80, 0x3D, 0xA1, 0xA0, 0x50, 55 | 0x28, 0x14, 0x09, 0x0C, 0x7A, 0x01, 0x01, 0x87, 0x80, 0xC0, 0x20, 0x10, 56 | 0x0B, 0xC6, 0x32, 0x09, 0x04, 0x82, 0x41, 0x20, 0xB8, 0xE0, 0x10, 0x01, 57 | 0xC0, 0x81, 0x02, 0x04, 0x08, 0x11, 0xFC, 0x10, 0x3E, 0x10, 0x84, 0x21, 58 | 0x08, 0x42, 0x3F, 0x00, 0xC0, 0x40, 0x40, 0x4F, 0x44, 0x58, 0x70, 0x48, 59 | 0x44, 0x42, 0xC7, 0x70, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x23, 60 | 0xF8, 0xB7, 0x64, 0x62, 0x31, 0x18, 0x8C, 0x46, 0x23, 0x91, 0x5E, 0x31, 61 | 0x90, 0x48, 0x24, 0x12, 0x09, 0x05, 0xC7, 0x3E, 0x31, 0xA0, 0x30, 0x18, 62 | 0x0C, 0x05, 0x8C, 0x7C, 0xDE, 0x30, 0x90, 0x28, 0x14, 0x0A, 0x05, 0x84, 63 | 0xBC, 0x40, 0x20, 0x38, 0x00, 0x3D, 0xA1, 0xA0, 0x50, 0x28, 0x14, 0x09, 64 | 0x0C, 0x7A, 0x01, 0x00, 0x80, 0xE0, 0xCE, 0xA1, 0x82, 0x04, 0x08, 0x10, 65 | 0x7C, 0x3A, 0x8D, 0x0B, 0x80, 0xF0, 0x70, 0xDE, 0x40, 0x40, 0xFC, 0x40, 66 | 0x40, 0x40, 0x40, 0x40, 0x41, 0x3E, 0xC3, 0x41, 0x41, 0x41, 0x41, 0x41, 67 | 0x43, 0x3D, 0xE3, 0xA0, 0x90, 0x84, 0x42, 0x20, 0xA0, 0x50, 0x10, 0xE3, 68 | 0xC0, 0x92, 0x4B, 0x25, 0x92, 0xA9, 0x98, 0x44, 0xE3, 0x31, 0x05, 0x01, 69 | 0x01, 0x41, 0x11, 0x05, 0xC7, 0xE3, 0xA0, 0x90, 0x84, 0x42, 0x40, 0xA0, 70 | 0x60, 0x10, 0x10, 0x08, 0x3E, 0x00, 0xFD, 0x08, 0x20, 0x82, 0x08, 0x10, 71 | 0xBF, 0x29, 0x24, 0xA2, 0x49, 0x26, 0xFF, 0xF8, 0x89, 0x24, 0x8A, 0x49, 72 | 0x2C, 0x61, 0x24, 0x30 }; 73 | 74 | const GFXglyph FreeMono9pt7bGlyphs[] = { 75 | { 0, 0, 0, 11, 0, 1 }, // 0x20 ' ' 76 | { 0, 2, 11, 11, 4, -10 }, // 0x21 '!' 77 | { 3, 6, 5, 11, 2, -10 }, // 0x22 '"' 78 | { 7, 7, 12, 11, 2, -10 }, // 0x23 '#' 79 | { 18, 8, 12, 11, 1, -10 }, // 0x24 '$' 80 | { 30, 7, 11, 11, 2, -10 }, // 0x25 '%' 81 | { 40, 7, 10, 11, 2, -9 }, // 0x26 '&' 82 | { 49, 3, 5, 11, 4, -10 }, // 0x27 ''' 83 | { 51, 2, 13, 11, 5, -10 }, // 0x28 '(' 84 | { 55, 2, 13, 11, 4, -10 }, // 0x29 ')' 85 | { 59, 7, 7, 11, 2, -10 }, // 0x2A '*' 86 | { 66, 7, 7, 11, 2, -8 }, // 0x2B '+' 87 | { 73, 3, 5, 11, 2, -1 }, // 0x2C ',' 88 | { 75, 9, 1, 11, 1, -5 }, // 0x2D '-' 89 | { 77, 2, 2, 11, 4, -1 }, // 0x2E '.' 90 | { 78, 7, 13, 11, 2, -11 }, // 0x2F '/' 91 | { 90, 7, 11, 11, 2, -10 }, // 0x30 '0' 92 | { 100, 5, 11, 11, 3, -10 }, // 0x31 '1' 93 | { 107, 7, 11, 11, 2, -10 }, // 0x32 '2' 94 | { 117, 8, 11, 11, 1, -10 }, // 0x33 '3' 95 | { 128, 6, 11, 11, 3, -10 }, // 0x34 '4' 96 | { 137, 7, 11, 11, 2, -10 }, // 0x35 '5' 97 | { 147, 7, 11, 11, 2, -10 }, // 0x36 '6' 98 | { 157, 7, 11, 11, 2, -10 }, // 0x37 '7' 99 | { 167, 7, 11, 11, 2, -10 }, // 0x38 '8' 100 | { 177, 7, 11, 11, 2, -10 }, // 0x39 '9' 101 | { 187, 2, 8, 11, 4, -7 }, // 0x3A ':' 102 | { 189, 3, 11, 11, 3, -7 }, // 0x3B ';' 103 | { 194, 8, 8, 11, 1, -8 }, // 0x3C '<' 104 | { 202, 9, 4, 11, 1, -6 }, // 0x3D '=' 105 | { 207, 9, 8, 11, 1, -8 }, // 0x3E '>' 106 | { 216, 7, 10, 11, 2, -9 }, // 0x3F '?' 107 | { 225, 8, 12, 11, 2, -10 }, // 0x40 '@' 108 | { 237, 11, 10, 11, 0, -9 }, // 0x41 'A' 109 | { 251, 9, 10, 11, 1, -9 }, // 0x42 'B' 110 | { 263, 9, 10, 11, 1, -9 }, // 0x43 'C' 111 | { 275, 9, 10, 11, 1, -9 }, // 0x44 'D' 112 | { 287, 9, 10, 11, 1, -9 }, // 0x45 'E' 113 | { 299, 9, 10, 11, 1, -9 }, // 0x46 'F' 114 | { 311, 10, 10, 11, 1, -9 }, // 0x47 'G' 115 | { 324, 9, 10, 11, 1, -9 }, // 0x48 'H' 116 | { 336, 5, 10, 11, 3, -9 }, // 0x49 'I' 117 | { 343, 8, 10, 11, 2, -9 }, // 0x4A 'J' 118 | { 353, 9, 10, 11, 1, -9 }, // 0x4B 'K' 119 | { 365, 8, 10, 11, 2, -9 }, // 0x4C 'L' 120 | { 375, 11, 10, 11, 0, -9 }, // 0x4D 'M' 121 | { 389, 9, 10, 11, 1, -9 }, // 0x4E 'N' 122 | { 401, 9, 10, 11, 1, -9 }, // 0x4F 'O' 123 | { 413, 8, 10, 11, 1, -9 }, // 0x50 'P' 124 | { 423, 9, 13, 11, 1, -9 }, // 0x51 'Q' 125 | { 438, 9, 10, 11, 1, -9 }, // 0x52 'R' 126 | { 450, 7, 10, 11, 2, -9 }, // 0x53 'S' 127 | { 459, 9, 10, 11, 1, -9 }, // 0x54 'T' 128 | { 471, 9, 10, 11, 1, -9 }, // 0x55 'U' 129 | { 483, 11, 10, 11, 0, -9 }, // 0x56 'V' 130 | { 497, 11, 10, 11, 0, -9 }, // 0x57 'W' 131 | { 511, 9, 10, 11, 1, -9 }, // 0x58 'X' 132 | { 523, 9, 10, 11, 1, -9 }, // 0x59 'Y' 133 | { 535, 7, 10, 11, 2, -9 }, // 0x5A 'Z' 134 | { 544, 2, 13, 11, 5, -10 }, // 0x5B '[' 135 | { 548, 7, 13, 11, 2, -11 }, // 0x5C '\' 136 | { 560, 2, 13, 11, 4, -10 }, // 0x5D ']' 137 | { 564, 7, 5, 11, 2, -10 }, // 0x5E '^' 138 | { 569, 11, 1, 11, 0, 2 }, // 0x5F '_' 139 | { 571, 3, 3, 11, 3, -11 }, // 0x60 '`' 140 | { 573, 9, 8, 11, 1, -7 }, // 0x61 'a' 141 | { 582, 9, 11, 11, 1, -10 }, // 0x62 'b' 142 | { 595, 7, 8, 11, 2, -7 }, // 0x63 'c' 143 | { 602, 9, 11, 11, 1, -10 }, // 0x64 'd' 144 | { 615, 8, 8, 11, 1, -7 }, // 0x65 'e' 145 | { 623, 6, 11, 11, 3, -10 }, // 0x66 'f' 146 | { 632, 9, 11, 11, 1, -7 }, // 0x67 'g' 147 | { 645, 9, 11, 11, 1, -10 }, // 0x68 'h' 148 | { 658, 7, 10, 11, 2, -9 }, // 0x69 'i' 149 | { 667, 5, 13, 11, 3, -9 }, // 0x6A 'j' 150 | { 676, 8, 11, 11, 2, -10 }, // 0x6B 'k' 151 | { 687, 7, 11, 11, 2, -10 }, // 0x6C 'l' 152 | { 697, 9, 8, 11, 1, -7 }, // 0x6D 'm' 153 | { 706, 9, 8, 11, 1, -7 }, // 0x6E 'n' 154 | { 715, 9, 8, 11, 1, -7 }, // 0x6F 'o' 155 | { 724, 9, 11, 11, 1, -7 }, // 0x70 'p' 156 | { 737, 9, 11, 11, 1, -7 }, // 0x71 'q' 157 | { 750, 7, 8, 11, 3, -7 }, // 0x72 'r' 158 | { 757, 7, 8, 11, 2, -7 }, // 0x73 's' 159 | { 764, 8, 10, 11, 2, -9 }, // 0x74 't' 160 | { 774, 8, 8, 11, 1, -7 }, // 0x75 'u' 161 | { 782, 9, 8, 11, 1, -7 }, // 0x76 'v' 162 | { 791, 9, 8, 11, 1, -7 }, // 0x77 'w' 163 | { 800, 9, 8, 11, 1, -7 }, // 0x78 'x' 164 | { 809, 9, 11, 11, 1, -7 }, // 0x79 'y' 165 | { 822, 7, 8, 11, 2, -7 }, // 0x7A 'z' 166 | { 829, 3, 13, 11, 4, -10 }, // 0x7B '{' 167 | { 834, 1, 13, 11, 5, -10 }, // 0x7C '|' 168 | { 836, 3, 13, 11, 4, -10 }, // 0x7D '}' 169 | { 841, 7, 3, 11, 2, -6 } }; // 0x7E '~' 170 | 171 | const GFXfont FreeMono9pt7b = { 172 | (uint8_t *)FreeMono9pt7bBitmaps, 173 | (GFXglyph *)FreeMono9pt7bGlyphs, 174 | 0x20, 0x7E, 18 }; 175 | 176 | // Approx. 1516 bytes 177 | -------------------------------------------------------------------------------- /main/fonts/FreeMonoOblique9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeMonoOblique9pt7bBitmaps[] = { 2 | 0x11, 0x22, 0x24, 0x40, 0x00, 0xC0, 0xDE, 0xE5, 0x29, 0x00, 0x09, 0x05, 3 | 0x02, 0x82, 0x47, 0xF8, 0xA0, 0x51, 0xFE, 0x28, 0x14, 0x0A, 0x09, 0x00, 4 | 0x08, 0x1D, 0x23, 0x40, 0x70, 0x1C, 0x02, 0x82, 0x84, 0x78, 0x20, 0x20, 5 | 0x1C, 0x11, 0x08, 0x83, 0x80, 0x18, 0x71, 0xC0, 0x1C, 0x11, 0x08, 0x83, 6 | 0x80, 0x1E, 0x60, 0x81, 0x03, 0x0A, 0x65, 0x46, 0x88, 0xE8, 0xFA, 0x80, 7 | 0x12, 0x24, 0x48, 0x88, 0x88, 0x88, 0x80, 0x01, 0x11, 0x11, 0x11, 0x22, 8 | 0x44, 0x80, 0x10, 0x22, 0x5B, 0xC3, 0x0A, 0x22, 0x00, 0x04, 0x02, 0x02, 9 | 0x1F, 0xF0, 0x80, 0x40, 0x20, 0x00, 0x36, 0x4C, 0x80, 0xFF, 0x80, 0xF0, 10 | 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 11 | 0x08, 0x08, 0x00, 0x1C, 0x45, 0x0A, 0x18, 0x30, 0x61, 0x42, 0x85, 0x11, 12 | 0xC0, 0x04, 0x38, 0x90, 0x20, 0x81, 0x02, 0x04, 0x08, 0x23, 0xF8, 0x07, 13 | 0x04, 0xC4, 0x20, 0x10, 0x10, 0x30, 0x20, 0x20, 0x60, 0x40, 0x3F, 0x80, 14 | 0x0F, 0x00, 0x40, 0x20, 0x20, 0x60, 0x18, 0x04, 0x02, 0x01, 0x43, 0x1E, 15 | 0x00, 0x03, 0x05, 0x0A, 0x12, 0x22, 0x22, 0x42, 0x7F, 0x04, 0x04, 0x1E, 16 | 0x1F, 0x88, 0x08, 0x05, 0xC3, 0x30, 0x08, 0x04, 0x02, 0x02, 0x42, 0x1E, 17 | 0x00, 0x07, 0x18, 0x20, 0x40, 0x5C, 0xA6, 0xC2, 0x82, 0x82, 0xC4, 0x78, 18 | 0xFF, 0x04, 0x10, 0x20, 0x82, 0x04, 0x10, 0x20, 0x81, 0x00, 0x1E, 0x23, 19 | 0x41, 0x41, 0x62, 0x1C, 0x66, 0x82, 0x82, 0x84, 0x78, 0x1E, 0x23, 0x41, 20 | 0x41, 0x43, 0x65, 0x3A, 0x02, 0x04, 0x18, 0xE0, 0x6C, 0x00, 0x36, 0x18, 21 | 0xC0, 0x00, 0x19, 0x8C, 0xC4, 0x00, 0x01, 0x83, 0x06, 0x0C, 0x06, 0x00, 22 | 0x80, 0x30, 0x04, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x20, 0x0C, 0x01, 0x00, 23 | 0x60, 0x20, 0x60, 0xC1, 0x80, 0x3D, 0x8E, 0x08, 0x10, 0xC6, 0x08, 0x00, 24 | 0x01, 0x80, 0x1C, 0x45, 0x0A, 0x79, 0x34, 0x69, 0x4E, 0x81, 0x03, 0x03, 25 | 0xC0, 0x0F, 0x00, 0x60, 0x12, 0x02, 0x40, 0x88, 0x21, 0x07, 0xE1, 0x04, 26 | 0x20, 0x5E, 0x3C, 0x3F, 0x84, 0x11, 0x04, 0x82, 0x3F, 0x88, 0x32, 0x04, 27 | 0x81, 0x60, 0xBF, 0xC0, 0x1E, 0x98, 0xD0, 0x28, 0x08, 0x04, 0x02, 0x01, 28 | 0x00, 0x41, 0x1F, 0x00, 0x3F, 0x0C, 0x22, 0x04, 0x81, 0x20, 0x48, 0x12, 29 | 0x09, 0x02, 0x43, 0x3F, 0x00, 0x3F, 0xC4, 0x11, 0x00, 0x88, 0x3E, 0x08, 30 | 0x82, 0x00, 0x82, 0x60, 0xBF, 0xE0, 0x3F, 0xE2, 0x08, 0x40, 0x11, 0x03, 31 | 0xE0, 0x44, 0x08, 0x01, 0x00, 0x60, 0x1F, 0x00, 0x1E, 0x98, 0xD0, 0x08, 32 | 0x08, 0x04, 0x7A, 0x05, 0x02, 0x41, 0x1F, 0x00, 0x3D, 0xE2, 0x18, 0x42, 33 | 0x08, 0x43, 0xF8, 0x41, 0x08, 0x21, 0x08, 0x21, 0x1E, 0xF0, 0x3F, 0x82, 34 | 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x20, 0x10, 0x7F, 0x00, 0x0F, 0xE0, 35 | 0x20, 0x04, 0x00, 0x80, 0x10, 0x02, 0x20, 0x84, 0x10, 0x84, 0x0F, 0x00, 36 | 0x3C, 0xE2, 0x10, 0x44, 0x11, 0x02, 0xC0, 0x64, 0x08, 0x81, 0x08, 0x61, 37 | 0x1E, 0x38, 0x3E, 0x02, 0x00, 0x80, 0x20, 0x10, 0x04, 0x01, 0x04, 0x42, 38 | 0x10, 0xBF, 0xE0, 0x38, 0x38, 0xC3, 0x05, 0x28, 0x29, 0x42, 0x52, 0x13, 39 | 0x10, 0x99, 0x84, 0x08, 0x20, 0x47, 0x8F, 0x00, 0x70, 0xE6, 0x08, 0xA1, 40 | 0x14, 0x22, 0x48, 0x49, 0x11, 0x22, 0x14, 0x43, 0x1E, 0x20, 0x1E, 0x18, 41 | 0x90, 0x28, 0x18, 0x0C, 0x06, 0x05, 0x02, 0x46, 0x1E, 0x00, 0x3F, 0x84, 42 | 0x31, 0x04, 0x81, 0x20, 0x8F, 0xC2, 0x00, 0x80, 0x60, 0x3E, 0x00, 0x1E, 43 | 0x18, 0x90, 0x28, 0x18, 0x0C, 0x06, 0x05, 0x02, 0x46, 0x1E, 0x08, 0x0F, 44 | 0x44, 0x60, 0x3F, 0x84, 0x31, 0x04, 0x81, 0x20, 0x8F, 0xC2, 0x10, 0x84, 45 | 0x60, 0xBC, 0x10, 0x0F, 0x88, 0xC8, 0x24, 0x01, 0x80, 0x38, 0x05, 0x02, 46 | 0xC2, 0x5E, 0x00, 0xFF, 0xC4, 0x44, 0x02, 0x01, 0x00, 0x80, 0x40, 0x60, 47 | 0x20, 0x7E, 0x00, 0xF1, 0xD0, 0x24, 0x09, 0x02, 0x41, 0xA0, 0x48, 0x12, 48 | 0x04, 0xC6, 0x1F, 0x00, 0xF1, 0xE8, 0x11, 0x02, 0x20, 0x82, 0x20, 0x44, 49 | 0x09, 0x01, 0x40, 0x28, 0x02, 0x00, 0xF1, 0xE8, 0x09, 0x12, 0x26, 0x45, 50 | 0x48, 0xAA, 0x29, 0x45, 0x28, 0xC6, 0x18, 0xC0, 0x38, 0xE2, 0x08, 0x26, 51 | 0x05, 0x00, 0x40, 0x18, 0x04, 0x81, 0x08, 0x41, 0x1C, 0x70, 0xE3, 0xA0, 52 | 0x90, 0x84, 0x81, 0x80, 0x80, 0x40, 0x20, 0x20, 0x7E, 0x00, 0x3F, 0x90, 53 | 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x7F, 0x00, 0x39, 0x08, 54 | 0x44, 0x21, 0x08, 0x42, 0x21, 0x0E, 0x00, 0x88, 0x44, 0x44, 0x22, 0x22, 55 | 0x11, 0x11, 0x38, 0x42, 0x11, 0x08, 0x42, 0x10, 0x84, 0x2E, 0x00, 0x08, 56 | 0x28, 0x92, 0x18, 0x20, 0xFF, 0xC0, 0xA4, 0x3E, 0x00, 0x80, 0x47, 0xA4, 57 | 0x34, 0x12, 0x18, 0xF7, 0x38, 0x01, 0x00, 0x40, 0x09, 0xE1, 0xC6, 0x20, 58 | 0x44, 0x09, 0x01, 0x30, 0x46, 0x13, 0xBC, 0x00, 0x1F, 0x48, 0x74, 0x0A, 59 | 0x00, 0x80, 0x20, 0x0C, 0x18, 0xF8, 0x01, 0x80, 0x40, 0x23, 0x96, 0x32, 60 | 0x0A, 0x05, 0x02, 0x81, 0x61, 0x1F, 0xE0, 0x1F, 0x30, 0xD0, 0x3F, 0xF8, 61 | 0x04, 0x01, 0x00, 0x7C, 0x07, 0xC3, 0x00, 0x80, 0xFE, 0x10, 0x04, 0x01, 62 | 0x00, 0x40, 0x10, 0x08, 0x0F, 0xE0, 0x1D, 0xD8, 0xC4, 0x12, 0x04, 0x82, 63 | 0x20, 0x8C, 0x61, 0xE8, 0x02, 0x01, 0x07, 0x80, 0x30, 0x04, 0x01, 0x00, 64 | 0x5C, 0x38, 0x88, 0x22, 0x08, 0x82, 0x21, 0x18, 0x4F, 0x3C, 0x04, 0x04, 65 | 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0xFF, 0x01, 0x00, 0x80, 66 | 0x03, 0xF0, 0x10, 0x08, 0x04, 0x02, 0x02, 0x01, 0x00, 0x80, 0x40, 0x47, 67 | 0xC0, 0x38, 0x08, 0x04, 0x02, 0x71, 0x20, 0xA0, 0xA0, 0x68, 0x24, 0x11, 68 | 0x38, 0xE0, 0x3C, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 69 | 0xFF, 0x3E, 0xE2, 0x64, 0x88, 0x91, 0x12, 0x24, 0x48, 0x91, 0x17, 0x33, 70 | 0x37, 0x14, 0x4C, 0x24, 0x12, 0x09, 0x08, 0x85, 0xE3, 0x1E, 0x10, 0x90, 71 | 0x30, 0x18, 0x0C, 0x0B, 0x08, 0x78, 0x33, 0xC3, 0x8C, 0x40, 0x88, 0x12, 72 | 0x02, 0x60, 0x8C, 0x31, 0x78, 0x20, 0x08, 0x03, 0xE0, 0x00, 0x1C, 0xD8, 73 | 0xC4, 0x12, 0x04, 0x81, 0x20, 0x4C, 0x21, 0xF8, 0x02, 0x00, 0x81, 0xF0, 74 | 0x73, 0x8E, 0x04, 0x04, 0x02, 0x01, 0x00, 0x81, 0xFC, 0x1F, 0x61, 0x40, 75 | 0x3C, 0x03, 0x81, 0x82, 0xFC, 0x10, 0x63, 0xF9, 0x02, 0x04, 0x10, 0x20, 76 | 0x40, 0x7C, 0xE3, 0x10, 0x90, 0x48, 0x24, 0x22, 0x11, 0x18, 0xF6, 0xF3, 77 | 0xD0, 0x44, 0x10, 0x88, 0x24, 0x09, 0x02, 0x80, 0x40, 0xE1, 0xD0, 0x24, 78 | 0x91, 0x24, 0x55, 0x19, 0x86, 0x61, 0x10, 0x39, 0xC4, 0x20, 0xB0, 0x30, 79 | 0x0C, 0x04, 0x86, 0x13, 0x8E, 0x3C, 0x71, 0x04, 0x10, 0x40, 0x88, 0x09, 80 | 0x00, 0xA0, 0x06, 0x00, 0x40, 0x08, 0x01, 0x00, 0xFC, 0x00, 0x7F, 0x42, 81 | 0x04, 0x08, 0x10, 0x20, 0x42, 0xFE, 0x0C, 0x41, 0x04, 0x30, 0x8C, 0x08, 82 | 0x21, 0x04, 0x10, 0x60, 0x24, 0x94, 0x92, 0x52, 0x40, 0x18, 0x20, 0x82, 83 | 0x10, 0x40, 0xC4, 0x10, 0x82, 0x08, 0xC0, 0x61, 0x24, 0x30 }; 84 | 85 | const GFXglyph FreeMonoOblique9pt7bGlyphs[] = { 86 | { 0, 0, 0, 11, 0, 1 }, // 0x20 ' ' 87 | { 0, 4, 11, 11, 4, -10 }, // 0x21 '!' 88 | { 6, 5, 5, 11, 4, -10 }, // 0x22 '"' 89 | { 10, 9, 12, 11, 2, -10 }, // 0x23 '#' 90 | { 24, 8, 12, 11, 3, -10 }, // 0x24 '$' 91 | { 36, 9, 11, 11, 2, -10 }, // 0x25 '%' 92 | { 49, 7, 10, 11, 2, -9 }, // 0x26 '&' 93 | { 58, 2, 5, 11, 6, -10 }, // 0x27 ''' 94 | { 60, 4, 13, 11, 6, -10 }, // 0x28 '(' 95 | { 67, 4, 13, 11, 3, -10 }, // 0x29 ')' 96 | { 74, 7, 7, 11, 4, -10 }, // 0x2A '*' 97 | { 81, 9, 8, 11, 2, -8 }, // 0x2B '+' 98 | { 90, 4, 5, 11, 2, -1 }, // 0x2C ',' 99 | { 93, 9, 1, 11, 2, -5 }, // 0x2D '-' 100 | { 95, 2, 2, 11, 4, -1 }, // 0x2E '.' 101 | { 96, 9, 13, 11, 2, -11 }, // 0x2F '/' 102 | { 111, 7, 11, 11, 3, -10 }, // 0x30 '0' 103 | { 121, 7, 11, 11, 2, -10 }, // 0x31 '1' 104 | { 131, 9, 11, 11, 2, -10 }, // 0x32 '2' 105 | { 144, 9, 11, 11, 2, -10 }, // 0x33 '3' 106 | { 157, 8, 11, 11, 2, -10 }, // 0x34 '4' 107 | { 168, 9, 11, 11, 2, -10 }, // 0x35 '5' 108 | { 181, 8, 11, 11, 3, -10 }, // 0x36 '6' 109 | { 192, 7, 11, 11, 4, -10 }, // 0x37 '7' 110 | { 202, 8, 11, 11, 3, -10 }, // 0x38 '8' 111 | { 213, 8, 11, 11, 3, -10 }, // 0x39 '9' 112 | { 224, 3, 8, 11, 4, -7 }, // 0x3A ':' 113 | { 227, 5, 11, 11, 2, -7 }, // 0x3B ';' 114 | { 234, 9, 8, 11, 2, -8 }, // 0x3C '<' 115 | { 243, 9, 4, 11, 2, -6 }, // 0x3D '=' 116 | { 248, 9, 8, 11, 2, -8 }, // 0x3E '>' 117 | { 257, 7, 10, 11, 4, -9 }, // 0x3F '?' 118 | { 266, 7, 12, 11, 3, -10 }, // 0x40 '@' 119 | { 277, 11, 10, 11, 0, -9 }, // 0x41 'A' 120 | { 291, 10, 10, 11, 1, -9 }, // 0x42 'B' 121 | { 304, 9, 10, 11, 2, -9 }, // 0x43 'C' 122 | { 316, 10, 10, 11, 1, -9 }, // 0x44 'D' 123 | { 329, 10, 10, 11, 1, -9 }, // 0x45 'E' 124 | { 342, 11, 10, 11, 1, -9 }, // 0x46 'F' 125 | { 356, 9, 10, 11, 2, -9 }, // 0x47 'G' 126 | { 368, 11, 10, 11, 1, -9 }, // 0x48 'H' 127 | { 382, 9, 10, 11, 2, -9 }, // 0x49 'I' 128 | { 394, 11, 10, 11, 2, -9 }, // 0x4A 'J' 129 | { 408, 11, 10, 11, 1, -9 }, // 0x4B 'K' 130 | { 422, 10, 10, 11, 1, -9 }, // 0x4C 'L' 131 | { 435, 13, 10, 11, 0, -9 }, // 0x4D 'M' 132 | { 452, 11, 10, 11, 1, -9 }, // 0x4E 'N' 133 | { 466, 9, 10, 11, 2, -9 }, // 0x4F 'O' 134 | { 478, 10, 10, 11, 1, -9 }, // 0x50 'P' 135 | { 491, 9, 13, 11, 2, -9 }, // 0x51 'Q' 136 | { 506, 10, 10, 11, 1, -9 }, // 0x52 'R' 137 | { 519, 9, 10, 11, 2, -9 }, // 0x53 'S' 138 | { 531, 9, 10, 11, 3, -9 }, // 0x54 'T' 139 | { 543, 10, 10, 11, 2, -9 }, // 0x55 'U' 140 | { 556, 11, 10, 11, 2, -9 }, // 0x56 'V' 141 | { 570, 11, 10, 11, 2, -9 }, // 0x57 'W' 142 | { 584, 11, 10, 11, 1, -9 }, // 0x58 'X' 143 | { 598, 9, 10, 11, 3, -9 }, // 0x59 'Y' 144 | { 610, 9, 10, 11, 2, -9 }, // 0x5A 'Z' 145 | { 622, 5, 13, 11, 5, -10 }, // 0x5B '[' 146 | { 631, 4, 14, 11, 4, -11 }, // 0x5C '\' 147 | { 638, 5, 13, 11, 2, -10 }, // 0x5D ']' 148 | { 647, 7, 5, 11, 3, -10 }, // 0x5E '^' 149 | { 652, 11, 1, 11, 0, 2 }, // 0x5F '_' 150 | { 654, 2, 3, 11, 5, -11 }, // 0x60 '`' 151 | { 655, 9, 8, 11, 2, -7 }, // 0x61 'a' 152 | { 664, 11, 11, 11, 0, -10 }, // 0x62 'b' 153 | { 680, 10, 8, 11, 2, -7 }, // 0x63 'c' 154 | { 690, 9, 11, 11, 2, -10 }, // 0x64 'd' 155 | { 703, 9, 8, 11, 2, -7 }, // 0x65 'e' 156 | { 712, 10, 11, 11, 2, -10 }, // 0x66 'f' 157 | { 726, 10, 11, 11, 2, -7 }, // 0x67 'g' 158 | { 740, 10, 11, 11, 1, -10 }, // 0x68 'h' 159 | { 754, 8, 11, 11, 2, -10 }, // 0x69 'i' 160 | { 765, 9, 14, 11, 1, -10 }, // 0x6A 'j' 161 | { 781, 9, 11, 11, 1, -10 }, // 0x6B 'k' 162 | { 794, 8, 11, 11, 2, -10 }, // 0x6C 'l' 163 | { 805, 11, 8, 11, 0, -7 }, // 0x6D 'm' 164 | { 816, 9, 8, 11, 1, -7 }, // 0x6E 'n' 165 | { 825, 9, 8, 11, 2, -7 }, // 0x6F 'o' 166 | { 834, 11, 11, 11, 0, -7 }, // 0x70 'p' 167 | { 850, 10, 11, 11, 2, -7 }, // 0x71 'q' 168 | { 864, 9, 8, 11, 2, -7 }, // 0x72 'r' 169 | { 873, 8, 8, 11, 2, -7 }, // 0x73 's' 170 | { 881, 7, 10, 11, 2, -9 }, // 0x74 't' 171 | { 890, 9, 8, 11, 2, -7 }, // 0x75 'u' 172 | { 899, 10, 8, 11, 2, -7 }, // 0x76 'v' 173 | { 909, 10, 8, 11, 2, -7 }, // 0x77 'w' 174 | { 919, 10, 8, 11, 1, -7 }, // 0x78 'x' 175 | { 929, 12, 11, 11, 0, -7 }, // 0x79 'y' 176 | { 946, 8, 8, 11, 2, -7 }, // 0x7A 'z' 177 | { 954, 6, 13, 11, 4, -10 }, // 0x7B '{' 178 | { 964, 3, 12, 11, 5, -9 }, // 0x7C '|' 179 | { 969, 6, 13, 11, 3, -10 }, // 0x7D '}' 180 | { 979, 7, 3, 11, 3, -6 } }; // 0x7E '~' 181 | 182 | const GFXfont FreeMonoOblique9pt7b = { 183 | (uint8_t *)FreeMonoOblique9pt7bBitmaps, 184 | (GFXglyph *)FreeMonoOblique9pt7bGlyphs, 185 | 0x20, 0x7E, 18 }; 186 | 187 | // Approx. 1654 bytes 188 | -------------------------------------------------------------------------------- /main/fonts/FreeMonoBold9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeMonoBold9pt7bBitmaps[] = { 2 | 0xFF, 0xFF, 0xD2, 0x1F, 0x80, 0xEC, 0x89, 0x12, 0x24, 0x40, 0x36, 0x36, 3 | 0x36, 0x7F, 0x7F, 0x36, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x00, 0x18, 0xFF, 4 | 0xFE, 0x3C, 0x1F, 0x1F, 0x83, 0x46, 0x8D, 0xF0, 0xC1, 0x83, 0x00, 0x61, 5 | 0x22, 0x44, 0x86, 0x67, 0x37, 0x11, 0x22, 0x4C, 0x70, 0x3C, 0x7E, 0x60, 6 | 0x60, 0x30, 0x7B, 0xDF, 0xCE, 0xFF, 0x7F, 0xC9, 0x24, 0x37, 0x66, 0xCC, 7 | 0xCC, 0xCC, 0x66, 0x31, 0xCE, 0x66, 0x33, 0x33, 0x33, 0x66, 0xC8, 0x18, 8 | 0x18, 0xFF, 0xFF, 0x3C, 0x3C, 0x66, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 9 | 0x18, 0x18, 0x18, 0x6B, 0x48, 0xFF, 0xFF, 0xC0, 0xF0, 0x02, 0x0C, 0x18, 10 | 0x60, 0xC3, 0x06, 0x0C, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x20, 0x00, 0x38, 11 | 0xFB, 0xBE, 0x3C, 0x78, 0xF1, 0xE3, 0xC7, 0xDD, 0xF1, 0xC0, 0x38, 0xF3, 12 | 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0xFD, 0xF8, 0x3C, 0xFE, 0xC7, 0x03, 13 | 0x03, 0x06, 0x0C, 0x18, 0x70, 0xE3, 0xFF, 0xFF, 0x7C, 0xFE, 0x03, 0x03, 14 | 0x03, 0x1E, 0x1E, 0x07, 0x03, 0x03, 0xFE, 0x7C, 0x1C, 0x38, 0xB1, 0x64, 15 | 0xD9, 0xBF, 0xFF, 0x3E, 0x7C, 0x7E, 0x3F, 0x18, 0x0F, 0xC7, 0xF3, 0x1C, 16 | 0x06, 0x03, 0xC3, 0xFF, 0x9F, 0x80, 0x0F, 0x3F, 0x30, 0x60, 0x60, 0xDC, 17 | 0xFE, 0xE3, 0xC3, 0x63, 0x7E, 0x3C, 0xFF, 0xFF, 0xC3, 0x03, 0x06, 0x06, 18 | 0x06, 0x0C, 0x0C, 0x0C, 0x18, 0x38, 0xFB, 0x1E, 0x3C, 0x6F, 0x9F, 0x63, 19 | 0xC7, 0x8F, 0xF1, 0xC0, 0x3C, 0x7E, 0xE6, 0xC3, 0xC3, 0xE7, 0x7F, 0x3B, 20 | 0x06, 0x0E, 0xFC, 0xF0, 0xF0, 0x0F, 0x6C, 0x00, 0x1A, 0xD2, 0x00, 0x01, 21 | 0x83, 0x87, 0x0E, 0x0F, 0x80, 0xE0, 0x1C, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 22 | 0x0F, 0xFF, 0xFC, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0xF9, 0xE3, 0xC1, 0x80, 23 | 0x7C, 0xFE, 0xC7, 0x03, 0x0E, 0x1C, 0x00, 0x00, 0x00, 0x30, 0x30, 0x1E, 24 | 0x1F, 0x1C, 0xDC, 0x6C, 0x76, 0x7B, 0x6D, 0xB6, 0xDB, 0x6F, 0xF3, 0xFC, 25 | 0x06, 0x33, 0xF8, 0x78, 0x3C, 0x07, 0xC0, 0x38, 0x05, 0x81, 0xB0, 0x36, 26 | 0x0F, 0xE1, 0xFC, 0x71, 0xDF, 0x7F, 0xEF, 0x80, 0xFF, 0x3F, 0xE6, 0x19, 27 | 0x86, 0x7F, 0x1F, 0xE6, 0x1D, 0x83, 0x60, 0xFF, 0xFF, 0xF0, 0x1F, 0xBF, 28 | 0xD8, 0xF8, 0x3C, 0x06, 0x03, 0x01, 0x80, 0x61, 0xBF, 0xC7, 0xC0, 0xFE, 29 | 0x3F, 0xE6, 0x19, 0x83, 0x60, 0xD8, 0x36, 0x0D, 0x83, 0x61, 0xBF, 0xEF, 30 | 0xE0, 0xFF, 0xFF, 0xD8, 0x6D, 0xB7, 0xC3, 0xE1, 0xB0, 0xC3, 0x61, 0xFF, 31 | 0xFF, 0xE0, 0xFF, 0xFF, 0xD8, 0x6D, 0xB7, 0xC3, 0xE1, 0xB0, 0xC0, 0x60, 32 | 0x7C, 0x3E, 0x00, 0x1F, 0x9F, 0xE6, 0x1B, 0x06, 0xC0, 0x30, 0x0C, 0x7F, 33 | 0x1F, 0xE1, 0x9F, 0xE3, 0xF0, 0xF7, 0xFB, 0xD8, 0xCC, 0x66, 0x33, 0xF9, 34 | 0xFC, 0xC6, 0x63, 0x7B, 0xFD, 0xE0, 0xFF, 0xF3, 0x0C, 0x30, 0xC3, 0x0C, 35 | 0x33, 0xFF, 0xC0, 0x1F, 0xC7, 0xF0, 0x30, 0x0C, 0x03, 0x00, 0xCC, 0x33, 36 | 0x0C, 0xC7, 0x3F, 0x87, 0xC0, 0xF7, 0xBD, 0xE6, 0x61, 0xB0, 0x78, 0x1F, 37 | 0x06, 0xE1, 0x98, 0x63, 0x3C, 0xFF, 0x3C, 0xFC, 0x7E, 0x0C, 0x06, 0x03, 38 | 0x01, 0x80, 0xC6, 0x63, 0x31, 0xFF, 0xFF, 0xE0, 0xE0, 0xFE, 0x3D, 0xC7, 39 | 0x3D, 0xE7, 0xBC, 0xD7, 0x9B, 0xB3, 0x76, 0x60, 0xDE, 0x3F, 0xC7, 0x80, 40 | 0xE1, 0xFE, 0x3D, 0xE3, 0x3C, 0x66, 0xCC, 0xDD, 0x99, 0xB3, 0x1E, 0x63, 41 | 0xDE, 0x3B, 0xC3, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, 42 | 0xF0, 0x1F, 0x07, 0x71, 0xC7, 0xF0, 0x7C, 0x00, 0xFE, 0x7F, 0x98, 0x6C, 43 | 0x36, 0x1B, 0xF9, 0xF8, 0xC0, 0x60, 0x7C, 0x3E, 0x00, 0x1F, 0x07, 0xF1, 44 | 0xC7, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1F, 0x07, 0x71, 0xC7, 0xF0, 0x7C, 45 | 0x0C, 0x33, 0xFE, 0x7F, 0x80, 0xFC, 0x7F, 0x18, 0xCC, 0x66, 0x73, 0xF1, 46 | 0xF0, 0xCC, 0x63, 0x7D, 0xFE, 0x60, 0x3F, 0xBF, 0xF0, 0x78, 0x0F, 0x03, 47 | 0xF8, 0x3F, 0x83, 0xC3, 0xFF, 0xBF, 0x80, 0xFF, 0xFF, 0xF6, 0x7B, 0x3D, 48 | 0x98, 0xC0, 0x60, 0x30, 0x18, 0x3F, 0x1F, 0x80, 0xF1, 0xFE, 0x3D, 0x83, 49 | 0x30, 0x66, 0x0C, 0xC1, 0x98, 0x33, 0x06, 0x60, 0xC7, 0xF0, 0x7C, 0x00, 50 | 0xFB, 0xFF, 0x7D, 0xC3, 0x18, 0xC3, 0x18, 0x36, 0x06, 0xC0, 0x50, 0x0E, 51 | 0x01, 0xC0, 0x10, 0x00, 0xFB, 0xFE, 0xF6, 0x0D, 0x93, 0x6E, 0xDB, 0xB7, 52 | 0xAD, 0xEE, 0x7B, 0x8E, 0xE3, 0x18, 0xF3, 0xFC, 0xF7, 0x38, 0xFC, 0x1E, 53 | 0x03, 0x01, 0xE0, 0xCC, 0x73, 0xBC, 0xFF, 0x3C, 0xF3, 0xFC, 0xF7, 0x38, 54 | 0xCC, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x0C, 0x0F, 0xC3, 0xF0, 0xFE, 0xFE, 55 | 0xC6, 0xCC, 0x18, 0x18, 0x30, 0x63, 0xC3, 0xFF, 0xFF, 0xFF, 0xCC, 0xCC, 56 | 0xCC, 0xCC, 0xCC, 0xFF, 0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 57 | 0x30, 0x30, 0x60, 0x60, 0xC0, 0x80, 0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 58 | 0xFF, 0x10, 0x71, 0xE3, 0x6C, 0x70, 0x40, 0xFF, 0xFF, 0xFC, 0x88, 0x80, 59 | 0x7E, 0x3F, 0x8F, 0xCF, 0xEE, 0x36, 0x1B, 0xFE, 0xFF, 0xE0, 0x38, 0x06, 60 | 0x01, 0xBC, 0x7F, 0x9C, 0x76, 0x0D, 0x83, 0x71, 0xFF, 0xEE, 0xF0, 0x3F, 61 | 0xBF, 0xF8, 0x78, 0x3C, 0x07, 0x05, 0xFE, 0x7E, 0x03, 0x80, 0xE0, 0x18, 62 | 0xF6, 0x7F, 0xB8, 0xEC, 0x1B, 0x06, 0xE3, 0x9F, 0xF3, 0xFC, 0x3E, 0x3F, 63 | 0xB0, 0xFF, 0xFF, 0xFE, 0x01, 0xFE, 0x7E, 0x1F, 0x3F, 0x30, 0x7E, 0x7E, 64 | 0x30, 0x30, 0x30, 0x30, 0xFE, 0xFE, 0x3F, 0xBF, 0xF9, 0xD8, 0x6C, 0x37, 65 | 0x39, 0xFC, 0x76, 0x03, 0x01, 0x8F, 0xC7, 0xC0, 0xE0, 0x70, 0x18, 0x0D, 66 | 0xC7, 0xF3, 0x99, 0x8C, 0xC6, 0x63, 0x7B, 0xFD, 0xE0, 0x18, 0x18, 0x00, 67 | 0x78, 0x78, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x60, 0x3F, 0xFC, 68 | 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0F, 0xFF, 0x80, 0xE0, 0x70, 0x18, 0x0D, 69 | 0xE6, 0xF3, 0xE1, 0xE0, 0xF8, 0x6E, 0x73, 0xF9, 0xE0, 0x78, 0x78, 0x18, 70 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xFD, 0x9F, 0xF9, 0x9B, 71 | 0x33, 0x66, 0x6C, 0xCD, 0xBD, 0xFF, 0xBF, 0xEE, 0x7F, 0x98, 0xCC, 0x66, 72 | 0x33, 0x1B, 0xDF, 0xEF, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C, 0x1F, 0x1D, 0xFC, 73 | 0x7C, 0xEF, 0x1F, 0xF9, 0xC3, 0xB0, 0x36, 0x06, 0xE1, 0xDF, 0xF3, 0x78, 74 | 0x60, 0x0C, 0x03, 0xE0, 0x7C, 0x00, 0x1E, 0xEF, 0xFF, 0x87, 0x60, 0x6C, 75 | 0x0D, 0xC3, 0x9F, 0xF0, 0xF6, 0x00, 0xC0, 0x18, 0x0F, 0x81, 0xF0, 0x77, 76 | 0xBF, 0xCF, 0x06, 0x03, 0x01, 0x83, 0xF9, 0xFC, 0x3F, 0xFF, 0xC3, 0xFC, 77 | 0x3F, 0xC3, 0xFF, 0xFC, 0x60, 0x60, 0x60, 0xFE, 0xFE, 0x60, 0x60, 0x60, 78 | 0x61, 0x7F, 0x3E, 0xE7, 0x73, 0x98, 0xCC, 0x66, 0x33, 0x19, 0xFE, 0x7F, 79 | 0xFB, 0xFF, 0x7C, 0xC6, 0x18, 0xC1, 0xB0, 0x36, 0x03, 0x80, 0x70, 0xF1, 80 | 0xFE, 0x3D, 0xBB, 0x37, 0x63, 0xF8, 0x77, 0x0E, 0xE1, 0x8C, 0xF7, 0xFB, 81 | 0xCD, 0x83, 0x83, 0xC3, 0xBB, 0xDF, 0xEF, 0xF3, 0xFC, 0xF6, 0x18, 0xCC, 82 | 0x33, 0x07, 0x81, 0xE0, 0x30, 0x0C, 0x06, 0x0F, 0xC3, 0xF0, 0xFF, 0xFF, 83 | 0x30, 0xC3, 0x0C, 0x7F, 0xFF, 0x37, 0x66, 0x66, 0xCC, 0x66, 0x66, 0x73, 84 | 0xFF, 0xFF, 0xFF, 0xF0, 0xCE, 0x66, 0x66, 0x33, 0x66, 0x66, 0xEC, 0x70, 85 | 0x7C, 0xF3, 0xC0, 0xC0 }; 86 | 87 | const GFXglyph FreeMonoBold9pt7bGlyphs[] = { 88 | { 0, 0, 0, 11, 0, 1 }, // 0x20 ' ' 89 | { 0, 3, 11, 11, 4, -10 }, // 0x21 '!' 90 | { 5, 7, 5, 11, 2, -10 }, // 0x22 '"' 91 | { 10, 8, 12, 11, 1, -10 }, // 0x23 '#' 92 | { 22, 7, 14, 11, 2, -11 }, // 0x24 '$' 93 | { 35, 7, 11, 11, 2, -10 }, // 0x25 '%' 94 | { 45, 8, 10, 11, 1, -9 }, // 0x26 '&' 95 | { 55, 3, 5, 11, 4, -10 }, // 0x27 ''' 96 | { 57, 4, 14, 11, 5, -10 }, // 0x28 '(' 97 | { 64, 4, 14, 11, 2, -10 }, // 0x29 ')' 98 | { 71, 8, 7, 11, 2, -10 }, // 0x2A '*' 99 | { 78, 8, 9, 11, 2, -8 }, // 0x2B '+' 100 | { 87, 3, 5, 11, 3, -1 }, // 0x2C ',' 101 | { 89, 9, 2, 11, 1, -5 }, // 0x2D '-' 102 | { 92, 2, 2, 11, 4, -1 }, // 0x2E '.' 103 | { 93, 7, 15, 11, 2, -12 }, // 0x2F '/' 104 | { 107, 7, 12, 11, 2, -11 }, // 0x30 '0' 105 | { 118, 7, 11, 11, 2, -10 }, // 0x31 '1' 106 | { 128, 8, 12, 11, 1, -11 }, // 0x32 '2' 107 | { 140, 8, 12, 11, 2, -11 }, // 0x33 '3' 108 | { 152, 7, 10, 11, 2, -9 }, // 0x34 '4' 109 | { 161, 9, 11, 11, 1, -10 }, // 0x35 '5' 110 | { 174, 8, 12, 11, 2, -11 }, // 0x36 '6' 111 | { 186, 8, 11, 11, 1, -10 }, // 0x37 '7' 112 | { 197, 7, 12, 11, 2, -11 }, // 0x38 '8' 113 | { 208, 8, 12, 11, 2, -11 }, // 0x39 '9' 114 | { 220, 2, 8, 11, 4, -7 }, // 0x3A ':' 115 | { 222, 3, 11, 11, 3, -7 }, // 0x3B ';' 116 | { 227, 9, 8, 11, 1, -8 }, // 0x3C '<' 117 | { 236, 9, 6, 11, 1, -7 }, // 0x3D '=' 118 | { 243, 9, 8, 11, 1, -8 }, // 0x3E '>' 119 | { 252, 8, 11, 11, 2, -10 }, // 0x3F '?' 120 | { 263, 9, 15, 11, 1, -11 }, // 0x40 '@' 121 | { 280, 11, 11, 11, 0, -10 }, // 0x41 'A' 122 | { 296, 10, 11, 11, 1, -10 }, // 0x42 'B' 123 | { 310, 9, 11, 11, 1, -10 }, // 0x43 'C' 124 | { 323, 10, 11, 11, 0, -10 }, // 0x44 'D' 125 | { 337, 9, 11, 11, 1, -10 }, // 0x45 'E' 126 | { 350, 9, 11, 11, 1, -10 }, // 0x46 'F' 127 | { 363, 10, 11, 11, 1, -10 }, // 0x47 'G' 128 | { 377, 9, 11, 11, 1, -10 }, // 0x48 'H' 129 | { 390, 6, 11, 11, 3, -10 }, // 0x49 'I' 130 | { 399, 10, 11, 11, 1, -10 }, // 0x4A 'J' 131 | { 413, 10, 11, 11, 1, -10 }, // 0x4B 'K' 132 | { 427, 9, 11, 11, 1, -10 }, // 0x4C 'L' 133 | { 440, 11, 11, 11, 0, -10 }, // 0x4D 'M' 134 | { 456, 11, 11, 11, 0, -10 }, // 0x4E 'N' 135 | { 472, 11, 11, 11, 0, -10 }, // 0x4F 'O' 136 | { 488, 9, 11, 11, 1, -10 }, // 0x50 'P' 137 | { 501, 11, 14, 11, 0, -10 }, // 0x51 'Q' 138 | { 521, 9, 11, 11, 1, -10 }, // 0x52 'R' 139 | { 534, 9, 11, 11, 1, -10 }, // 0x53 'S' 140 | { 547, 9, 11, 11, 1, -10 }, // 0x54 'T' 141 | { 560, 11, 11, 11, 0, -10 }, // 0x55 'U' 142 | { 576, 11, 11, 11, 0, -10 }, // 0x56 'V' 143 | { 592, 10, 11, 11, 0, -10 }, // 0x57 'W' 144 | { 606, 10, 11, 11, 0, -10 }, // 0x58 'X' 145 | { 620, 10, 11, 11, 0, -10 }, // 0x59 'Y' 146 | { 634, 8, 11, 11, 2, -10 }, // 0x5A 'Z' 147 | { 645, 4, 14, 11, 5, -10 }, // 0x5B '[' 148 | { 652, 7, 15, 11, 2, -12 }, // 0x5C '\' 149 | { 666, 4, 14, 11, 2, -10 }, // 0x5D ']' 150 | { 673, 7, 6, 11, 2, -11 }, // 0x5E '^' 151 | { 679, 11, 2, 11, 0, 3 }, // 0x5F '_' 152 | { 682, 3, 3, 11, 3, -11 }, // 0x60 '`' 153 | { 684, 9, 8, 11, 1, -7 }, // 0x61 'a' 154 | { 693, 10, 11, 11, 0, -10 }, // 0x62 'b' 155 | { 707, 9, 8, 11, 1, -7 }, // 0x63 'c' 156 | { 716, 10, 11, 11, 1, -10 }, // 0x64 'd' 157 | { 730, 9, 8, 11, 1, -7 }, // 0x65 'e' 158 | { 739, 8, 11, 11, 2, -10 }, // 0x66 'f' 159 | { 750, 9, 12, 11, 1, -7 }, // 0x67 'g' 160 | { 764, 9, 11, 11, 1, -10 }, // 0x68 'h' 161 | { 777, 8, 11, 11, 2, -10 }, // 0x69 'i' 162 | { 788, 6, 15, 11, 2, -10 }, // 0x6A 'j' 163 | { 800, 9, 11, 11, 1, -10 }, // 0x6B 'k' 164 | { 813, 8, 11, 11, 2, -10 }, // 0x6C 'l' 165 | { 824, 11, 8, 11, 0, -7 }, // 0x6D 'm' 166 | { 835, 9, 8, 11, 1, -7 }, // 0x6E 'n' 167 | { 844, 9, 8, 11, 1, -7 }, // 0x6F 'o' 168 | { 853, 11, 12, 11, 0, -7 }, // 0x70 'p' 169 | { 870, 11, 12, 11, 0, -7 }, // 0x71 'q' 170 | { 887, 9, 8, 11, 1, -7 }, // 0x72 'r' 171 | { 896, 8, 8, 11, 2, -7 }, // 0x73 's' 172 | { 904, 8, 11, 11, 1, -10 }, // 0x74 't' 173 | { 915, 9, 8, 11, 1, -7 }, // 0x75 'u' 174 | { 924, 11, 8, 11, 0, -7 }, // 0x76 'v' 175 | { 935, 11, 8, 11, 0, -7 }, // 0x77 'w' 176 | { 946, 9, 8, 11, 1, -7 }, // 0x78 'x' 177 | { 955, 10, 12, 11, 0, -7 }, // 0x79 'y' 178 | { 970, 7, 8, 11, 2, -7 }, // 0x7A 'z' 179 | { 977, 4, 14, 11, 3, -10 }, // 0x7B '{' 180 | { 984, 2, 14, 11, 5, -10 }, // 0x7C '|' 181 | { 988, 4, 14, 11, 4, -10 }, // 0x7D '}' 182 | { 995, 9, 4, 11, 1, -6 } }; // 0x7E '~' 183 | 184 | const GFXfont FreeMonoBold9pt7b = { 185 | (uint8_t *)FreeMonoBold9pt7bBitmaps, 186 | (GFXglyph *)FreeMonoBold9pt7bGlyphs, 187 | 0x20, 0x7E, 18 }; 188 | 189 | // Approx. 1672 bytes 190 | -------------------------------------------------------------------------------- /main/fonts/FreeSerif9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeSerif9pt7bBitmaps[] = { 2 | 0xFF, 0xEA, 0x03, 0xDE, 0xF7, 0x20, 0x11, 0x09, 0x04, 0x82, 0x4F, 0xF9, 3 | 0x10, 0x89, 0xFF, 0x24, 0x12, 0x09, 0x0C, 0x80, 0x10, 0x7C, 0xD6, 0xD2, 4 | 0xD0, 0xF0, 0x38, 0x1E, 0x17, 0x93, 0x93, 0xD6, 0x7C, 0x10, 0x38, 0x43, 5 | 0x3C, 0x39, 0x21, 0x8A, 0x0C, 0x50, 0x65, 0x39, 0xCB, 0x20, 0xB9, 0x05, 6 | 0x88, 0x4C, 0x44, 0x64, 0x21, 0xC0, 0x0E, 0x00, 0xC8, 0x06, 0x40, 0x32, 7 | 0x01, 0xA0, 0x07, 0x78, 0x31, 0x87, 0x88, 0x46, 0x86, 0x34, 0x30, 0xC1, 8 | 0xC7, 0x17, 0xCF, 0x00, 0xFE, 0x08, 0x88, 0x84, 0x63, 0x18, 0xC6, 0x10, 9 | 0x82, 0x08, 0x20, 0x82, 0x08, 0x21, 0x0C, 0x63, 0x18, 0xC4, 0x22, 0x22, 10 | 0x00, 0x63, 0x9A, 0xDC, 0x72, 0xB6, 0x08, 0x08, 0x04, 0x02, 0x01, 0x0F, 11 | 0xF8, 0x40, 0x20, 0x10, 0x08, 0x00, 0xD8, 0xF0, 0xF0, 0x08, 0x84, 0x22, 12 | 0x10, 0x8C, 0x42, 0x31, 0x00, 0x1C, 0x31, 0x98, 0xD8, 0x3C, 0x1E, 0x0F, 13 | 0x07, 0x83, 0xC1, 0xE0, 0xD8, 0xC4, 0x61, 0xC0, 0x13, 0x8C, 0x63, 0x18, 14 | 0xC6, 0x31, 0x8C, 0x67, 0x80, 0x3C, 0x4E, 0x86, 0x06, 0x06, 0x04, 0x0C, 15 | 0x08, 0x10, 0x20, 0x41, 0xFE, 0x3C, 0xC6, 0x06, 0x04, 0x1C, 0x3E, 0x07, 16 | 0x03, 0x03, 0x03, 0x06, 0xF8, 0x04, 0x18, 0x71, 0x64, 0xC9, 0xA3, 0x46, 17 | 0xFE, 0x18, 0x30, 0x60, 0x0F, 0x10, 0x20, 0x3C, 0x0E, 0x07, 0x03, 0x03, 18 | 0x03, 0x02, 0x04, 0xF8, 0x07, 0x1C, 0x30, 0x60, 0x60, 0xDC, 0xE6, 0xC3, 19 | 0xC3, 0xC3, 0x43, 0x66, 0x3C, 0x7F, 0x82, 0x02, 0x02, 0x04, 0x04, 0x04, 20 | 0x08, 0x08, 0x08, 0x10, 0x10, 0x3C, 0x8F, 0x1E, 0x3E, 0x4F, 0x06, 0x36, 21 | 0xC7, 0x8F, 0x1B, 0x33, 0xC0, 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0xC3, 22 | 0x63, 0x3F, 0x06, 0x06, 0x0C, 0x38, 0x60, 0xF0, 0x0F, 0xD8, 0x00, 0x03, 23 | 0x28, 0x01, 0x87, 0x0E, 0x1C, 0x0C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x80, 24 | 0xFF, 0x80, 0x00, 0x00, 0x0F, 0xF8, 0x80, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 25 | 0xC0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00, 0x79, 0x1A, 0x18, 0x30, 0x60, 0x83, 26 | 0x04, 0x10, 0x20, 0x40, 0x03, 0x00, 0x0F, 0x83, 0x8C, 0x60, 0x26, 0x02, 27 | 0xC7, 0x9C, 0xC9, 0xD8, 0x9D, 0x99, 0xD9, 0x26, 0xEC, 0x60, 0x03, 0x04, 28 | 0x0F, 0x80, 0x02, 0x00, 0x10, 0x01, 0xC0, 0x16, 0x00, 0x98, 0x04, 0xC0, 29 | 0x43, 0x03, 0xF8, 0x20, 0x61, 0x03, 0x18, 0x1D, 0xE1, 0xF0, 0xFF, 0x86, 30 | 0x1C, 0xC1, 0x98, 0x33, 0x0C, 0x7E, 0x0C, 0x31, 0x83, 0x30, 0x66, 0x0C, 31 | 0xC3, 0x7F, 0xC0, 0x1F, 0x26, 0x1D, 0x81, 0xE0, 0x1C, 0x01, 0x80, 0x30, 32 | 0x06, 0x00, 0xC0, 0x0C, 0x00, 0xC1, 0x8F, 0xC0, 0xFF, 0x03, 0x1C, 0x30, 33 | 0x63, 0x07, 0x30, 0x33, 0x03, 0x30, 0x33, 0x03, 0x30, 0x33, 0x06, 0x30, 34 | 0xCF, 0xF0, 0xFF, 0x98, 0x26, 0x01, 0x80, 0x61, 0x1F, 0xC6, 0x11, 0x80, 35 | 0x60, 0x18, 0x16, 0x0F, 0xFE, 0xFF, 0xB0, 0x58, 0x0C, 0x06, 0x13, 0xF9, 36 | 0x84, 0xC0, 0x60, 0x30, 0x18, 0x1E, 0x00, 0x1F, 0x23, 0x0E, 0x60, 0x26, 37 | 0x00, 0xC0, 0x0C, 0x0F, 0xC0, 0x6C, 0x06, 0xC0, 0x66, 0x06, 0x30, 0x60, 38 | 0xF8, 0xF1, 0xEC, 0x19, 0x83, 0x30, 0x66, 0x0C, 0xFF, 0x98, 0x33, 0x06, 39 | 0x60, 0xCC, 0x19, 0x83, 0x78, 0xF0, 0xF6, 0x66, 0x66, 0x66, 0x66, 0x6F, 40 | 0x3C, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x6D, 0xBC, 0xF3, 0xE6, 0x08, 41 | 0x61, 0x06, 0x20, 0x64, 0x07, 0x80, 0x6C, 0x06, 0x60, 0x63, 0x06, 0x18, 42 | 0x60, 0xCF, 0x3F, 0xF0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 43 | 0x80, 0x60, 0x18, 0x16, 0x0B, 0xFE, 0xF0, 0x0E, 0x70, 0x38, 0xE0, 0x71, 44 | 0xE1, 0x62, 0xC2, 0xC5, 0xC9, 0x89, 0x93, 0x13, 0x26, 0x23, 0x8C, 0x47, 45 | 0x18, 0x84, 0x33, 0x88, 0xF0, 0xE0, 0xEE, 0x09, 0xC1, 0x2C, 0x25, 0xC4, 46 | 0x9C, 0x91, 0x92, 0x1A, 0x41, 0xC8, 0x19, 0x03, 0x70, 0x20, 0x1F, 0x06, 47 | 0x31, 0x83, 0x20, 0x2C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x68, 0x09, 48 | 0x83, 0x18, 0xC1, 0xF0, 0xFE, 0x31, 0x98, 0x6C, 0x36, 0x1B, 0x19, 0xF8, 49 | 0xC0, 0x60, 0x30, 0x18, 0x1E, 0x00, 0x1F, 0x06, 0x31, 0x83, 0x20, 0x2C, 50 | 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x68, 0x19, 0x83, 0x18, 0xC0, 0xE0, 51 | 0x0E, 0x00, 0xE0, 0x07, 0xFE, 0x0C, 0x61, 0x86, 0x30, 0xC6, 0x18, 0xC6, 52 | 0x1F, 0x83, 0x70, 0x67, 0x0C, 0x71, 0x87, 0x78, 0x70, 0x1D, 0x31, 0x98, 53 | 0x4C, 0x07, 0x80, 0xE0, 0x1C, 0x07, 0x01, 0xA0, 0xD8, 0xCB, 0xC0, 0xFF, 54 | 0xF8, 0xCE, 0x18, 0x83, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 55 | 0xC0, 0x18, 0x07, 0x80, 0xF0, 0xEC, 0x09, 0x81, 0x30, 0x26, 0x04, 0xC0, 56 | 0x98, 0x13, 0x02, 0x60, 0x4C, 0x08, 0xC2, 0x0F, 0x80, 0xF8, 0x77, 0x02, 57 | 0x30, 0x23, 0x04, 0x18, 0x41, 0x84, 0x0C, 0x80, 0xC8, 0x07, 0x00, 0x70, 58 | 0x02, 0x00, 0x20, 0xFB, 0xE7, 0xB0, 0xC0, 0x8C, 0x20, 0x86, 0x18, 0x41, 59 | 0x8C, 0x40, 0xCB, 0x20, 0x65, 0x90, 0x1A, 0x70, 0x0E, 0x38, 0x03, 0x1C, 60 | 0x01, 0x04, 0x00, 0x82, 0x00, 0xFC, 0xF9, 0x83, 0x06, 0x10, 0x19, 0x00, 61 | 0xD0, 0x03, 0x00, 0x1C, 0x01, 0x30, 0x11, 0xC1, 0x86, 0x08, 0x19, 0xE3, 62 | 0xF0, 0xF8, 0xF6, 0x06, 0x30, 0x41, 0x88, 0x1D, 0x00, 0xD0, 0x06, 0x00, 63 | 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xF0, 0x3F, 0xCC, 0x11, 0x06, 0x01, 64 | 0x80, 0x70, 0x0C, 0x03, 0x00, 0xE0, 0x38, 0x06, 0x05, 0xC1, 0x7F, 0xE0, 65 | 0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB8, 0x82, 0x10, 0x82, 0x10, 0x86, 0x10, 66 | 0x86, 0x10, 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xF8, 0x18, 0x1C, 0x34, 0x26, 67 | 0x62, 0x42, 0xC1, 0xFF, 0x80, 0x84, 0x20, 0x79, 0x98, 0x30, 0xE6, 0xD9, 68 | 0xB3, 0x3F, 0x20, 0x70, 0x18, 0x0C, 0x06, 0x03, 0x71, 0xCC, 0xC3, 0x61, 69 | 0xB0, 0xD8, 0x6C, 0x63, 0xE0, 0x3C, 0xCF, 0x06, 0x0C, 0x18, 0x18, 0x9E, 70 | 0x01, 0x03, 0x80, 0xC0, 0x60, 0x31, 0xD9, 0x9D, 0x86, 0xC3, 0x61, 0xB0, 71 | 0xCC, 0x63, 0xF0, 0x3C, 0x46, 0xFE, 0xC0, 0xC0, 0xE1, 0x62, 0x3C, 0x1E, 72 | 0x41, 0x83, 0x06, 0x1E, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x0F, 0x00, 0x3C, 73 | 0x19, 0xF6, 0x31, 0x8C, 0x1E, 0x08, 0x04, 0x01, 0xFC, 0x40, 0xB0, 0x2E, 74 | 0x11, 0xF8, 0x20, 0x70, 0x18, 0x0C, 0x06, 0x03, 0x71, 0xCC, 0xC6, 0x63, 75 | 0x31, 0x98, 0xCC, 0x6F, 0x78, 0x60, 0x02, 0xE6, 0x66, 0x66, 0xF0, 0x18, 76 | 0x00, 0x33, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8B, 0x80, 0x20, 0x70, 0x18, 77 | 0x0C, 0x06, 0x03, 0x3D, 0x88, 0xD8, 0x78, 0x36, 0x19, 0x8C, 0x6F, 0x78, 78 | 0x2E, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF0, 0xEE, 0x71, 0xCE, 0x66, 0x31, 79 | 0x98, 0xC6, 0x63, 0x19, 0x8C, 0x66, 0x31, 0xBD, 0xEF, 0xEE, 0x39, 0x98, 80 | 0xCC, 0x66, 0x33, 0x19, 0x8D, 0xEF, 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1E, 81 | 0x0D, 0x8C, 0x7C, 0xEE, 0x39, 0x98, 0x6C, 0x36, 0x1B, 0x0D, 0x8C, 0xFC, 82 | 0x60, 0x30, 0x18, 0x1E, 0x00, 0x3D, 0x31, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 83 | 0x8C, 0xFE, 0x03, 0x01, 0x80, 0xC0, 0xF0, 0x6D, 0xC6, 0x18, 0x61, 0x86, 84 | 0x3C, 0x76, 0x38, 0x58, 0x3E, 0x38, 0xFE, 0x27, 0x98, 0xC6, 0x31, 0x8C, 85 | 0x38, 0xE7, 0x31, 0x98, 0xCC, 0x66, 0x33, 0x19, 0x8C, 0x7F, 0xF3, 0x61, 86 | 0x22, 0x32, 0x14, 0x1C, 0x08, 0x08, 0xEF, 0x36, 0x61, 0x62, 0x22, 0x32, 87 | 0x35, 0x41, 0x9C, 0x18, 0x81, 0x08, 0xF7, 0x12, 0x0E, 0x03, 0x01, 0xC1, 88 | 0x21, 0x09, 0xCF, 0xF3, 0x61, 0x62, 0x32, 0x34, 0x14, 0x1C, 0x08, 0x08, 89 | 0x08, 0x10, 0xE0, 0xFD, 0x18, 0x60, 0x83, 0x0C, 0x70, 0xFE, 0x19, 0x8C, 90 | 0x63, 0x18, 0xC4, 0x61, 0x8C, 0x63, 0x18, 0xC3, 0xFF, 0xF0, 0xC3, 0x18, 91 | 0xC6, 0x31, 0x84, 0x33, 0x18, 0xC6, 0x31, 0x98, 0x70, 0x24, 0xC1, 0xC0 }; 92 | 93 | const GFXglyph FreeSerif9pt7bGlyphs[] = { 94 | { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' 95 | { 0, 2, 12, 6, 2, -11 }, // 0x21 '!' 96 | { 3, 5, 4, 7, 1, -11 }, // 0x22 '"' 97 | { 6, 9, 12, 9, 0, -11 }, // 0x23 '#' 98 | { 20, 8, 14, 9, 1, -12 }, // 0x24 '$' 99 | { 34, 13, 12, 15, 1, -11 }, // 0x25 '%' 100 | { 54, 13, 13, 14, 1, -12 }, // 0x26 '&' 101 | { 76, 2, 4, 4, 1, -11 }, // 0x27 ''' 102 | { 77, 5, 15, 6, 1, -11 }, // 0x28 '(' 103 | { 87, 5, 15, 6, 0, -11 }, // 0x29 ')' 104 | { 97, 6, 8, 9, 3, -11 }, // 0x2A '*' 105 | { 103, 9, 9, 10, 0, -8 }, // 0x2B '+' 106 | { 114, 2, 3, 4, 2, 0 }, // 0x2C ',' 107 | { 115, 4, 1, 6, 1, -3 }, // 0x2D '-' 108 | { 116, 2, 2, 5, 1, -1 }, // 0x2E '.' 109 | { 117, 5, 12, 5, 0, -11 }, // 0x2F '/' 110 | { 125, 9, 13, 9, 0, -12 }, // 0x30 '0' 111 | { 140, 5, 13, 9, 2, -12 }, // 0x31 '1' 112 | { 149, 8, 12, 9, 1, -11 }, // 0x32 '2' 113 | { 161, 8, 12, 9, 0, -11 }, // 0x33 '3' 114 | { 173, 7, 12, 9, 1, -11 }, // 0x34 '4' 115 | { 184, 8, 12, 9, 0, -11 }, // 0x35 '5' 116 | { 196, 8, 13, 9, 1, -12 }, // 0x36 '6' 117 | { 209, 8, 12, 9, 0, -11 }, // 0x37 '7' 118 | { 221, 7, 13, 9, 1, -12 }, // 0x38 '8' 119 | { 233, 8, 14, 9, 1, -12 }, // 0x39 '9' 120 | { 247, 2, 8, 5, 1, -7 }, // 0x3A ':' 121 | { 249, 3, 10, 5, 1, -7 }, // 0x3B ';' 122 | { 253, 9, 9, 10, 1, -8 }, // 0x3C '<' 123 | { 264, 9, 5, 10, 1, -6 }, // 0x3D '=' 124 | { 270, 10, 9, 10, 0, -8 }, // 0x3E '>' 125 | { 282, 7, 13, 8, 1, -12 }, // 0x3F '?' 126 | { 294, 12, 13, 16, 2, -12 }, // 0x40 '@' 127 | { 314, 13, 12, 13, 0, -11 }, // 0x41 'A' 128 | { 334, 11, 12, 11, 0, -11 }, // 0x42 'B' 129 | { 351, 11, 12, 12, 1, -11 }, // 0x43 'C' 130 | { 368, 12, 12, 13, 0, -11 }, // 0x44 'D' 131 | { 386, 10, 12, 11, 1, -11 }, // 0x45 'E' 132 | { 401, 9, 12, 10, 1, -11 }, // 0x46 'F' 133 | { 415, 12, 12, 13, 1, -11 }, // 0x47 'G' 134 | { 433, 11, 12, 13, 1, -11 }, // 0x48 'H' 135 | { 450, 4, 12, 6, 1, -11 }, // 0x49 'I' 136 | { 456, 6, 12, 7, 0, -11 }, // 0x4A 'J' 137 | { 465, 12, 12, 13, 1, -11 }, // 0x4B 'K' 138 | { 483, 10, 12, 11, 1, -11 }, // 0x4C 'L' 139 | { 498, 15, 12, 16, 0, -11 }, // 0x4D 'M' 140 | { 521, 11, 12, 13, 1, -11 }, // 0x4E 'N' 141 | { 538, 11, 13, 13, 1, -12 }, // 0x4F 'O' 142 | { 556, 9, 12, 10, 1, -11 }, // 0x50 'P' 143 | { 570, 11, 16, 13, 1, -12 }, // 0x51 'Q' 144 | { 592, 11, 12, 12, 1, -11 }, // 0x52 'R' 145 | { 609, 9, 12, 10, 0, -11 }, // 0x53 'S' 146 | { 623, 11, 12, 11, 0, -11 }, // 0x54 'T' 147 | { 640, 11, 12, 13, 1, -11 }, // 0x55 'U' 148 | { 657, 12, 12, 13, 0, -11 }, // 0x56 'V' 149 | { 675, 17, 12, 17, 0, -11 }, // 0x57 'W' 150 | { 701, 13, 12, 13, 0, -11 }, // 0x58 'X' 151 | { 721, 12, 12, 13, 0, -11 }, // 0x59 'Y' 152 | { 739, 11, 12, 11, 0, -11 }, // 0x5A 'Z' 153 | { 756, 3, 15, 6, 2, -11 }, // 0x5B '[' 154 | { 762, 5, 12, 5, 0, -11 }, // 0x5C '\' 155 | { 770, 3, 15, 6, 1, -11 }, // 0x5D ']' 156 | { 776, 8, 7, 8, 0, -11 }, // 0x5E '^' 157 | { 783, 9, 1, 9, 0, 2 }, // 0x5F '_' 158 | { 785, 4, 3, 5, 0, -11 }, // 0x60 '`' 159 | { 787, 7, 8, 8, 1, -7 }, // 0x61 'a' 160 | { 794, 9, 13, 9, 0, -12 }, // 0x62 'b' 161 | { 809, 7, 8, 8, 0, -7 }, // 0x63 'c' 162 | { 816, 9, 13, 9, 0, -12 }, // 0x64 'd' 163 | { 831, 8, 8, 8, 0, -7 }, // 0x65 'e' 164 | { 839, 7, 13, 7, 1, -12 }, // 0x66 'f' 165 | { 851, 10, 12, 8, 0, -7 }, // 0x67 'g' 166 | { 866, 9, 13, 9, 0, -12 }, // 0x68 'h' 167 | { 881, 4, 11, 5, 1, -10 }, // 0x69 'i' 168 | { 887, 5, 15, 6, 0, -10 }, // 0x6A 'j' 169 | { 897, 9, 13, 9, 1, -12 }, // 0x6B 'k' 170 | { 912, 4, 13, 5, 1, -12 }, // 0x6C 'l' 171 | { 919, 14, 8, 14, 0, -7 }, // 0x6D 'm' 172 | { 933, 9, 8, 9, 0, -7 }, // 0x6E 'n' 173 | { 942, 9, 8, 9, 0, -7 }, // 0x6F 'o' 174 | { 951, 9, 12, 9, 0, -7 }, // 0x70 'p' 175 | { 965, 9, 12, 9, 0, -7 }, // 0x71 'q' 176 | { 979, 6, 8, 6, 0, -7 }, // 0x72 'r' 177 | { 985, 6, 8, 7, 1, -7 }, // 0x73 's' 178 | { 991, 5, 9, 5, 0, -8 }, // 0x74 't' 179 | { 997, 9, 8, 9, 0, -7 }, // 0x75 'u' 180 | { 1006, 8, 8, 8, 0, -7 }, // 0x76 'v' 181 | { 1014, 12, 8, 12, 0, -7 }, // 0x77 'w' 182 | { 1026, 9, 8, 9, 0, -7 }, // 0x78 'x' 183 | { 1035, 8, 12, 8, 0, -7 }, // 0x79 'y' 184 | { 1047, 7, 8, 7, 1, -7 }, // 0x7A 'z' 185 | { 1054, 5, 16, 9, 1, -12 }, // 0x7B '{' 186 | { 1064, 1, 12, 4, 1, -11 }, // 0x7C '|' 187 | { 1066, 5, 16, 9, 3, -11 }, // 0x7D '}' 188 | { 1076, 9, 3, 9, 0, -5 } }; // 0x7E '~' 189 | 190 | const GFXfont FreeSerif9pt7b = { 191 | (uint8_t *)FreeSerif9pt7bBitmaps, 192 | (GFXglyph *)FreeSerif9pt7bGlyphs, 193 | 0x20, 0x7E, 22 }; 194 | 195 | // Approx. 1752 bytes 196 | -------------------------------------------------------------------------------- /main/fonts/FreeSans9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeSans9pt7bBitmaps[] = { 2 | 0xFF, 0xFF, 0xF8, 0xC0, 0xDE, 0xF7, 0x20, 0x09, 0x86, 0x41, 0x91, 0xFF, 3 | 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, 0x10, 0x1F, 4 | 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 5 | 0x33, 0xF0, 0x40, 0x20, 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 6 | 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 7 | 0x04, 0x63, 0x04, 0x77, 0x08, 0x3C, 0x0E, 0x06, 0x60, 0xCC, 0x19, 0x81, 8 | 0xE0, 0x18, 0x0F, 0x03, 0x36, 0xC2, 0xD8, 0x73, 0x06, 0x31, 0xE3, 0xC4, 9 | 0xFE, 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, 0x8C, 0x46, 10 | 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, 0x25, 0x7E, 0xA5, 0x00, 0x30, 11 | 0xC3, 0x3F, 0x30, 0xC3, 0x0C, 0xD6, 0xF0, 0xC0, 0x08, 0x44, 0x21, 0x10, 12 | 0x84, 0x42, 0x11, 0x08, 0x00, 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 13 | 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 14 | 0x30, 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 15 | 0x10, 0x08, 0x07, 0xF8, 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 16 | 0x03, 0xC3, 0xC3, 0x66, 0x3C, 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 17 | 0xFE, 0x18, 0x30, 0x60, 0xC0, 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 18 | 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, 0x1E, 0x31, 0x98, 0x78, 19 | 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, 0xFF, 20 | 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, 21 | 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 22 | 0x6C, 0x63, 0xE0, 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 23 | 0x03, 0xC2, 0x66, 0x3C, 0xC0, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x64, 0xA0, 24 | 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, 0xFF, 25 | 0x80, 0x00, 0x1F, 0xF0, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x18, 0x38, 0x71, 26 | 0xC0, 0x80, 0x00, 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 27 | 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 28 | 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 29 | 0x31, 0xE6, 0x11, 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 30 | 0x70, 0x40, 0x0F, 0xE0, 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 31 | 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, 0x30, 32 | 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 33 | 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 34 | 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, 35 | 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 36 | 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 37 | 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, 0xFF, 0xC0, 0xC0, 38 | 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x0F, 0x83, 39 | 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 40 | 0x03, 0x60, 0x73, 0x0F, 0x0F, 0x10, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 41 | 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, 42 | 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 43 | 0x8F, 0x1E, 0x27, 0x80, 0xC0, 0xD8, 0x33, 0x0C, 0x63, 0x0C, 0xC1, 0xB8, 44 | 0x3F, 0x07, 0x30, 0xC3, 0x18, 0x63, 0x06, 0x60, 0x6C, 0x0C, 0xC0, 0xC0, 45 | 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xE0, 46 | 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 47 | 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, 0x80, 0xE0, 0x7C, 0x0F, 48 | 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 49 | 0xE0, 0x7C, 0x0E, 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 50 | 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, 51 | 0x00, 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 52 | 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 53 | 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 54 | 0x60, 0xC0, 0xFB, 0x00, 0x08, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 55 | 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 56 | 0x70, 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 57 | 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 58 | 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0xC0, 0x78, 0x0F, 59 | 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 60 | 0xB0, 0x61, 0xF0, 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 61 | 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, 0xC1, 0x81, 0x30, 62 | 0xE1, 0x98, 0x70, 0xCC, 0x28, 0x66, 0x26, 0x21, 0x13, 0x30, 0xC8, 0x98, 63 | 0x6C, 0x4C, 0x14, 0x34, 0x0A, 0x1A, 0x07, 0x07, 0x03, 0x03, 0x80, 0x81, 64 | 0x80, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x0F, 0x00, 0xE0, 0x06, 0x00, 65 | 0xF0, 0x19, 0x01, 0x98, 0x30, 0xC6, 0x0E, 0x60, 0x60, 0xC0, 0x36, 0x06, 66 | 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 67 | 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 68 | 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, 0xFB, 0x6D, 69 | 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 70 | 0x10, 0x80, 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, 0x30, 0x60, 0xA2, 71 | 0x44, 0xD8, 0xA1, 0x80, 0xFF, 0xC0, 0xC6, 0x30, 0x7E, 0x71, 0xB0, 0xC0, 72 | 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, 0xC0, 0x60, 0x30, 0x1B, 73 | 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, 0x3C, 74 | 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x03, 0x03, 0x03, 75 | 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x3C, 0x66, 76 | 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x36, 0x6F, 0x66, 0x66, 77 | 0x66, 0x66, 0x60, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 78 | 0x3B, 0x03, 0x03, 0xC6, 0x7C, 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 79 | 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC0, 0x30, 0x03, 80 | 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x4C, 81 | 0x46, 0x63, 0x61, 0xF0, 0xEC, 0x62, 0x31, 0x98, 0x6C, 0x30, 0xFF, 0xFF, 82 | 0xFF, 0xC0, 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 83 | 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 84 | 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 85 | 0xC3, 0x66, 0x3C, 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 86 | 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 87 | 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, 0xDF, 0x31, 0x8C, 0x63, 0x18, 88 | 0xC6, 0x00, 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, 89 | 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 90 | 0xC3, 0xC3, 0xC7, 0x7B, 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 91 | 0x28, 0x1C, 0x0C, 0x00, 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 92 | 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, 0x43, 0x62, 0x36, 93 | 0x1C, 0x18, 0x1C, 0x3C, 0x26, 0x62, 0x43, 0xC1, 0x21, 0x98, 0xCC, 0x42, 94 | 0x61, 0xB0, 0xD0, 0x38, 0x1C, 0x0C, 0x06, 0x03, 0x01, 0x03, 0x00, 0xFE, 95 | 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, 0x36, 0x66, 0x66, 0x6E, 96 | 0xCE, 0x66, 0x66, 0x66, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC6, 0x66, 97 | 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, 0x61, 0x24, 0x38 }; 98 | 99 | const GFXglyph FreeSans9pt7bGlyphs[] = { 100 | { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' 101 | { 0, 2, 13, 6, 2, -12 }, // 0x21 '!' 102 | { 4, 5, 4, 6, 1, -12 }, // 0x22 '"' 103 | { 7, 10, 12, 10, 0, -11 }, // 0x23 '#' 104 | { 22, 9, 16, 10, 1, -13 }, // 0x24 '$' 105 | { 40, 16, 13, 16, 1, -12 }, // 0x25 '%' 106 | { 66, 11, 13, 12, 1, -12 }, // 0x26 '&' 107 | { 84, 2, 4, 4, 1, -12 }, // 0x27 ''' 108 | { 85, 4, 17, 6, 1, -12 }, // 0x28 '(' 109 | { 94, 4, 17, 6, 1, -12 }, // 0x29 ')' 110 | { 103, 5, 5, 7, 1, -12 }, // 0x2A '*' 111 | { 107, 6, 8, 11, 3, -7 }, // 0x2B '+' 112 | { 113, 2, 4, 5, 2, 0 }, // 0x2C ',' 113 | { 114, 4, 1, 6, 1, -4 }, // 0x2D '-' 114 | { 115, 2, 1, 5, 1, 0 }, // 0x2E '.' 115 | { 116, 5, 13, 5, 0, -12 }, // 0x2F '/' 116 | { 125, 8, 13, 10, 1, -12 }, // 0x30 '0' 117 | { 138, 4, 13, 10, 3, -12 }, // 0x31 '1' 118 | { 145, 9, 13, 10, 1, -12 }, // 0x32 '2' 119 | { 160, 8, 13, 10, 1, -12 }, // 0x33 '3' 120 | { 173, 7, 13, 10, 2, -12 }, // 0x34 '4' 121 | { 185, 9, 13, 10, 1, -12 }, // 0x35 '5' 122 | { 200, 9, 13, 10, 1, -12 }, // 0x36 '6' 123 | { 215, 8, 13, 10, 0, -12 }, // 0x37 '7' 124 | { 228, 9, 13, 10, 1, -12 }, // 0x38 '8' 125 | { 243, 8, 13, 10, 1, -12 }, // 0x39 '9' 126 | { 256, 2, 10, 5, 1, -9 }, // 0x3A ':' 127 | { 259, 3, 12, 5, 1, -8 }, // 0x3B ';' 128 | { 264, 9, 9, 11, 1, -8 }, // 0x3C '<' 129 | { 275, 9, 4, 11, 1, -5 }, // 0x3D '=' 130 | { 280, 9, 9, 11, 1, -8 }, // 0x3E '>' 131 | { 291, 9, 13, 10, 1, -12 }, // 0x3F '?' 132 | { 306, 17, 16, 18, 1, -12 }, // 0x40 '@' 133 | { 340, 12, 13, 12, 0, -12 }, // 0x41 'A' 134 | { 360, 11, 13, 12, 1, -12 }, // 0x42 'B' 135 | { 378, 11, 13, 13, 1, -12 }, // 0x43 'C' 136 | { 396, 11, 13, 13, 1, -12 }, // 0x44 'D' 137 | { 414, 9, 13, 11, 1, -12 }, // 0x45 'E' 138 | { 429, 8, 13, 11, 1, -12 }, // 0x46 'F' 139 | { 442, 12, 13, 14, 1, -12 }, // 0x47 'G' 140 | { 462, 11, 13, 13, 1, -12 }, // 0x48 'H' 141 | { 480, 2, 13, 5, 2, -12 }, // 0x49 'I' 142 | { 484, 7, 13, 10, 1, -12 }, // 0x4A 'J' 143 | { 496, 11, 13, 12, 1, -12 }, // 0x4B 'K' 144 | { 514, 8, 13, 10, 1, -12 }, // 0x4C 'L' 145 | { 527, 13, 13, 15, 1, -12 }, // 0x4D 'M' 146 | { 549, 11, 13, 13, 1, -12 }, // 0x4E 'N' 147 | { 567, 13, 13, 14, 1, -12 }, // 0x4F 'O' 148 | { 589, 10, 13, 12, 1, -12 }, // 0x50 'P' 149 | { 606, 13, 14, 14, 1, -12 }, // 0x51 'Q' 150 | { 629, 12, 13, 13, 1, -12 }, // 0x52 'R' 151 | { 649, 10, 13, 12, 1, -12 }, // 0x53 'S' 152 | { 666, 9, 13, 11, 1, -12 }, // 0x54 'T' 153 | { 681, 11, 13, 13, 1, -12 }, // 0x55 'U' 154 | { 699, 11, 13, 12, 0, -12 }, // 0x56 'V' 155 | { 717, 17, 13, 17, 0, -12 }, // 0x57 'W' 156 | { 745, 12, 13, 12, 0, -12 }, // 0x58 'X' 157 | { 765, 12, 13, 12, 0, -12 }, // 0x59 'Y' 158 | { 785, 10, 13, 11, 1, -12 }, // 0x5A 'Z' 159 | { 802, 3, 17, 5, 1, -12 }, // 0x5B '[' 160 | { 809, 5, 13, 5, 0, -12 }, // 0x5C '\' 161 | { 818, 3, 17, 5, 0, -12 }, // 0x5D ']' 162 | { 825, 7, 7, 8, 1, -12 }, // 0x5E '^' 163 | { 832, 10, 1, 10, 0, 3 }, // 0x5F '_' 164 | { 834, 4, 3, 5, 0, -12 }, // 0x60 '`' 165 | { 836, 9, 10, 10, 1, -9 }, // 0x61 'a' 166 | { 848, 9, 13, 10, 1, -12 }, // 0x62 'b' 167 | { 863, 8, 10, 9, 1, -9 }, // 0x63 'c' 168 | { 873, 8, 13, 10, 1, -12 }, // 0x64 'd' 169 | { 886, 8, 10, 10, 1, -9 }, // 0x65 'e' 170 | { 896, 4, 13, 5, 1, -12 }, // 0x66 'f' 171 | { 903, 8, 14, 10, 1, -9 }, // 0x67 'g' 172 | { 917, 8, 13, 10, 1, -12 }, // 0x68 'h' 173 | { 930, 2, 13, 4, 1, -12 }, // 0x69 'i' 174 | { 934, 4, 17, 4, 0, -12 }, // 0x6A 'j' 175 | { 943, 9, 13, 9, 1, -12 }, // 0x6B 'k' 176 | { 958, 2, 13, 4, 1, -12 }, // 0x6C 'l' 177 | { 962, 13, 10, 15, 1, -9 }, // 0x6D 'm' 178 | { 979, 8, 10, 10, 1, -9 }, // 0x6E 'n' 179 | { 989, 8, 10, 10, 1, -9 }, // 0x6F 'o' 180 | { 999, 9, 13, 10, 1, -9 }, // 0x70 'p' 181 | { 1014, 8, 13, 10, 1, -9 }, // 0x71 'q' 182 | { 1027, 5, 10, 6, 1, -9 }, // 0x72 'r' 183 | { 1034, 8, 10, 9, 1, -9 }, // 0x73 's' 184 | { 1044, 4, 12, 5, 1, -11 }, // 0x74 't' 185 | { 1050, 8, 10, 10, 1, -9 }, // 0x75 'u' 186 | { 1060, 9, 10, 9, 0, -9 }, // 0x76 'v' 187 | { 1072, 13, 10, 13, 0, -9 }, // 0x77 'w' 188 | { 1089, 8, 10, 9, 0, -9 }, // 0x78 'x' 189 | { 1099, 9, 14, 9, 0, -9 }, // 0x79 'y' 190 | { 1115, 7, 10, 9, 1, -9 }, // 0x7A 'z' 191 | { 1124, 4, 17, 6, 1, -12 }, // 0x7B '{' 192 | { 1133, 2, 17, 4, 2, -12 }, // 0x7C '|' 193 | { 1138, 4, 17, 6, 1, -12 }, // 0x7D '}' 194 | { 1147, 7, 3, 9, 1, -7 } }; // 0x7E '~' 195 | 196 | const GFXfont FreeSans9pt7b = { 197 | (uint8_t *)FreeSans9pt7bBitmaps, 198 | (GFXglyph *)FreeSans9pt7bGlyphs, 199 | 0x20, 0x7E, 22 }; 200 | 201 | // Approx. 1822 bytes 202 | -------------------------------------------------------------------------------- /main/fonts/FreeSerifBold9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeSerifBold9pt7bBitmaps[] = { 2 | 0xFF, 0xF4, 0x92, 0x1F, 0xF0, 0xCF, 0x3C, 0xE3, 0x88, 0x13, 0x09, 0x84, 3 | 0xC2, 0x47, 0xF9, 0x90, 0xC8, 0x4C, 0xFF, 0x13, 0x09, 0x0C, 0x86, 0x40, 4 | 0x10, 0x38, 0xD6, 0x92, 0xD2, 0xF0, 0x7C, 0x3E, 0x17, 0x93, 0x93, 0xD6, 5 | 0x7C, 0x10, 0x3C, 0x21, 0xCF, 0x0E, 0x24, 0x30, 0xA0, 0xC5, 0x03, 0x34, 6 | 0xE7, 0x26, 0x40, 0xB9, 0x04, 0xC4, 0x23, 0x30, 0x8C, 0x84, 0x1C, 0x0F, 7 | 0x00, 0xCC, 0x06, 0x60, 0x3E, 0x00, 0xE7, 0x8F, 0x18, 0x9C, 0x8C, 0xE4, 8 | 0xE3, 0xC7, 0x9E, 0x3C, 0x72, 0xFD, 0xE0, 0xFF, 0x80, 0x32, 0x44, 0xCC, 9 | 0xCC, 0xCC, 0xC4, 0x62, 0x10, 0x84, 0x22, 0x33, 0x33, 0x33, 0x32, 0x64, 10 | 0x80, 0x31, 0x6B, 0xB1, 0x8E, 0xD6, 0x8C, 0x00, 0x08, 0x04, 0x02, 0x01, 11 | 0x0F, 0xF8, 0x40, 0x20, 0x10, 0x08, 0x00, 0xDF, 0x95, 0x00, 0xFF, 0xFF, 12 | 0x80, 0x0C, 0x21, 0x86, 0x10, 0xC3, 0x08, 0x61, 0x84, 0x30, 0xC0, 0x1C, 13 | 0x33, 0x98, 0xDC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xB1, 0x98, 0xC3, 14 | 0x80, 0x08, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0xBF, 0x3C, 0x3F, 15 | 0x23, 0xC0, 0xE0, 0x70, 0x30, 0x38, 0x18, 0x18, 0x18, 0x5F, 0xDF, 0xE0, 16 | 0x7C, 0x8E, 0x0E, 0x0E, 0x0C, 0x1E, 0x07, 0x03, 0x03, 0x02, 0xE6, 0xF8, 17 | 0x06, 0x0E, 0x0E, 0x3E, 0x2E, 0x4E, 0x8E, 0x8E, 0xFF, 0xFF, 0x0E, 0x0E, 18 | 0x3F, 0x7E, 0x40, 0x40, 0xF8, 0xFC, 0x1E, 0x06, 0x02, 0x02, 0xE4, 0xF8, 19 | 0x07, 0x1C, 0x30, 0x70, 0xFC, 0xE6, 0xE7, 0xE7, 0xE7, 0x67, 0x66, 0x3C, 20 | 0x7F, 0x3F, 0xA0, 0xD0, 0x40, 0x60, 0x30, 0x10, 0x18, 0x0C, 0x04, 0x06, 21 | 0x03, 0x00, 0x3C, 0xC6, 0xC6, 0xC6, 0xFC, 0x7C, 0x3E, 0xCF, 0xC7, 0xC7, 22 | 0xC6, 0x7C, 0x3E, 0x33, 0xB8, 0xDC, 0x7E, 0x3F, 0x1D, 0xCE, 0x7F, 0x07, 23 | 0x07, 0x0F, 0x1C, 0x00, 0xFF, 0x80, 0x3F, 0xE0, 0xFF, 0x80, 0x37, 0xE5, 24 | 0x40, 0x00, 0x00, 0x70, 0x78, 0x78, 0x78, 0x38, 0x03, 0x80, 0x3C, 0x03, 25 | 0xC0, 0x30, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0xC0, 0x3C, 0x03, 26 | 0xC0, 0x1C, 0x01, 0xC1, 0xE1, 0xE1, 0xE0, 0xE0, 0x00, 0x00, 0x3D, 0x9F, 27 | 0x3E, 0x70, 0xE1, 0x04, 0x08, 0x00, 0x70, 0xE1, 0xC0, 0x0F, 0x81, 0x83, 28 | 0x18, 0xC4, 0x89, 0x9C, 0x4C, 0xE4, 0x67, 0x22, 0x39, 0x22, 0x4F, 0xE3, 29 | 0x00, 0x0C, 0x10, 0x1F, 0x00, 0x02, 0x00, 0x30, 0x01, 0xC0, 0x0E, 0x00, 30 | 0xB8, 0x05, 0xC0, 0x4F, 0x02, 0x38, 0x3F, 0xE1, 0x07, 0x18, 0x3D, 0xE3, 31 | 0xF0, 0xFF, 0x87, 0x1C, 0xE3, 0x9C, 0x73, 0x9C, 0x7F, 0x0E, 0x71, 0xC7, 32 | 0x38, 0xE7, 0x1C, 0xE7, 0x7F, 0xC0, 0x1F, 0x26, 0x1D, 0xC1, 0xB0, 0x1E, 33 | 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x0E, 0x04, 0xE1, 0x0F, 0xC0, 0xFF, 34 | 0x0E, 0x71, 0xC7, 0x38, 0x77, 0x0E, 0xE1, 0xDC, 0x3B, 0x87, 0x70, 0xCE, 35 | 0x39, 0xC6, 0x7F, 0x80, 0xFF, 0xCE, 0x19, 0xC1, 0x38, 0x87, 0x30, 0xFE, 36 | 0x1C, 0xC3, 0x88, 0x70, 0x2E, 0x0D, 0xC3, 0x7F, 0xE0, 0xFF, 0xDC, 0x37, 37 | 0x05, 0xC4, 0x73, 0x1F, 0xC7, 0x31, 0xC4, 0x70, 0x1C, 0x07, 0x03, 0xE0, 38 | 0x1F, 0x23, 0x0E, 0x70, 0x6E, 0x02, 0xE0, 0x0E, 0x00, 0xE1, 0xFE, 0x0E, 39 | 0x60, 0xE7, 0x0E, 0x38, 0xE0, 0xF8, 0xF9, 0xF7, 0x0E, 0x70, 0xE7, 0x0E, 40 | 0x70, 0xE7, 0xFE, 0x70, 0xE7, 0x0E, 0x70, 0xE7, 0x0E, 0x70, 0xEF, 0x9F, 41 | 0xFB, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9D, 0xF0, 0x1F, 0x0E, 0x0E, 0x0E, 42 | 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0xCE, 0xCC, 0x78, 0xF9, 0xF3, 43 | 0x82, 0x1C, 0x20, 0xE2, 0x07, 0x20, 0x3F, 0x01, 0xDC, 0x0E, 0x70, 0x73, 44 | 0xC3, 0x8F, 0x1C, 0x3D, 0xF3, 0xF0, 0xF8, 0x0E, 0x01, 0xC0, 0x38, 0x07, 45 | 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x2E, 0x09, 0xC3, 0x7F, 0xE0, 0xF8, 46 | 0x0F, 0x3C, 0x1E, 0x3C, 0x1E, 0x2E, 0x2E, 0x2E, 0x2E, 0x26, 0x4E, 0x27, 47 | 0x4E, 0x27, 0x4E, 0x23, 0x8E, 0x23, 0x8E, 0x21, 0x0E, 0x71, 0x1F, 0xF0, 48 | 0xEE, 0x09, 0xE1, 0x3E, 0x25, 0xE4, 0x9E, 0x91, 0xD2, 0x1E, 0x43, 0xC8, 49 | 0x39, 0x03, 0x70, 0x20, 0x1F, 0x83, 0x0C, 0x70, 0xEE, 0x07, 0xE0, 0x7E, 50 | 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0E, 0x30, 0xC1, 0xF8, 0xFF, 0x1C, 51 | 0xE7, 0x1D, 0xC7, 0x71, 0xDC, 0xE7, 0xF1, 0xC0, 0x70, 0x1C, 0x07, 0x03, 52 | 0xE0, 0x0F, 0x83, 0x9C, 0x70, 0xE6, 0x06, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 53 | 0x07, 0xE0, 0x76, 0x06, 0x30, 0xC1, 0x98, 0x0F, 0x00, 0x78, 0x03, 0xE0, 54 | 0xFF, 0x07, 0x38, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x38, 0x7E, 0x07, 0x70, 55 | 0x77, 0x87, 0x3C, 0x71, 0xEF, 0x8F, 0x39, 0x47, 0xC1, 0xC0, 0xF0, 0x7C, 56 | 0x3E, 0x0F, 0x83, 0xC3, 0xC6, 0xBC, 0xFF, 0xFC, 0xE3, 0x8E, 0x10, 0xE0, 57 | 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x01, 0xF0, 58 | 0xF8, 0xEE, 0x09, 0xC1, 0x38, 0x27, 0x04, 0xE0, 0x9C, 0x13, 0x82, 0x70, 59 | 0x4E, 0x08, 0xE2, 0x0F, 0x80, 0xFC, 0x7B, 0xC1, 0x0E, 0x08, 0x70, 0x81, 60 | 0xC4, 0x0E, 0x20, 0x7A, 0x01, 0xD0, 0x0E, 0x80, 0x38, 0x01, 0xC0, 0x04, 61 | 0x00, 0x20, 0x00, 0xFD, 0xFB, 0xDC, 0x38, 0x43, 0x87, 0x10, 0xE1, 0xC4, 62 | 0x38, 0xF2, 0x07, 0x2E, 0x81, 0xD3, 0xA0, 0x34, 0x70, 0x0E, 0x1C, 0x03, 63 | 0x87, 0x00, 0x60, 0x80, 0x10, 0x20, 0xFE, 0xF3, 0xC3, 0x0F, 0x10, 0x39, 64 | 0x00, 0xF0, 0x03, 0x80, 0x1E, 0x01, 0x70, 0x09, 0xC0, 0x8F, 0x08, 0x3D, 65 | 0xF3, 0xF0, 0xFC, 0x7B, 0xC1, 0x8E, 0x08, 0x38, 0x81, 0xE8, 0x07, 0x40, 66 | 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1F, 0x00, 0xFF, 0xD8, 67 | 0x72, 0x1E, 0x43, 0x80, 0xE0, 0x1C, 0x07, 0x01, 0xC0, 0x38, 0x2E, 0x0F, 68 | 0x83, 0x7F, 0xE0, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xF0, 0xC1, 69 | 0x06, 0x18, 0x20, 0xC3, 0x04, 0x18, 0x60, 0x83, 0x0C, 0xF3, 0x33, 0x33, 70 | 0x33, 0x33, 0x33, 0x33, 0xF0, 0x18, 0x1C, 0x34, 0x26, 0x62, 0x43, 0xC1, 71 | 0xFF, 0x80, 0xC6, 0x30, 0x7C, 0x63, 0xB1, 0xC0, 0xE1, 0xF3, 0x3B, 0x9D, 72 | 0xCE, 0xFF, 0x80, 0xF0, 0x1C, 0x07, 0x01, 0xDC, 0x7B, 0x9C, 0x77, 0x1D, 73 | 0xC7, 0x71, 0xDC, 0x77, 0x39, 0x3C, 0x3C, 0xED, 0x9F, 0x0E, 0x1C, 0x38, 74 | 0x39, 0x3C, 0x07, 0x80, 0xE0, 0x38, 0xEE, 0x77, 0xB8, 0xEE, 0x3B, 0x8E, 75 | 0xE3, 0xB8, 0xE7, 0x78, 0xEF, 0x3C, 0x66, 0xE6, 0xFE, 0xE0, 0xE0, 0xE0, 76 | 0x72, 0x3C, 0x3E, 0xED, 0xC7, 0xC7, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC7, 77 | 0xC0, 0x31, 0xDF, 0xBF, 0x7E, 0xE7, 0x90, 0x60, 0xFC, 0xFE, 0x0C, 0x17, 78 | 0xC0, 0xF0, 0x1C, 0x07, 0x01, 0xDC, 0x7B, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 79 | 0x9C, 0xE7, 0x3B, 0xFF, 0x73, 0x9D, 0xE7, 0x39, 0xCE, 0x73, 0x9D, 0xF0, 80 | 0x1C, 0x71, 0xCF, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x7D, 0xBE, 81 | 0xF0, 0x1C, 0x07, 0x01, 0xCE, 0x71, 0x1C, 0x87, 0x41, 0xF8, 0x77, 0x1C, 82 | 0xE7, 0x1B, 0xEF, 0xF3, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9D, 0xF0, 0xF7, 83 | 0x38, 0xF7, 0xB9, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 84 | 0x39, 0xCE, 0xFF, 0xFE, 0xF7, 0x1E, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 85 | 0x39, 0xCE, 0xFF, 0xC0, 0x3E, 0x31, 0xB8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8E, 86 | 0xC6, 0x3E, 0x00, 0xF7, 0x1E, 0xE7, 0x1D, 0xC7, 0x71, 0xDC, 0x77, 0x1D, 87 | 0xCE, 0x7F, 0x1C, 0x07, 0x01, 0xC0, 0xF8, 0x00, 0x3C, 0x9C, 0xEE, 0x3B, 88 | 0x8E, 0xE3, 0xB8, 0xEE, 0x39, 0xCE, 0x3F, 0x80, 0xE0, 0x38, 0x0E, 0x07, 89 | 0xC0, 0xF7, 0x7B, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0xF8, 0x7E, 0x73, 90 | 0xC7, 0x8E, 0x39, 0xB0, 0x10, 0xCF, 0x9C, 0x71, 0xC7, 0x1C, 0x71, 0xD3, 91 | 0x80, 0xF7, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x3F, 92 | 0xC0, 0xFB, 0xB8, 0x8C, 0x87, 0x43, 0xC0, 0xE0, 0x70, 0x10, 0x08, 0x00, 93 | 0xF7, 0xB6, 0x31, 0x73, 0xA3, 0x3A, 0x3D, 0xA3, 0xDC, 0x18, 0xC1, 0x88, 94 | 0x10, 0x80, 0xFB, 0xB8, 0x8E, 0x83, 0x81, 0xC0, 0xF0, 0x98, 0xCE, 0xEF, 95 | 0x80, 0xF7, 0x62, 0x72, 0x34, 0x34, 0x3C, 0x18, 0x18, 0x10, 0x10, 0x10, 96 | 0xE0, 0xE0, 0xFF, 0x1C, 0x70, 0xE3, 0x87, 0x1C, 0x71, 0xFE, 0x19, 0x8C, 97 | 0x63, 0x18, 0xCC, 0x61, 0x8C, 0x63, 0x18, 0xC3, 0xFF, 0xF8, 0xC3, 0x18, 98 | 0xC6, 0x31, 0x86, 0x33, 0x18, 0xC6, 0x31, 0x98, 0xF0, 0x8E }; 99 | 100 | const GFXglyph FreeSerifBold9pt7bGlyphs[] = { 101 | { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' 102 | { 0, 3, 12, 6, 1, -11 }, // 0x21 '!' 103 | { 5, 6, 5, 10, 2, -11 }, // 0x22 '"' 104 | { 9, 9, 13, 9, 0, -12 }, // 0x23 '#' 105 | { 24, 8, 14, 9, 1, -12 }, // 0x24 '$' 106 | { 38, 14, 12, 18, 2, -11 }, // 0x25 '%' 107 | { 59, 13, 12, 15, 1, -11 }, // 0x26 '&' 108 | { 79, 2, 5, 5, 1, -11 }, // 0x27 ''' 109 | { 81, 4, 15, 6, 1, -11 }, // 0x28 '(' 110 | { 89, 4, 15, 6, 1, -11 }, // 0x29 ')' 111 | { 97, 7, 7, 9, 2, -11 }, // 0x2A '*' 112 | { 104, 9, 9, 12, 1, -8 }, // 0x2B '+' 113 | { 115, 3, 6, 4, 1, -2 }, // 0x2C ',' 114 | { 118, 4, 2, 6, 1, -4 }, // 0x2D '-' 115 | { 119, 3, 3, 4, 1, -2 }, // 0x2E '.' 116 | { 121, 6, 13, 5, 0, -11 }, // 0x2F '/' 117 | { 131, 9, 12, 9, 0, -11 }, // 0x30 '0' 118 | { 145, 6, 12, 9, 1, -11 }, // 0x31 '1' 119 | { 154, 9, 12, 9, 0, -11 }, // 0x32 '2' 120 | { 168, 8, 12, 9, 0, -11 }, // 0x33 '3' 121 | { 180, 8, 12, 9, 1, -11 }, // 0x34 '4' 122 | { 192, 8, 12, 9, 1, -11 }, // 0x35 '5' 123 | { 204, 8, 12, 9, 1, -11 }, // 0x36 '6' 124 | { 216, 9, 12, 9, 0, -11 }, // 0x37 '7' 125 | { 230, 8, 12, 9, 1, -11 }, // 0x38 '8' 126 | { 242, 9, 12, 9, 0, -11 }, // 0x39 '9' 127 | { 256, 3, 9, 6, 1, -8 }, // 0x3A ':' 128 | { 260, 3, 12, 6, 2, -8 }, // 0x3B ';' 129 | { 265, 10, 10, 12, 1, -9 }, // 0x3C '<' 130 | { 278, 10, 5, 12, 1, -6 }, // 0x3D '=' 131 | { 285, 10, 10, 12, 1, -8 }, // 0x3E '>' 132 | { 298, 7, 12, 9, 1, -11 }, // 0x3F '?' 133 | { 309, 13, 12, 17, 2, -11 }, // 0x40 '@' 134 | { 329, 13, 12, 13, 0, -11 }, // 0x41 'A' 135 | { 349, 11, 12, 12, 0, -11 }, // 0x42 'B' 136 | { 366, 11, 12, 13, 1, -11 }, // 0x43 'C' 137 | { 383, 11, 12, 13, 1, -11 }, // 0x44 'D' 138 | { 400, 11, 12, 12, 1, -11 }, // 0x45 'E' 139 | { 417, 10, 12, 11, 1, -11 }, // 0x46 'F' 140 | { 432, 12, 12, 14, 1, -11 }, // 0x47 'G' 141 | { 450, 12, 12, 14, 1, -11 }, // 0x48 'H' 142 | { 468, 5, 12, 7, 1, -11 }, // 0x49 'I' 143 | { 476, 8, 14, 9, 0, -11 }, // 0x4A 'J' 144 | { 490, 13, 12, 14, 1, -11 }, // 0x4B 'K' 145 | { 510, 11, 12, 12, 1, -11 }, // 0x4C 'L' 146 | { 527, 16, 12, 17, 0, -11 }, // 0x4D 'M' 147 | { 551, 11, 12, 13, 1, -11 }, // 0x4E 'N' 148 | { 568, 12, 12, 14, 1, -11 }, // 0x4F 'O' 149 | { 586, 10, 12, 11, 1, -11 }, // 0x50 'P' 150 | { 601, 12, 15, 14, 1, -11 }, // 0x51 'Q' 151 | { 624, 12, 12, 13, 1, -11 }, // 0x52 'R' 152 | { 642, 8, 12, 10, 1, -11 }, // 0x53 'S' 153 | { 654, 12, 12, 12, 0, -11 }, // 0x54 'T' 154 | { 672, 11, 12, 13, 1, -11 }, // 0x55 'U' 155 | { 689, 13, 13, 13, 0, -11 }, // 0x56 'V' 156 | { 711, 18, 12, 18, 0, -11 }, // 0x57 'W' 157 | { 738, 13, 12, 13, 0, -11 }, // 0x58 'X' 158 | { 758, 13, 12, 13, 0, -11 }, // 0x59 'Y' 159 | { 778, 11, 12, 12, 1, -11 }, // 0x5A 'Z' 160 | { 795, 4, 15, 6, 1, -11 }, // 0x5B '[' 161 | { 803, 6, 13, 5, 0, -11 }, // 0x5C '\' 162 | { 813, 4, 15, 6, 1, -11 }, // 0x5D ']' 163 | { 821, 8, 7, 10, 1, -11 }, // 0x5E '^' 164 | { 828, 9, 1, 9, 0, 3 }, // 0x5F '_' 165 | { 830, 4, 3, 6, 0, -12 }, // 0x60 '`' 166 | { 832, 9, 9, 9, 0, -8 }, // 0x61 'a' 167 | { 843, 10, 12, 10, 0, -11 }, // 0x62 'b' 168 | { 858, 7, 9, 8, 0, -8 }, // 0x63 'c' 169 | { 866, 10, 12, 10, 0, -11 }, // 0x64 'd' 170 | { 881, 8, 9, 8, 0, -8 }, // 0x65 'e' 171 | { 890, 7, 12, 7, 0, -11 }, // 0x66 'f' 172 | { 901, 7, 13, 9, 1, -8 }, // 0x67 'g' 173 | { 913, 10, 12, 10, 0, -11 }, // 0x68 'h' 174 | { 928, 5, 12, 5, 0, -11 }, // 0x69 'i' 175 | { 936, 6, 16, 7, 0, -11 }, // 0x6A 'j' 176 | { 948, 10, 12, 10, 0, -11 }, // 0x6B 'k' 177 | { 963, 5, 12, 5, 0, -11 }, // 0x6C 'l' 178 | { 971, 15, 9, 15, 0, -8 }, // 0x6D 'm' 179 | { 988, 10, 9, 10, 0, -8 }, // 0x6E 'n' 180 | { 1000, 9, 9, 9, 0, -8 }, // 0x6F 'o' 181 | { 1011, 10, 13, 10, 0, -8 }, // 0x70 'p' 182 | { 1028, 10, 13, 10, 0, -8 }, // 0x71 'q' 183 | { 1045, 8, 9, 8, 0, -8 }, // 0x72 'r' 184 | { 1054, 5, 9, 7, 1, -8 }, // 0x73 's' 185 | { 1060, 6, 11, 6, 0, -10 }, // 0x74 't' 186 | { 1069, 10, 9, 10, 0, -8 }, // 0x75 'u' 187 | { 1081, 9, 9, 9, 0, -8 }, // 0x76 'v' 188 | { 1092, 12, 9, 13, 0, -8 }, // 0x77 'w' 189 | { 1106, 9, 9, 9, 0, -8 }, // 0x78 'x' 190 | { 1117, 8, 13, 9, 0, -8 }, // 0x79 'y' 191 | { 1130, 7, 9, 8, 1, -8 }, // 0x7A 'z' 192 | { 1138, 5, 16, 7, 0, -12 }, // 0x7B '{' 193 | { 1148, 1, 13, 4, 1, -11 }, // 0x7C '|' 194 | { 1150, 5, 16, 7, 2, -12 }, // 0x7D '}' 195 | { 1160, 8, 2, 9, 1, -4 } }; // 0x7E '~' 196 | 197 | const GFXfont FreeSerifBold9pt7b = { 198 | (uint8_t *)FreeSerifBold9pt7bBitmaps, 199 | (GFXglyph *)FreeSerifBold9pt7bGlyphs, 200 | 0x20, 0x7E, 22 }; 201 | 202 | // Approx. 1834 bytes 203 | -------------------------------------------------------------------------------- /main/fonts/FreeSerifItalic9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeSerifItalic9pt7bBitmaps[] = { 2 | 0x11, 0x12, 0x22, 0x24, 0x40, 0x0C, 0xDE, 0xE5, 0x40, 0x04, 0x82, 0x20, 3 | 0x98, 0x24, 0x7F, 0xC4, 0x82, 0x23, 0xFC, 0x24, 0x11, 0x04, 0x83, 0x20, 4 | 0x1C, 0x1B, 0x99, 0x4D, 0x26, 0x81, 0xC0, 0x70, 0x1C, 0x13, 0x49, 0xA4, 5 | 0xDA, 0xC7, 0xC1, 0x00, 0x80, 0x1C, 0x61, 0xCF, 0x0E, 0x28, 0x30, 0xA0, 6 | 0xC5, 0x03, 0x34, 0xE7, 0xAE, 0x40, 0xB1, 0x05, 0x84, 0x26, 0x20, 0x99, 7 | 0x84, 0x3C, 0x03, 0x80, 0x6C, 0x06, 0xC0, 0x78, 0x06, 0x01, 0xEF, 0x66, 8 | 0x24, 0x24, 0xC3, 0x8C, 0x10, 0xE3, 0x87, 0xCE, 0xFA, 0x08, 0x21, 0x08, 9 | 0x61, 0x8C, 0x30, 0xC3, 0x0C, 0x30, 0x41, 0x02, 0x00, 0x10, 0x40, 0x82, 10 | 0x0C, 0x30, 0xC3, 0x0C, 0x61, 0x84, 0x21, 0x08, 0x00, 0x30, 0xCA, 0x5E, 11 | 0x6A, 0x93, 0x08, 0x08, 0x04, 0x02, 0x01, 0x0F, 0xF8, 0x40, 0x20, 0x10, 12 | 0x08, 0x00, 0x56, 0xF0, 0xF0, 0x03, 0x02, 0x06, 0x04, 0x08, 0x08, 0x10, 13 | 0x30, 0x20, 0x60, 0x40, 0xC0, 0x0E, 0x0C, 0x8C, 0x6C, 0x36, 0x1F, 0x0F, 14 | 0x07, 0x87, 0xC3, 0x61, 0xB1, 0x88, 0x83, 0x80, 0x04, 0x70, 0xC3, 0x08, 15 | 0x21, 0x86, 0x10, 0x43, 0x08, 0xF8, 0x1C, 0x67, 0x83, 0x03, 0x02, 0x06, 16 | 0x0C, 0x08, 0x10, 0x20, 0x42, 0xFC, 0x0F, 0x08, 0xC0, 0x60, 0xC1, 0xE0, 17 | 0x38, 0x0C, 0x06, 0x03, 0x01, 0x01, 0x1F, 0x00, 0x01, 0x01, 0x81, 0x41, 18 | 0x61, 0x21, 0x11, 0x18, 0x88, 0xFF, 0x02, 0x03, 0x01, 0x00, 0x0F, 0x84, 19 | 0x04, 0x03, 0x80, 0x60, 0x18, 0x0C, 0x06, 0x03, 0x03, 0x03, 0x1E, 0x00, 20 | 0x01, 0x83, 0x87, 0x07, 0x03, 0x03, 0x73, 0xCD, 0x86, 0xC3, 0x61, 0xB1, 21 | 0x88, 0xC3, 0xC0, 0x7F, 0x40, 0x80, 0x80, 0x40, 0x40, 0x60, 0x20, 0x20, 22 | 0x10, 0x10, 0x18, 0x08, 0x00, 0x1E, 0x19, 0xCC, 0x66, 0x33, 0xB0, 0xE0, 23 | 0x50, 0xCC, 0xC3, 0x61, 0xB0, 0xCC, 0xC3, 0xC0, 0x0E, 0x19, 0x8C, 0x6C, 24 | 0x36, 0x1B, 0x0D, 0x86, 0xE6, 0x3F, 0x03, 0x03, 0x06, 0x0C, 0x00, 0x33, 25 | 0x00, 0x00, 0xCC, 0x33, 0x00, 0x00, 0x44, 0x48, 0x01, 0x83, 0x86, 0x1C, 26 | 0x0C, 0x03, 0x80, 0x30, 0x07, 0x00, 0x80, 0xFF, 0x80, 0x00, 0x00, 0x0F, 27 | 0xF8, 0xC0, 0x1C, 0x03, 0x80, 0x70, 0x18, 0x38, 0x70, 0xC0, 0x80, 0x00, 28 | 0x3C, 0x8C, 0x18, 0x30, 0xC3, 0x0C, 0x20, 0x40, 0x80, 0x06, 0x00, 0x0F, 29 | 0xC0, 0xC3, 0x0C, 0x04, 0xC7, 0xBC, 0x64, 0xE2, 0x27, 0x31, 0x39, 0x91, 30 | 0xCC, 0x93, 0x3B, 0x0E, 0x00, 0x1F, 0x80, 0x01, 0x00, 0x60, 0x14, 0x04, 31 | 0xC0, 0x98, 0x23, 0x07, 0xE1, 0x04, 0x20, 0x88, 0x1B, 0x8F, 0x80, 0x3F, 32 | 0xC1, 0x8C, 0x21, 0x8C, 0x31, 0x8C, 0x3E, 0x04, 0x61, 0x86, 0x30, 0xC4, 33 | 0x19, 0x86, 0x7F, 0x80, 0x07, 0x91, 0x86, 0x30, 0x26, 0x02, 0x60, 0x0C, 34 | 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x61, 0x83, 0xE0, 0x3F, 0xC0, 35 | 0x63, 0x82, 0x0C, 0x30, 0x31, 0x81, 0x8C, 0x0C, 0x40, 0x66, 0x07, 0x30, 36 | 0x31, 0x03, 0x18, 0x71, 0xFE, 0x00, 0x3F, 0xF0, 0xC2, 0x08, 0x21, 0x80, 37 | 0x19, 0x81, 0xF8, 0x11, 0x03, 0x10, 0x30, 0x02, 0x04, 0x60, 0x8F, 0xF8, 38 | 0x3F, 0xF0, 0xC2, 0x08, 0x21, 0x80, 0x19, 0x81, 0xF8, 0x11, 0x03, 0x10, 39 | 0x30, 0x02, 0x00, 0x60, 0x0F, 0x80, 0x07, 0x91, 0x87, 0x30, 0x26, 0x02, 40 | 0x60, 0x0C, 0x00, 0xC1, 0xFC, 0x0C, 0xC0, 0xCC, 0x0C, 0x60, 0x83, 0xF0, 41 | 0x3E, 0x3C, 0x30, 0x60, 0x81, 0x06, 0x0C, 0x18, 0x30, 0x7F, 0x81, 0x06, 42 | 0x0C, 0x18, 0x30, 0x60, 0x81, 0x06, 0x0C, 0x3C, 0x78, 0x1E, 0x18, 0x20, 43 | 0xC1, 0x83, 0x04, 0x18, 0x30, 0x41, 0x87, 0x80, 0x0F, 0x81, 0x80, 0x80, 44 | 0xC0, 0x60, 0x20, 0x30, 0x18, 0x0C, 0x04, 0x36, 0x1E, 0x00, 0x3E, 0x78, 45 | 0x61, 0x82, 0x10, 0x31, 0x01, 0xB0, 0x0E, 0x00, 0x58, 0x06, 0x60, 0x33, 46 | 0x01, 0x0C, 0x18, 0x61, 0xE7, 0xC0, 0x3E, 0x01, 0x80, 0x20, 0x0C, 0x01, 47 | 0x80, 0x30, 0x04, 0x01, 0x80, 0x30, 0x04, 0x0D, 0x83, 0x7F, 0xE0, 0x1C, 48 | 0x07, 0x0C, 0x0E, 0x0C, 0x14, 0x14, 0x1C, 0x14, 0x2C, 0x16, 0x4C, 0x26, 49 | 0x48, 0x26, 0x98, 0x27, 0x18, 0x27, 0x10, 0x42, 0x30, 0xF4, 0x7C, 0x38, 50 | 0x78, 0x60, 0x83, 0x04, 0x2C, 0x41, 0x22, 0x09, 0x10, 0x4D, 0x84, 0x28, 51 | 0x21, 0x41, 0x06, 0x10, 0x21, 0xE1, 0x00, 0x07, 0x83, 0x18, 0xC1, 0xB0, 52 | 0x36, 0x07, 0xC0, 0xF0, 0x3E, 0x06, 0xC0, 0xD8, 0x31, 0x8C, 0x1E, 0x00, 53 | 0x3F, 0xC1, 0x9C, 0x21, 0x8C, 0x31, 0x86, 0x31, 0x87, 0xE1, 0x80, 0x30, 54 | 0x04, 0x01, 0x80, 0x78, 0x00, 0x07, 0x83, 0x18, 0xC1, 0x98, 0x36, 0x07, 55 | 0xC0, 0xF0, 0x1E, 0x06, 0xC0, 0xD8, 0x31, 0x04, 0x13, 0x01, 0x80, 0x70, 56 | 0xB7, 0xE0, 0x3F, 0xC1, 0x8C, 0x21, 0x8C, 0x31, 0x8C, 0x3F, 0x04, 0xC1, 57 | 0x98, 0x31, 0x84, 0x31, 0x86, 0x78, 0x70, 0x1E, 0x4C, 0x63, 0x08, 0xC0, 58 | 0x38, 0x07, 0x00, 0x60, 0x0C, 0x43, 0x10, 0xC6, 0x62, 0x70, 0x7F, 0xE9, 59 | 0x8E, 0x31, 0x04, 0x01, 0x80, 0x30, 0x06, 0x00, 0x80, 0x30, 0x06, 0x00, 60 | 0x80, 0x7E, 0x00, 0x7C, 0xF3, 0x02, 0x30, 0x46, 0x04, 0x60, 0x46, 0x04, 61 | 0x40, 0x8C, 0x08, 0xC0, 0x8C, 0x10, 0xE3, 0x03, 0xC0, 0xF8, 0xEC, 0x0C, 62 | 0x81, 0x18, 0x43, 0x08, 0x62, 0x0C, 0x81, 0x90, 0x14, 0x03, 0x00, 0x60, 63 | 0x08, 0x00, 0xFB, 0xCE, 0x43, 0x0C, 0x86, 0x11, 0x8C, 0x43, 0x38, 0x86, 64 | 0xB2, 0x0D, 0x24, 0x1C, 0x50, 0x38, 0xA0, 0x21, 0x80, 0x42, 0x01, 0x04, 65 | 0x00, 0x3E, 0x71, 0x82, 0x0C, 0x40, 0xC8, 0x07, 0x00, 0x60, 0x06, 0x00, 66 | 0xB0, 0x13, 0x02, 0x18, 0x61, 0x8F, 0x3E, 0xF9, 0xC8, 0x23, 0x10, 0xC8, 67 | 0x34, 0x05, 0x01, 0x80, 0x40, 0x30, 0x0C, 0x03, 0x03, 0xE0, 0x3F, 0xE4, 68 | 0x19, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x40, 0x18, 0x06, 0x05, 69 | 0x81, 0x7F, 0xE0, 0x0E, 0x10, 0x20, 0x81, 0x02, 0x04, 0x10, 0x20, 0x40, 70 | 0x82, 0x04, 0x08, 0x1C, 0x00, 0x81, 0x04, 0x18, 0x20, 0xC1, 0x04, 0x08, 71 | 0x20, 0x41, 0x38, 0x20, 0x82, 0x08, 0x41, 0x04, 0x10, 0xC2, 0x08, 0x20, 72 | 0x8C, 0x00, 0x18, 0x18, 0x2C, 0x24, 0x46, 0x42, 0x83, 0xFF, 0x80, 0xD8, 73 | 0x80, 0x1F, 0x98, 0x98, 0x4C, 0x2C, 0x36, 0x33, 0x3A, 0xEE, 0x38, 0x08, 74 | 0x04, 0x02, 0x03, 0x71, 0xCC, 0xC6, 0xC3, 0x63, 0x21, 0x93, 0x8F, 0x00, 75 | 0x1F, 0x33, 0x60, 0xC0, 0xC0, 0xC0, 0xC4, 0x78, 0x01, 0x80, 0x40, 0x60, 76 | 0x20, 0xF1, 0x89, 0x8C, 0xC4, 0xC2, 0x63, 0x33, 0xAE, 0xE0, 0x0E, 0x65, 77 | 0x8B, 0x2F, 0x98, 0x31, 0x3C, 0x01, 0xE0, 0x40, 0x08, 0x02, 0x00, 0x40, 78 | 0x3E, 0x03, 0x00, 0x40, 0x08, 0x01, 0x00, 0x60, 0x0C, 0x01, 0x00, 0x20, 79 | 0x04, 0x01, 0x00, 0xC0, 0x00, 0x1E, 0x19, 0xD8, 0xCC, 0xE1, 0xC3, 0x01, 80 | 0xE0, 0xBC, 0x82, 0x41, 0x31, 0x0F, 0x00, 0x38, 0x08, 0x04, 0x02, 0x03, 81 | 0x39, 0x6C, 0xC6, 0x46, 0x63, 0x21, 0x11, 0xB8, 0xE0, 0x30, 0x00, 0xE2, 82 | 0x44, 0xC8, 0xCE, 0x06, 0x00, 0x00, 0x00, 0xC0, 0x83, 0x04, 0x08, 0x10, 83 | 0x60, 0x81, 0x02, 0x04, 0x70, 0x38, 0x10, 0x10, 0x10, 0x37, 0x22, 0x24, 84 | 0x38, 0x78, 0x48, 0x4D, 0xC6, 0x73, 0x32, 0x26, 0x64, 0x4C, 0xDE, 0x77, 85 | 0x39, 0x5E, 0xCC, 0xCC, 0xCE, 0x66, 0x62, 0x22, 0x11, 0x11, 0xB9, 0x8E, 86 | 0x77, 0x3B, 0x33, 0x62, 0x62, 0x42, 0x4D, 0xCE, 0x0F, 0x18, 0xD8, 0x7C, 87 | 0x3C, 0x3E, 0x1B, 0x18, 0xF0, 0x3B, 0x87, 0x31, 0x8C, 0x43, 0x31, 0x88, 88 | 0x62, 0x30, 0xF0, 0x60, 0x10, 0x04, 0x03, 0x80, 0x0F, 0x18, 0x98, 0x4C, 89 | 0x2C, 0x26, 0x33, 0x38, 0xEC, 0x04, 0x02, 0x03, 0x03, 0xC0, 0x76, 0x50, 90 | 0xC1, 0x06, 0x08, 0x10, 0x60, 0x1A, 0x6C, 0xC8, 0xC0, 0xD1, 0xB3, 0x5C, 91 | 0x23, 0xC8, 0xC4, 0x21, 0x18, 0xE0, 0xC3, 0x42, 0x42, 0xC6, 0x86, 0x8C, 92 | 0x9D, 0xEE, 0x62, 0xC4, 0x89, 0xA3, 0x47, 0x0C, 0x10, 0xE2, 0x2C, 0x44, 93 | 0xD8, 0x9D, 0x23, 0xA4, 0x65, 0x0C, 0xC1, 0x10, 0x19, 0x95, 0x43, 0x01, 94 | 0x80, 0xC0, 0xA0, 0x91, 0x8E, 0x70, 0x88, 0x46, 0x23, 0x20, 0x90, 0x50, 95 | 0x28, 0x18, 0x08, 0x08, 0x08, 0x18, 0x00, 0x3F, 0x42, 0x04, 0x08, 0x10, 96 | 0x20, 0x40, 0x72, 0x0E, 0x08, 0x61, 0x04, 0x30, 0x86, 0x08, 0x61, 0x04, 97 | 0x30, 0xC3, 0x8F, 0x00, 0xFF, 0xF0, 0x1E, 0x0C, 0x10, 0x20, 0xC1, 0x82, 98 | 0x04, 0x1C, 0x30, 0x40, 0x83, 0x04, 0x08, 0x20, 0x60, 0x99, 0x8E }; 99 | 100 | const GFXglyph FreeSerifItalic9pt7bGlyphs[] = { 101 | { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' 102 | { 0, 4, 12, 6, 1, -11 }, // 0x21 '!' 103 | { 6, 5, 4, 6, 3, -11 }, // 0x22 '"' 104 | { 9, 10, 12, 9, 0, -11 }, // 0x23 '#' 105 | { 24, 9, 15, 9, 1, -12 }, // 0x24 '$' 106 | { 41, 14, 12, 15, 1, -11 }, // 0x25 '%' 107 | { 62, 12, 12, 14, 1, -11 }, // 0x26 '&' 108 | { 80, 2, 4, 4, 3, -11 }, // 0x27 ''' 109 | { 81, 6, 15, 6, 1, -11 }, // 0x28 '(' 110 | { 93, 6, 15, 6, 0, -11 }, // 0x29 ')' 111 | { 105, 6, 8, 9, 3, -11 }, // 0x2A '*' 112 | { 111, 9, 9, 12, 1, -8 }, // 0x2B '+' 113 | { 122, 2, 4, 5, 0, -1 }, // 0x2C ',' 114 | { 123, 4, 1, 6, 1, -3 }, // 0x2D '-' 115 | { 124, 2, 2, 5, 0, -1 }, // 0x2E '.' 116 | { 125, 8, 12, 5, 0, -11 }, // 0x2F '/' 117 | { 137, 9, 13, 9, 1, -12 }, // 0x30 '0' 118 | { 152, 6, 13, 9, 1, -12 }, // 0x31 '1' 119 | { 162, 8, 12, 9, 1, -11 }, // 0x32 '2' 120 | { 174, 9, 12, 9, 0, -11 }, // 0x33 '3' 121 | { 188, 9, 12, 9, 0, -11 }, // 0x34 '4' 122 | { 202, 9, 12, 9, 0, -11 }, // 0x35 '5' 123 | { 216, 9, 13, 9, 1, -12 }, // 0x36 '6' 124 | { 231, 9, 12, 9, 1, -11 }, // 0x37 '7' 125 | { 245, 9, 13, 9, 1, -12 }, // 0x38 '8' 126 | { 260, 9, 13, 9, 0, -12 }, // 0x39 '9' 127 | { 275, 4, 8, 4, 1, -7 }, // 0x3A ':' 128 | { 279, 4, 10, 4, 1, -7 }, // 0x3B ';' 129 | { 284, 9, 9, 10, 1, -8 }, // 0x3C '<' 130 | { 295, 9, 5, 12, 2, -6 }, // 0x3D '=' 131 | { 301, 9, 9, 10, 1, -8 }, // 0x3E '>' 132 | { 312, 7, 12, 8, 2, -11 }, // 0x3F '?' 133 | { 323, 13, 12, 14, 1, -11 }, // 0x40 '@' 134 | { 343, 11, 11, 12, 0, -10 }, // 0x41 'A' 135 | { 359, 11, 12, 11, 0, -11 }, // 0x42 'B' 136 | { 376, 12, 12, 11, 1, -11 }, // 0x43 'C' 137 | { 394, 13, 12, 13, 0, -11 }, // 0x44 'D' 138 | { 414, 12, 12, 10, 0, -11 }, // 0x45 'E' 139 | { 432, 12, 12, 10, 0, -11 }, // 0x46 'F' 140 | { 450, 12, 12, 12, 1, -11 }, // 0x47 'G' 141 | { 468, 14, 12, 13, 0, -11 }, // 0x48 'H' 142 | { 489, 7, 12, 6, 0, -11 }, // 0x49 'I' 143 | { 500, 9, 12, 8, 0, -11 }, // 0x4A 'J' 144 | { 514, 13, 12, 12, 0, -11 }, // 0x4B 'K' 145 | { 534, 11, 12, 10, 0, -11 }, // 0x4C 'L' 146 | { 551, 16, 12, 15, 0, -11 }, // 0x4D 'M' 147 | { 575, 13, 12, 12, 0, -11 }, // 0x4E 'N' 148 | { 595, 11, 12, 12, 1, -11 }, // 0x4F 'O' 149 | { 612, 11, 12, 10, 0, -11 }, // 0x50 'P' 150 | { 629, 11, 15, 12, 1, -11 }, // 0x51 'Q' 151 | { 650, 11, 12, 11, 0, -11 }, // 0x52 'R' 152 | { 667, 10, 12, 8, 0, -11 }, // 0x53 'S' 153 | { 682, 11, 12, 11, 2, -11 }, // 0x54 'T' 154 | { 699, 12, 12, 13, 2, -11 }, // 0x55 'U' 155 | { 717, 11, 12, 12, 2, -11 }, // 0x56 'V' 156 | { 734, 15, 12, 16, 2, -11 }, // 0x57 'W' 157 | { 757, 12, 12, 12, 0, -11 }, // 0x58 'X' 158 | { 775, 10, 12, 11, 2, -11 }, // 0x59 'Y' 159 | { 790, 11, 12, 10, 0, -11 }, // 0x5A 'Z' 160 | { 807, 7, 15, 7, 0, -11 }, // 0x5B '[' 161 | { 821, 6, 12, 9, 2, -11 }, // 0x5C '\' 162 | { 830, 6, 15, 7, 1, -11 }, // 0x5D ']' 163 | { 842, 8, 7, 8, 0, -11 }, // 0x5E '^' 164 | { 849, 9, 1, 9, 0, 2 }, // 0x5F '_' 165 | { 851, 3, 3, 5, 2, -11 }, // 0x60 '`' 166 | { 853, 9, 8, 9, 0, -7 }, // 0x61 'a' 167 | { 862, 9, 12, 9, 0, -11 }, // 0x62 'b' 168 | { 876, 8, 8, 7, 0, -7 }, // 0x63 'c' 169 | { 884, 9, 12, 9, 0, -11 }, // 0x64 'd' 170 | { 898, 7, 8, 7, 0, -7 }, // 0x65 'e' 171 | { 905, 11, 17, 8, -1, -12 }, // 0x66 'f' 172 | { 929, 9, 12, 8, 0, -7 }, // 0x67 'g' 173 | { 943, 9, 12, 9, 0, -11 }, // 0x68 'h' 174 | { 957, 4, 12, 4, 1, -11 }, // 0x69 'i' 175 | { 963, 7, 16, 5, -1, -11 }, // 0x6A 'j' 176 | { 977, 8, 12, 8, 0, -11 }, // 0x6B 'k' 177 | { 989, 4, 12, 5, 1, -11 }, // 0x6C 'l' 178 | { 995, 13, 8, 13, 0, -7 }, // 0x6D 'm' 179 | { 1008, 8, 8, 9, 0, -7 }, // 0x6E 'n' 180 | { 1016, 9, 8, 9, 0, -7 }, // 0x6F 'o' 181 | { 1025, 10, 12, 8, -1, -7 }, // 0x70 'p' 182 | { 1040, 9, 12, 9, 0, -7 }, // 0x71 'q' 183 | { 1054, 7, 8, 7, 0, -7 }, // 0x72 'r' 184 | { 1061, 7, 8, 6, 0, -7 }, // 0x73 's' 185 | { 1068, 5, 9, 4, 0, -8 }, // 0x74 't' 186 | { 1074, 8, 8, 9, 1, -7 }, // 0x75 'u' 187 | { 1082, 7, 8, 8, 1, -7 }, // 0x76 'v' 188 | { 1089, 11, 8, 12, 1, -7 }, // 0x77 'w' 189 | { 1100, 9, 8, 8, -1, -7 }, // 0x78 'x' 190 | { 1109, 9, 12, 9, 0, -7 }, // 0x79 'y' 191 | { 1123, 8, 9, 7, 0, -7 }, // 0x7A 'z' 192 | { 1132, 6, 15, 7, 1, -11 }, // 0x7B '{' 193 | { 1144, 1, 12, 5, 2, -11 }, // 0x7C '|' 194 | { 1146, 7, 16, 7, 0, -12 }, // 0x7D '}' 195 | { 1160, 8, 3, 10, 1, -5 } }; // 0x7E '~' 196 | 197 | const GFXfont FreeSerifItalic9pt7b = { 198 | (uint8_t *)FreeSerifItalic9pt7bBitmaps, 199 | (GFXglyph *)FreeSerifItalic9pt7bGlyphs, 200 | 0x20, 0x7E, 22 }; 201 | 202 | // Approx. 1835 bytes 203 | -------------------------------------------------------------------------------- /main/fonts/FreeMonoBoldOblique9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeMonoBoldOblique9pt7bBitmaps[] = { 2 | 0x39, 0xCC, 0x67, 0x31, 0x8C, 0x07, 0x38, 0x6C, 0xD9, 0x36, 0x48, 0x80, 3 | 0x09, 0x0D, 0x86, 0xCF, 0xF7, 0xF9, 0xB3, 0xFD, 0xFE, 0x6C, 0x36, 0x1B, 4 | 0x00, 0x00, 0x06, 0x07, 0x07, 0xE6, 0x33, 0x01, 0xE0, 0x7C, 0x06, 0x43, 5 | 0x33, 0xBF, 0x83, 0x03, 0x00, 0x80, 0x1C, 0x11, 0x10, 0x88, 0x83, 0xB8, 6 | 0xF3, 0xB8, 0x22, 0x21, 0x11, 0x07, 0x00, 0x0F, 0x1F, 0x30, 0x30, 0x38, 7 | 0x7B, 0xDF, 0xCE, 0xFF, 0x7E, 0xFA, 0x80, 0x19, 0x8C, 0xC6, 0x63, 0x18, 8 | 0xC6, 0x31, 0xC6, 0x30, 0x31, 0xC6, 0x31, 0x8C, 0x63, 0x31, 0x98, 0xCC, 9 | 0x40, 0x08, 0x08, 0xFF, 0xFF, 0x38, 0x6C, 0x6C, 0x0C, 0x06, 0x03, 0x1F, 10 | 0xFF, 0xF8, 0xC0, 0x60, 0x30, 0x10, 0x00, 0x36, 0x4C, 0x80, 0xFF, 0xFF, 11 | 0xC0, 0xFC, 0x00, 0x00, 0x0C, 0x03, 0x00, 0xC0, 0x18, 0x06, 0x01, 0x80, 12 | 0x30, 0x0C, 0x03, 0x00, 0x60, 0x18, 0x06, 0x00, 0xC0, 0x30, 0x00, 0x0F, 13 | 0x0F, 0xCC, 0x6C, 0x36, 0x1B, 0x0D, 0x05, 0x86, 0xC3, 0x63, 0x3F, 0x8F, 14 | 0x00, 0x06, 0x1C, 0x3C, 0x6C, 0x0C, 0x0C, 0x08, 0x18, 0x18, 0x18, 0xFE, 15 | 0xFE, 0x07, 0x83, 0xF1, 0x8C, 0x43, 0x00, 0xC0, 0xE0, 0x70, 0x38, 0x38, 16 | 0x1C, 0x6F, 0xF3, 0xFC, 0x1F, 0x1F, 0xC0, 0x60, 0x30, 0x30, 0x70, 0x38, 17 | 0x06, 0x03, 0x03, 0xBF, 0x9F, 0x80, 0x03, 0x07, 0x0B, 0x1B, 0x32, 0x66, 18 | 0xFF, 0xFF, 0x1E, 0x1E, 0x3F, 0x9F, 0x98, 0x0F, 0xC7, 0xF3, 0x18, 0x0C, 19 | 0x06, 0x06, 0x7F, 0x1E, 0x00, 0x07, 0x87, 0xCE, 0x06, 0x06, 0x03, 0xF3, 20 | 0xFD, 0xC6, 0xC3, 0x63, 0xBF, 0x8F, 0x80, 0xFF, 0xFF, 0xC3, 0x06, 0x06, 21 | 0x0C, 0x18, 0x18, 0x30, 0x30, 0x60, 0x1F, 0x1F, 0xDC, 0x6C, 0x36, 0x31, 22 | 0xF1, 0xF8, 0xC6, 0xC3, 0x63, 0xBF, 0x8F, 0x80, 0x1E, 0x3F, 0x33, 0x63, 23 | 0x63, 0x67, 0x7F, 0x3E, 0x06, 0x1C, 0xF8, 0xF0, 0x77, 0x00, 0x00, 0xEE, 24 | 0x1C, 0x70, 0x00, 0x00, 0x03, 0x0C, 0x61, 0x08, 0x00, 0x00, 0xC1, 0xE1, 25 | 0xE1, 0xE0, 0xF0, 0x07, 0x00, 0xF0, 0x0C, 0x7F, 0xDF, 0xF0, 0x00, 0x00, 26 | 0x7F, 0xFF, 0xF0, 0x30, 0x0F, 0x00, 0xE0, 0x1E, 0x07, 0xC7, 0x87, 0x83, 27 | 0x00, 0x7D, 0xFF, 0x18, 0x30, 0xE3, 0x9C, 0x30, 0x01, 0xC3, 0x80, 0x0F, 28 | 0x0F, 0xCC, 0x6C, 0x36, 0x72, 0x79, 0x7D, 0xB6, 0xDA, 0x6F, 0xB3, 0xD8, 29 | 0x0C, 0x07, 0xE1, 0xE0, 0x0F, 0x83, 0xF0, 0x1E, 0x03, 0xC0, 0xD8, 0x31, 30 | 0x87, 0xF1, 0xFE, 0x30, 0xDF, 0x3F, 0xC7, 0x80, 0x3F, 0xC7, 0xFC, 0x61, 31 | 0x8C, 0x31, 0xFC, 0x3F, 0x84, 0x19, 0x83, 0x30, 0x6F, 0xFB, 0xFE, 0x00, 32 | 0x0F, 0xF1, 0xFF, 0x30, 0x66, 0x06, 0x60, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 33 | 0xE0, 0xC7, 0xF8, 0x3F, 0x00, 0x3F, 0x87, 0xF8, 0x63, 0x8C, 0x31, 0x06, 34 | 0x60, 0xCC, 0x19, 0x86, 0x31, 0xCF, 0xF3, 0xF8, 0x00, 0x3F, 0xE3, 0xFE, 35 | 0x18, 0x61, 0xB6, 0x1F, 0x01, 0xF0, 0x32, 0x03, 0x00, 0x30, 0x4F, 0xFC, 36 | 0xFF, 0xC0, 0x3F, 0xF3, 0xFE, 0x18, 0x61, 0xB6, 0x1F, 0x03, 0xF0, 0x32, 37 | 0x03, 0x00, 0x30, 0x0F, 0xC0, 0xFC, 0x00, 0x0F, 0xE3, 0xFC, 0xC1, 0x30, 38 | 0x06, 0x01, 0x80, 0x31, 0xF6, 0x3E, 0xE1, 0x9F, 0xF0, 0xF8, 0x00, 0x1E, 39 | 0xF3, 0xCF, 0x18, 0x61, 0x84, 0x10, 0xC3, 0xFC, 0x3F, 0xC3, 0x08, 0x31, 40 | 0x8F, 0xBC, 0xFB, 0xC0, 0x3F, 0xCF, 0xF0, 0x60, 0x10, 0x0C, 0x03, 0x00, 41 | 0xC0, 0x20, 0x18, 0x3F, 0xCF, 0xF0, 0x07, 0xF0, 0x7F, 0x00, 0x80, 0x18, 42 | 0x01, 0x80, 0x18, 0x61, 0x84, 0x10, 0xC3, 0x0F, 0xE0, 0x7C, 0x00, 0x3E, 43 | 0xE7, 0xFC, 0x66, 0x0D, 0x81, 0x60, 0x7C, 0x0E, 0xC1, 0x98, 0x31, 0x1F, 44 | 0x3B, 0xE7, 0x00, 0x3F, 0x07, 0xE0, 0x30, 0x06, 0x00, 0xC0, 0x10, 0x06, 45 | 0x00, 0xC3, 0x18, 0x6F, 0xFB, 0xFF, 0x00, 0x38, 0x39, 0xC3, 0xC7, 0x3C, 46 | 0x79, 0xE3, 0xDA, 0x1F, 0xF0, 0x9D, 0x8C, 0xCC, 0x60, 0x67, 0xCF, 0x3C, 47 | 0x78, 0x3C, 0xF9, 0xE7, 0x87, 0x18, 0x3C, 0xC1, 0x66, 0x1B, 0xB0, 0xCD, 48 | 0x06, 0x78, 0x31, 0xC3, 0xCE, 0x3E, 0x30, 0x0F, 0x0F, 0xE7, 0x1D, 0x83, 49 | 0xC0, 0xF0, 0x3C, 0x0F, 0x06, 0xE3, 0x9F, 0xC3, 0xC0, 0x3F, 0xC7, 0xFC, 50 | 0x61, 0x8C, 0x31, 0x8E, 0x3F, 0x87, 0xE1, 0x80, 0x30, 0x0F, 0xC3, 0xF0, 51 | 0x00, 0x0F, 0x0F, 0xE7, 0x1D, 0x83, 0xC0, 0xF0, 0x3C, 0x0F, 0x06, 0xE3, 52 | 0x1F, 0xC3, 0xC0, 0x80, 0x7F, 0x3F, 0xC0, 0x3F, 0xC3, 0xFE, 0x18, 0x61, 53 | 0x86, 0x10, 0xE3, 0xFC, 0x3F, 0x83, 0x18, 0x31, 0xCF, 0x8F, 0xF8, 0x70, 54 | 0x1E, 0xCF, 0xF7, 0x19, 0x80, 0x70, 0x1F, 0x81, 0xF3, 0x0C, 0xC3, 0x3F, 55 | 0x8B, 0xC0, 0x7F, 0xCF, 0xF9, 0x93, 0x66, 0x60, 0xC0, 0x18, 0x02, 0x00, 56 | 0xC0, 0x18, 0x0F, 0xC1, 0xF8, 0x00, 0xF9, 0xFF, 0x7D, 0x83, 0x30, 0x64, 57 | 0x09, 0x83, 0x30, 0x66, 0x0C, 0xE3, 0x0F, 0xC0, 0xF0, 0x00, 0xF9, 0xFE, 58 | 0x3D, 0x83, 0x30, 0xC6, 0x30, 0xE6, 0x0D, 0x81, 0xB0, 0x3C, 0x07, 0x00, 59 | 0x60, 0x00, 0xF9, 0xFF, 0x3D, 0x83, 0x36, 0x64, 0xC8, 0xBF, 0x35, 0xE7, 60 | 0xB8, 0xE7, 0x1C, 0xE3, 0x18, 0x00, 0x3C, 0xF3, 0xCF, 0x1C, 0xC0, 0xD8, 61 | 0x0F, 0x00, 0x60, 0x0F, 0x01, 0xB8, 0x31, 0x8F, 0x3C, 0xF3, 0xC0, 0x79, 62 | 0xEE, 0x38, 0xC6, 0x19, 0x81, 0xE0, 0x38, 0x06, 0x00, 0xC0, 0x18, 0x0F, 63 | 0xC3, 0xF8, 0x00, 0x3F, 0xCF, 0xF3, 0x18, 0xCC, 0x06, 0x03, 0x01, 0x80, 64 | 0xC6, 0x61, 0xBF, 0xCF, 0xF0, 0x1E, 0x3C, 0xC1, 0x83, 0x06, 0x08, 0x30, 65 | 0x60, 0xC1, 0x06, 0x0F, 0x1E, 0x00, 0x06, 0x31, 0x86, 0x31, 0x8C, 0x31, 66 | 0x8C, 0x61, 0x8C, 0x60, 0x1E, 0x78, 0x30, 0x60, 0xC1, 0x86, 0x0C, 0x18, 67 | 0x30, 0x41, 0x8F, 0x1E, 0x00, 0x08, 0x1C, 0x3C, 0x76, 0xE7, 0xC3, 0x7F, 68 | 0xFF, 0xFC, 0x88, 0x80, 0x0F, 0x07, 0xE1, 0xF9, 0xFE, 0xE3, 0x30, 0xCF, 69 | 0xFD, 0xFF, 0x38, 0x07, 0x00, 0x60, 0x0F, 0xC1, 0xFC, 0x71, 0xCC, 0x19, 70 | 0x83, 0x30, 0xDF, 0xFB, 0xBC, 0x00, 0x1F, 0xCF, 0xF6, 0x1B, 0x00, 0xC0, 71 | 0x30, 0x0F, 0xF1, 0xF8, 0x01, 0xE0, 0x38, 0x03, 0x0F, 0x63, 0xFC, 0xC3, 72 | 0x30, 0x66, 0x0C, 0xC3, 0x9F, 0xF9, 0xF7, 0x00, 0x1F, 0x1F, 0xD8, 0x3F, 73 | 0xFF, 0xFE, 0x1B, 0xFC, 0xF8, 0x07, 0xC3, 0xF1, 0x81, 0xFE, 0x7F, 0x84, 74 | 0x03, 0x00, 0xC0, 0x30, 0x3F, 0x8F, 0xE0, 0x1E, 0xE7, 0xFD, 0x86, 0x60, 75 | 0xCC, 0x19, 0xC6, 0x3F, 0xC1, 0xD8, 0x03, 0x00, 0xE1, 0xF8, 0x3E, 0x00, 76 | 0x38, 0x1E, 0x01, 0x00, 0xDC, 0x3F, 0x8C, 0x62, 0x19, 0x84, 0x63, 0x3D, 77 | 0xFF, 0x7C, 0x06, 0x03, 0x00, 0x03, 0xC3, 0xE0, 0x20, 0x30, 0x18, 0x0C, 78 | 0x3F, 0xFF, 0xE0, 0x01, 0x81, 0x80, 0x07, 0xF3, 0xF8, 0x0C, 0x04, 0x06, 79 | 0x03, 0x01, 0x80, 0xC0, 0x40, 0x67, 0xE3, 0xE0, 0x38, 0x0E, 0x01, 0x80, 80 | 0x4F, 0x37, 0xCF, 0x83, 0xC0, 0xF0, 0x26, 0x39, 0xEE, 0x78, 0x1F, 0x0F, 81 | 0x01, 0x80, 0xC0, 0x60, 0x20, 0x30, 0x18, 0x0C, 0x3F, 0xFF, 0xE0, 0x7E, 82 | 0xE7, 0xFF, 0x33, 0x32, 0x63, 0x66, 0x36, 0x62, 0xF7, 0x7F, 0x67, 0x77, 83 | 0x8F, 0xF8, 0xC3, 0x10, 0x66, 0x08, 0xC3, 0x3C, 0x7F, 0x8F, 0x1F, 0x0F, 84 | 0xE6, 0x1F, 0x03, 0xC0, 0xF8, 0x67, 0xF0, 0xF8, 0x3F, 0xE3, 0xFF, 0x1C, 85 | 0x31, 0x83, 0x18, 0x31, 0x86, 0x3F, 0xE3, 0x78, 0x30, 0x03, 0x00, 0xFC, 86 | 0x0F, 0x80, 0x1E, 0xEF, 0xFD, 0x86, 0x60, 0xCC, 0x19, 0xC7, 0x3F, 0xE1, 87 | 0xE8, 0x03, 0x00, 0x60, 0x3E, 0x07, 0xC0, 0x39, 0xDF, 0xF1, 0xC0, 0x60, 88 | 0x10, 0x0C, 0x0F, 0xF3, 0xF8, 0x1F, 0x7F, 0x63, 0x7E, 0x1F, 0xC3, 0xFE, 89 | 0xFC, 0x10, 0x08, 0x0C, 0x1F, 0xEF, 0xF1, 0x80, 0x80, 0xC0, 0x60, 0x3F, 90 | 0x8F, 0x80, 0xF3, 0xFC, 0xF6, 0x09, 0x86, 0x61, 0x98, 0xE7, 0xF8, 0xFE, 91 | 0xFB, 0xFF, 0x7C, 0xC6, 0x19, 0x83, 0x60, 0x6C, 0x07, 0x00, 0xC0, 0xF1, 92 | 0xFE, 0x3D, 0xB3, 0x37, 0xC7, 0xF8, 0xEE, 0x1D, 0xC3, 0x30, 0x79, 0xEF, 93 | 0x38, 0xEE, 0x0F, 0x01, 0xE0, 0x6E, 0x3C, 0xE7, 0xBC, 0x3C, 0xF3, 0x8F, 94 | 0x18, 0xC1, 0x9C, 0x19, 0x81, 0xF0, 0x0E, 0x00, 0xE0, 0x0C, 0x01, 0x80, 95 | 0xFC, 0x0F, 0xC0, 0x7F, 0xBF, 0xD9, 0xC1, 0x83, 0x83, 0x1B, 0xFD, 0xFE, 96 | 0x06, 0x1C, 0x60, 0xC1, 0x86, 0x3C, 0x70, 0x30, 0x41, 0x83, 0x07, 0x06, 97 | 0x00, 0x33, 0x32, 0x26, 0x66, 0x44, 0xCC, 0xC8, 0x0C, 0x0E, 0x04, 0x0C, 98 | 0x0C, 0x0C, 0x0F, 0x0F, 0x18, 0x18, 0x10, 0x30, 0xF0, 0xE0, 0x38, 0x7C, 99 | 0xF7, 0xC1, 0xC0 }; 100 | 101 | const GFXglyph FreeMonoBoldOblique9pt7bGlyphs[] = { 102 | { 0, 0, 0, 11, 0, 1 }, // 0x20 ' ' 103 | { 0, 5, 11, 11, 4, -10 }, // 0x21 '!' 104 | { 7, 7, 5, 11, 4, -10 }, // 0x22 '"' 105 | { 12, 9, 12, 11, 2, -10 }, // 0x23 '#' 106 | { 26, 9, 14, 11, 2, -11 }, // 0x24 '$' 107 | { 42, 9, 11, 11, 2, -10 }, // 0x25 '%' 108 | { 55, 8, 10, 11, 2, -9 }, // 0x26 '&' 109 | { 65, 2, 5, 11, 6, -10 }, // 0x27 ''' 110 | { 67, 5, 14, 11, 5, -10 }, // 0x28 '(' 111 | { 76, 5, 14, 11, 2, -10 }, // 0x29 ')' 112 | { 85, 8, 7, 11, 3, -10 }, // 0x2A '*' 113 | { 92, 9, 9, 11, 2, -8 }, // 0x2B '+' 114 | { 103, 4, 5, 11, 2, -1 }, // 0x2C ',' 115 | { 106, 9, 2, 11, 2, -5 }, // 0x2D '-' 116 | { 109, 3, 2, 11, 4, -1 }, // 0x2E '.' 117 | { 110, 11, 15, 11, 1, -12 }, // 0x2F '/' 118 | { 131, 9, 12, 11, 2, -11 }, // 0x30 '0' 119 | { 145, 8, 12, 11, 2, -11 }, // 0x31 '1' 120 | { 157, 10, 12, 11, 1, -11 }, // 0x32 '2' 121 | { 172, 9, 12, 11, 2, -11 }, // 0x33 '3' 122 | { 186, 8, 10, 11, 2, -9 }, // 0x34 '4' 123 | { 196, 9, 11, 11, 3, -10 }, // 0x35 '5' 124 | { 209, 9, 12, 11, 3, -11 }, // 0x36 '6' 125 | { 223, 8, 11, 11, 3, -10 }, // 0x37 '7' 126 | { 234, 9, 12, 11, 2, -11 }, // 0x38 '8' 127 | { 248, 8, 12, 11, 3, -11 }, // 0x39 '9' 128 | { 260, 4, 8, 11, 4, -7 }, // 0x3A ':' 129 | { 264, 6, 11, 11, 2, -7 }, // 0x3B ';' 130 | { 273, 10, 8, 11, 2, -8 }, // 0x3C '<' 131 | { 283, 10, 6, 11, 1, -7 }, // 0x3D '=' 132 | { 291, 10, 8, 11, 1, -8 }, // 0x3E '>' 133 | { 301, 7, 11, 11, 4, -10 }, // 0x3F '?' 134 | { 311, 9, 15, 11, 2, -11 }, // 0x40 '@' 135 | { 328, 11, 11, 11, 0, -10 }, // 0x41 'A' 136 | { 344, 11, 11, 11, 0, -10 }, // 0x42 'B' 137 | { 360, 12, 11, 11, 1, -10 }, // 0x43 'C' 138 | { 377, 11, 11, 11, 0, -10 }, // 0x44 'D' 139 | { 393, 12, 11, 11, 0, -10 }, // 0x45 'E' 140 | { 410, 12, 11, 11, 0, -10 }, // 0x46 'F' 141 | { 427, 11, 11, 11, 1, -10 }, // 0x47 'G' 142 | { 443, 12, 11, 11, 0, -10 }, // 0x48 'H' 143 | { 460, 10, 11, 11, 1, -10 }, // 0x49 'I' 144 | { 474, 12, 11, 11, 0, -10 }, // 0x4A 'J' 145 | { 491, 11, 11, 11, 0, -10 }, // 0x4B 'K' 146 | { 507, 11, 11, 11, 0, -10 }, // 0x4C 'L' 147 | { 523, 13, 11, 11, 0, -10 }, // 0x4D 'M' 148 | { 541, 13, 11, 11, 0, -10 }, // 0x4E 'N' 149 | { 559, 10, 11, 11, 1, -10 }, // 0x4F 'O' 150 | { 573, 11, 11, 11, 0, -10 }, // 0x50 'P' 151 | { 589, 10, 14, 11, 1, -10 }, // 0x51 'Q' 152 | { 607, 12, 11, 11, 0, -10 }, // 0x52 'R' 153 | { 624, 10, 11, 11, 2, -10 }, // 0x53 'S' 154 | { 638, 11, 11, 11, 1, -10 }, // 0x54 'T' 155 | { 654, 11, 11, 11, 1, -10 }, // 0x55 'U' 156 | { 670, 11, 11, 11, 1, -10 }, // 0x56 'V' 157 | { 686, 11, 11, 11, 1, -10 }, // 0x57 'W' 158 | { 702, 12, 11, 11, 0, -10 }, // 0x58 'X' 159 | { 719, 11, 11, 11, 1, -10 }, // 0x59 'Y' 160 | { 735, 10, 11, 11, 1, -10 }, // 0x5A 'Z' 161 | { 749, 7, 14, 11, 4, -10 }, // 0x5B '[' 162 | { 762, 5, 15, 11, 4, -12 }, // 0x5C '\' 163 | { 772, 7, 14, 11, 2, -10 }, // 0x5D ']' 164 | { 785, 8, 6, 11, 3, -11 }, // 0x5E '^' 165 | { 791, 11, 2, 11, -1, 3 }, // 0x5F '_' 166 | { 794, 3, 3, 11, 5, -11 }, // 0x60 '`' 167 | { 796, 10, 8, 11, 1, -7 }, // 0x61 'a' 168 | { 806, 11, 11, 11, 0, -10 }, // 0x62 'b' 169 | { 822, 10, 8, 11, 1, -7 }, // 0x63 'c' 170 | { 832, 11, 11, 11, 1, -10 }, // 0x64 'd' 171 | { 848, 9, 8, 11, 1, -7 }, // 0x65 'e' 172 | { 857, 10, 11, 11, 2, -10 }, // 0x66 'f' 173 | { 871, 11, 12, 11, 1, -7 }, // 0x67 'g' 174 | { 888, 10, 11, 11, 1, -10 }, // 0x68 'h' 175 | { 902, 9, 11, 11, 1, -10 }, // 0x69 'i' 176 | { 915, 9, 15, 11, 1, -10 }, // 0x6A 'j' 177 | { 932, 10, 11, 11, 1, -10 }, // 0x6B 'k' 178 | { 946, 9, 11, 11, 1, -10 }, // 0x6C 'l' 179 | { 959, 12, 8, 11, 0, -7 }, // 0x6D 'm' 180 | { 971, 11, 8, 11, 1, -7 }, // 0x6E 'n' 181 | { 982, 10, 8, 11, 1, -7 }, // 0x6F 'o' 182 | { 992, 12, 12, 11, -1, -7 }, // 0x70 'p' 183 | { 1010, 11, 12, 11, 1, -7 }, // 0x71 'q' 184 | { 1027, 10, 8, 11, 1, -7 }, // 0x72 'r' 185 | { 1037, 8, 8, 11, 2, -7 }, // 0x73 's' 186 | { 1045, 9, 11, 11, 1, -10 }, // 0x74 't' 187 | { 1058, 10, 8, 11, 1, -7 }, // 0x75 'u' 188 | { 1068, 11, 8, 11, 1, -7 }, // 0x76 'v' 189 | { 1079, 11, 8, 11, 1, -7 }, // 0x77 'w' 190 | { 1090, 11, 8, 11, 1, -7 }, // 0x78 'x' 191 | { 1101, 12, 12, 11, 0, -7 }, // 0x79 'y' 192 | { 1119, 9, 8, 11, 2, -7 }, // 0x7A 'z' 193 | { 1128, 7, 14, 11, 3, -10 }, // 0x7B '{' 194 | { 1141, 4, 14, 11, 4, -10 }, // 0x7C '|' 195 | { 1148, 8, 14, 11, 2, -10 }, // 0x7D '}' 196 | { 1162, 9, 4, 11, 2, -6 } }; // 0x7E '~' 197 | 198 | const GFXfont FreeMonoBoldOblique9pt7b = { 199 | (uint8_t *)FreeMonoBoldOblique9pt7bBitmaps, 200 | (GFXglyph *)FreeMonoBoldOblique9pt7bGlyphs, 201 | 0x20, 0x7E, 18 }; 202 | 203 | // Approx. 1839 bytes 204 | -------------------------------------------------------------------------------- /main/fonts/FreeSansBold9pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t FreeSansBold9pt7bBitmaps[] = { 2 | 0xFF, 0xFF, 0xFE, 0x48, 0x7E, 0xEF, 0xDF, 0xBF, 0x74, 0x40, 0x19, 0x86, 3 | 0x67, 0xFD, 0xFF, 0x33, 0x0C, 0xC3, 0x33, 0xFE, 0xFF, 0x99, 0x86, 0x61, 4 | 0x90, 0x10, 0x1F, 0x1F, 0xDE, 0xFF, 0x3F, 0x83, 0xC0, 0xFC, 0x1F, 0x09, 5 | 0xFC, 0xFE, 0xF7, 0xF1, 0xE0, 0x40, 0x38, 0x10, 0x7C, 0x30, 0xC6, 0x20, 6 | 0xC6, 0x40, 0xC6, 0x40, 0x7C, 0x80, 0x39, 0x9C, 0x01, 0x3E, 0x03, 0x63, 7 | 0x02, 0x63, 0x04, 0x63, 0x0C, 0x3E, 0x08, 0x1C, 0x0E, 0x01, 0xF8, 0x3B, 8 | 0x83, 0xB8, 0x3F, 0x01, 0xE0, 0x3E, 0x67, 0x76, 0xE3, 0xEE, 0x1C, 0xF3, 9 | 0xC7, 0xFE, 0x3F, 0x70, 0xFF, 0xF4, 0x18, 0x63, 0x1C, 0x73, 0x8E, 0x38, 10 | 0xE3, 0x8E, 0x18, 0x70, 0xC3, 0x06, 0x08, 0x61, 0x83, 0x0E, 0x38, 0x71, 11 | 0xC7, 0x1C, 0x71, 0xC6, 0x38, 0xE3, 0x18, 0x40, 0x21, 0x3E, 0x45, 0x28, 12 | 0x38, 0x70, 0xE7, 0xFF, 0xE7, 0x0E, 0x1C, 0xFC, 0x9C, 0xFF, 0xC0, 0xFC, 13 | 0x08, 0xC4, 0x23, 0x10, 0x84, 0x62, 0x11, 0x88, 0x00, 0x3E, 0x3F, 0x9D, 14 | 0xDC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xDD, 0xCF, 0xE3, 0xE0, 15 | 0x08, 0xFF, 0xF3, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x80, 0x3E, 0x3F, 0xB8, 16 | 0xFC, 0x70, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0F, 0xF7, 0xF8, 17 | 0x3C, 0x7F, 0xE7, 0xE7, 0x07, 0x0C, 0x0E, 0x07, 0x07, 0xE7, 0xE7, 0x7E, 18 | 0x3C, 0x0E, 0x1E, 0x1E, 0x2E, 0x2E, 0x4E, 0x4E, 0x8E, 0xFF, 0xFF, 0x0E, 19 | 0x0E, 0x0E, 0x7F, 0x3F, 0x90, 0x18, 0x0D, 0xE7, 0xFB, 0x9E, 0x07, 0x03, 20 | 0x81, 0xF1, 0xFF, 0xE7, 0xC0, 0x3E, 0x3F, 0x9C, 0xFC, 0x0E, 0xE7, 0xFB, 21 | 0xDF, 0xC7, 0xE3, 0xF1, 0xDD, 0xEF, 0xE3, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, 22 | 0xE0, 0x60, 0x70, 0x30, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x80, 0x3F, 23 | 0x1F, 0xEE, 0x3F, 0x87, 0xE3, 0xCF, 0xC7, 0xFB, 0xCF, 0xE1, 0xF8, 0x7F, 24 | 0x3D, 0xFE, 0x3F, 0x00, 0x3E, 0x3F, 0xBD, 0xDC, 0x7E, 0x3F, 0x1F, 0xDE, 25 | 0xFF, 0x3B, 0x81, 0xF9, 0xCF, 0xE3, 0xC0, 0xFC, 0x00, 0x07, 0xE0, 0xFC, 26 | 0x00, 0x07, 0xE5, 0xE0, 0x00, 0x83, 0xC7, 0xDF, 0x0C, 0x07, 0x80, 0xF8, 27 | 0x1F, 0x01, 0x80, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x70, 28 | 0x3F, 0x03, 0xE0, 0x38, 0x7D, 0xF1, 0xE0, 0x80, 0x00, 0x3E, 0x3F, 0xB8, 29 | 0xFC, 0x70, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x0E, 0x00, 0x03, 0x81, 0xC0, 30 | 0x03, 0xF0, 0x0F, 0xFC, 0x1E, 0x0E, 0x38, 0x02, 0x70, 0xE9, 0x63, 0x19, 31 | 0xC2, 0x19, 0xC6, 0x11, 0xC6, 0x33, 0xC6, 0x32, 0x63, 0xFE, 0x73, 0xDC, 32 | 0x3C, 0x00, 0x1F, 0xF8, 0x07, 0xF0, 0x07, 0x00, 0xF0, 0x0F, 0x80, 0xF8, 33 | 0x1D, 0x81, 0x9C, 0x19, 0xC3, 0x8C, 0x3F, 0xE7, 0xFE, 0x70, 0x66, 0x07, 34 | 0xE0, 0x70, 0xFF, 0x9F, 0xFB, 0x83, 0xF0, 0x7E, 0x0F, 0xFF, 0x3F, 0xF7, 35 | 0x06, 0xE0, 0xFC, 0x1F, 0x83, 0xFF, 0xEF, 0xF8, 0x1F, 0x83, 0xFE, 0x78, 36 | 0xE7, 0x07, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x07, 0x78, 37 | 0xF3, 0xFE, 0x1F, 0x80, 0xFF, 0x8F, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, 0x7E, 38 | 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x0E, 0xE0, 0xEF, 0xFC, 0xFF, 0x80, 39 | 0xFF, 0xFF, 0xF8, 0x1C, 0x0E, 0x07, 0xFB, 0xFD, 0xC0, 0xE0, 0x70, 0x38, 40 | 0x1F, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 0x1C, 0x0E, 0x07, 0xFB, 0xFD, 0xC0, 41 | 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0x0F, 0x87, 0xF9, 0xE3, 0xB8, 0x3E, 42 | 0x01, 0xC0, 0x38, 0xFF, 0x1F, 0xE0, 0x6E, 0x0D, 0xE3, 0x9F, 0xD0, 0xF2, 43 | 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 44 | 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x07, 45 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xE7, 0xE7, 0xE7, 0x7E, 0x3C, 46 | 0xE0, 0xEE, 0x1C, 0xE3, 0x8E, 0x70, 0xEE, 0x0F, 0xC0, 0xFE, 0x0F, 0x70, 47 | 0xE7, 0x0E, 0x38, 0xE1, 0xCE, 0x0E, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 48 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xF8, 0x7F, 0xE1, 49 | 0xFF, 0x87, 0xFE, 0x1F, 0xEC, 0x7F, 0xB3, 0x7E, 0xCD, 0xFB, 0x37, 0xEC, 50 | 0xDF, 0x9E, 0x7E, 0x79, 0xF9, 0xE7, 0xE7, 0x9C, 0xE0, 0xFE, 0x1F, 0xC3, 51 | 0xFC, 0x7F, 0xCF, 0xD9, 0xFB, 0xBF, 0x37, 0xE7, 0xFC, 0x7F, 0x87, 0xF0, 52 | 0xFE, 0x0E, 0x0F, 0x81, 0xFF, 0x1E, 0x3C, 0xE0, 0xEE, 0x03, 0xF0, 0x1F, 53 | 0x80, 0xFC, 0x07, 0xE0, 0x3B, 0x83, 0x9E, 0x3C, 0x7F, 0xC0, 0xF8, 0x00, 54 | 0xFF, 0x9F, 0xFB, 0x87, 0xF0, 0x7E, 0x0F, 0xC3, 0xFF, 0xF7, 0xFC, 0xE0, 55 | 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x0F, 0x81, 0xFF, 0x1E, 0x3C, 0xE0, 56 | 0xEE, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE1, 0xBB, 0x8F, 0x9E, 0x3C, 57 | 0x7F, 0xE0, 0xFB, 0x80, 0x08, 0xFF, 0x8F, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, 58 | 0xEE, 0x0E, 0xFF, 0xCF, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 59 | 0xF0, 0x3F, 0x0F, 0xFB, 0xC7, 0xF0, 0x7E, 0x01, 0xFC, 0x1F, 0xF0, 0x3F, 60 | 0x00, 0xFC, 0x1D, 0xC7, 0xBF, 0xE1, 0xF8, 0xFF, 0xFF, 0xC7, 0x03, 0x81, 61 | 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0xFC, 62 | 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 63 | 0xC7, 0xBF, 0xE1, 0xF0, 0x60, 0x67, 0x0E, 0x70, 0xE3, 0x0C, 0x30, 0xC3, 64 | 0x9C, 0x19, 0x81, 0x98, 0x1F, 0x80, 0xF0, 0x0F, 0x00, 0xF0, 0x06, 0x00, 65 | 0x61, 0xC3, 0xB8, 0xE1, 0x9C, 0x70, 0xCE, 0x3C, 0xE3, 0x36, 0x71, 0x9B, 66 | 0x30, 0xED, 0x98, 0x36, 0x7C, 0x1B, 0x3C, 0x0F, 0x1E, 0x07, 0x8F, 0x01, 67 | 0xC3, 0x80, 0xE1, 0x80, 0x70, 0xE7, 0x8E, 0x39, 0xC1, 0xF8, 0x1F, 0x80, 68 | 0xF0, 0x07, 0x00, 0xF0, 0x1F, 0x81, 0x9C, 0x39, 0xC7, 0x0E, 0x70, 0xE0, 69 | 0xE0, 0xFC, 0x39, 0xC7, 0x18, 0xC3, 0xB8, 0x36, 0x07, 0xC0, 0x70, 0x0E, 70 | 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, 0xE0, 0xF0, 71 | 0x70, 0x70, 0x70, 0x78, 0x38, 0x38, 0x1F, 0xFF, 0xF8, 0xFF, 0xEE, 0xEE, 72 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xF0, 0x86, 0x10, 0x86, 0x10, 0x84, 0x30, 73 | 0x84, 0x30, 0x80, 0xFF, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7F, 0xF0, 74 | 0x18, 0x1C, 0x3C, 0x3E, 0x36, 0x66, 0x63, 0xC3, 0xFF, 0xC0, 0xCC, 0x3F, 75 | 0x1F, 0xEE, 0x38, 0x0E, 0x3F, 0x9E, 0xEE, 0x3B, 0x9E, 0xFF, 0x9E, 0xE0, 76 | 0xE0, 0x38, 0x0E, 0x03, 0xBC, 0xFF, 0xBC, 0xEE, 0x1F, 0x87, 0xE1, 0xF8, 77 | 0x7F, 0x3B, 0xFE, 0xEF, 0x00, 0x1F, 0x3F, 0xDC, 0x7C, 0x0E, 0x07, 0x03, 78 | 0x80, 0xE3, 0x7F, 0x8F, 0x00, 0x03, 0x81, 0xC0, 0xE7, 0x77, 0xFB, 0xBF, 79 | 0x8F, 0xC7, 0xE3, 0xF1, 0xFD, 0xEF, 0xF3, 0xB8, 0x3E, 0x3F, 0x9C, 0xDC, 80 | 0x3F, 0xFF, 0xFF, 0x81, 0xC3, 0x7F, 0x8F, 0x00, 0x3B, 0xDD, 0xFF, 0xB9, 81 | 0xCE, 0x73, 0x9C, 0xE7, 0x00, 0x3B, 0xBF, 0xDD, 0xFC, 0x7E, 0x3F, 0x1F, 82 | 0x8F, 0xEF, 0x7F, 0x9D, 0xC0, 0xFC, 0x77, 0xF1, 0xF0, 0xE0, 0x70, 0x38, 83 | 0x1D, 0xEF, 0xFF, 0x9F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x38, 84 | 0xFC, 0x7F, 0xFF, 0xFF, 0xFE, 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 85 | 0x7F, 0xE0, 0xE0, 0x70, 0x38, 0x1C, 0x7E, 0x77, 0x73, 0xF1, 0xF8, 0xFE, 86 | 0x77, 0x39, 0xDC, 0x6E, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0x7B, 87 | 0xFF, 0xFE, 0x39, 0xF8, 0xE7, 0xE3, 0x9F, 0x8E, 0x7E, 0x39, 0xF8, 0xE7, 88 | 0xE3, 0x9F, 0x8E, 0x70, 0xEF, 0x7F, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 89 | 0xC7, 0xE3, 0xF1, 0xC0, 0x1E, 0x1F, 0xE7, 0x3B, 0x87, 0xE1, 0xF8, 0x7E, 90 | 0x1D, 0xCE, 0x7F, 0x87, 0x80, 0xEF, 0x3F, 0xEF, 0x3B, 0x87, 0xE1, 0xF8, 91 | 0x7E, 0x1F, 0xCE, 0xFF, 0xBB, 0xCE, 0x03, 0x80, 0xE0, 0x38, 0x00, 0x3B, 92 | 0xBF, 0xFD, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xEF, 0x7F, 0x9D, 0xC0, 0xE0, 93 | 0x70, 0x38, 0x1C, 0xEF, 0xFF, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x3E, 94 | 0x3F, 0xB8, 0xFC, 0x0F, 0xC3, 0xFC, 0x3F, 0xC7, 0xFF, 0x1F, 0x00, 0x73, 95 | 0xBF, 0xF7, 0x39, 0xCE, 0x73, 0x9E, 0x70, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 96 | 0x3F, 0x1F, 0x8F, 0xC7, 0xFF, 0xBD, 0xC0, 0xE1, 0x98, 0x67, 0x39, 0xCC, 97 | 0x33, 0x0D, 0xC3, 0xE0, 0x78, 0x1E, 0x07, 0x00, 0xE3, 0x1D, 0x9E, 0x66, 98 | 0x79, 0x99, 0xE6, 0x77, 0xB8, 0xD2, 0xC3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 99 | 0x73, 0x80, 0x73, 0x9C, 0xE3, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0xFC, 100 | 0x73, 0x9C, 0xE0, 0xE1, 0xD8, 0x67, 0x39, 0xCE, 0x33, 0x0E, 0xC3, 0xE0, 101 | 0x78, 0x1E, 0x03, 0x00, 0xC0, 0x70, 0x38, 0x0E, 0x00, 0xFE, 0xFE, 0x0E, 102 | 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x37, 0x66, 0x66, 0x6E, 0xE6, 103 | 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0x80, 0xCE, 0x66, 0x66, 0x67, 0x76, 104 | 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E }; 105 | 106 | const GFXglyph FreeSansBold9pt7bGlyphs[] = { 107 | { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' 108 | { 0, 3, 13, 6, 2, -12 }, // 0x21 '!' 109 | { 5, 7, 5, 9, 1, -12 }, // 0x22 '"' 110 | { 10, 10, 12, 10, 0, -11 }, // 0x23 '#' 111 | { 25, 9, 15, 10, 1, -13 }, // 0x24 '$' 112 | { 42, 16, 13, 16, 0, -12 }, // 0x25 '%' 113 | { 68, 12, 13, 13, 1, -12 }, // 0x26 '&' 114 | { 88, 3, 5, 5, 1, -12 }, // 0x27 ''' 115 | { 90, 6, 17, 6, 1, -12 }, // 0x28 '(' 116 | { 103, 6, 17, 6, 0, -12 }, // 0x29 ')' 117 | { 116, 5, 6, 7, 1, -12 }, // 0x2A '*' 118 | { 120, 7, 8, 11, 2, -7 }, // 0x2B '+' 119 | { 127, 3, 5, 4, 1, -1 }, // 0x2C ',' 120 | { 129, 5, 2, 6, 0, -5 }, // 0x2D '-' 121 | { 131, 3, 2, 4, 1, -1 }, // 0x2E '.' 122 | { 132, 5, 13, 5, 0, -12 }, // 0x2F '/' 123 | { 141, 9, 13, 10, 1, -12 }, // 0x30 '0' 124 | { 156, 5, 13, 10, 2, -12 }, // 0x31 '1' 125 | { 165, 9, 13, 10, 1, -12 }, // 0x32 '2' 126 | { 180, 8, 13, 10, 1, -12 }, // 0x33 '3' 127 | { 193, 8, 13, 10, 2, -12 }, // 0x34 '4' 128 | { 206, 9, 13, 10, 1, -12 }, // 0x35 '5' 129 | { 221, 9, 13, 10, 1, -12 }, // 0x36 '6' 130 | { 236, 9, 13, 10, 0, -12 }, // 0x37 '7' 131 | { 251, 10, 13, 10, 0, -12 }, // 0x38 '8' 132 | { 268, 9, 13, 10, 1, -12 }, // 0x39 '9' 133 | { 283, 3, 9, 4, 1, -8 }, // 0x3A ':' 134 | { 287, 3, 12, 4, 1, -8 }, // 0x3B ';' 135 | { 292, 9, 9, 11, 1, -8 }, // 0x3C '<' 136 | { 303, 9, 6, 11, 1, -6 }, // 0x3D '=' 137 | { 310, 9, 9, 11, 1, -8 }, // 0x3E '>' 138 | { 321, 9, 13, 11, 1, -12 }, // 0x3F '?' 139 | { 336, 16, 15, 18, 0, -12 }, // 0x40 '@' 140 | { 366, 12, 13, 13, 0, -12 }, // 0x41 'A' 141 | { 386, 11, 13, 13, 1, -12 }, // 0x42 'B' 142 | { 404, 12, 13, 13, 1, -12 }, // 0x43 'C' 143 | { 424, 12, 13, 13, 1, -12 }, // 0x44 'D' 144 | { 444, 9, 13, 12, 1, -12 }, // 0x45 'E' 145 | { 459, 9, 13, 11, 1, -12 }, // 0x46 'F' 146 | { 474, 11, 13, 14, 1, -12 }, // 0x47 'G' 147 | { 492, 11, 13, 13, 1, -12 }, // 0x48 'H' 148 | { 510, 3, 13, 6, 1, -12 }, // 0x49 'I' 149 | { 515, 8, 13, 10, 1, -12 }, // 0x4A 'J' 150 | { 528, 12, 13, 13, 1, -12 }, // 0x4B 'K' 151 | { 548, 8, 13, 11, 1, -12 }, // 0x4C 'L' 152 | { 561, 14, 13, 16, 1, -12 }, // 0x4D 'M' 153 | { 584, 11, 13, 14, 1, -12 }, // 0x4E 'N' 154 | { 602, 13, 13, 14, 1, -12 }, // 0x4F 'O' 155 | { 624, 11, 13, 12, 1, -12 }, // 0x50 'P' 156 | { 642, 13, 14, 14, 1, -12 }, // 0x51 'Q' 157 | { 665, 12, 13, 13, 1, -12 }, // 0x52 'R' 158 | { 685, 11, 13, 12, 1, -12 }, // 0x53 'S' 159 | { 703, 9, 13, 12, 2, -12 }, // 0x54 'T' 160 | { 718, 11, 13, 13, 1, -12 }, // 0x55 'U' 161 | { 736, 12, 13, 12, 0, -12 }, // 0x56 'V' 162 | { 756, 17, 13, 17, 0, -12 }, // 0x57 'W' 163 | { 784, 12, 13, 12, 0, -12 }, // 0x58 'X' 164 | { 804, 11, 13, 12, 1, -12 }, // 0x59 'Y' 165 | { 822, 9, 13, 11, 1, -12 }, // 0x5A 'Z' 166 | { 837, 4, 17, 6, 1, -12 }, // 0x5B '[' 167 | { 846, 5, 13, 5, 0, -12 }, // 0x5C '\' 168 | { 855, 4, 17, 6, 0, -12 }, // 0x5D ']' 169 | { 864, 8, 8, 11, 1, -12 }, // 0x5E '^' 170 | { 872, 10, 1, 10, 0, 4 }, // 0x5F '_' 171 | { 874, 3, 2, 5, 0, -12 }, // 0x60 '`' 172 | { 875, 10, 10, 10, 1, -9 }, // 0x61 'a' 173 | { 888, 10, 13, 11, 1, -12 }, // 0x62 'b' 174 | { 905, 9, 10, 10, 1, -9 }, // 0x63 'c' 175 | { 917, 9, 13, 11, 1, -12 }, // 0x64 'd' 176 | { 932, 9, 10, 10, 1, -9 }, // 0x65 'e' 177 | { 944, 5, 13, 6, 1, -12 }, // 0x66 'f' 178 | { 953, 9, 14, 11, 1, -9 }, // 0x67 'g' 179 | { 969, 9, 13, 11, 1, -12 }, // 0x68 'h' 180 | { 984, 3, 13, 5, 1, -12 }, // 0x69 'i' 181 | { 989, 4, 17, 5, 0, -12 }, // 0x6A 'j' 182 | { 998, 9, 13, 10, 1, -12 }, // 0x6B 'k' 183 | { 1013, 3, 13, 5, 1, -12 }, // 0x6C 'l' 184 | { 1018, 14, 10, 16, 1, -9 }, // 0x6D 'm' 185 | { 1036, 9, 10, 11, 1, -9 }, // 0x6E 'n' 186 | { 1048, 10, 10, 11, 1, -9 }, // 0x6F 'o' 187 | { 1061, 10, 14, 11, 1, -9 }, // 0x70 'p' 188 | { 1079, 9, 14, 11, 1, -9 }, // 0x71 'q' 189 | { 1095, 6, 10, 7, 1, -9 }, // 0x72 'r' 190 | { 1103, 9, 10, 10, 1, -9 }, // 0x73 's' 191 | { 1115, 5, 12, 6, 1, -11 }, // 0x74 't' 192 | { 1123, 9, 10, 11, 1, -9 }, // 0x75 'u' 193 | { 1135, 10, 10, 10, 0, -9 }, // 0x76 'v' 194 | { 1148, 14, 10, 14, 0, -9 }, // 0x77 'w' 195 | { 1166, 10, 10, 10, 0, -9 }, // 0x78 'x' 196 | { 1179, 10, 14, 10, 0, -9 }, // 0x79 'y' 197 | { 1197, 8, 10, 9, 1, -9 }, // 0x7A 'z' 198 | { 1207, 4, 17, 7, 1, -12 }, // 0x7B '{' 199 | { 1216, 1, 17, 5, 2, -12 }, // 0x7C '|' 200 | { 1219, 4, 17, 7, 2, -12 }, // 0x7D '}' 201 | { 1228, 8, 2, 9, 0, -4 } }; // 0x7E '~' 202 | 203 | const GFXfont FreeSansBold9pt7b = { 204 | (uint8_t *)FreeSansBold9pt7bBitmaps, 205 | (GFXglyph *)FreeSansBold9pt7bGlyphs, 206 | 0x20, 0x7E, 22 }; 207 | 208 | // Approx. 1902 bytes 209 | -------------------------------------------------------------------------------- /main/www/script.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function(event) { 2 | var baseHost = document.location.origin 3 | var streamUrlbase = baseHost + ':81/stream' 4 | var streamUrl = streamUrlbase 5 | 6 | const framesize = document.getElementById('framesize') 7 | const ledGroup = document.getElementById('led-group') 8 | const awb = document.getElementById('awb_gain') 9 | const wb = document.getElementById('wb_mode-group') 10 | const agc = document.getElementById('agc') 11 | const agcGain = document.getElementById('agc_gain-group') 12 | const gainCeiling = document.getElementById('gainceiling-group') 13 | const aec = document.getElementById('aec') 14 | const exposure = document.getElementById('aec_value-group') 15 | const mdns_instance = document.getElementById('mdns-instance-group') 16 | const ntpServer = document.getElementById('ntp_server-group') 17 | const timezone = document.getElementById('timezone-group') 18 | const dhcp = document.getElementById('dhcp') 19 | const ip = document.getElementById('ip-group') 20 | const netmask = document.getElementById('netmask-group') 21 | const gateway = document.getElementById('gateway-group') 22 | const dns1 = document.getElementById('dns1-group') 23 | const dns2 = document.getElementById('dns2-group') 24 | const restoreButton = document.getElementById('restore-defaults') 25 | const rebootButton = document.getElementById('reboot-camera') 26 | const storeButton = document.getElementById('store-settings') 27 | const refreshButton = document.getElementById('refresh-settings') 28 | const streamButton = document.getElementById('toggle-stream') 29 | const stillButton = document.getElementById('get-still') 30 | const view = document.getElementById('stream') 31 | const viewContainer = document.getElementById('stream-container') 32 | const streamWindowLink = document.getElementById('stream-window-link') 33 | const http_auth = document.getElementById('http_auth') 34 | const http_password = document.getElementById('http_password-group') 35 | const http_user = document.getElementById('http_user-group') 36 | 37 | function hide(el) { 38 | el.classList.add('hidden') 39 | } 40 | 41 | function show(el) { 42 | el.classList.remove('hidden') 43 | } 44 | 45 | function disable(el) { 46 | el.classList.add('disabled') 47 | el.disabled = true 48 | } 49 | 50 | function enable(el) { 51 | el.classList.remove('disabled') 52 | el.disabled = false 53 | } 54 | 55 | function stopStream() { 56 | window.stop(); 57 | streamButton.innerHTML = 'Start Stream' 58 | } 59 | 60 | function startStream() { 61 | // var surl = `${streamUrl}/stream` 62 | // if (state.http_auth == 1) { 63 | // //add username and password when auth enabled 64 | // surl = surl.replace("://", "://" + state.http_user + ":" + state.http_password + "@") 65 | // } 66 | 67 | console.log("Starting Stream: " + `${streamUrl}`) 68 | 69 | view.src = `${streamUrl}` 70 | 71 | show(view) 72 | show(viewContainer) 73 | streamButton.innerHTML = 'Stop Stream' 74 | } 75 | 76 | function refreshme() { 77 | window.location.reload(true); 78 | } 79 | 80 | function rebootCamera() { 81 | const query = `${baseHost}/reboot` 82 | fetch(query) 83 | .then(response => { 84 | console.log(`request to ${query} finished, status: ${response.status}`) 85 | if (response.status == 200) 86 | //Reload the page and ignore the browser cache after 5seconds 87 | setTimeout(refreshme, 10000) 88 | }) 89 | } 90 | 91 | function storeSettings() { 92 | const query = `${baseHost}/store` 93 | fetch(query) 94 | .then(response => { 95 | console.log(`request to ${query} finished, status: ${response.status}`) 96 | if (response.status != 200) 97 | alert("Failed to store camera settings. Is the camera connected?") 98 | }) 99 | } 100 | 101 | function fetchSettings() { 102 | fetch(`${baseHost}/status`) 103 | .then(function(response) { 104 | return response.json() 105 | }) 106 | .then(function(state) { 107 | document 108 | .querySelectorAll('.default-action') 109 | .forEach(el => { 110 | updateValue(el, state[el.id], false) 111 | }) 112 | document.title = state.hostname 113 | 114 | 115 | 116 | var pageTitle = document.getElementById("page-title") 117 | if (pageTitle) { 118 | pageTitle.innerHTML = state.hostname 119 | } 120 | if (typeof state.mdns_instance == 'undefined') { 121 | hide(mdns_instance) 122 | } 123 | if (typeof state.ntp_server == 'undefined') { 124 | hide(ntpServer) 125 | hide(timezone) 126 | } 127 | 128 | 129 | if (state.http_auth == 1) { 130 | //add username and password when auth enabled 131 | streamUrl = `${streamUrlbase}` + '-' + state.http_password 132 | streamWindowLink.href = `${streamUrlbase}` + '-' + state.http_password 133 | } else { 134 | streamUrl = `${streamUrlbase}` 135 | streamWindowLink.href = `${streamUrlbase}` 136 | } 137 | 138 | // Update the LED intensity slider max-value together with the related label 139 | if (state.led_intensity !== -1 && state.led_max_intensity) { 140 | let led_intensity_slider = document.getElementById("led_intensity"); 141 | led_intensity_slider.max = state.led_max_intensity; 142 | let led_intensity_range_max = document.querySelector('#led-group > div.range-max'); 143 | led_intensity_range_max.innerText = state.led_max_intensity; 144 | } 145 | 146 | document.getElementById("fps_out").value = state.fps 147 | document.getElementById("quality_out").value = state.quality 148 | document.getElementById("brightness_out").value = state.brightness 149 | document.getElementById("contrast_out").value = state.contrast 150 | document.getElementById("saturation_out").value = state.saturation 151 | document.getElementById("led_intensity_out").value = state.led_intensity 152 | document.getElementById("ae_level_out").value = state.ae_level 153 | document.getElementById("aec_value_out").value = state.aec_value 154 | document.getElementById("agc_gain_out").value = state.agc_gain 155 | document.getElementById("gainceiling_out").value = state.gainceiling 156 | 157 | }) 158 | } 159 | 160 | function resetDefaults() { 161 | const query = `${baseHost}/reset` 162 | fetch(query) 163 | .then(response => { 164 | console.log(`request to ${query} finished, status: ${response.status}`) 165 | if (response.status != 200) 166 | alert("Failed to reset the camera to firmware defaults. Is the camera connected?") 167 | }) 168 | } 169 | 170 | function updateValue(el, value, updateRemote) { 171 | updateRemote = updateRemote == null ? true : updateRemote 172 | let initialValue 173 | if (el.type === 'checkbox') { 174 | initialValue = el.checked 175 | value = !!value 176 | el.checked = value 177 | } else { 178 | initialValue = el.value 179 | // Prevent undefined or null stringified values 180 | el.value = (value === undefined || value === null) ? '' : value 181 | } 182 | 183 | if (updateRemote && initialValue !== value) { 184 | updateConfig(el); 185 | } else if (!updateRemote) { 186 | if (el.id === "aec") { 187 | value ? hide(exposure) : show(exposure) 188 | } else if (el.id === "agc") { 189 | if (value) { 190 | show(gainCeiling) 191 | hide(agcGain) 192 | } else { 193 | hide(gainCeiling) 194 | show(agcGain) 195 | } 196 | } else if (el.id === "awb_gain") { 197 | value ? show(wb) : hide(wb) 198 | } else if (el.id == "led_intensity") { 199 | value > -1 ? show(ledGroup) : hide(ledGroup) 200 | } else if (el.id == "dhcp") { 201 | if (value) { 202 | hide(ip) 203 | hide(netmask) 204 | hide(gateway) 205 | hide(dns1) 206 | hide(dns2) 207 | } else { 208 | show(ip) 209 | show(netmask) 210 | show(gateway) 211 | show(dns1) 212 | show(dns2) 213 | } 214 | } else if(el.id == "http_auth"){ 215 | if (value) { 216 | show(http_user) 217 | show(http_password) 218 | } else { 219 | hide(http_user) 220 | hide(http_password) 221 | } 222 | } 223 | } 224 | } 225 | 226 | function updateConfig(el) { 227 | let value 228 | switch (el.type) { 229 | case 'checkbox': 230 | value = el.checked ? 1 : 0 231 | break 232 | case 'range': 233 | case 'text': 234 | case 'password': 235 | case 'select-one': 236 | value = encodeURIComponent(el.value) 237 | break 238 | case 'button': 239 | case 'submit': 240 | value = '1' 241 | break 242 | default: 243 | return 244 | } 245 | 246 | const query = `${baseHost}/control?var=${el.id}&val=${value}` 247 | 248 | fetch(query) 249 | .then(response => { 250 | console.log(`request to ${query} finished, status: ${response.status}`) 251 | }) 252 | } 253 | 254 | // Attach actions to buttons 255 | 256 | restoreButton.onclick = () => { 257 | if (confirm("Are you sure you want to restore default settings?")) { 258 | stopStream() 259 | hide(viewContainer) 260 | resetDefaults() 261 | //rebootCamera() 262 | } 263 | } 264 | 265 | rebootButton.onclick = () => { 266 | if (confirm("Are you sure you want to reboot the camera?")) { 267 | stopStream() 268 | hide(viewContainer) 269 | rebootCamera() 270 | } 271 | } 272 | 273 | storeButton.onclick = () => { 274 | storeSettings(); 275 | } 276 | 277 | refreshButton.onclick = () => { 278 | fetchSettings(); 279 | } 280 | 281 | stillButton.onclick = () => { 282 | stopStream() 283 | view.src = `${baseHost}/capture?_cb=${Date.now()}` 284 | show(viewContainer) 285 | } 286 | 287 | streamButton.onclick = () => { 288 | const streamEnabled = streamButton.innerHTML === 'Stop Stream' 289 | if (streamEnabled) { 290 | stopStream() 291 | } else { 292 | startStream() 293 | } 294 | } 295 | 296 | streamWindowLink.onclick = () => { 297 | const streamEnabled = streamButton.innerHTML === 'Stop Stream' 298 | if (streamEnabled) { 299 | stopStream() 300 | } 301 | } 302 | 303 | streamButton.onerror = () => { 304 | window.stop() 305 | streamButton.innerHTML = 'Start Stream' 306 | hide(view) 307 | hide(viewContainer) 308 | } 309 | 310 | // Attach default on change action 311 | document 312 | .querySelectorAll('.default-action') 313 | .forEach(el => { 314 | el.onchange = () => updateConfig(el) 315 | }) 316 | 317 | agc.onchange = () => { 318 | updateConfig(agc) 319 | if (agc.checked) { 320 | show(gainCeiling) 321 | hide(agcGain) 322 | } else { 323 | hide(gainCeiling) 324 | show(agcGain) 325 | } 326 | } 327 | 328 | aec.onchange = () => { 329 | updateConfig(aec) 330 | aec.checked ? hide(exposure) : show(exposure) 331 | } 332 | 333 | awb.onchange = () => { 334 | updateConfig(awb) 335 | awb.checked ? show(wb) : hide(wb) 336 | } 337 | 338 | framesize.onchange = () => { 339 | updateConfig(framesize) 340 | } 341 | 342 | dhcp.onchange = () => { 343 | updateConfig(dhcp) 344 | if (dhcp.checked) { 345 | hide(ip) 346 | hide(netmask) 347 | hide(gateway) 348 | hide(dns1) 349 | hide(dns2) 350 | } else { 351 | show(ip) 352 | show(netmask) 353 | show(gateway) 354 | show(dns1) 355 | show(dns2) 356 | } 357 | } 358 | 359 | 360 | http_auth.onchange = () => { 361 | updateConfig(http_auth) 362 | if (http_auth.checked) { 363 | show(http_user) 364 | show(http_password) 365 | } else { 366 | hide(http_user) 367 | hide(http_password) 368 | } 369 | } 370 | 371 | document 372 | .querySelectorAll('.close') 373 | .forEach(el => { 374 | el.onclick = () => { 375 | hide(el.parentNode) 376 | } 377 | }) 378 | 379 | streamWindowLink.href = `${streamUrlbase}` 380 | fetchSettings() 381 | setTimeout(() => { startStream() ; }, 2000) 382 | }) 383 | --------------------------------------------------------------------------------