├── platformio.ini ├── common_functions.h ├── forecast_record.h ├── common_functions.cpp ├── License.txt ├── lang_pt.h ├── lang_es.h ├── lang_cz.h ├── lang_no.h ├── lang_nl.h ├── lang.h ├── lang_pl.h ├── lang_it.h ├── lang_fr.h ├── lang_gr.h ├── owm_credentials.h ├── common.h ├── Waveshare_2_13_T5.ino └── epaper_fonts.h /platformio.ini: -------------------------------------------------------------------------------- 1 | [platformio] 2 | ; esp32dev works for the majority of ESP32 based dev boards, change this 3 | ; for your board if desired 4 | default_envs = esp32dev 5 | src_dir = . 6 | extra_configs = ../platformio.inc 7 | 8 | [gfxlib] 9 | lib_deps = ${GxEPD2.lib_deps} 10 | 11 | 12 | -------------------------------------------------------------------------------- /common_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_FUNCTIONS_H_ 2 | #define COMMON_FUNCTIONS_H_ 3 | #include 4 | 5 | float mm_to_inches(float value_mm); 6 | float hPa_to_inHg(float value_hPa); 7 | int JulianDate(int d, int m, int y); 8 | float SumOfPrecip(float DataArray[], int readings); 9 | String TitleCase(String text); 10 | double NormalizedMoonPhase(int d, int m, int y); 11 | 12 | #endif /* ifndef COMMON_FUNCTIONS_H_ */ 13 | -------------------------------------------------------------------------------- /forecast_record.h: -------------------------------------------------------------------------------- 1 | #ifndef FORECAST_RECORD_H_ 2 | #define FORECAST_RECORD_H_ 3 | 4 | #include 5 | 6 | typedef struct { // For current Day and Day 1, 2, 3, etc 7 | int Dt; 8 | String Period; 9 | String Icon; 10 | String Trend; 11 | String Main0; 12 | String Forecast0; 13 | String Forecast1; 14 | String Forecast2; 15 | String Description; 16 | String Time; 17 | String Country; 18 | float lat; 19 | float lon; 20 | float Temperature; 21 | float Feelslike; 22 | float Humidity; 23 | float High; 24 | float Low; 25 | float Winddir; 26 | float Windspeed; 27 | float Rainfall; 28 | float Snowfall; 29 | float Pop; 30 | float Pressure; 31 | int Cloudcover; 32 | int Visibility; 33 | int Sunrise; 34 | int Sunset; 35 | int Timezone; 36 | } Forecast_record_type; 37 | 38 | #endif /* ifndef FORECAST_RECORD_H_ */ 39 | -------------------------------------------------------------------------------- /common_functions.cpp: -------------------------------------------------------------------------------- 1 | #include "common_functions.h" 2 | float mm_to_inches(float value_mm) 3 | { 4 | return 0.0393701 * value_mm; 5 | } 6 | 7 | float hPa_to_inHg(float value_hPa) 8 | { 9 | return 0.02953 * value_hPa; 10 | } 11 | 12 | int JulianDate(int d, int m, int y) { 13 | int mm, yy, k1, k2, k3, j; 14 | yy = y - (int)((12 - m) / 10); 15 | mm = m + 9; 16 | if (mm >= 12) mm = mm - 12; 17 | k1 = (int)(365.25 * (yy + 4712)); 18 | k2 = (int)(30.6001 * mm + 0.5); 19 | k3 = (int)((int)((yy / 100) + 49) * 0.75) - 38; 20 | // 'j' for dates in Julian calendar: 21 | j = k1 + k2 + d + 59 + 1; 22 | if (j > 2299160) j = j - k3; // 'j' is the Julian date at 12h UT (Universal Time) For Gregorian calendar: 23 | return j; 24 | } 25 | 26 | float SumOfPrecip(float DataArray[], int readings) { 27 | float sum = 0; 28 | for (int i = 0; i < readings; i++) { 29 | sum += DataArray[i]; 30 | } 31 | return sum; 32 | } 33 | 34 | String TitleCase(String text){ 35 | if (text.length() > 0) { 36 | String temp_text = text.substring(0,1); 37 | temp_text.toUpperCase(); 38 | return temp_text + text.substring(1); // Title-case the string 39 | } 40 | else return text; 41 | } 42 | 43 | double NormalizedMoonPhase(int d, int m, int y) { 44 | int j = JulianDate(d, m, y); 45 | //Calculate the approximate phase of the moon 46 | double Phase = (j + 4.867) / 29.53059; 47 | return (Phase - (int) Phase); 48 | } 49 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | This software, the ideas and concepts is Copyright (c) David Bird 2014 and beyond. 2 | 3 | 4 | All rights to this software are reserved. 5 | 6 | It is prohibited to redistribute or reproduce of any part or all of the software contents in any form other than the following: 7 | 8 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 9 | 10 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 11 | 12 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 13 | 14 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 15 | 16 | 5. You MUST include all of this copyright and permission notice ('as annotated') and this shall be included in all copies or substantial portions of the software and where the software use is visible to an end-user. 17 | 18 | 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. 21 | 22 | 23 | 24 | FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | 26 | 27 | 28 | IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /lang_pt.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "Previsão 3 dias"; 5 | const String TXT_CONDITIONS = "Condições"; 6 | const String TXT_DAYS = "(Dias)"; 7 | const String TXT_TEMPERATURES = "Temperatura"; 8 | const String TXT_TEMPERATURE_C = "Temperatura (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatura (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Umidade (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Pressão"; 14 | const String TXT_PRESSURE_HPA = "Pressão (hPa)"; 15 | const String TXT_PRESSURE_IN = "Pressão (in)"; 16 | const String TXT_PRESSURE_STEADY = "Estável"; 17 | const String TXT_PRESSURE_RISING = "Subindo"; 18 | const String TXT_PRESSURE_FALLING = "Baixando"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Chuva (mm)"; 22 | const String TXT_RAINFALL_IN = "Chuva (in)"; 23 | const String TXT_SNOWFALL_MM = "Neve (mm)"; 24 | const String TXT_SNOWFALL_IN = "Neve (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Prec."; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Amanhecer"; 30 | const String TXT_SUNSET = "Anoitecer"; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "Nova"; 34 | const String TXT_MOON_WAXING_CRESCENT = "Crescente"; 35 | const String TXT_MOON_FIRST_QUARTER = "Quarto crescente"; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Crescente gibosa"; 37 | const String TXT_MOON_FULL = "Cheia"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Minguante gibosa"; 39 | const String TXT_MOON_THIRD_QUARTER = "Quarto minguante"; 40 | const String TXT_MOON_WANING_CRESCENT = "Minguante"; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Power"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Atualizado:"; 46 | 47 | 48 | //Wind 49 | const String TXT_WIND_SPEED_DIRECTION = "Velocidade/Direção vento"; 50 | const String TXT_N = "N"; 51 | const String TXT_NNE = "NNE"; 52 | const String TXT_NE = "NE"; 53 | const String TXT_ENE = "ENE"; 54 | const String TXT_E = "L"; 55 | const String TXT_ESE = "ESE"; 56 | const String TXT_SE = "SE"; 57 | const String TXT_SSE = "SSE"; 58 | const String TXT_S = "S"; 59 | const String TXT_SSW = "SSO"; 60 | const String TXT_SW = "SO"; 61 | const String TXT_WSW = "OSO"; 62 | const String TXT_W = "O"; 63 | const String TXT_WNW = "ONO"; 64 | const String TXT_NW = "NO"; 65 | const String TXT_NNW = "NNO"; 66 | 67 | //Day of the week 68 | const char* weekday_D[] = { "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb" }; 69 | 70 | //Month 71 | const char* month_M[] = { "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dec" }; 72 | 73 | -------------------------------------------------------------------------------- /lang_es.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "Previsión 3 días"; 5 | const String TXT_CONDITIONS = "Condiciones"; 6 | const String TXT_DAYS = "(Días)"; 7 | const String TXT_TEMPERATURES = "Temperatura"; 8 | const String TXT_TEMPERATURE_C = "Temperatura (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatura (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Humedad (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Presión"; 14 | const String TXT_PRESSURE_HPA = "Presión (hPa)"; 15 | const String TXT_PRESSURE_IN = "Presión (in)"; 16 | const String TXT_PRESSURE_STEADY = "Estable"; 17 | const String TXT_PRESSURE_RISING = "Subiendo"; 18 | const String TXT_PRESSURE_FALLING = "Bajando"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Lluvia (mm)"; 22 | const String TXT_RAINFALL_IN = "Lluvia (in)"; 23 | const String TXT_SNOWFALL_MM = "Nieve (mm)"; 24 | const String TXT_SNOWFALL_IN = "Nieve (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Prec."; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Amanecer"; 30 | const String TXT_SUNSET = "Ocaso"; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "Nueva"; 34 | const String TXT_MOON_WAXING_CRESCENT = "Creciente"; 35 | const String TXT_MOON_FIRST_QUARTER = "Cuarto creciente"; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Creciente gibosa"; 37 | const String TXT_MOON_FULL = "Llena"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Menguante gibosa"; 39 | const String TXT_MOON_THIRD_QUARTER = "Cuarto menguante"; 40 | const String TXT_MOON_WANING_CRESCENT = "Menguante"; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Power"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Actualizado:"; 46 | 47 | 48 | //Wind 49 | const String TXT_WIND_SPEED_DIRECTION = "Velocidad/Dirección viento"; 50 | const String TXT_N = "N"; 51 | const String TXT_NNE = "NNE"; 52 | const String TXT_NE = "NE"; 53 | const String TXT_ENE = "ENE"; 54 | const String TXT_E = "E"; 55 | const String TXT_ESE = "ESE"; 56 | const String TXT_SE = "SE"; 57 | const String TXT_SSE = "SSE"; 58 | const String TXT_S = "S"; 59 | const String TXT_SSW = "SSO"; 60 | const String TXT_SW = "SO"; 61 | const String TXT_WSW = "OSO"; 62 | const String TXT_W = "W"; 63 | const String TXT_WNW = "ONO"; 64 | const String TXT_NW = "NO"; 65 | const String TXT_NNW = "NNO"; 66 | 67 | //Day of the week 68 | const char* weekday_D[] = { "Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb" }; 69 | 70 | //Month 71 | const char* month_M[] = { "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic" }; 72 | 73 | -------------------------------------------------------------------------------- /lang_cz.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_te 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "3-denní předpověd"; 5 | const String TXT_CONDITIONS = "Situace"; 6 | const String TXT_DAYS = "(Dny)"; 7 | const String TXT_TEMPERATURES = "Teplota"; 8 | const String TXT_TEMPERATURE_C = "Teplota (*C)"; 9 | const String TXT_TEMPERATURE_F = "Teplota (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Vlhkost (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Tlak"; 14 | const String TXT_PRESSURE_HPA = "Tlak (hPa)"; 15 | const String TXT_PRESSURE_IN = "Tlak (in)"; 16 | const String TXT_PRESSURE_STEADY = "Konstantní"; 17 | const String TXT_PRESSURE_RISING = "Stoupající"; 18 | const String TXT_PRESSURE_FALLING = "Klesající"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Srážky (mm)"; 22 | const String TXT_RAINFALL_IN = "Srážky (in)"; 23 | const String TXT_SNOWFALL_MM = "Sněžení (mm)"; 24 | const String TXT_SNOWFALL_IN = "Sněžení (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Srážky"; 26 | 27 | //Sun 28 | const String TXT_SUNRISE = "Východ slunce"; 29 | const String TXT_SUNSET = "Západ slunce"; 30 | 31 | //Moon 32 | const String TXT_MOON_NEW = "Nov"; 33 | const String TXT_MOON_WAXING_CRESCENT = "Dorůst. srpek"; 34 | const String TXT_MOON_FIRST_QUARTER = "První čtvrt"; 35 | const String TXT_MOON_WAXING_GIBBOUS = "Dorůst. měsíc"; 36 | const String TXT_MOON_FULL = "Úplněk"; 37 | const String TXT_MOON_WANING_GIBBOUS = "Couvající měsíc"; 38 | const String TXT_MOON_THIRD_QUARTER = "Poslední čtvrt"; 39 | const String TXT_MOON_WANING_CRESCENT = "Ubývající srpek"; 40 | 41 | //Power / WiFi 42 | const String TXT_POWER = "Síla"; 43 | const String TXT_WIFI = "WiFi"; 44 | const char* TXT_UPDATED = "Aktual.:"; 45 | 46 | 47 | //Wind 48 | const String TXT_WIND_SPEED_DIRECTION = "Rýchl. větra/směr"; 49 | const String TXT_N = "S"; 50 | const String TXT_NNE = "SSV"; 51 | const String TXT_NE = "SV"; 52 | const String TXT_ENE = "VSV"; 53 | const String TXT_E = "V"; 54 | const String TXT_ESE = "VJV"; 55 | const String TXT_SE = "JV"; 56 | const String TXT_SSE = "JJV"; 57 | const String TXT_S = "J"; 58 | const String TXT_SSW = "JJZ"; 59 | const String TXT_SW = "JZ"; 60 | const String TXT_WSW = "ZJZ"; 61 | const String TXT_W = "Z"; 62 | const String TXT_WNW = "ZSZ"; 63 | const String TXT_NW = "SZ"; 64 | const String TXT_NNW = "SSZ"; 65 | 66 | //Day of the week 67 | const char* weekday_D[] = { "Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob" }; 68 | 69 | //Month 70 | const char* month_M[] = { "Led", "Úno", "Bře", "Dub", "Kvě", "Čvn", "Čvc", "Srp", "Zář", "Říj", "Lis", "Pro" }; 71 | 72 | -------------------------------------------------------------------------------- /lang_no.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "3 dagers værvarsel"; 5 | const String TXT_CONDITIONS = "Tilstand"; 6 | const String TXT_DAYS = "(Dager)"; 7 | const String TXT_TEMPERATURES = "Temperatur"; 8 | const String TXT_TEMPERATURE_C = "Temperatur (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatur (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Luftfuktighet (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Lufttrykk"; 14 | const String TXT_PRESSURE_HPA = "Lufttrykk(hPa)"; 15 | const String TXT_PRESSURE_IN = "Lufttrykk (in)"; 16 | const String TXT_PRESSURE_STEADY = "Stabilt"; 17 | const String TXT_PRESSURE_RISING = "Stigende"; 18 | const String TXT_PRESSURE_FALLING = "Fallende"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Regn (mm)"; 22 | const String TXT_RAINFALL_IN = "Regn (in)"; 23 | const String TXT_SNOWFALL_MM = "Snø (mm)"; 24 | const String TXT_SNOWFALL_IN = "Snø (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Nedbør"; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Solopp."; 30 | const String TXT_SUNSET = "Solned."; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "Nymåne"; 34 | const String TXT_MOON_WAXING_CRESCENT = "Vokse-må.sigd"; 35 | const String TXT_MOON_FIRST_QUARTER = "Halvmåne,vok."; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Voksemåne,ny"; 37 | const String TXT_MOON_FULL = "Fullmåne"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Minkemåne,ne"; 39 | const String TXT_MOON_THIRD_QUARTER = "Halvmåne,min."; 40 | const String TXT_MOON_WANING_CRESCENT = "Minke-må.sigd"; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Batteri"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Oppdatert:"; 46 | 47 | 48 | //Wind 49 | const String TXT_WIND_SPEED_DIRECTION = "Wind Speed/Direction"; 50 | const String TXT_N = "N"; 51 | const String TXT_NNE = "NNØ"; 52 | const String TXT_NE = "NØ"; 53 | const String TXT_ENE = "ØNØ"; 54 | const String TXT_E = "Ø"; 55 | const String TXT_ESE = "ØSØ"; 56 | const String TXT_SE = "SØ"; 57 | const String TXT_SSE = "SSØ"; 58 | const String TXT_S = "S"; 59 | const String TXT_SSW = "SSV"; 60 | const String TXT_SW = "SV"; 61 | const String TXT_WSW = "VSV"; 62 | const String TXT_W = "V"; 63 | const String TXT_WNW = "VNV"; 64 | const String TXT_NW = "NV"; 65 | const String TXT_NNW = "NNV"; 66 | 67 | //Day of the week 68 | const char* weekday_D[] = { "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør" }; 69 | 70 | //Month 71 | const char* month_M[] = { "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des" }; 72 | -------------------------------------------------------------------------------- /lang_nl.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "3-Daagse weersvoorspelling"; 5 | const String TXT_CONDITIONS = "Weersomstandigheden"; 6 | const String TXT_DAYS = "(Dagen)"; 7 | const String TXT_TEMPERATURES = "Temperatuur"; 8 | const String TXT_TEMPERATURE_C = "Temperatuur (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatuur (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Luchtvochtigheid (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Luchtdruk"; 14 | const String TXT_PRESSURE_HPA = "Luchtdruk (hPa)"; 15 | const String TXT_PRESSURE_IN = "Luchtdruk (in)"; 16 | const String TXT_PRESSURE_STEADY = "Stabiel"; 17 | const String TXT_PRESSURE_RISING = "Steigend"; 18 | const String TXT_PRESSURE_FALLING = "Dalend"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Neerslag (mm)"; 22 | const String TXT_RAINFALL_IN = "Neerslag (in)"; 23 | const String TXT_SNOWFALL_MM = "Sneeuwval (mm)"; 24 | const String TXT_SNOWFALL_IN = "Sneeuwval (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Neerslag"; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Zonsopgang"; 30 | const String TXT_SUNSET = "Zonsondergang"; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "Nieuwe maan"; 34 | const String TXT_MOON_WAXING_CRESCENT = "wassende maan"; 35 | const String TXT_MOON_FIRST_QUARTER = "Eerste kwartier"; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Wassende maan"; 37 | const String TXT_MOON_FULL = "Volle maan"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Krimpende maan"; 39 | const String TXT_MOON_THIRD_QUARTER = "Laatste kwartier"; 40 | const String TXT_MOON_WANING_CRESCENT = "Krimpende maan"; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Accu"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Bijgewerkt:"; 46 | 47 | 48 | //Wind 49 | const String TXT_WIND_SPEED_DIRECTION = "Windstreek en snelheid"; 50 | const String TXT_N = "N"; 51 | const String TXT_NNE = "NNO"; 52 | const String TXT_NE = "NO"; 53 | const String TXT_ENE = "ONO"; 54 | const String TXT_E = "O"; 55 | const String TXT_ESE = "OZO"; 56 | const String TXT_SE = "ZO"; 57 | const String TXT_SSE = "ZZO"; 58 | const String TXT_S = "Z"; 59 | const String TXT_SSW = "ZZW"; 60 | const String TXT_SW = "ZW"; 61 | const String TXT_WSW = "WZW"; 62 | const String TXT_W = "W"; 63 | const String TXT_WNW = "WNW"; 64 | const String TXT_NW = "NW"; 65 | const String TXT_NNW = "NNW"; 66 | 67 | //Day of the week 68 | const char* weekday_D[] = { "Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za" }; 69 | 70 | //Month 71 | const char* month_M[] = { "Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; 72 | 73 | 74 | -------------------------------------------------------------------------------- /lang.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "3-Day Forecast Values"; 5 | const String TXT_CONDITIONS = "Conditions"; 6 | const String TXT_DAYS = "(Days)"; 7 | const String TXT_TEMPERATURES = "Temperature"; 8 | const String TXT_TEMPERATURE_C = "Temperature (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperature (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Humidity (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Pressure"; 14 | const String TXT_PRESSURE_HPA = "Pressure (hPa)"; 15 | const String TXT_PRESSURE_IN = "Pressure (in)"; 16 | const String TXT_PRESSURE_STEADY = "Steady"; 17 | const String TXT_PRESSURE_RISING = "Rising"; 18 | const String TXT_PRESSURE_FALLING = "Falling"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Rainfall (mm)"; 22 | const String TXT_RAINFALL_IN = "Rainfall (in)"; 23 | const String TXT_SNOWFALL_MM = "Snowfall (mm)"; 24 | const String TXT_SNOWFALL_IN = "Snowfall (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Prec."; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Sunrise"; 30 | const String TXT_SUNSET = "Sunset"; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "New"; 34 | const String TXT_MOON_WAXING_CRESCENT = "Waxing Crescent"; 35 | const String TXT_MOON_FIRST_QUARTER = "First Quarter"; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Waxing Gibbous"; 37 | const String TXT_MOON_FULL = "Full"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Waning Gibbous"; 39 | const String TXT_MOON_THIRD_QUARTER = "Third Quarter"; 40 | const String TXT_MOON_WANING_CRESCENT = "Waning Crescent"; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Power"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Updated:"; 46 | 47 | 48 | //Wind 49 | const String TXT_WIND_SPEED_DIRECTION = "Wind Speed/Direction"; 50 | const String TXT_N = "N"; 51 | const String TXT_NNE = "NNE"; 52 | const String TXT_NE = "NE"; 53 | const String TXT_ENE = "ENE"; 54 | const String TXT_E = "E"; 55 | const String TXT_ESE = "ESE"; 56 | const String TXT_SE = "SE"; 57 | const String TXT_SSE = "SSE"; 58 | const String TXT_S = "S"; 59 | const String TXT_SSW = "SSW"; 60 | const String TXT_SW = "SW"; 61 | const String TXT_WSW = "WSW"; 62 | const String TXT_W = "W"; 63 | const String TXT_WNW = "WNW"; 64 | const String TXT_NW = "NW"; 65 | const String TXT_NNW = "NNW"; 66 | 67 | //Day of the week 68 | const char* weekday_D[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 69 | 70 | //Month 71 | const char* month_M[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 72 | 73 | -------------------------------------------------------------------------------- /lang_pl.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "Prognoza 3-dniowa"; 5 | const String TXT_CONDITIONS = "Warunki"; 6 | const String TXT_DAYS = "(dni)"; 7 | const String TXT_TEMPERATURES = "Temperatura"; 8 | const String TXT_TEMPERATURE_C = "Temperatura (*C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatura (*F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Wilgotność (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Ciśnienie"; 14 | const String TXT_PRESSURE_HPA = "Ciśnienie (hPa)"; 15 | const String TXT_PRESSURE_IN = "Ciśnienie (in)"; 16 | const String TXT_PRESSURE_STEADY = "Stałe"; 17 | const String TXT_PRESSURE_RISING = "Rośnie"; 18 | const String TXT_PRESSURE_FALLING = "Spada"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Deszcz (mm)"; 22 | const String TXT_RAINFALL_IN = "Deszcz (in)"; 23 | const String TXT_SNOWFALL_MM = "Śnieg (mm)"; 24 | const String TXT_SNOWFALL_IN = "Śnieg (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Opad."; 26 | 27 | 28 | //Sun 29 | const String TXT_SUNRISE = "Wschód sł."; 30 | const String TXT_SUNSET = "Zachód sł."; 31 | 32 | //Moon 33 | const String TXT_MOON_NEW = "Nów"; 34 | const String TXT_MOON_WAXING_CRESCENT = "Przybywający sierp"; 35 | const String TXT_MOON_FIRST_QUARTER = "Pierwsza kwadra"; 36 | const String TXT_MOON_WAXING_GIBBOUS = "Przybywający garbaty"; 37 | const String TXT_MOON_FULL = "Pełnia"; 38 | const String TXT_MOON_WANING_GIBBOUS = "Ubywający garbaty"; 39 | const String TXT_MOON_THIRD_QUARTER = "Ostatnia kwadra"; 40 | const String TXT_MOON_WANING_CRESCENT = "Ubywający sierp "; 41 | 42 | //Power / WiFi 43 | const String TXT_POWER = "Zasilanie"; 44 | const String TXT_WIFI = "WiFi"; 45 | const char* TXT_UPDATED = "Aktualizacja:"; 46 | 47 | 48 | //Wind 49 | //These are left untranslated due to string length constraints, but usually we use the English notation anyway 50 | const String TXT_WIND_SPEED_DIRECTION = "Prędkość/Kierunek wiatru"; 51 | const String TXT_N = "N"; 52 | const String TXT_NNE = "NNE"; 53 | const String TXT_NE = "NE"; 54 | const String TXT_ENE = "ENE"; 55 | const String TXT_E = "E"; 56 | const String TXT_ESE = "ESE"; 57 | const String TXT_SE = "SE"; 58 | const String TXT_SSE = "SSE"; 59 | const String TXT_S = "S"; 60 | const String TXT_SSW = "SSW"; 61 | const String TXT_SW = "SW"; 62 | const String TXT_WSW = "WSW"; 63 | const String TXT_W = "W"; 64 | const String TXT_WNW = "WNW"; 65 | const String TXT_NW = "NW"; 66 | const String TXT_NNW = "NNW"; 67 | 68 | //Day of the week 69 | const char* weekday_D[] = { "Nie", "Pon", "Wto", "Śro", "Czw", "Pią", "Sob" }; 70 | 71 | //Month 72 | const char* month_M[] = { "Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru" }; 73 | 74 | -------------------------------------------------------------------------------- /lang_it.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "Previsioni a 3 giorni"; 5 | const String TXT_CONDITIONS = "Condizioni"; 6 | const String TXT_DAYS = "(Giorni)"; 7 | const String TXT_TEMPERATURES = "Temperature"; 8 | const String TXT_TEMPERATURE_C = "Temperatura (°C)"; 9 | const String TXT_TEMPERATURE_F = "Temperatura (°F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Umidità (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Pressione"; 14 | const String TXT_PRESSURE_HPA = "Pressione (hPa)"; 15 | const String TXT_PRESSURE_IN = "Pressione (in)"; 16 | const String TXT_PRESSURE_STEADY = "\nCostante"; 17 | const String TXT_PRESSURE_RISING = "\nCrescente"; 18 | const String TXT_PRESSURE_FALLING = "\nDiminuzione"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Piogge (mm)"; 22 | const String TXT_RAINFALL_IN = "Piogge (in)"; 23 | const String TXT_SNOWFALL_MM = "Neve (mm)"; 24 | const String TXT_SNOWFALL_IN = "Neve (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Precipitazioni (breve)"; 26 | const String TXT_RAIN = " Pioggia"; 27 | const String TXT_SNOW = " Neve"; 28 | const String TXT_EQUAL_RAIN = " = Pioggia"; 29 | const String TXT_EQUAL_SNOW = " = Neve"; 30 | 31 | //Sun 32 | const String TXT_SUNRISE = "Alba: "; 33 | const int TXT_X_SUNSET = 16; 34 | const String TXT_SUNSET = " Tra: "; 35 | 36 | //Moon 37 | const String TXT_MOON = "Luna"; 38 | const String TXT_PHASE = "Fase: "; 39 | const String TXT_MOON_NEW = "Luna nuova"; 40 | const String TXT_MOON_WAXING_CRESCENT = "Luna crescente"; 41 | const String TXT_MOON_FIRST_QUARTER = "Primo quarto"; 42 | const String TXT_MOON_WAXING_GIBBOUS = "Gibbosa crescente"; 43 | const String TXT_MOON_FULL = "Luna Piena"; 44 | const String TXT_MOON_WANING_GIBBOUS = "Gibbosa calante"; 45 | const String TXT_MOON_THIRD_QUARTER = "Ultimo quarto"; 46 | const String TXT_MOON_WANING_CRESCENT = "Luna calante"; 47 | 48 | //Power / WiFi 49 | const String TXT_POWER = "Segnale"; 50 | const int TXT_X_POWER = 45; 51 | const String TXT_WIFI = "WiFi"; 52 | const char* TXT_UPDATED = "Aggiornato:"; 53 | 54 | 55 | //Wind 56 | const String TXT_WIND_SPEED_DIRECTION = "Velocità e Direzione Vento"; 57 | const String TXT_N = "N"; 58 | const String TXT_NNE = "NNE"; 59 | const String TXT_NE = "NE"; 60 | const String TXT_ENE = "ENE"; 61 | const String TXT_E = "E"; 62 | const String TXT_ESE = "ESE"; 63 | const String TXT_SE = "SE"; 64 | const String TXT_SSE = "SSE"; 65 | const String TXT_S = "S"; 66 | const String TXT_SSW = "SSO"; 67 | const String TXT_SW = "SO"; 68 | const String TXT_WSW = "OSO"; 69 | const String TXT_W = "O"; 70 | const String TXT_WNW = "ONO"; 71 | const String TXT_NW = "NO"; 72 | const String TXT_NNW = "NNO"; 73 | 74 | 75 | //Day of the week 76 | const char* weekday_D[] = { "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab" }; 77 | 78 | //Month 79 | const char* month_M[] = { "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic" }; 80 | 81 | -------------------------------------------------------------------------------- /lang_fr.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperature - Humidity - Forecast 4 | const String TXT_FORECAST_VALUES = "Prévision sur 3 jours"; 5 | const String TXT_CONDITIONS = "Conditions"; 6 | const String TXT_DAYS = "(Jours)"; 7 | const String TXT_TEMPERATURES = "Température"; 8 | const String TXT_TEMPERATURE_C = "Température (°C)"; 9 | const String TXT_TEMPERATURE_F = "Température (°F)"; 10 | const String TXT_HUMIDITY_PERCENT = "Humidité (%)"; 11 | 12 | // Pressure 13 | const String TXT_PRESSURE = "Pression"; 14 | const String TXT_PRESSURE_HPA = "Pression (hPa)"; 15 | const String TXT_PRESSURE_IN = "Pression (in)"; 16 | const String TXT_PRESSURE_STEADY = "\nStable"; 17 | const String TXT_PRESSURE_RISING = "\nMontante"; 18 | const String TXT_PRESSURE_FALLING = "\nEn baisse"; 19 | 20 | //RainFall / SnowFall 21 | const String TXT_RAINFALL_MM = "Précipations (mm)"; 22 | const String TXT_RAINFALL_IN = "Précipations (in)"; 23 | const String TXT_SNOWFALL_MM = "Chute de neige (mm)"; 24 | const String TXT_SNOWFALL_IN = "Chute de neige (in)"; 25 | const String TXT_PRECIPITATION_SOON = "Précipitation (proche)"; 26 | const String TXT_RAIN = " Pluie"; 27 | const String TXT_SNOW = " Neige"; 28 | const String TXT_EQUAL_RAIN = "= Pluie"; 29 | const String TXT_EQUAL_SNOW = " = Neige"; 30 | 31 | //Sun 32 | const String TXT_SUNRISE = "Lever : "; 33 | const int TXT_X_SUNSET = 5; 34 | const String TXT_SUNSET = "Coucher : "; 35 | 36 | //Moon 37 | const String TXT_MOON = "Lune"; 38 | const String TXT_PHASE = "Phase: "; 39 | const String TXT_MOON_NEW = "Nouvelle"; 40 | const String TXT_MOON_WAXING_CRESCENT = "Premier croissant"; 41 | const String TXT_MOON_FIRST_QUARTER = "Premier quartier"; 42 | const String TXT_MOON_WAXING_GIBBOUS = "Gibbeuse crois."; 43 | const String TXT_MOON_FULL = "Pleine"; 44 | const String TXT_MOON_WANING_GIBBOUS = "Gibbeuse décrois."; 45 | const String TXT_MOON_THIRD_QUARTER = "Dernier quartier"; 46 | const String TXT_MOON_WANING_CRESCENT = "Dernier croissant"; 47 | 48 | //Power / WiFi 49 | const String TXT_POWER = "Batterie"; 50 | const int TXT_X_POWER = 42; 51 | const String TXT_WIFI = "WiFi"; 52 | const char* TXT_UPDATED = "Mis à jour:"; 53 | 54 | 55 | //Wind 56 | const String TXT_WIND_SPEED_DIRECTION = "Vitesse & Direction du vent"; 57 | const String TXT_N = "N"; 58 | const String TXT_NNE = "NNE"; 59 | const String TXT_NE = "NE"; 60 | const String TXT_ENE = "ENE"; 61 | const String TXT_E = "E"; 62 | const String TXT_ESE = "ESE"; 63 | const String TXT_SE = "SE"; 64 | const String TXT_SSE = "SSE"; 65 | const String TXT_S = "S"; 66 | const String TXT_SSW = "SSO"; 67 | const String TXT_SW = "SO"; 68 | const String TXT_WSW = "OSO"; 69 | const String TXT_W = "O"; 70 | const String TXT_WNW = "ONO"; 71 | const String TXT_NW = "NO"; 72 | const String TXT_NNW = "NNO"; 73 | 74 | //Day of the week 75 | const char* weekday_D[] = { "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam" }; 76 | 77 | //Month 78 | const char* month_M[] = { "Janv.", "Févr.", "Mars", "Avril", "Mai", "Juin", "Juil.", "Août", "Sept", "Oct.", "Nov.", "Déc." }; 79 | 80 | -------------------------------------------------------------------------------- /lang_gr.h: -------------------------------------------------------------------------------- 1 | #define FONT(x) x##_tf 2 | 3 | //Temperatur - Luftfeuchtigkeit - Vorschau 4 | const String TXT_FORECAST_VALUES = "3 Tages Vorhersage"; 5 | const String TXT_CONDITIONS = "Aktuelles Wetter"; 6 | const String TXT_DAYS = "(Tage)"; 7 | const String TXT_TEMPERATURES = "Temperatur"; 8 | const String TXT_TEMPERATURE_C = "Temperatur [°C]"; 9 | const String TXT_TEMPERATURE_F = "Temperatur [°F]"; 10 | const String TXT_HUMIDITY_PERCENT = "Luftfeuchte [%]"; 11 | 12 | //Luftdruck 13 | const String TXT_PRESSURE = "Luftdruck"; 14 | const String TXT_PRESSURE_HPA = "Luftdruck [hPa]"; 15 | const String TXT_PRESSURE_IN = "Luftdruck [in]"; 16 | const String TXT_PRESSURE_STEADY = "beständig"; 17 | const String TXT_PRESSURE_RISING = "steigend"; 18 | const String TXT_PRESSURE_FALLING = "fallend"; 19 | 20 | //Niederschlag / Schneefall 21 | const String TXT_RAINFALL_MM = "mm Regen"; 22 | const String TXT_RAINFALL_IN = "in Regen"; 23 | const String TXT_SNOWFALL_MM = "mm Schnee"; 24 | const String TXT_SNOWFALL_IN = "in Schnee"; 25 | const String TXT_PRECIPITATION_SOON = "in Kürze"; 26 | 27 | //Sonne 28 | const String TXT_SUNRISE = "Sonnenaufg."; 29 | const String TXT_SUNSET = "Sonnenunterg."; 30 | 31 | //Mond 32 | const String TXT_MOON_NEW = "Neumond"; // Neumond 33 | const String TXT_MOON_WAXING_CRESCENT = "zunehmende Sichel"; // erstes Viertel bzw. zunehmende Sichel 34 | const String TXT_MOON_FIRST_QUARTER = "zunehmender Halbmond"; // zunehmender Halbmond 35 | const String TXT_MOON_WAXING_GIBBOUS = "zweites Viertel"; // zweites Viertel 36 | const String TXT_MOON_FULL = "Vollmond"; // Vollmond 37 | const String TXT_MOON_WANING_GIBBOUS = "drittes Viertel"; // drittes Viertel 38 | const String TXT_MOON_THIRD_QUARTER = "abnehmender Halbmond"; // abnehmender Halbmond 39 | const String TXT_MOON_WANING_CRESCENT = "abnehmende Sichel"; // letztes Viertel bzw. abnehmende Sichel 40 | 41 | //Energie / WLAN 42 | const String TXT_POWER = "Akku"; 43 | const String TXT_WIFI = "WLAN"; 44 | const char* TXT_UPDATED = "aktualisiert:"; 45 | 46 | //Wind 47 | const String TXT_WIND_SPEED_DIRECTION = "Wind Geschw./Richtung"; 48 | const String TXT_N = "N"; 49 | const String TXT_NNE = "NNO"; 50 | const String TXT_NE = "NO"; 51 | const String TXT_ENE = "ONO"; 52 | const String TXT_E = "O"; 53 | const String TXT_ESE = "OSO"; 54 | const String TXT_SE = "SO"; 55 | const String TXT_SSE = "SSO"; 56 | const String TXT_S = "S"; 57 | const String TXT_SSW = "SSW"; 58 | const String TXT_SW = "SW"; 59 | const String TXT_WSW = "WSW"; 60 | const String TXT_W = "W"; 61 | const String TXT_WNW = "WNW"; 62 | const String TXT_NW = "NW"; 63 | const String TXT_NNW = "NNW"; 64 | 65 | //Wochentag 66 | /* 67 | const char* weekday_D[] = { "Sonntag", 68 | "Montag", 69 | "Dienstag", 70 | "Mittwoch", 71 | "Donnerstag", 72 | "Freitag", 73 | "Samstag"}; 74 | */ 75 | const char* weekday_D[] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" }; 76 | 77 | //Monat 78 | const char* month_M[] = { "Jan", "Feb", "März", "Apr", "Mai", "Juni", "Juli", "Aug", "Sep", "Okt", "Nov", "Dez" }; 79 | -------------------------------------------------------------------------------- /owm_credentials.h: -------------------------------------------------------------------------------- 1 | // Change to your WiFi credentials 2 | const char* ssid = "your_ssid"; 3 | const char* password = "your_password"; 4 | 5 | // Use your own API key by signing up for a free developer account at https://openweathermap.org/ 6 | String apikey = "your_api_key"; // See: https://openweathermap.org/ 7 | const char server[] = "api.openweathermap.org"; 8 | //http://api.openweathermap.org/data/2.5/forecast?q=Melksham,UK&APPID=your_OWM_API_key&mode=json&units=metric&cnt=40 9 | //http://api.openweathermap.org/data/2.5/weather?q=Melksham,UK&APPID=your_OWM_API_key&mode=json&units=metric&cnt=1 10 | //Set your location according to OWM locations 11 | String City = "Wolfenbüttel"; // Your home city See: http://bulk.openweathermap.org/sample/ 12 | String Country = "DE"; // Your _ISO-3166-1_two-letter_country_code country code, on OWM find your nearest city and the country code is displayed 13 | // https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes 14 | String Language = "DE"; // NOTE: Only the weather description is translated by OWM 15 | // Examples: Arabic (AR) Czech (CZ) English (EN) Greek (EL) Persian(Farsi) (FA) Galician (GL) Hungarian (HU) Japanese (JA) 16 | // Korean (KR) Latvian (LA) Lithuanian (LT) Macedonian (MK) Slovak (SK) Slovenian (SL) Vietnamese (VI) 17 | String Hemisphere = "north"; // or "south" 18 | String Units = "M"; // Use 'M' for Metric or I for Imperial 19 | const char* Timezone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Choose your time zone from: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv 20 | // See below for examples 21 | const char* ntpServer = "0.europe.pool.ntp.org"; // Or, choose a time server close to you, but in most cases it's best to use pool.ntp.org to find an NTP server 22 | // then the NTP system decides e.g. 0.pool.ntp.org, 1.pool.ntp.org as the NTP syem tries to find the closest available servers 23 | // EU "0.europe.pool.ntp.org" 24 | // US "0.north-america.pool.ntp.org" 25 | // See: https://www.ntppool.org/en/ 26 | int gmtOffset_sec = 0; // UK normal time is GMT, so GMT Offset is 0, for US (-5Hrs) is typically -18000, AU is typically (+8hrs) 28800 27 | int daylightOffset_sec = 3600; // In the UK DST is +1hr or 3600-secs, other countries may use 2hrs 7200 or 30-mins 1800 or 5.5hrs 19800 Ahead of GMT use + offset behind - offset 28 | 29 | // Example time zones 30 | //const char* Timezone = "MET-1METDST,M3.5.0/01,M10.5.0/02"; // Most of Europe 31 | //const char* Timezone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Central Europe 32 | //const char* Timezone = "EST-2METDST,M3.5.0/01,M10.5.0/02"; // Most of Europe 33 | //const char* Timezone = "EST5EDT,M3.2.0,M11.1.0"; // EST USA 34 | //const char* Timezone = "CST6CDT,M3.2.0,M11.1.0"; // CST USA 35 | //const char* Timezone = "MST7MDT,M4.1.0,M10.5.0"; // MST USA 36 | //const char* Timezone = "NZST-12NZDT,M9.5.0,M4.1.0/3"; // Auckland 37 | //const char* Timezone = "EET-2EEST,M3.5.5/0,M10.5.5/0"; // Asia 38 | //const char* Timezone = "ACST-9:30ACDT,M10.1.0,M4.1.0/3": // Australia 39 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H_ 2 | #define COMMON_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "forecast_record.h" 9 | #include "common_functions.h" 10 | 11 | //######################################################################################### 12 | void Convert_Readings_to_Imperial() { 13 | WxConditions[0].Pressure = hPa_to_inHg(WxConditions[0].Pressure); 14 | WxForecast[1].Rainfall = mm_to_inches(WxForecast[1].Rainfall); 15 | WxForecast[1].Snowfall = mm_to_inches(WxForecast[1].Snowfall); 16 | } 17 | 18 | //######################################################################################### 19 | // Problems with stucturing JSON decodes, see here: https://arduinojson.org/assistant/ 20 | bool DecodeWeather(WiFiClient& json, String Type) { 21 | Serial.print(F("\nCreating object...and ")); 22 | // allocate the JsonDocument 23 | DynamicJsonDocument doc(35 * 1024); 24 | // Deserialize the JSON document 25 | DeserializationError error = deserializeJson(doc, json); 26 | // Test if parsing succeeds. 27 | if (error) { 28 | Serial.print(F("deserializeJson() failed: ")); 29 | Serial.println(error.c_str()); 30 | return false; 31 | } 32 | // convert it to a JsonObject 33 | JsonObject root = doc.as(); 34 | Serial.println(" Decoding " + Type + " data"); 35 | if (Type == "weather") { 36 | // All Serial.println statements are for diagnostic purposes and not required, remove if not needed 37 | WxConditions[0].lon = root["coord"]["lon"].as(); Serial.println(" Lon: "+String(WxConditions[0].lon)); 38 | WxConditions[0].lat = root["coord"]["lat"].as(); Serial.println(" Lat: "+String(WxConditions[0].lat)); 39 | WxConditions[0].Main0 = root["weather"][0]["main"].as(); Serial.println("Main: "+String(WxConditions[0].Main0)); 40 | WxConditions[0].Forecast0 = root["weather"][0]["description"].as(); Serial.println("For0: "+String(WxConditions[0].Forecast0)); 41 | WxConditions[0].Forecast1 = root["weather"][1]["description"].as(); Serial.println("For1: "+String(WxConditions[0].Forecast1)); 42 | WxConditions[0].Forecast2 = root["weather"][2]["description"].as(); Serial.println("For2: "+String(WxConditions[0].Forecast2)); 43 | WxConditions[0].Icon = root["weather"][0]["icon"].as(); Serial.println("Icon: "+String(WxConditions[0].Icon)); 44 | WxConditions[0].Temperature = root["main"]["temp"].as(); Serial.println("Temp: "+String(WxConditions[0].Temperature)); 45 | WxConditions[0].Pressure = root["main"]["pressure"].as(); Serial.println("Pres: "+String(WxConditions[0].Pressure)); 46 | WxConditions[0].Humidity = root["main"]["humidity"].as(); Serial.println("Humi: "+String(WxConditions[0].Humidity)); 47 | WxConditions[0].Low = root["main"]["temp_min"].as(); Serial.println("TLow: "+String(WxConditions[0].Low)); 48 | WxConditions[0].High = root["main"]["temp_max"].as(); Serial.println("THig: "+String(WxConditions[0].High)); 49 | WxConditions[0].Windspeed = root["wind"]["speed"].as(); Serial.println("WSpd: "+String(WxConditions[0].Windspeed)); 50 | WxConditions[0].Winddir = root["wind"]["deg"].as(); Serial.println("WDir: "+String(WxConditions[0].Winddir)); 51 | WxConditions[0].Cloudcover = root["clouds"]["all"].as(); Serial.println("CCov: "+String(WxConditions[0].Cloudcover)); // in % of cloud cover 52 | WxConditions[0].Visibility = root["visibility"].as(); Serial.println("Visi: "+String(WxConditions[0].Visibility)); // in metres 53 | WxConditions[0].Rainfall = root["rain"]["1h"].as(); Serial.println("Rain: "+String(WxConditions[0].Rainfall)); 54 | WxConditions[0].Snowfall = root["snow"]["1h"].as(); Serial.println("Snow: "+String(WxConditions[0].Snowfall)); 55 | WxConditions[0].Country = root["sys"]["country"].as(); Serial.println("Ctry: "+String(WxConditions[0].Country)); 56 | WxConditions[0].Sunrise = root["sys"]["sunrise"].as(); Serial.println("SRis: "+String(WxConditions[0].Sunrise)); 57 | WxConditions[0].Sunset = root["sys"]["sunset"].as(); Serial.println("SSet: "+String(WxConditions[0].Sunset)); 58 | WxConditions[0].Timezone = root["timezone"].as(); Serial.println("TZon: "+String(WxConditions[0].Timezone)); } 59 | if (Type == "forecast") { 60 | //Serial.println(json); 61 | Serial.print(F("\nReceiving Forecast period - ")); //------------------------------------------------ 62 | JsonArray list = root["list"]; 63 | for (byte r = 0; r < max_readings; r++) { 64 | Serial.println("\nPeriod-" + String(r) + "--------------"); 65 | WxForecast[r].Dt = list[r]["dt"].as(); Serial.println("DTim: "+String(WxForecast[r].Dt)); 66 | WxForecast[r].Temperature = list[r]["main"]["temp"].as(); Serial.println("Temp: "+String(WxForecast[r].Temperature)); 67 | WxForecast[r].Low = list[r]["main"]["temp_min"].as(); Serial.println("TLow: "+String(WxForecast[r].Low)); 68 | WxForecast[r].High = list[r]["main"]["temp_max"].as(); Serial.println("THig: "+String(WxForecast[r].High)); 69 | WxForecast[r].Pressure = list[r]["main"]["pressure"].as(); Serial.println("Pres: "+String(WxForecast[r].Pressure)); 70 | WxForecast[r].Humidity = list[r]["main"]["humidity"].as(); Serial.println("Humi: "+String(WxForecast[r].Humidity)); 71 | WxForecast[r].Forecast0 = list[r]["weather"][0]["main"].as(); Serial.println("For0: "+String(WxForecast[r].Forecast0)); 72 | WxForecast[r].Forecast1 = list[r]["weather"][1]["main"].as(); Serial.println("For1: "+String(WxForecast[r].Forecast1)); 73 | WxForecast[r].Forecast2 = list[r]["weather"][2]["main"].as(); Serial.println("For2: "+String(WxForecast[r].Forecast2)); 74 | WxForecast[r].Icon = list[r]["weather"][0]["icon"].as(); Serial.println("Icon: "+String(WxForecast[r].Icon)); 75 | WxForecast[r].Description = list[r]["weather"][0]["description"].as(); Serial.println("Desc: "+String(WxForecast[r].Description)); 76 | WxForecast[r].Cloudcover = list[r]["clouds"]["all"].as(); Serial.println("CCov: "+String(WxForecast[r].Cloudcover)); // in % of cloud cover 77 | WxForecast[r].Windspeed = list[r]["wind"]["speed"].as(); Serial.println("WSpd: "+String(WxForecast[r].Windspeed)); 78 | WxForecast[r].Winddir = list[r]["wind"]["deg"].as(); Serial.println("WDir: "+String(WxForecast[r].Winddir)); 79 | WxForecast[r].Rainfall = list[r]["rain"]["3h"].as(); Serial.println("Rain: "+String(WxForecast[r].Rainfall)); 80 | WxForecast[r].Snowfall = list[r]["snow"]["3h"].as(); Serial.println("Snow: "+String(WxForecast[r].Snowfall)); 81 | WxForecast[r].Pop = list[r]["pop"].as(); Serial.println("Pop: "+String(WxForecast[r].Pop)); 82 | WxForecast[r].Period = list[r]["dt_txt"].as(); Serial.println("Peri: "+String(WxForecast[r].Period)); 83 | } 84 | //------------------------------------------ 85 | float pressure_trend = WxForecast[2].Pressure - WxForecast[0].Pressure; // Measure pressure slope between ~now and later 86 | pressure_trend = ((int)(pressure_trend * 10)) / 10.0; // Remove any small variations less than 0.1 87 | WxConditions[0].Trend = "0"; 88 | if (pressure_trend > 0) WxConditions[0].Trend = "+"; 89 | if (pressure_trend < 0) WxConditions[0].Trend = "-"; 90 | if (pressure_trend == 0) WxConditions[0].Trend = "0"; 91 | 92 | if (Units == "I") Convert_Readings_to_Imperial(); 93 | } 94 | return true; 95 | } 96 | //######################################################################################### 97 | String ConvertUnixTime(int unix_time) { 98 | // Returns either '21:12 ' or ' 09:12pm' depending on Units mode 99 | time_t tm = unix_time; 100 | struct tm *now_tm = gmtime(&tm); 101 | char output[40]; 102 | if (Units == "M") { 103 | strftime(output, sizeof(output), "%H:%M %d/%m/%y", now_tm); 104 | } 105 | else { 106 | strftime(output, sizeof(output), "%I:%M%P %m/%d/%y", now_tm); 107 | } 108 | return output; 109 | } 110 | //######################################################################################### 111 | //WiFiClient client; // wifi client object 112 | 113 | bool obtain_wx_data(WiFiClient& client, const String& RequestType) { 114 | const String units = (Units == "M" ? "metric" : "imperial"); 115 | client.stop(); // close connection before sending a new request 116 | HTTPClient http; 117 | String uri = "/data/2.5/" + RequestType + "?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language; 118 | if(RequestType != "weather") 119 | { 120 | uri += "&cnt=" + String(max_readings); 121 | } 122 | //http.begin(uri,test_root_ca); //HTTPS example connection 123 | http.begin(client, server, 80, uri); 124 | int httpCode = http.GET(); 125 | if(httpCode == HTTP_CODE_OK) { 126 | if (!DecodeWeather(http.getStream(), RequestType)) return false; 127 | client.stop(); 128 | http.end(); 129 | return true; 130 | } 131 | else 132 | { 133 | Serial.printf("connection failed, error: %s", http.errorToString(httpCode).c_str()); 134 | client.stop(); 135 | http.end(); 136 | return false; 137 | } 138 | http.end(); 139 | return true; 140 | } 141 | #endif /* ifndef COMMON_H_ */ 142 | -------------------------------------------------------------------------------- /Waveshare_2_13_T5.ino: -------------------------------------------------------------------------------- 1 | /* ESP Weather Display using an EPD 2.13" Display, obtains data from Open Weather Map, decodes it and then displays it. 2 | #################################################################################################################################### 3 | This software, the ideas and concepts is Copyright (c) David Bird 2018. All rights to this software are reserved. 4 | 5 | Any redistribution or reproduction of any part or all of the contents in any form is prohibited other than the following: 6 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 7 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 8 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 9 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 10 | 11 | The above copyright ('as annotated') notice and this permission notice shall be included in all copies or substantial portions of the Software and where the 12 | software use is visible to an end-user. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY 15 | OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | See more at http://www.dsbird.org.uk 19 | */ 20 | 21 | #include "owm_credentials.h" 22 | #include // https://github.com/bblanchon/ArduinoJson 23 | #include // Built-in 24 | #include "time.h" 25 | #include 26 | #define ENABLE_GxEPD2_display 0 27 | #include 28 | #include 29 | #include 30 | #include "forecast_record.h" 31 | #include "lang.h" // Localisation (English) 32 | //#include "lang_cz.h" // Localisation (Czech) 33 | //#include "lang_fr.h" // Localisation (French) 34 | //#include "lang_gr.h" // Localisation (German) 35 | //#include "lang_it.h" // Localisation (Italian) 36 | //#include "lang_nl.h" // Localisation (Dutch) 37 | //#include "lang_pl.h" // Localisation (Polish) 38 | 39 | //#define DRAW_GRID 1 //Help debug layout changes 40 | #define SCREEN_WIDTH 250 41 | #define SCREEN_HEIGHT 122 42 | 43 | #define DONE 18 //Connected to the DONE pin of the TPL5110 44 | 45 | 46 | 47 | enum alignmentType {LEFT, RIGHT, CENTER}; 48 | 49 | 50 | // Connections for Lilygo TTGO T5 V2.3_2.13 from 51 | // https://github.com/lewisxhe/TTGO-EPaper-Series#board-pins 52 | static const uint8_t EPD_BUSY = 16; 53 | static const uint8_t EPD_CS = 10; 54 | static const uint8_t EPD_RST = 4; 55 | static const uint8_t EPD_DC = 2; //Data/Command 56 | static const uint8_t EPD_SCK = 12; //CLK on pinout? 57 | static const uint8_t EPD_MISO = -1; // Master-In Slave-Out not used, as no data from display 58 | static const uint8_t EPD_MOSI = 11; 59 | 60 | 61 | //GxEPD2_3C display(GxEPD2_213_B74(/*CS=D8*/ EPD_CS, /*DC=D3*/ EPD_DC, /*RST=D4*/ EPD_RST, /*BUSY=D2*/ EPD_BUSY)); 62 | GxEPD2_3C display(GxEPD2_213_Z98c(/*CS=D8*/ EPD_CS, /*DC=D3*/ EPD_DC, /*RST=D4*/ EPD_RST, /*BUSY=D2*/ EPD_BUSY)); // GDEY0213Z98 122x250, SSD1680 63 | //GxEPD2_3C display(GxEPD2_213_B74(/*CS=D8*/ EPD_CS, /*DC=D3*/ EPD_DC, /*RST=D4*/ EPD_RST, /*BUSY=D2*/ EPD_BUSY)); 64 | //#WeAct 2.13 screen module, you need to change GxEPD2_213_B73 to GxEPD2_213_B74 65 | U8G2_FOR_ADAFRUIT_GFX u8g2Fonts; // Select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall 66 | // Using fonts: 67 | // u8g2_font_helvB08_tf 68 | // u8g2_font_helvB10_tf 69 | // u8g2_font_helvB12_tf 70 | // u8g2_font_helvB14_tf 71 | // u8g2_font_helvB24_tf 72 | 73 | //################# LIBRARIES ########################## 74 | String version = "6.5"; // Version of this program 75 | //################ VARIABLES ########################### 76 | 77 | bool LargeIcon = true, SmallIcon = false; 78 | #define Large 7 // For best results use odd numbers 79 | #define Small 3 // For best results use odd numbers 80 | String time_str, date_str; // strings to hold time and date 81 | int wifi_signal, CurrentHour = 0, CurrentMin = 0, CurrentSec = 0; 82 | long StartTime = 0; 83 | 84 | //################ PROGRAM VARIABLES and OBJECTS ########################################## 85 | #define max_readings 5 86 | 87 | Forecast_record_type WxConditions[1]; 88 | Forecast_record_type WxForecast[max_readings]; 89 | 90 | #include "common.h" 91 | 92 | float pressure_readings[max_readings] = {0}; 93 | float temperature_readings[max_readings] = {0}; 94 | float humidity_readings[max_readings] = {0}; 95 | float rain_readings[max_readings] = {0}; 96 | float snow_readings[max_readings] = {0}; 97 | 98 | long SleepDuration = 30; // Sleep time in minutes, aligned to the nearest minute boundary, so if 30 will always update at 00 or 30 past the hour 99 | int WakeupTime = 6; // Don't wakeup until after 07:00 to save battery power 100 | int SleepTime = 23; // Sleep after (23+1) 00:00 to save battery power 101 | 102 | //######################################################################################### 103 | void setup() { 104 | pinMode(DONE, OUTPUT); 105 | digitalWrite(DONE, LOW); 106 | StartTime = millis(); 107 | //Serial.begin(115200); 108 | if (StartWiFi() == WL_CONNECTED && SetupTime() == true) { 109 | if ((CurrentHour >= WakeupTime && CurrentHour <= SleepTime)) { 110 | Serial.println("Initialising Display"); 111 | InitialiseDisplay(); // Give screen time to initialise by getting weather data! 112 | byte Attempts = 1; 113 | bool RxWeather = false, RxForecast = false; 114 | Serial.println("Attempt to get weather"); 115 | WiFiClient client; // wifi client object 116 | while ((RxWeather == false || RxForecast == false) && Attempts <= 5) { // Try up-to 2 time for Weather and Forecast data 117 | if (RxWeather == false) RxWeather = obtain_wx_data(client, "weather"); 118 | if (RxForecast == false) RxForecast = obtain_wx_data(client, "forecast"); 119 | Attempts++; 120 | } 121 | if (RxWeather && RxForecast) { // Only if received both Weather or Forecast proceed 122 | StopWiFi(); // Reduces power consumption 123 | Serial.println("Displaying Weather"); 124 | DisplayWeather(); 125 | display.display(false); // Full screen update mode 126 | } 127 | } 128 | } 129 | BeginSleep(); 130 | } 131 | //######################################################################################### 132 | void loop() { // this will never run! 133 | } 134 | //######################################################################################### 135 | void BeginSleep() { 136 | display.powerOff(); 137 | 138 | while (1) { 139 | digitalWrite(DONE, HIGH); 140 | delay(1); 141 | digitalWrite(DONE, LOW); 142 | delay(1); 143 | } 144 | 145 | } 146 | //######################################################################################### 147 | void DisplayWeather() { // 2.13" e-paper display is 250x122 useable resolution 148 | #if DRAW_GRID 149 | Draw_Grid(); 150 | #endif 151 | UpdateLocalTime(); 152 | Draw_Heading_Section(); // Top line of the display 153 | Draw_Main_Weather_Section(); // Centre section of display for Location, temperature, Weather report, Wx Symbol and wind direction 154 | //Gak, each forecast is about 45 wide, which means we can fit about 5.5 of them onto our 250 wide screen. 155 | // Leaves us a little 25 wide gap on the right - let's see if we can find something to fill that out with. 156 | //Index from 0, not 1 - gets us more useful 'near' data. 157 | // For instance, indexing from 1 at 10am got us our first 3h prediction at 15:00, which is a *long* way off. 158 | // Indexing from 0 made that 12:00, which is much more useful. 159 | Draw_3hr_Forecast(0, 96, 0); // First 3hr forecast box 160 | Draw_3hr_Forecast(44, 96, 1); // Second 3hr forecast box 161 | Draw_3hr_Forecast(88, 96, 2); // Third 3hr forecast box 162 | Draw_3hr_Forecast(132, 96, 3); // Fourth 3hr forecast box 163 | Draw_3hr_Forecast(176, 96, 4); // Fifth 3hr forecast box 164 | DisplayAstronomySection(145, 18); // Astronomy section Sun rise/set and Moon phase plus icon 165 | // Not really enough space for these 166 | //if (WxConditions[0].Visibility > 0) Visibility(110, 40, String(WxConditions[0].Visibility) + "M"); 167 | //if (WxConditions[0].Cloudcover > 0) CloudCover(110, 55, WxConditions[0].Cloudcover); 168 | //DrawBattery(20, 12); 169 | } 170 | //######################################################################################### 171 | // Help debug screen layout by drawing a grid of little crosses 172 | void Draw_Grid() { 173 | int x, y; 174 | const int grid_step = 10; 175 | 176 | //Draw the screen border so we know how far we can push things out 177 | display.drawLine(0, 0, SCREEN_WIDTH-1, 0, GxEPD_BLACK); //across top 178 | display.drawLine(0, SCREEN_HEIGHT-1, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, GxEPD_BLACK); //across bottom 179 | display.drawLine(0, 0, 0, SCREEN_HEIGHT-1, GxEPD_BLACK); //lhs 180 | display.drawLine(SCREEN_WIDTH-1, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, GxEPD_BLACK); //rhs 181 | 182 | for( x=grid_step; xtm_mday; 251 | const int month_utc = now_utc->tm_mon + 1; 252 | const int year_utc = now_utc->tm_year + 1900; 253 | drawString(x, y + 32, MoonPhase(day_utc, month_utc, year_utc, Hemisphere), LEFT); 254 | DrawMoon(x+60, y-17, day_utc, month_utc, year_utc, Hemisphere); 255 | } 256 | //######################################################################################### 257 | String MoonPhase(int d, int m, int y, String hemisphere) { 258 | int c, e; 259 | double jd; 260 | int b; 261 | if (m < 3) { 262 | y--; 263 | m += 12; 264 | } 265 | ++m; 266 | c = 365.25 * y; 267 | e = 30.6 * m; 268 | jd = c + e + d - 694039.09; /* jd is total days elapsed */ 269 | jd /= 29.53059; /* divide by the moon cycle (29.53 days) */ 270 | b = jd; /* int(jd) -> b, take integer part of jd */ 271 | jd -= b; /* subtract integer part to leave fractional part of original jd */ 272 | b = jd * 8 + 0.5; /* scale fraction from 0-8 and round by adding 0.5 */ 273 | b = b & 7; /* 0 and 8 are the same phase so modulo 8 for 0 */ 274 | if (hemisphere == "south") b = 7 - b; 275 | if (b == 0) return TXT_MOON_NEW; // New; 0% illuminated 276 | if (b == 1) return TXT_MOON_WAXING_CRESCENT; // Waxing crescent; 25% illuminated 277 | if (b == 2) return TXT_MOON_FIRST_QUARTER; // First quarter; 50% illuminated 278 | if (b == 3) return TXT_MOON_WAXING_GIBBOUS; // Waxing gibbous; 75% illuminated 279 | if (b == 4) return TXT_MOON_FULL; // Full; 100% illuminated 280 | if (b == 5) return TXT_MOON_WANING_GIBBOUS; // Waning gibbous; 75% illuminated 281 | if (b == 6) return TXT_MOON_THIRD_QUARTER; // Third quarter; 50% illuminated 282 | if (b == 7) return TXT_MOON_WANING_CRESCENT; // Waning crescent; 25% illuminated 283 | return ""; 284 | } 285 | //######################################################################################### 286 | void DrawMoon(int x, int y, int dd, int mm, int yy, String hemisphere) { 287 | const int diameter = 30; 288 | double Phase = NormalizedMoonPhase(dd, mm, yy); 289 | hemisphere.toLowerCase(); 290 | if (hemisphere == "south") Phase = 1 - Phase; 291 | // Draw dark part of moon 292 | display.fillCircle(x + diameter - 1, y + diameter, diameter / 2 + 1, GxEPD_BLACK); 293 | const int number_of_lines = 90; 294 | for (double Ypos = 0; Ypos <= number_of_lines / 2; Ypos++) { 295 | double Xpos = sqrt(number_of_lines / 2 * number_of_lines / 2 - Ypos * Ypos); 296 | // Determine the edges of the lighted part of the moon 297 | double Rpos = 2 * Xpos; 298 | double Xpos1, Xpos2; 299 | if (Phase < 0.5) { 300 | Xpos1 = -Xpos; 301 | Xpos2 = Rpos - 2 * Phase * Rpos - Xpos; 302 | } 303 | else { 304 | Xpos1 = Xpos; 305 | Xpos2 = Xpos - 2 * Phase * Rpos + Rpos; 306 | } 307 | // Draw light part of moon 308 | double pW1x = (Xpos1 + number_of_lines) / number_of_lines * diameter + x; 309 | double pW1y = (number_of_lines - Ypos) / number_of_lines * diameter + y; 310 | double pW2x = (Xpos2 + number_of_lines) / number_of_lines * diameter + x; 311 | double pW2y = (number_of_lines - Ypos) / number_of_lines * diameter + y; 312 | double pW3x = (Xpos1 + number_of_lines) / number_of_lines * diameter + x; 313 | double pW3y = (Ypos + number_of_lines) / number_of_lines * diameter + y; 314 | double pW4x = (Xpos2 + number_of_lines) / number_of_lines * diameter + x; 315 | double pW4y = (Ypos + number_of_lines) / number_of_lines * diameter + y; 316 | display.drawLine(pW1x, pW1y, pW2x, pW2y, GxEPD_WHITE); 317 | display.drawLine(pW3x, pW3y, pW4x, pW4y, GxEPD_WHITE); 318 | } 319 | display.drawCircle(x + diameter - 1, y + diameter, diameter / 2, GxEPD_BLACK); 320 | } 321 | //######################################################################################### 322 | // Squeeze some wind info into a tiny space - just the speed, direction, and an arrow 323 | // No nice compass :-( 324 | void DrawSmallWind(int x, int y, float angle, float windspeed) { 325 | #define Cradius 15 326 | float dx = Cradius * cos((angle - 90) * PI / 180) + x; // calculate X position 327 | float dy = Cradius * sin((angle - 90) * PI / 180) + y; // calculate Y position 328 | //arrow(x+35, y+1, Cradius - 3, angle, 10, 20); // Show wind direction as just an arrow 329 | u8g2Fonts.setFont(u8g2_font_helvB08_tf); 330 | drawString(x, y+15, WindDegToDirection(angle), CENTER); 331 | drawString(x+5, y+25, String(windspeed, 1), CENTER); 332 | drawString(x+5, y+35, String(Units == "M" ? " m/s" : " mph"), CENTER); 333 | } 334 | //######################################################################################### 335 | void DrawWind(int x, int y, float angle, float windspeed) { 336 | #define Cradius 15 337 | float dx = Cradius * cos((angle - 90) * PI / 180) + x; // calculate X position 338 | float dy = Cradius * sin((angle - 90) * PI / 180) + y; // calculate Y position 339 | arrow(x, y, Cradius - 3, angle, 10, 12); // Show wind direction on outer circle 340 | display.drawCircle(x, y, Cradius + 2, GxEPD_BLACK); 341 | display.drawCircle(x, y, Cradius + 3, GxEPD_BLACK); 342 | for (int m = 0; m < 360; m = m + 45) { 343 | dx = Cradius * cos(m * PI / 180); // calculate X position 344 | dy = Cradius * sin(m * PI / 180); // calculate Y position 345 | display.drawLine(x + dx, y + dy, x + dx * 0.8, y + dy * 0.8, GxEPD_BLACK); 346 | } 347 | u8g2Fonts.setFont(u8g2_font_helvB10_tf); 348 | drawString(x - 7, y + Cradius + 10, WindDegToDirection(angle), CENTER); 349 | u8g2Fonts.setFont(u8g2_font_helvB08_tf); 350 | drawString(x, y - Cradius - 14, String(windspeed, 1) + (Units == "M" ? " m/s" : " mph"), CENTER); 351 | } 352 | //######################################################################################### 353 | String WindDegToDirection(float winddirection) { 354 | int dir = int((winddirection / 22.5) + 0.5); 355 | String Ord_direction[16] = {TXT_N, TXT_NNE, TXT_NE, TXT_ENE, TXT_E, TXT_ESE, TXT_SE, TXT_SSE, TXT_S, TXT_SSW, TXT_SW, TXT_WSW, TXT_W, TXT_WNW, TXT_NW, TXT_NNW}; 356 | return Ord_direction[(dir % 16)]; 357 | } 358 | //######################################################################################### 359 | void arrow(int x, int y, int asize, float aangle, int pwidth, int plength) { 360 | // x,y is the centre poistion of the arrow and asize is the radius out from the x,y position 361 | // aangle is angle to draw the pointer at e.g. at 45° for NW 362 | // pwidth is the pointer width in pixels 363 | // plength is the pointer length in pixels 364 | float dx = (asize + 28) * cos((aangle - 90) * PI / 180) + x; // calculate X position 365 | float dy = (asize + 28) * sin((aangle - 90) * PI / 180) + y; // calculate Y position 366 | float x1 = 0; float y1 = plength; 367 | float x2 = pwidth / 2; float y2 = pwidth / 2; 368 | float x3 = -pwidth / 2; float y3 = pwidth / 2; 369 | float angle = aangle * PI / 180; 370 | float xx1 = x1 * cos(angle) - y1 * sin(angle) + dx; 371 | float yy1 = y1 * cos(angle) + x1 * sin(angle) + dy; 372 | float xx2 = x2 * cos(angle) - y2 * sin(angle) + dx; 373 | float yy2 = y2 * cos(angle) + x2 * sin(angle) + dy; 374 | float xx3 = x3 * cos(angle) - y3 * sin(angle) + dx; 375 | float yy3 = y3 * cos(angle) + x3 * sin(angle) + dy; 376 | display.fillTriangle(xx1, yy1, xx3, yy3, xx2, yy2, GxEPD_BLACK); 377 | } 378 | //######################################################################################### 379 | void DrawPressureTrend(int x, int y, float pressure, String slope) { 380 | drawString(x, y, String(pressure, (Units == "M"?0:1)) + (Units == "M" ? "hPa" : "in"), LEFT); 381 | x = x + 48 - (Units == "M"?0:15); y = y + 3; 382 | if (slope == "+") { 383 | display.drawLine(x, y, x + 4, y - 4, GxEPD_BLACK); 384 | display.drawLine(x + 4, y - 4, x + 8, y, GxEPD_BLACK); 385 | } 386 | else if (slope == "0") { 387 | display.drawLine(x + 3, y - 4, x + 8, y, GxEPD_BLACK); 388 | display.drawLine(x + 3, y + 4, x + 8, y, GxEPD_BLACK); 389 | } 390 | else if (slope == "-") { 391 | display.drawLine(x, y, x + 4, y + 4, GxEPD_BLACK); 392 | display.drawLine(x + 4, y + 4, x + 8, y, GxEPD_BLACK); 393 | } 394 | } 395 | //######################################################################################### 396 | void DisplayWXicon(int x, int y, String IconName, bool IconSize) { 397 | Serial.println("Icon name: " + IconName); 398 | if (IconName == "01d" || IconName == "01n") Sunny(x, y, IconSize, IconName); 399 | else if (IconName == "02d" || IconName == "02n") MostlySunny(x, y, IconSize, IconName); 400 | else if (IconName == "03d" || IconName == "03n") Cloudy(x, y, IconSize, IconName); 401 | else if (IconName == "04d" || IconName == "04n") MostlyCloudy(x, y, IconSize, IconName); 402 | else if (IconName == "09d" || IconName == "09n") ChanceRain(x, y, IconSize, IconName); 403 | else if (IconName == "10d" || IconName == "10n") Rain(x, y, IconSize, IconName); 404 | else if (IconName == "11d" || IconName == "11n") Tstorms(x, y, IconSize, IconName); 405 | else if (IconName == "13d" || IconName == "13n") Snow(x, y, IconSize, IconName); 406 | else if (IconName == "50d") Haze(x, y, IconSize, IconName); 407 | else if (IconName == "50n") Fog(x, y, IconSize, IconName); 408 | else Nodata(x, y, IconSize, IconName); 409 | } 410 | //######################################################################################### 411 | uint8_t StartWiFi() { 412 | Serial.print("\r\nConnecting to: "); Serial.println(String(ssid)); 413 | IPAddress dns(8, 8, 8, 8); // Google DNS 414 | WiFi.disconnect(); 415 | WiFi.mode(WIFI_STA); // switch off AP 416 | WiFi.setAutoConnect(true); 417 | WiFi.setAutoReconnect(true); 418 | WiFi.begin(ssid, password); 419 | unsigned long start = millis(); 420 | uint8_t connectionStatus; 421 | bool AttemptConnection = true; 422 | while (AttemptConnection) { 423 | connectionStatus = WiFi.status(); 424 | if (millis() > start + 15000) { // Wait 15-secs maximum 425 | AttemptConnection = false; 426 | } 427 | if (connectionStatus == WL_CONNECTED || connectionStatus == WL_CONNECT_FAILED) { 428 | AttemptConnection = false; 429 | } 430 | delay(50); 431 | } 432 | if (connectionStatus == WL_CONNECTED) { 433 | wifi_signal = WiFi.RSSI(); // Get Wifi Signal strength now, because the WiFi will be turned off to save power! 434 | Serial.println("WiFi connected at: " + WiFi.localIP().toString()); 435 | } 436 | else Serial.println("WiFi connection *** FAILED ***"); 437 | return connectionStatus; 438 | } 439 | //######################################################################################### 440 | void StopWiFi() { 441 | WiFi.disconnect(); 442 | WiFi.mode(WIFI_OFF); 443 | } 444 | //######################################################################################### 445 | boolean SetupTime() { 446 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer, "time.nist.gov"); //(gmtOffset_sec, daylightOffset_sec, ntpServer) 447 | setenv("TZ", Timezone, 1); //setenv()adds the "TZ" variable to the environment with a value TimeZone, only used if set to 1, 0 means no change 448 | tzset(); // Set the TZ environment variable 449 | delay(100); 450 | bool TimeStatus = UpdateLocalTime(); 451 | return TimeStatus; 452 | } 453 | //######################################################################################### 454 | boolean UpdateLocalTime() { 455 | struct tm timeinfo; 456 | char time_output[30], day_output[30], update_time[30]; 457 | while (!getLocalTime(&timeinfo, 5000)) { // Wait for 5-sec for time to synchronise 458 | Serial.println("Failed to obtain time"); 459 | return false; 460 | } 461 | CurrentHour = timeinfo.tm_hour; 462 | CurrentMin = timeinfo.tm_min; 463 | CurrentSec = timeinfo.tm_sec; 464 | //See http://www.cplusplus.com/reference/ctime/strftime/ 465 | Serial.println(&timeinfo, "%a %b %d %Y %H:%M:%S"); // Displays: Saturday, June 24 2017 14:05:49 466 | if (Units == "M") { 467 | if ((Language == "CZ") || (Language == "DE") || (Language == "NL") || (Language == "PL") || (Language == "GR")) { 468 | sprintf(day_output, "%s, %02u. %s %02u", weekday_D[timeinfo.tm_wday], timeinfo.tm_mday, month_M[timeinfo.tm_mon], (timeinfo.tm_year) % 100); // day_output >> So., 23. Juni 19 << 469 | } 470 | else 471 | { 472 | sprintf(day_output, "%s %02u-%s-%02u", weekday_D[timeinfo.tm_wday], timeinfo.tm_mday, month_M[timeinfo.tm_mon], (timeinfo.tm_year) % 100); 473 | } 474 | strftime(update_time, sizeof(update_time), "%H:%M", &timeinfo); // Creates: '@ 14:05', 24h, no am or pm or seconds. and change from 30 to 8 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 475 | sprintf(time_output, "%s", update_time); 476 | } 477 | else 478 | { 479 | strftime(day_output, sizeof(day_output), "%a %b-%d-%y", &timeinfo); // Creates 'Sat May-31-2019' 480 | strftime(update_time, sizeof(update_time), "%H:%M", &timeinfo); // Creates: '@ 02:05' - 24h, no seconds or am/pm 481 | sprintf(time_output, "%s", update_time); 482 | } 483 | date_str = day_output; 484 | time_str = time_output; 485 | return true; 486 | } 487 | //######################################################################################### 488 | void DrawBattery(int x, int y) { 489 | uint8_t percentage = 100; 490 | float voltage = analogRead(35) / 4096.0 * 7.46; 491 | if (voltage > 1 ) { // Only display if there is a valid reading 492 | Serial.println("Voltage = " + String(voltage)); 493 | percentage = 2836.9625 * pow(voltage, 4) - 43987.4889 * pow(voltage, 3) + 255233.8134 * pow(voltage, 2) - 656689.7123 * voltage + 632041.7303; 494 | if (voltage >= 4.20) percentage = 100; 495 | if (voltage <= 3.50) percentage = 0; 496 | display.drawRect(x + 15, y - 12, 19, 10, GxEPD_BLACK); 497 | display.fillRect(x + 34, y - 10, 2, 5, GxEPD_BLACK); 498 | display.fillRect(x + 17, y - 10, 15 * percentage / 100.0, 6, GxEPD_BLACK); 499 | drawString(x + 60, y - 11, String(percentage) + "%", RIGHT); 500 | //drawString(x + 13, y + 5, String(voltage, 2) + "v", CENTER); 501 | } 502 | } 503 | //######################################################################################### 504 | // Symbols are drawn on a relative 10x10grid and 1 scale unit = 1 drawing unit 505 | void addcloud(int x, int y, int scale, int linesize) { 506 | //Draw cloud outer 507 | display.fillCircle(x - scale * 3, y, scale, GxEPD_BLACK); // Left most circle 508 | display.fillCircle(x + scale * 3, y, scale, GxEPD_BLACK); // Right most circle 509 | display.fillCircle(x - scale, y - scale, scale * 1.4, GxEPD_BLACK); // left middle upper circle 510 | display.fillCircle(x + scale * 1.5, y - scale * 1.3, scale * 1.75, GxEPD_BLACK); // Right middle upper circle 511 | display.fillRect(x - scale * 3 - 1, y - scale, scale * 6, scale * 2 + 1, GxEPD_BLACK); // Upper and lower lines 512 | //Clear cloud inner 513 | display.fillCircle(x - scale * 3, y, scale - linesize, GxEPD_WHITE); // Clear left most circle 514 | display.fillCircle(x + scale * 3, y, scale - linesize, GxEPD_WHITE); // Clear right most circle 515 | display.fillCircle(x - scale, y - scale, scale * 1.4 - linesize, GxEPD_WHITE); // left middle upper circle 516 | display.fillCircle(x + scale * 1.5, y - scale * 1.3, scale * 1.75 - linesize, GxEPD_WHITE); // Right middle upper circle 517 | display.fillRect(x - scale * 3 + 2, y - scale + linesize - 1, scale * 5.9, scale * 2 - linesize * 2 + 2, GxEPD_WHITE); // Upper and lower lines 518 | } 519 | //######################################################################################### 520 | void addraindrop(int x, int y, int scale) { 521 | display.fillCircle(x, y, scale / 2, GxEPD_RED); 522 | display.fillTriangle(x - scale / 2, y, x, y - scale * 1.2, x + scale / 2, y , GxEPD_RED); 523 | x = x + scale * 1.6; y = y + scale / 3; 524 | display.fillCircle(x, y, scale / 2, GxEPD_RED); 525 | display.fillTriangle(x - scale / 2, y, x, y - scale * 1.2, x + scale / 2, y , GxEPD_RED); 526 | } 527 | //######################################################################################### 528 | void addrain(int x, int y, int scale, bool IconSize) { 529 | if (IconSize == SmallIcon) scale *= 1.34; 530 | for (int d = 0; d < 4; d++) { 531 | addraindrop(x + scale * (7.8 - d * 1.95) - scale * 5.2, y + scale * 2.1 - scale / 6, scale / 1.6); 532 | } 533 | } 534 | //######################################################################################### 535 | void addsnow(int x, int y, int scale, bool IconSize) { 536 | int dxo, dyo, dxi, dyi; 537 | for (int flakes = 0; flakes < 5; flakes++) { 538 | for (int i = 0; i < 360; i = i + 45) { 539 | dxo = 0.5 * scale * cos((i - 90) * 3.14 / 180); dxi = dxo * 0.1; 540 | dyo = 0.5 * scale * sin((i - 90) * 3.14 / 180); dyi = dyo * 0.1; 541 | display.drawLine(dxo + x + flakes * 1.5 * scale - scale * 3, dyo + y + scale * 2, dxi + x + 0 + flakes * 1.5 * scale - scale * 3, dyi + y + scale * 2, GxEPD_BLACK); 542 | } 543 | } 544 | } 545 | //######################################################################################### 546 | void addtstorm(int x, int y, int scale) { 547 | y = y + scale / 2; 548 | for (int i = 0; i < 5; i++) { 549 | display.drawLine(x - scale * 4 + scale * i * 1.5 + 0, y + scale * 1.5, x - scale * 3.5 + scale * i * 1.5 + 0, y + scale, GxEPD_BLACK); 550 | if (scale != Small) { 551 | display.drawLine(x - scale * 4 + scale * i * 1.5 + 1, y + scale * 1.5, x - scale * 3.5 + scale * i * 1.5 + 1, y + scale, GxEPD_BLACK); 552 | display.drawLine(x - scale * 4 + scale * i * 1.5 + 2, y + scale * 1.5, x - scale * 3.5 + scale * i * 1.5 + 2, y + scale, GxEPD_BLACK); 553 | } 554 | display.drawLine(x - scale * 4 + scale * i * 1.5, y + scale * 1.5 + 0, x - scale * 3 + scale * i * 1.5 + 0, y + scale * 1.5 + 0, GxEPD_BLACK); 555 | if (scale != Small) { 556 | display.drawLine(x - scale * 4 + scale * i * 1.5, y + scale * 1.5 + 1, x - scale * 3 + scale * i * 1.5 + 0, y + scale * 1.5 + 1, GxEPD_BLACK); 557 | display.drawLine(x - scale * 4 + scale * i * 1.5, y + scale * 1.5 + 2, x - scale * 3 + scale * i * 1.5 + 0, y + scale * 1.5 + 2, GxEPD_BLACK); 558 | } 559 | display.drawLine(x - scale * 3.5 + scale * i * 1.4 + 0, y + scale * 2.5, x - scale * 3 + scale * i * 1.5 + 0, y + scale * 1.5, GxEPD_BLACK); 560 | if (scale != Small) { 561 | display.drawLine(x - scale * 3.5 + scale * i * 1.4 + 1, y + scale * 2.5, x - scale * 3 + scale * i * 1.5 + 1, y + scale * 1.5, GxEPD_BLACK); 562 | display.drawLine(x - scale * 3.5 + scale * i * 1.4 + 2, y + scale * 2.5, x - scale * 3 + scale * i * 1.5 + 2, y + scale * 1.5, GxEPD_BLACK); 563 | } 564 | } 565 | } 566 | //######################################################################################### 567 | void addsun(int x, int y, int scale, bool IconSize) { 568 | int linesize = 3; 569 | if (IconSize == SmallIcon) linesize = 1; 570 | display.fillRect(x - scale * 2, y, scale * 4, linesize, GxEPD_BLACK); 571 | display.fillRect(x, y - scale * 2, linesize, scale * 4, GxEPD_BLACK); 572 | display.drawLine(x - scale * 1.3, y - scale * 1.3, x + scale * 1.3, y + scale * 1.3, GxEPD_BLACK); 573 | display.drawLine(x - scale * 1.3, y + scale * 1.3, x + scale * 1.3, y - scale * 1.3, GxEPD_BLACK); 574 | if (IconSize == LargeIcon) { 575 | display.drawLine(1 + x - scale * 1.3, y - scale * 1.3, 1 + x + scale * 1.3, y + scale * 1.3, GxEPD_BLACK); 576 | display.drawLine(2 + x - scale * 1.3, y - scale * 1.3, 2 + x + scale * 1.3, y + scale * 1.3, GxEPD_BLACK); 577 | display.drawLine(3 + x - scale * 1.3, y - scale * 1.3, 3 + x + scale * 1.3, y + scale * 1.3, GxEPD_BLACK); 578 | display.drawLine(1 + x - scale * 1.3, y + scale * 1.3, 1 + x + scale * 1.3, y - scale * 1.3, GxEPD_BLACK); 579 | display.drawLine(2 + x - scale * 1.3, y + scale * 1.3, 2 + x + scale * 1.3, y - scale * 1.3, GxEPD_BLACK); 580 | display.drawLine(3 + x - scale * 1.3, y + scale * 1.3, 3 + x + scale * 1.3, y - scale * 1.3, GxEPD_BLACK); 581 | } 582 | display.fillCircle(x, y, scale * 1.3, GxEPD_WHITE); 583 | display.fillCircle(x, y, scale, GxEPD_BLACK); 584 | display.fillCircle(x, y, scale - linesize, GxEPD_RED); 585 | } 586 | //######################################################################################### 587 | void addfog(int x, int y, int scale, int linesize, bool IconSize) { 588 | if (IconSize == SmallIcon) { 589 | linesize = 1; 590 | y = y - 1; 591 | } else y = y - 3; 592 | for (int i = 0; i < 6; i++) { 593 | display.fillRect(x - scale * 3, y + scale * 1.5, scale * 6, linesize, GxEPD_BLACK); 594 | display.fillRect(x - scale * 3, y + scale * 2.0, scale * 6, linesize, GxEPD_BLACK); 595 | display.fillRect(x - scale * 3, y + scale * 2.6, scale * 6, linesize, GxEPD_BLACK); 596 | } 597 | } 598 | 599 | //######################################################################################### 600 | void CloudCover(int x, int y, int CCover) { 601 | addcloud(x - 9, y - 3, Small * 0.6, 2); // Cloud top left 602 | addcloud(x + 3, y - 3, Small * 0.6, 2); // Cloud top right 603 | addcloud(x, y, Small * 0.6, 2); // Main cloud 604 | u8g2Fonts.setFont(u8g2_font_helvB08_tf); 605 | drawString(x + 15, y - 5, String(CCover) + "%", LEFT); 606 | } 607 | //######################################################################################### 608 | void Sunny(int x, int y, bool IconSize, String IconName) { 609 | int scale = Small; 610 | 611 | y = y + 2; // Shift down small sun icon 612 | 613 | if (IconName.endsWith("n")){ 614 | scale = scale * 1.8; 615 | addmoon(x+20, y+15 , scale, LargeIcon); 616 | }else{ 617 | scale = scale * 1.6; 618 | addsun(x-3, y-4, scale, IconSize); 619 | } 620 | 621 | } 622 | //######################################################################################### 623 | void MostlySunny(int x, int y, bool IconSize, String IconName) { 624 | int scale = Small, linesize = 1, offset = 4; 625 | 626 | //if (IconName.endsWith("n")) addmoon(x, y + offset + (IconSize ? -8 : 0), scale, IconSize); 627 | //addcloud(x, y + offset, scale, linesize); 628 | // addsun(x - scale * 1.8, y - scale * 1.8 + offset, scale, IconSize); 629 | 630 | if (IconName.endsWith("n")) { 631 | addmoon(x + scale * 1.8 , y + scale * 1.8 + 5, scale*1.5, IconSize); 632 | 633 | addcloud(x, y + offset, scale, linesize); 634 | }else{ 635 | 636 | addsun(x - scale * 1.8, y - scale * 1.8, scale, IconSize); 637 | addcloud(x, y + offset, scale, linesize); 638 | } 639 | } 640 | //######################################################################################### 641 | void MostlyCloudy(int x, int y, bool IconSize, String IconName) { 642 | int scale = Small, linesize = 1 , offset = 4; 643 | 644 | if (IconName.endsWith("n")) { 645 | addmoon(x + scale * 1.8 , y + scale * 1.8 - 2, scale*1.5, IconSize); 646 | addcloud(x, y - offset, scale, linesize); 647 | addcloud(x+1, y + offset, scale, linesize); 648 | }else{ 649 | addcloud(x, y - offset, scale, linesize); 650 | addsun(x - scale * 1.8, y - scale * 1.8, scale, IconSize); 651 | addcloud(x+1, y + offset, scale, linesize); 652 | } 653 | } 654 | //######################################################################################### 655 | void Cloudy(int x, int y, bool IconSize, String IconName) { 656 | int scale = Small, linesize = 1, offset = 4; 657 | 658 | //if (IconName.endsWith("n")) addmoon(x, y + offset, scale, IconSize); 659 | //addcloud(x, y + offset, scale, linesize); 660 | 661 | if (IconName.endsWith("n")) { 662 | //addmoon(x + scale * 1.8 , y + scale * 1.8 +10, scale*1.5, IconSize); 663 | addcloud(x, y + offset, scale, linesize); 664 | }else{ 665 | addcloud(x, y + offset, scale, linesize); 666 | } 667 | 668 | } 669 | //######################################################################################### 670 | void Rain(int x, int y, bool IconSize, String IconName) { 671 | int scale = Small, linesize = 1; 672 | 673 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 674 | addcloud(x, y, scale, linesize); 675 | addrain(x, y, scale, IconSize); 676 | } 677 | //######################################################################################### 678 | void ExpectRain(int x, int y, bool IconSize, String IconName) { 679 | int scale = Small, linesize = 1; 680 | 681 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 682 | addsun(x - scale * 1.8, y - scale * 1.8, scale, IconSize); 683 | addcloud(x, y, scale, linesize); 684 | addrain(x, y, scale, IconSize); 685 | } 686 | //######################################################################################### 687 | void ChanceRain(int x, int y, bool IconSize, String IconName) { 688 | int scale = Small, linesize = 1; 689 | 690 | if (IconName.endsWith("n")) addmoon(x - (IconSize ? 8 : 0), y, scale, IconSize); 691 | addsun(x - scale * 1.8, y - scale * 1.8, scale, IconSize); 692 | addcloud(x, y, scale, linesize); 693 | addrain(x, y, scale, IconSize); 694 | } 695 | //######################################################################################### 696 | void Tstorms(int x, int y, bool IconSize, String IconName) { 697 | int scale = Small, linesize = 1; 698 | 699 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 700 | addcloud(x, y, scale, linesize); 701 | addtstorm(x, y, scale); 702 | } 703 | //######################################################################################### 704 | void Snow(int x, int y, bool IconSize, String IconName) { 705 | int scale = Small, linesize = 1; 706 | 707 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 708 | addcloud(x, y, scale, linesize); 709 | addsnow(x, y, scale, IconSize); 710 | } 711 | //######################################################################################### 712 | void Fog(int x, int y, bool IconSize, String IconName) { 713 | int linesize = 1, scale = Small; 714 | 715 | y = y + 5; 716 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 717 | addcloud(x, y - 5, scale, linesize); 718 | addfog(x, y - 2, scale, linesize, IconSize); 719 | } 720 | //######################################################################################### 721 | void Haze(int x, int y, bool IconSize, String IconName) { 722 | int linesize = 1, scale = Small; 723 | 724 | if (IconName.endsWith("n")) addmoon(x, y, scale, IconSize); 725 | addsun(x, y - 2, scale * 1.4, IconSize); 726 | addfog(x, y + 3 - (IconSize ? 12 : 0), scale * 1.4, linesize, IconSize); 727 | } 728 | //######################################################################################### 729 | void Visibility(int x, int y, String Visi) { 730 | y = y - 3; // 731 | float start_angle = 0.52, end_angle = 2.61; 732 | int r = 10; 733 | for (float i = start_angle; i < end_angle; i = i + 0.05) { 734 | display.drawPixel(x + r * cos(i), y - r / 2 + r * sin(i), GxEPD_BLACK); 735 | display.drawPixel(x + r * cos(i), 1 + y - r / 2 + r * sin(i), GxEPD_BLACK); 736 | } 737 | start_angle = 3.61; end_angle = 5.78; 738 | for (float i = start_angle; i < end_angle; i = i + 0.05) { 739 | display.drawPixel(x + r * cos(i), y + r / 2 + r * sin(i), GxEPD_BLACK); 740 | display.drawPixel(x + r * cos(i), 1 + y + r / 2 + r * sin(i), GxEPD_BLACK); 741 | } 742 | display.fillCircle(x, y, r / 4, GxEPD_BLACK); 743 | u8g2Fonts.setFont(u8g2_font_helvB08_tf); 744 | drawString(x + 12, y - 3, Visi, LEFT); 745 | } 746 | //######################################################################################### 747 | void addmoon(int x, int y, int scale, bool IconSize) { 748 | if (IconSize == LargeIcon) { 749 | x = x - 5; y = y + 5; 750 | display.fillCircle(x - 21, y - 23, scale, GxEPD_BLACK); 751 | display.fillCircle(x - 14, y - 23, scale * 1.7, GxEPD_WHITE); 752 | } 753 | else 754 | { 755 | display.fillCircle(x - 16, y - 11, scale, GxEPD_BLACK); 756 | display.fillCircle(x - 11, y - 11, scale * 1.7, GxEPD_WHITE); 757 | } 758 | } 759 | //######################################################################################### 760 | void Nodata(int x, int y, bool IconSize, String IconName) { 761 | if (IconSize == LargeIcon) u8g2Fonts.setFont(u8g2_font_helvB24_tf); else u8g2Fonts.setFont(u8g2_font_helvB10_tf); 762 | drawString(x - 3, y - 8, "?", CENTER); 763 | u8g2Fonts.setFont(u8g2_font_helvB08_tf); 764 | } 765 | //######################################################################################### 766 | void drawString(int x, int y, String text, alignmentType alignment) { 767 | int16_t x1, y1; //the bounds of x,y and w and h of the variable 'text' in pixels. 768 | uint16_t w, h; 769 | display.setTextWrap(false); 770 | display.getTextBounds(text, x, y, &x1, &y1, &w, &h); 771 | if (alignment == RIGHT) x = x - w; 772 | if (alignment == CENTER) x = x - w / 2; 773 | u8g2Fonts.setCursor(x, y + h); 774 | u8g2Fonts.print(text); 775 | } 776 | //######################################################################################### 777 | void drawStringMaxWidth(int x, int y, unsigned int text_width, String text, alignmentType alignment) { 778 | int16_t x1, y1; //the bounds of x,y and w and h of the variable 'text' in pixels. 779 | uint16_t w, h; 780 | display.getTextBounds(text, x, y, &x1, &y1, &w, &h); 781 | if (alignment == RIGHT) x = x - w; 782 | if (alignment == CENTER) x = x - w / 2; 783 | u8g2Fonts.setCursor(x, y); 784 | if (text.length() > text_width * 2) { 785 | u8g2Fonts.setFont(u8g2_font_helvB10_tf); 786 | text_width = 42; 787 | y = y - 3; 788 | } 789 | u8g2Fonts.println(text.substring(0, text_width)); 790 | if (text.length() > text_width) { 791 | u8g2Fonts.setCursor(x, y + h + 15); 792 | String secondLine = text.substring(text_width); 793 | secondLine.trim(); // Remove any leading spaces 794 | u8g2Fonts.println(secondLine); 795 | } 796 | } 797 | //######################################################################################### 798 | void InitialiseDisplay() { 799 | Serial.println("Begin InitialiseDisplay..."); 800 | display.init(115200, true, 2, false); 801 | // display.init(); for older Waveshare HAT's 802 | SPI.end(); 803 | SPI.begin(EPD_SCK, EPD_MISO, EPD_MOSI, EPD_CS); 804 | display.setRotation(1); // Use 1 or 3 for landscape modes 805 | u8g2Fonts.begin(display); // connect u8g2 procedures to Adafruit GFX 806 | u8g2Fonts.setFontMode(1); // use u8g2 transparent mode (this is default) 807 | u8g2Fonts.setFontDirection(0); // left to right (this is default) 808 | u8g2Fonts.setForegroundColor(GxEPD_BLACK); // apply Adafruit GFX color 809 | u8g2Fonts.setBackgroundColor(GxEPD_WHITE); // apply Adafruit GFX color 810 | u8g2Fonts.setFont(u8g2_font_helvB10_tf); // Explore u8g2 fonts from here: https://github.com/olikraus/u8g2/wiki/fntlistall 811 | display.fillScreen(GxEPD_WHITE); 812 | display.setFullWindow(); 813 | Serial.println("... End InitialiseDisplay"); 814 | } 815 | 816 | /* 817 | Version 6.0 reformatted to use u8g2 fonts 818 | 1. Screen layout revised 819 | 2. Made consitent with other versions specifically 7x5 variant 820 | 3. Introduced Visibility in Metres, Cloud cover in % and RH in % 821 | 4. Correct sunrise/sunset time when in imperial mode. 822 | 823 | Version 6.1 Provided connection support for Waveshare ESP32 driver board 824 | 825 | Version 6.2 Changed GxEPD2 initialisation from 115200 to 0 826 | 1. display.init(115200); becomes display.init(0); to stop blank screen following update to GxEPD2 827 | 828 | Version 6.3 changed u8g2 fonts selection 829 | 1. Omitted 'FONT(' and added _tf to font names either Regular (R) or Bold (B) 830 | 831 | Version 6.4 832 | 1. Added an extra 20-secs sleep delay to allow for slow ESP32 RTC timers 833 | 834 | Version 6.5 835 | 1. Modified for GxEPD2 836 | 837 | */ 838 | -------------------------------------------------------------------------------- /epaper_fonts.h: -------------------------------------------------------------------------------- 1 | const uint8_t DejaVu_Sans_Bold_11Bitmaps[] PROGMEM = { 2 | 0x00, 0xDB, 0x6C, 0x36, 0xAA, 0xA0, 0x12, 0x0B, 0x05, 0x8F, 0xE2, 0x47, 3 | 0xF1, 0xA0, 0x90, 0x10, 0x7E, 0xD0, 0xF0, 0xFE, 0x1E, 0x16, 0xFC, 0x10, 4 | 0x10, 0x61, 0x12, 0x42, 0x58, 0x32, 0x00, 0x98, 0x34, 0x84, 0x91, 0x0C, 5 | 0x3C, 0x30, 0x18, 0x0E, 0x6D, 0xB6, 0x73, 0x18, 0xF6, 0x69, 0x96, 0x66, 6 | 0xCC, 0xCC, 0xCC, 0x66, 0xCC, 0x66, 0x66, 0x66, 0xCC, 0x64, 0xA4, 0xC0, 7 | 0x00, 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10, 0x66, 0x48, 0xEE, 0xD8, 8 | 0x11, 0x88, 0x46, 0x21, 0x18, 0x80, 0x79, 0x9B, 0x36, 0x6C, 0xD9, 0xB3, 9 | 0x3C, 0xF0, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x7E, 0xF8, 0x18, 0x30, 0xC3, 10 | 0x0C, 0x30, 0x7E, 0x79, 0x18, 0x33, 0xC0, 0xC1, 0xA3, 0x3C, 0x1C, 0x3C, 11 | 0x6C, 0x4C, 0x8C, 0xFE, 0x0C, 0x0C, 0xF9, 0x83, 0x07, 0xC0, 0xC1, 0x83, 12 | 0x7C, 0x78, 0xC3, 0x07, 0xCC, 0xD9, 0xB3, 0x3C, 0xFC, 0x18, 0x60, 0xC3, 13 | 0x06, 0x18, 0x30, 0x79, 0x9B, 0x31, 0x8C, 0xD9, 0xB3, 0x3C, 0x79, 0x9B, 14 | 0x36, 0x67, 0xC1, 0x86, 0x3C, 0xD8, 0x0D, 0x80, 0x66, 0x00, 0x66, 0x48, 15 | 0x02, 0x1C, 0xE0, 0xE0, 0x1C, 0x02, 0xFE, 0x00, 0xFE, 0x80, 0x70, 0x0E, 16 | 0x0E, 0x70, 0x80, 0xF0, 0x63, 0x9C, 0x60, 0x06, 0x18, 0x1E, 0x0C, 0x31, 17 | 0x7E, 0x59, 0xAA, 0x15, 0x42, 0xAC, 0xD2, 0xFC, 0x61, 0x03, 0xC0, 0x18, 18 | 0x1E, 0x0F, 0x04, 0x86, 0x63, 0xF1, 0x99, 0x86, 0xFC, 0xC6, 0xC6, 0xFC, 19 | 0xC6, 0xC6, 0xC6, 0xFC, 0x3E, 0x62, 0xC0, 0xC0, 0xC0, 0xC0, 0x62, 0x3E, 20 | 0xF8, 0xCC, 0xC6, 0xC6, 0xC6, 0xC6, 0xCC, 0xF8, 0xFD, 0x83, 0x07, 0xEC, 21 | 0x18, 0x30, 0x7E, 0xFD, 0x83, 0x07, 0xEC, 0x18, 0x30, 0x60, 0x3E, 0x62, 22 | 0xC0, 0xC0, 0xCE, 0xC6, 0x66, 0x3E, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 23 | 0xC6, 0xC6, 0xDB, 0x6D, 0xB6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x37, 0x00, 24 | 0xC6, 0x66, 0x36, 0x1E, 0x0F, 0x06, 0xC3, 0x31, 0x8C, 0xC1, 0x83, 0x06, 25 | 0x0C, 0x18, 0x30, 0x7E, 0xE3, 0xB8, 0xEF, 0x7B, 0x56, 0xDD, 0xB2, 0x6C, 26 | 0x1B, 0x06, 0xE6, 0xE6, 0xE6, 0xD6, 0xD6, 0xCE, 0xCE, 0xCE, 0x3C, 0x33, 27 | 0x30, 0xD8, 0x6C, 0x36, 0x19, 0x98, 0x78, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 28 | 0xC0, 0xC0, 0xC0, 0x3C, 0x33, 0x30, 0xD8, 0x6C, 0x36, 0x19, 0x98, 0x78, 29 | 0x0C, 0x03, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xF8, 0xCC, 0xCC, 0xC6, 0x79, 30 | 0x93, 0x07, 0x87, 0xC1, 0xA3, 0x7C, 0xFF, 0x0C, 0x06, 0x03, 0x01, 0x80, 31 | 0xC0, 0x60, 0x30, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC3, 32 | 0x33, 0x19, 0x8C, 0xC2, 0x41, 0xE0, 0xF0, 0x30, 0xC4, 0x6C, 0xE6, 0x6E, 33 | 0xC6, 0xAC, 0x7B, 0xC3, 0xB8, 0x31, 0x83, 0x18, 0xC3, 0x33, 0x19, 0x87, 34 | 0x83, 0xC3, 0x31, 0x99, 0x86, 0xC3, 0x33, 0x19, 0x87, 0x81, 0x80, 0xC0, 35 | 0x60, 0x30, 0xFE, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFE, 0xF6, 0x31, 36 | 0x8C, 0x63, 0x18, 0xC7, 0x80, 0x86, 0x10, 0x86, 0x10, 0x86, 0x10, 0xF1, 37 | 0x8C, 0x63, 0x18, 0xC6, 0x37, 0x80, 0x38, 0x6C, 0xC6, 0xFC, 0xC6, 0x78, 38 | 0x19, 0xF6, 0x6C, 0xCF, 0x80, 0xC1, 0x83, 0x07, 0xCC, 0xD9, 0xB3, 0x66, 39 | 0xF8, 0x7B, 0x0C, 0x30, 0xC1, 0xE0, 0x0C, 0x18, 0x33, 0xEC, 0xD9, 0xB3, 40 | 0x66, 0x7C, 0x79, 0x9B, 0xF6, 0x0C, 0x0F, 0x80, 0x39, 0x86, 0x3E, 0x61, 41 | 0x86, 0x18, 0x60, 0x7D, 0x9B, 0x36, 0x6C, 0xCF, 0x83, 0x3C, 0xC1, 0x83, 42 | 0x07, 0xCC, 0xD9, 0xB3, 0x66, 0xCC, 0xD8, 0x6D, 0xB6, 0xC0, 0x66, 0x06, 43 | 0x66, 0x66, 0x66, 0xC0, 0xC0, 0xC0, 0xC0, 0xCC, 0xD8, 0xF0, 0xF0, 0xD8, 44 | 0xCC, 0xDB, 0x6D, 0xB6, 0xC0, 0xFF, 0x99, 0x9B, 0x33, 0x66, 0x6C, 0xCD, 45 | 0x99, 0x80, 0xF9, 0x9B, 0x36, 0x6C, 0xD9, 0x80, 0x79, 0x9B, 0x36, 0x6C, 46 | 0xCF, 0x00, 0xF9, 0x9B, 0x36, 0x6C, 0xDF, 0x30, 0x60, 0x7D, 0x9B, 0x36, 47 | 0x6C, 0xCF, 0x83, 0x06, 0xF6, 0x31, 0x8C, 0x60, 0x7B, 0x0F, 0x1E, 0x1B, 48 | 0xC0, 0x61, 0x8F, 0x98, 0x61, 0x86, 0x1E, 0xCD, 0x9B, 0x36, 0x6C, 0xCF, 49 | 0x80, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0xC9, 0xB7, 0x6D, 0x59, 0xDC, 50 | 0x63, 0x18, 0xC0, 0xC6, 0x6C, 0x38, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 51 | 0x28, 0x38, 0x30, 0x30, 0x60, 0xF8, 0x63, 0x18, 0xC3, 0xE0, 0x3C, 0x60, 52 | 0xC1, 0x8E, 0x06, 0x0C, 0x18, 0x30, 0x38, 0xAA, 0xAA, 0xA8, 0xF0, 0x60, 53 | 0xC1, 0x81, 0xC6, 0x0C, 0x18, 0x31, 0xC0 54 | }; 55 | 56 | const GFXglyph DejaVu_Sans_Bold_11Glyphs[] PROGMEM = { 57 | { 0, 1, 1, 5, 0, 0 } // ' ' 58 | ,{ 1, 3, 8, 6, 2, -8 } // '!' 59 | ,{ 4, 4, 3, 7, 1, -8 } // '"' 60 | ,{ 6, 9, 8, 10, 1, -8 } // '#' 61 | ,{ 15, 8, 10, 9, 0, -8 } // '$' 62 | ,{ 25, 11, 8, 12, 1, -8 } // '%' 63 | ,{ 36, 9, 8, 11, 1, -8 } // '&' 64 | ,{ 45, 4, 4, 4, 0, -8 } // ''' 65 | ,{ 47, 4, 10, 6, 1, -9 } // '(' 66 | ,{ 52, 4, 10, 6, 1, -9 } // ')' 67 | ,{ 57, 5, 5, 7, 0, -8 } // '*' 68 | ,{ 61, 8, 7, 10, 1, -7 } // '+' 69 | ,{ 68, 4, 4, 5, 0, -2 } // ',' 70 | ,{ 70, 4, 2, 6, 1, -4 } // '-' 71 | ,{ 71, 3, 2, 5, 1, -2 } // '.' 72 | ,{ 72, 5, 9, 5, 0, -8 } // '/' 73 | ,{ 78, 7, 8, 9, 1, -8 } // '0' 74 | ,{ 85, 7, 8, 9, 1, -8 } // '1' 75 | ,{ 92, 7, 8, 9, 1, -8 } // '2' 76 | ,{ 99, 7, 8, 9, 1, -8 } // '3' 77 | ,{ 106, 8, 8, 9, 1, -8 } // '4' 78 | ,{ 114, 7, 8, 9, 1, -8 } // '5' 79 | ,{ 121, 7, 8, 9, 1, -8 } // '6' 80 | ,{ 128, 7, 8, 9, 1, -8 } // '7' 81 | ,{ 135, 7, 8, 9, 1, -8 } // '8' 82 | ,{ 142, 7, 8, 9, 1, -8 } // '9' 83 | ,{ 149, 3, 6, 5, 1, -6 } // ':' 84 | ,{ 152, 4, 8, 5, 0, -6 } // ';' 85 | ,{ 156, 8, 6, 10, 1, -7 } // '<' 86 | ,{ 162, 8, 3, 10, 1, -5 } // '=' 87 | ,{ 165, 8, 6, 10, 1, -7 } // '>' 88 | ,{ 171, 6, 8, 7, 1, -8 } // '?' 89 | ,{ 177, 11, 10, 12, 1, -8 } // '@' 90 | ,{ 191, 9, 8, 9, 0, -8 } // 'A' 91 | ,{ 200, 8, 8, 10, 1, -8 } // 'B' 92 | ,{ 208, 8, 8, 10, 1, -8 } // 'C' 93 | ,{ 216, 8, 8, 10, 1, -8 } // 'D' 94 | ,{ 224, 7, 8, 9, 1, -8 } // 'E' 95 | ,{ 231, 7, 8, 9, 1, -8 } // 'F' 96 | ,{ 238, 8, 8, 10, 1, -8 } // 'G' 97 | ,{ 246, 8, 8, 10, 1, -8 } // 'H' 98 | ,{ 254, 3, 8, 5, 1, -8 } // 'I' 99 | ,{ 257, 5, 10, 5, -1, -8 } // 'J' 100 | ,{ 264, 9, 8, 10, 1, -8 } // 'K' 101 | ,{ 273, 7, 8, 8, 1, -8 } // 'L' 102 | ,{ 280, 10, 8, 12, 1, -8 } // 'M' 103 | ,{ 290, 8, 8, 10, 1, -8 } // 'N' 104 | ,{ 298, 9, 8, 11, 1, -8 } // 'O' 105 | ,{ 307, 8, 8, 9, 1, -8 } // 'P' 106 | ,{ 315, 9, 10, 11, 1, -8 } // 'Q' 107 | ,{ 327, 8, 8, 9, 1, -8 } // 'R' 108 | ,{ 335, 7, 8, 9, 1, -8 } // 'S' 109 | ,{ 342, 9, 8, 9, 0, -8 } // 'T' 110 | ,{ 351, 8, 8, 10, 1, -8 } // 'U' 111 | ,{ 359, 9, 8, 9, 0, -8 } // 'V' 112 | ,{ 368, 12, 8, 14, 1, -8 } // 'W' 113 | ,{ 380, 9, 8, 9, 0, -8 } // 'X' 114 | ,{ 389, 9, 8, 9, 0, -8 } // 'Y' 115 | ,{ 398, 8, 8, 9, 1, -8 } // 'Z' 116 | ,{ 406, 5, 10, 6, 1, -9 } // '[' 117 | ,{ 413, 5, 9, 5, 0, -8 } // '\' 118 | ,{ 419, 5, 10, 6, 0, -9 } // ']' 119 | ,{ 426, 8, 3, 10, 1, -8 } // '^' 120 | ,{ 429, 7, 1, 7, 0, 2 } // '_' 121 | ,{ 430, 4, 2, 7, 1, -9 } // '`' 122 | ,{ 431, 7, 6, 9, 1, -6 } // 'a' 123 | ,{ 437, 7, 9, 9, 1, -9 } // 'b' 124 | ,{ 445, 6, 6, 8, 1, -6 } // 'c' 125 | ,{ 450, 7, 9, 9, 1, -9 } // 'd' 126 | ,{ 458, 7, 6, 9, 1, -6 } // 'e' 127 | ,{ 464, 6, 9, 6, 0, -9 } // 'f' 128 | ,{ 471, 7, 8, 9, 1, -6 } // 'g' 129 | ,{ 478, 7, 9, 9, 1, -9 } // 'h' 130 | ,{ 486, 3, 9, 5, 1, -9 } // 'i' 131 | ,{ 490, 4, 11, 5, 0, -9 } // 'j' 132 | ,{ 496, 8, 9, 8, 1, -9 } // 'k' 133 | ,{ 505, 3, 9, 5, 1, -9 } // 'l' 134 | ,{ 509, 11, 6, 12, 1, -6 } // 'm' 135 | ,{ 518, 7, 6, 9, 1, -6 } // 'n' 136 | ,{ 524, 7, 6, 9, 1, -6 } // 'o' 137 | ,{ 530, 7, 8, 9, 1, -6 } // 'p' 138 | ,{ 537, 7, 8, 9, 1, -6 } // 'q' 139 | ,{ 544, 5, 6, 6, 1, -6 } // 'r' 140 | ,{ 548, 6, 6, 8, 1, -6 } // 's' 141 | ,{ 553, 6, 8, 6, 0, -8 } // 't' 142 | ,{ 559, 7, 6, 9, 1, -6 } // 'u' 143 | ,{ 565, 8, 6, 8, 0, -6 } // 'v' 144 | ,{ 571, 10, 6, 12, 1, -6 } // 'w' 145 | ,{ 579, 8, 6, 8, 0, -6 } // 'x' 146 | ,{ 585, 8, 8, 8, 0, -6 } // 'y' 147 | ,{ 593, 6, 6, 8, 1, -6 } // 'z' 148 | ,{ 598, 7, 10, 9, 1, -9 } // '{' 149 | ,{ 607, 2, 11, 5, 1, -8 } // '|' 150 | ,{ 610, 7, 10, 9, 1, -9 } // '}' 151 | }; 152 | 153 | const GFXfont DejaVu_Sans_Bold_11 PROGMEM = { 154 | (uint8_t *)DejaVu_Sans_Bold_11Bitmaps, (GFXglyph *)DejaVu_Sans_Bold_11Glyphs, 0x20, 0x7E, 14 155 | }; 156 | 157 | const uint8_t DSEG7_Classic_Bold_21Bitmaps[] PROGMEM = { 158 | 0x00, 0x00, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 159 | 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 160 | 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 161 | 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 162 | 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 163 | 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0x79, 0x9A, 0x14, 0x2C, 0xCF, 164 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0A, 0x14, 0x28, 165 | 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 166 | 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 167 | 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 168 | 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 169 | 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 170 | 0x80, 0x7F, 0x3F, 0xE7, 0xF0, 0xDB, 0x00, 0x06, 0x0C, 0x18, 0x60, 0xC1, 171 | 0x86, 0x0C, 0x18, 0x60, 0xC1, 0x86, 0x0C, 0x18, 0x60, 0xC1, 0x80, 0x00, 172 | 0x00, 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 173 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x00, 0x60, 0x00, 0x30, 0x06, 0xE0, 0x3B, 174 | 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xED, 0xFD, 0xAF, 0xFA, 175 | 0x7F, 0xF0, 0x26, 0xEE, 0xEE, 0xEE, 0x60, 0x6E, 0xEE, 0xEE, 0xE6, 0x20, 176 | 0x7F, 0xF0, 0xFF, 0xA1, 0xFD, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 177 | 0x80, 0x0E, 0x00, 0x38, 0x7F, 0x63, 0xFE, 0x37, 0xF0, 0xE0, 0x03, 0x80, 178 | 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0D, 0xFC, 0x2F, 0xF8, 0x7F, 179 | 0xF0, 0xFF, 0xE3, 0xFE, 0x8F, 0xEC, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 180 | 0xC0, 0x0E, 0x00, 0x71, 0xFD, 0x9F, 0xF0, 0x7F, 0x60, 0x07, 0x00, 0x38, 181 | 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x8F, 0xEC, 0xFF, 0xAF, 0xFE, 0x00, 182 | 0x80, 0x0B, 0x00, 0x6E, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 183 | 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 0x81, 0xFD, 0x80, 0x0E, 0x00, 0x38, 0x00, 184 | 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0x60, 0x00, 0x80, 0x7F, 0xF2, 185 | 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 186 | 0xE0, 0x03, 0x7F, 0x03, 0xFE, 0x07, 0xF6, 0x00, 0x38, 0x00, 0xE0, 0x03, 187 | 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE1, 0xFD, 0x8F, 0xFA, 0x7F, 0xF0, 0x7F, 188 | 0xF2, 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 189 | 0x00, 0xE0, 0x03, 0x7F, 0x03, 0xFE, 0x37, 0xF6, 0xE0, 0x3B, 0x80, 0xEE, 190 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xED, 0xFD, 0xAF, 0xFA, 0x7F, 0xF0, 191 | 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 192 | 0xB8, 0x0E, 0xE0, 0x3B, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00, 193 | 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x01, 0x80, 0x02, 0x7F, 194 | 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 195 | 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x37, 0xF6, 0xE0, 0x3B, 0x80, 0xEE, 196 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xED, 0xFD, 0xAF, 0xFA, 0x7F, 0xF0, 197 | 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 198 | 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x07, 0xF6, 0x00, 0x38, 0x00, 199 | 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE1, 0xFD, 0x8F, 0xFA, 0x7F, 200 | 0xF0, 0xDB, 0x00, 0x00, 0x1B, 0x00, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 201 | 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 202 | 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 203 | 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 204 | 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 205 | 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 206 | 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 207 | 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 208 | 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x37, 0xF6, 0xE0, 0x3B, 0x80, 209 | 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 0x01, 0xA0, 0x02, 0x80, 210 | 0x03, 0x00, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 211 | 0x00, 0xDF, 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 212 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x1F, 0xC1, 213 | 0xFF, 0x37, 0xF1, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 214 | 0x06, 0xFE, 0x2F, 0xF8, 0xFF, 0xE0, 0x00, 0x08, 0x00, 0x60, 0x03, 0x80, 215 | 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x1F, 0xD8, 0xFF, 0x8D, 216 | 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 217 | 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x7F, 0xF5, 0xFF, 0x37, 0xF1, 0xC0, 0x0E, 218 | 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x0F, 0xF9, 0xBF, 219 | 0x8E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x37, 0xF1, 220 | 0x7F, 0xC7, 0xFF, 0x00, 0x7F, 0xF5, 0xFF, 0x37, 0xF1, 0xC0, 0x0E, 0x00, 221 | 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x0F, 0xF9, 0xBF, 0x8E, 222 | 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x30, 0x01, 0x00, 223 | 0x00, 0x7F, 0xF2, 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 224 | 0x00, 0x38, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x30, 0x06, 0xE0, 0x3B, 225 | 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xED, 0xFD, 0xAF, 0xFA, 226 | 0x7F, 0xF0, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 227 | 0x0E, 0x00, 0x38, 0x00, 0xDF, 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 228 | 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x00, 0x68, 0x00, 0x80, 229 | 0x6E, 0xEE, 0xEE, 0xE6, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x80, 0x0E, 230 | 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x18, 0x00, 0x0C, 0x01, 231 | 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 232 | 0x6B, 0xFE, 0x9F, 0xFC, 0x7F, 0xF2, 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 233 | 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x7F, 0x03, 0xFE, 0x37, 234 | 0xF6, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 235 | 0x01, 0xA0, 0x02, 0x80, 0x06, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 236 | 0x03, 0x80, 0x1C, 0x00, 0xC0, 0x00, 0x00, 0x30, 0x01, 0xC0, 0x0E, 0x00, 237 | 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x2F, 0xF8, 0xFF, 0xE0, 238 | 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 239 | 0xB8, 0x0E, 0xE0, 0x3B, 0x00, 0x60, 0x00, 0x30, 0x06, 0xE0, 0x3B, 0x80, 240 | 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 0x01, 0xA0, 0x02, 0x1F, 241 | 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 242 | 0x0E, 0xE0, 0x3B, 0x00, 0x68, 0x00, 0x80, 0x1F, 0xC0, 0xFF, 0x8D, 0xFD, 243 | 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 244 | 0x6B, 0xFE, 0x9F, 0xFC, 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 245 | 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x37, 246 | 0xF0, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0C, 247 | 0x00, 0x20, 0x00, 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 248 | 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x07, 0xF6, 249 | 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x01, 250 | 0x80, 0x02, 0x1F, 0xC3, 0xFE, 0xDF, 0xCE, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 251 | 0x0E, 0x00, 0xE0, 0x0C, 0x00, 0x80, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x00, 252 | 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xDF, 0xC0, 0xFF, 253 | 0x81, 0xFD, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 254 | 0x38, 0x7F, 0x63, 0xFE, 0x9F, 0xFC, 0x80, 0x06, 0x00, 0x38, 0x01, 0xC0, 255 | 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xDF, 0xC1, 0xFF, 0x37, 0xF1, 256 | 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x2F, 257 | 0xF8, 0xFF, 0xE0, 0xC0, 0x1B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 258 | 0x80, 0xEE, 0x03, 0xB7, 0xF6, 0xBF, 0xE9, 0xFF, 0xC0, 0x80, 0x0B, 0x00, 259 | 0x6E, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xC0, 260 | 0x18, 0x00, 0x0C, 0x01, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 261 | 0x0E, 0xE0, 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x80, 0x0B, 0x00, 0x6E, 262 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 263 | 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 264 | 0xE0, 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x80, 0x0B, 0x00, 0x6E, 0x03, 265 | 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 266 | 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 267 | 0x3B, 0x00, 0x68, 0x00, 0x80, 0x80, 0x0B, 0x00, 0x6E, 0x03, 0xB8, 0x0E, 268 | 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 0x81, 0xFD, 269 | 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x7F, 270 | 0x63, 0xFE, 0x9F, 0xFC, 0x7F, 0xF0, 0xFF, 0xA1, 0xFD, 0x80, 0x0E, 0x00, 271 | 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 272 | 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0D, 273 | 0xFC, 0x2F, 0xF8, 0x7F, 0xF0, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 274 | 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 275 | 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 276 | 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 277 | 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 278 | 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 279 | 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0x7F, 280 | 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 281 | 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x37, 0xF6, 0xE0, 0x3B, 0x80, 0xEE, 282 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 0x01, 0xA0, 0x02, 0x80, 0x03, 283 | 0x00, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 284 | 0xDF, 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 285 | 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x1F, 0xC1, 0xFF, 286 | 0x37, 0xF1, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 287 | 0xFE, 0x2F, 0xF8, 0xFF, 0xE0, 0x00, 0x08, 0x00, 0x60, 0x03, 0x80, 0x0E, 288 | 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x1F, 0xD8, 0xFF, 0x8D, 0xFD, 289 | 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 290 | 0x6B, 0xFE, 0x9F, 0xFC, 0x7F, 0xF5, 0xFF, 0x37, 0xF1, 0xC0, 0x0E, 0x00, 291 | 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x0F, 0xF9, 0xBF, 0x8E, 292 | 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x37, 0xF1, 0x7F, 293 | 0xC7, 0xFF, 0x00, 0x7F, 0xF5, 0xFF, 0x37, 0xF1, 0xC0, 0x0E, 0x00, 0x70, 294 | 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x0F, 0xF9, 0xBF, 0x8E, 0x00, 295 | 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x30, 0x01, 0x00, 0x00, 296 | 0x7F, 0xF2, 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 297 | 0x38, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x30, 0x06, 0xE0, 0x3B, 0x80, 298 | 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xED, 0xFD, 0xAF, 0xFA, 0x7F, 299 | 0xF0, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 300 | 0x00, 0x38, 0x00, 0xDF, 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 301 | 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x00, 0x68, 0x00, 0x80, 0x6E, 302 | 0xEE, 0xEE, 0xE6, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x80, 0x0E, 0x00, 303 | 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x18, 0x00, 0x0C, 0x01, 0xB8, 304 | 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x6B, 305 | 0xFE, 0x9F, 0xFC, 0x7F, 0xF2, 0xFF, 0x8D, 0xFC, 0x38, 0x00, 0xE0, 0x03, 306 | 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x7F, 0x03, 0xFE, 0x37, 0xF6, 307 | 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 0x01, 308 | 0xA0, 0x02, 0x80, 0x06, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 309 | 0x80, 0x1C, 0x00, 0xC0, 0x00, 0x00, 0x30, 0x01, 0xC0, 0x0E, 0x00, 0x70, 310 | 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x2F, 0xF8, 0xFF, 0xE0, 0x7F, 311 | 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 312 | 0x0E, 0xE0, 0x3B, 0x00, 0x60, 0x00, 0x30, 0x06, 0xE0, 0x3B, 0x80, 0xEE, 313 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEC, 0x01, 0xA0, 0x02, 0x1F, 0xC0, 314 | 0xFF, 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 315 | 0xE0, 0x3B, 0x00, 0x68, 0x00, 0x80, 0x1F, 0xC0, 0xFF, 0x8D, 0xFD, 0xB8, 316 | 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x6B, 317 | 0xFE, 0x9F, 0xFC, 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 318 | 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x37, 0xF0, 319 | 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0C, 0x00, 320 | 0x20, 0x00, 0x7F, 0xF2, 0xFF, 0xAD, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 321 | 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x7F, 0x63, 0xFE, 0x07, 0xF6, 0x00, 322 | 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x01, 0x80, 323 | 0x02, 0x1F, 0xC3, 0xFE, 0xDF, 0xCE, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 324 | 0x00, 0xE0, 0x0C, 0x00, 0x80, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x38, 325 | 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xDF, 0xC0, 0xFF, 0x81, 326 | 0xFD, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 327 | 0x7F, 0x63, 0xFE, 0x9F, 0xFC, 0x80, 0x06, 0x00, 0x38, 0x01, 0xC0, 0x0E, 328 | 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xDF, 0xC1, 0xFF, 0x37, 0xF1, 0xC0, 329 | 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xFE, 0x2F, 0xF8, 330 | 0xFF, 0xE0, 0xC0, 0x1B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 331 | 0xEE, 0x03, 0xB7, 0xF6, 0xBF, 0xE9, 0xFF, 0xC0, 0x80, 0x0B, 0x00, 0x6E, 332 | 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xC0, 0x18, 333 | 0x00, 0x0C, 0x01, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 334 | 0xE0, 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x80, 0x0B, 0x00, 0x6E, 0x03, 335 | 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 336 | 0x8D, 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 337 | 0x3B, 0x7F, 0x6B, 0xFE, 0x9F, 0xFC, 0x80, 0x0B, 0x00, 0x6E, 0x03, 0xB8, 338 | 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 0x8D, 339 | 0xFD, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 340 | 0x00, 0x68, 0x00, 0x80, 0x80, 0x0B, 0x00, 0x6E, 0x03, 0xB8, 0x0E, 0xE0, 341 | 0x3B, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xDF, 0xD8, 0xFF, 0x81, 0xFD, 0x80, 342 | 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x7F, 0x63, 343 | 0xFE, 0x9F, 0xFC, 0x7F, 0xF0, 0xFF, 0xA1, 0xFD, 0x80, 0x0E, 0x00, 0x38, 344 | 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 0x00, 345 | 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0D, 0xFC, 346 | 0x2F, 0xF8, 0x7F, 0xF0, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 0x85, 347 | 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 0x42, 348 | 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80, 0xFD, 0x0A, 0x14, 0x28, 0x50, 0xA1, 349 | 0x42, 0x85, 0x0A, 0x14, 0x28, 0x5F, 0x80 350 | }; 351 | 352 | const GFXglyph DSEG7_Classic_Bold_21Glyphs[] PROGMEM = { 353 | { 0, 1, 1, 5, 0, 0 } // ' ' 354 | , { 1, 1, 1, 18, 0, 0 } // '!' 355 | , { 2, 7, 14, 9, 1, -14 } // '"' 356 | , { 15, 7, 14, 9, 1, -14 } // '#' 357 | , { 28, 7, 14, 9, 1, -14 } // '$' 358 | , { 41, 7, 14, 9, 1, -14 } // '%' 359 | , { 54, 7, 14, 9, 1, -14 } // '&' 360 | , { 67, 7, 14, 9, 1, -20 } // ''' 361 | , { 80, 7, 14, 9, 1, -14 } // '(' 362 | , { 93, 7, 14, 9, 1, -14 } // ')' 363 | , { 106, 7, 14, 9, 1, -14 } // '*' 364 | , { 119, 7, 14, 9, 1, -14 } // '+' 365 | , { 132, 7, 14, 9, 1, -14 } // ',' 366 | , { 145, 10, 3, 18, 4, -12 } // '-' 367 | , { 149, 3, 3, 1, -1, -3 } // '.' 368 | , { 151, 7, 19, 9, 1, -19 } // '/' 369 | , { 169, 14, 21, 18, 2, -21 } // '0' 370 | , { 206, 4, 19, 18, 12, -20 } // '1' 371 | , { 216, 14, 21, 18, 2, -21 } // '2' 372 | , { 253, 13, 21, 18, 3, -21 } // '3' 373 | , { 288, 14, 19, 18, 2, -20 } // '4' 374 | , { 322, 14, 21, 18, 2, -21 } // '5' 375 | , { 359, 14, 21, 18, 2, -21 } // '6' 376 | , { 396, 14, 20, 18, 2, -21 } // '7' 377 | , { 431, 14, 21, 18, 2, -21 } // '8' 378 | , { 468, 14, 21, 18, 2, -21 } // '9' 379 | , { 505, 3, 11, 5, 1, -16 } // ':' 380 | , { 510, 7, 14, 9, 1, -14 } // ';' 381 | , { 523, 7, 14, 9, 1, -14 } // '<' 382 | , { 536, 7, 14, 9, 1, -14 } // '=' 383 | , { 549, 7, 14, 9, 1, -14 } // '>' 384 | , { 562, 7, 14, 9, 1, -14 } // '?' 385 | , { 575, 7, 14, 9, 1, -14 } // '@' 386 | , { 588, 14, 20, 18, 2, -21 } // 'A' 387 | , { 623, 14, 20, 18, 2, -20 } // 'B' 388 | , { 658, 13, 12, 18, 2, -12 } // 'C' 389 | , { 678, 14, 20, 18, 2, -20 } // 'D' 390 | , { 713, 13, 21, 18, 2, -21 } // 'E' 391 | , { 748, 13, 20, 18, 2, -21 } // 'F' 392 | , { 781, 14, 21, 18, 2, -21 } // 'G' 393 | , { 818, 14, 19, 18, 2, -20 } // 'H' 394 | , { 852, 4, 9, 18, 12, -10 } // 'I' 395 | , { 857, 14, 20, 18, 2, -20 } // 'J' 396 | , { 892, 14, 20, 18, 2, -21 } // 'K' 397 | , { 927, 13, 20, 18, 2, -20 } // 'L' 398 | , { 960, 14, 20, 18, 2, -21 } // 'M' 399 | , { 995, 14, 11, 18, 2, -12 } // 'N' 400 | , { 1015, 14, 12, 18, 2, -12 } // 'O' 401 | , { 1036, 14, 20, 18, 2, -21 } // 'P' 402 | , { 1071, 14, 20, 18, 2, -21 } // 'Q' 403 | , { 1106, 12, 11, 18, 2, -12 } // 'R' 404 | , { 1123, 14, 20, 18, 2, -20 } // 'S' 405 | , { 1158, 13, 20, 18, 2, -20 } // 'T' 406 | , { 1191, 14, 10, 18, 2, -10 } // 'U' 407 | , { 1209, 14, 20, 18, 2, -20 } // 'V' 408 | , { 1244, 14, 20, 18, 2, -20 } // 'W' 409 | , { 1279, 14, 19, 18, 2, -20 } // 'X' 410 | , { 1313, 14, 20, 18, 2, -20 } // 'Y' 411 | , { 1348, 14, 21, 18, 2, -21 } // 'Z' 412 | , { 1385, 7, 14, 9, 1, -14 } // '[' 413 | , { 1398, 7, 14, 9, 1, -14 } // '\' 414 | , { 1411, 7, 14, 9, 1, -14 } // ']' 415 | , { 1424, 7, 14, 9, 1, -14 } // '^' 416 | , { 1437, 7, 14, 9, 1, -14 } // '_' 417 | , { 1450, 7, 14, 9, 1, -14 } // '`' 418 | , { 1463, 14, 20, 18, 2, -21 } // 'a' 419 | , { 1498, 14, 20, 18, 2, -20 } // 'b' 420 | , { 1533, 13, 12, 18, 2, -12 } // 'c' 421 | , { 1553, 14, 20, 18, 2, -20 } // 'd' 422 | , { 1588, 13, 21, 18, 2, -21 } // 'e' 423 | , { 1623, 13, 20, 18, 2, -21 } // 'f' 424 | , { 1656, 14, 21, 18, 2, -21 } // 'g' 425 | , { 1693, 14, 19, 18, 2, -20 } // 'h' 426 | , { 1727, 4, 9, 18, 12, -10 } // 'i' 427 | , { 1732, 14, 20, 18, 2, -20 } // 'j' 428 | , { 1767, 14, 20, 18, 2, -21 } // 'k' 429 | , { 1802, 13, 20, 18, 2, -20 } // 'l' 430 | , { 1835, 14, 20, 18, 2, -21 } // 'm' 431 | , { 1870, 14, 11, 18, 2, -12 } // 'n' 432 | , { 1890, 14, 12, 18, 2, -12 } // 'o' 433 | , { 1911, 14, 20, 18, 2, -21 } // 'p' 434 | , { 1946, 14, 20, 18, 2, -21 } // 'q' 435 | , { 1981, 12, 11, 18, 2, -12 } // 'r' 436 | , { 1998, 14, 20, 18, 2, -20 } // 's' 437 | , { 2033, 13, 20, 18, 2, -20 } // 't' 438 | , { 2066, 14, 10, 18, 2, -10 } // 'u' 439 | , { 2084, 14, 20, 18, 2, -20 } // 'v' 440 | , { 2119, 14, 20, 18, 2, -20 } // 'w' 441 | , { 2154, 14, 19, 18, 2, -20 } // 'x' 442 | , { 2188, 14, 20, 18, 2, -20 } // 'y' 443 | , { 2223, 14, 21, 18, 2, -21 } // 'z' 444 | , { 2260, 7, 14, 9, 1, -14 } // '{' 445 | , { 2273, 7, 14, 9, 1, -14 } // '|' 446 | , { 2286, 7, 14, 9, 1, -14 } // '}' 447 | }; 448 | 449 | const GFXfont DSEG7_Classic_Bold_21 PROGMEM = { 450 | (uint8_t *)DSEG7_Classic_Bold_21Bitmaps, (GFXglyph *)DSEG7_Classic_Bold_21Glyphs, 0x20, 0x7E, 23 451 | }; 452 | 453 | const uint8_t DSEG7_Classic_Bold_11Bitmaps[] PROGMEM = { 454 | 0x00, 0x00, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 455 | 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 456 | 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0xE0, 0x00, 0x00, 0xF4, 0xA5, 0x29, 0x4A, 457 | 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 458 | 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF8, 0xC0, 0x10, 459 | 0x88, 0x44, 0x22, 0x10, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x00, 0x82, 0x82, 460 | 0x82, 0x82, 0x7C, 0x2A, 0x8A, 0xA0, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x7C, 461 | 0x80, 0x80, 0x80, 0x80, 0x7C, 0xF8, 0x08, 0x10, 0x20, 0x5F, 0x01, 0x02, 462 | 0x04, 0x0B, 0xE0, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x02, 0x02, 0x02, 463 | 0x02, 0x7C, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x7C, 464 | 0x7C, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7C, 465 | 0x82, 0x82, 0x82, 0x82, 0x00, 0x02, 0x02, 0x02, 0x02, 0x7C, 0x82, 0x82, 466 | 0x82, 0x82, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7C, 0x82, 0x82, 0x82, 467 | 0x82, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x7C, 0xC0, 0x04, 0x00, 0xF4, 0xA5, 468 | 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 469 | 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 470 | 0xA5, 0x29, 0x4A, 0x5E, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 0x82, 471 | 0x82, 0x82, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 472 | 0x7C, 0x7D, 0x02, 0x04, 0x08, 0x0F, 0x80, 0x00, 0x02, 0x02, 0x02, 0x02, 473 | 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7D, 0x02, 0x04, 0x08, 0x0F, 0xA0, 474 | 0x40, 0x81, 0x01, 0xF0, 0x7D, 0x02, 0x04, 0x08, 0x0F, 0xA0, 0x40, 0x81, 475 | 0x00, 0x7C, 0x80, 0x80, 0x80, 0x80, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 476 | 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0xAA, 0x00, 477 | 0x02, 0x02, 0x02, 0x02, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7C, 0x80, 478 | 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x01, 0x02, 0x04, 0x08, 479 | 0x00, 0x20, 0x40, 0x81, 0x01, 0xF0, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x00, 480 | 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 0x82, 481 | 0x82, 0x82, 0x7C, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x80, 0x80, 0x80, 482 | 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x7D, 483 | 0x02, 0x04, 0x08, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x02, 0x02, 484 | 0x02, 0x02, 0x7C, 0x01, 0x02, 0x04, 0x08, 0x0F, 0xA0, 0x40, 0x81, 0x01, 485 | 0xF0, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 0x82, 0x00, 486 | 0x82, 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 487 | 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 0x82, 488 | 0x82, 0x82, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x02, 0x02, 0x02, 0x02, 489 | 0x7C, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 490 | 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 491 | 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 492 | 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 493 | 0x82, 0x82, 0x82, 0x82, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 494 | 0x82, 0x82, 0x7C, 0x7D, 0x02, 0x04, 0x08, 0x0F, 0x80, 0x00, 0x02, 0x02, 495 | 0x02, 0x02, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7D, 0x02, 0x04, 0x08, 496 | 0x0F, 0xA0, 0x40, 0x81, 0x01, 0xF0, 0x7D, 0x02, 0x04, 0x08, 0x0F, 0xA0, 497 | 0x40, 0x81, 0x00, 0x7C, 0x80, 0x80, 0x80, 0x80, 0x00, 0x82, 0x82, 0x82, 498 | 0x82, 0x7C, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 499 | 0xAA, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 500 | 0x7C, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x01, 0x02, 501 | 0x04, 0x08, 0x00, 0x20, 0x40, 0x81, 0x01, 0xF0, 0x7C, 0x82, 0x82, 0x82, 502 | 0x82, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 503 | 0x82, 0x82, 0x82, 0x82, 0x7C, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x80, 504 | 0x80, 0x80, 0x80, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x02, 0x02, 0x02, 505 | 0x02, 0x7D, 0x02, 0x04, 0x08, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 506 | 0x02, 0x02, 0x02, 0x02, 0x7C, 0x01, 0x02, 0x04, 0x08, 0x0F, 0xA0, 0x40, 507 | 0x81, 0x01, 0xF0, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 508 | 0x82, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 0x82, 509 | 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 510 | 0x82, 0x82, 0x82, 0x82, 0x00, 0x82, 0x82, 0x82, 0x82, 0x7C, 0x02, 0x02, 511 | 0x02, 0x02, 0x7C, 0x7C, 0x02, 0x02, 0x02, 0x02, 0x00, 0x80, 0x80, 0x80, 512 | 0x80, 0x7C, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 0xF4, 0xA5, 0x29, 0x4A, 0x5E, 513 | 0xF4, 0xA5, 0x29, 0x4A, 0x5E 514 | }; 515 | 516 | const GFXglyph DSEG7_Classic_Bold_11Glyphs[] PROGMEM = { 517 | { 0, 1, 1, 3, 0, 0 } // ' ' 518 | , { 1, 1, 1, 10, 0, 0 } // '!' 519 | , { 2, 5, 8, 5, 0, -8 } // '"' 520 | , { 7, 5, 8, 5, 0, -8 } // '#' 521 | , { 12, 5, 8, 5, 0, -8 } // '$' 522 | , { 17, 5, 8, 5, 0, -8 } // '%' 523 | , { 22, 5, 8, 5, 0, -8 } // '&' 524 | , { 27, 5, 8, 5, 0, -11 } // ''' 525 | , { 32, 5, 8, 5, 0, -8 } // '(' 526 | , { 37, 5, 8, 5, 0, -8 } // ')' 527 | , { 42, 5, 8, 5, 0, -8 } // '*' 528 | , { 47, 5, 8, 5, 0, -8 } // '+' 529 | , { 52, 5, 8, 5, 0, -8 } // ',' 530 | , { 57, 6, 1, 10, 2, -6 } // '-' 531 | , { 58, 3, 1, 1, -1, -1 } // '.' 532 | , { 59, 5, 8, 5, 0, -8 } // '/' 533 | , { 64, 8, 11, 10, 1, -11 } // '0' 534 | , { 75, 2, 10, 10, 7, -11 } // '1' 535 | , { 78, 8, 11, 10, 1, -11 } // '2' 536 | , { 89, 7, 11, 10, 2, -11 } // '3' 537 | , { 99, 8, 10, 10, 1, -11 } // '4' 538 | , { 109, 8, 11, 10, 1, -11 } // '5' 539 | , { 120, 8, 11, 10, 1, -11 } // '6' 540 | , { 131, 8, 10, 10, 1, -11 } // '7' 541 | , { 141, 8, 11, 10, 1, -11 } // '8' 542 | , { 152, 8, 11, 10, 1, -11 } // '9' 543 | , { 163, 3, 6, 3, 0, -8 } // ':' 544 | , { 166, 5, 8, 5, 0, -8 } // ';' 545 | , { 171, 5, 8, 5, 0, -8 } // '<' 546 | , { 176, 5, 8, 5, 0, -8 } // '=' 547 | , { 181, 5, 8, 5, 0, -8 } // '>' 548 | , { 186, 5, 8, 5, 0, -8 } // '?' 549 | , { 191, 5, 8, 5, 0, -8 } // '@' 550 | , { 196, 8, 10, 10, 1, -11 } // 'A' 551 | , { 206, 8, 11, 10, 1, -11 } // 'B' 552 | , { 217, 7, 6, 10, 1, -6 } // 'C' 553 | , { 223, 8, 11, 10, 1, -11 } // 'D' 554 | , { 234, 7, 11, 10, 1, -11 } // 'E' 555 | , { 244, 7, 10, 10, 1, -11 } // 'F' 556 | , { 253, 8, 11, 10, 1, -11 } // 'G' 557 | , { 264, 8, 10, 10, 1, -11 } // 'H' 558 | , { 274, 2, 4, 10, 7, -5 } // 'I' 559 | , { 275, 8, 11, 10, 1, -11 } // 'J' 560 | , { 286, 8, 10, 10, 1, -11 } // 'K' 561 | , { 296, 7, 11, 10, 1, -11 } // 'L' 562 | , { 306, 8, 10, 10, 1, -11 } // 'M' 563 | , { 316, 8, 5, 10, 1, -6 } // 'N' 564 | , { 321, 8, 6, 10, 1, -6 } // 'O' 565 | , { 327, 8, 10, 10, 1, -11 } // 'P' 566 | , { 337, 8, 10, 10, 1, -11 } // 'Q' 567 | , { 347, 7, 5, 10, 1, -6 } // 'R' 568 | , { 352, 8, 11, 10, 1, -11 } // 'S' 569 | , { 363, 7, 11, 10, 1, -11 } // 'T' 570 | , { 373, 8, 5, 10, 1, -5 } // 'U' 571 | , { 378, 8, 11, 10, 1, -11 } // 'V' 572 | , { 389, 8, 11, 10, 1, -11 } // 'W' 573 | , { 400, 8, 10, 10, 1, -11 } // 'X' 574 | , { 410, 8, 11, 10, 1, -11 } // 'Y' 575 | , { 421, 8, 11, 10, 1, -11 } // 'Z' 576 | , { 432, 5, 8, 5, 0, -8 } // '[' 577 | , { 437, 5, 8, 5, 0, -8 } // '\' 578 | , { 442, 5, 8, 5, 0, -8 } // ']' 579 | , { 447, 5, 8, 5, 0, -8 } // '^' 580 | , { 452, 5, 8, 5, 0, -8 } // '_' 581 | , { 457, 5, 8, 5, 0, -8 } // '`' 582 | , { 462, 8, 10, 10, 1, -11 } // 'a' 583 | , { 472, 8, 11, 10, 1, -11 } // 'b' 584 | , { 483, 7, 6, 10, 1, -6 } // 'c' 585 | , { 489, 8, 11, 10, 1, -11 } // 'd' 586 | , { 500, 7, 11, 10, 1, -11 } // 'e' 587 | , { 510, 7, 10, 10, 1, -11 } // 'f' 588 | , { 519, 8, 11, 10, 1, -11 } // 'g' 589 | , { 530, 8, 10, 10, 1, -11 } // 'h' 590 | , { 540, 2, 4, 10, 7, -5 } // 'i' 591 | , { 541, 8, 11, 10, 1, -11 } // 'j' 592 | , { 552, 8, 10, 10, 1, -11 } // 'k' 593 | , { 562, 7, 11, 10, 1, -11 } // 'l' 594 | , { 572, 8, 10, 10, 1, -11 } // 'm' 595 | , { 582, 8, 5, 10, 1, -6 } // 'n' 596 | , { 587, 8, 6, 10, 1, -6 } // 'o' 597 | , { 593, 8, 10, 10, 1, -11 } // 'p' 598 | , { 603, 8, 10, 10, 1, -11 } // 'q' 599 | , { 613, 7, 5, 10, 1, -6 } // 'r' 600 | , { 618, 8, 11, 10, 1, -11 } // 's' 601 | , { 629, 7, 11, 10, 1, -11 } // 't' 602 | , { 639, 8, 5, 10, 1, -5 } // 'u' 603 | , { 644, 8, 11, 10, 1, -11 } // 'v' 604 | , { 655, 8, 11, 10, 1, -11 } // 'w' 605 | , { 666, 8, 10, 10, 1, -11 } // 'x' 606 | , { 676, 8, 11, 10, 1, -11 } // 'y' 607 | , { 687, 8, 11, 10, 1, -11 } // 'z' 608 | , { 698, 5, 8, 5, 0, -8 } // '{' 609 | , { 703, 5, 8, 5, 0, -8 } // '|' 610 | , { 708, 5, 8, 5, 0, -8 } // '}' 611 | }; 612 | 613 | const GFXfont DSEG7_Classic_Bold_11 PROGMEM = { 614 | (uint8_t *)DSEG7_Classic_Bold_11Bitmaps, (GFXglyph *)DSEG7_Classic_Bold_11Glyphs, 0x20, 0x7E, 12 615 | }; 616 | 617 | const uint8_t DSEG7_Classic_Bold_18Bitmaps[] PROGMEM = { 618 | 0x00, 0x00, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 619 | 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 620 | 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0x00, 0xF3, 0x93, 0x97, 0xF6, 0x06, 0x0C, 621 | 0x0C, 0x18, 0x18, 0x30, 0x70, 0x60, 0xDE, 0xD2, 0xD2, 0x9E, 0x00, 0xFA, 622 | 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xF9, 0x9F, 0xFA, 0x28, 623 | 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 624 | 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 625 | 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 626 | 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0x7F, 0x1F, 0xC0, 0xD8, 0x04, 627 | 0x30, 0xC3, 0x0C, 0x61, 0x86, 0x30, 0xC3, 0x18, 0x63, 0x8C, 0x20, 0x7F, 628 | 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 629 | 0x28, 0x02, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 630 | 0xA7, 0xFC, 0x5B, 0x6D, 0xB2, 0x5B, 0x6D, 0xB2, 0x7F, 0xC3, 0xFA, 0x00, 631 | 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x3F, 0xAB, 0xF8, 0xC0, 632 | 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xBF, 0x87, 0xFC, 0xFF, 633 | 0x8F, 0xE8, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x7F, 0x4F, 634 | 0xE8, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x7F, 0x5F, 0xF0, 635 | 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 636 | 0x3F, 0xA0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x02, 637 | 0x7F, 0xCB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 638 | 0xBF, 0x83, 0xFA, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 639 | 0x3F, 0xA7, 0xFC, 0x7F, 0xCB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 640 | 0xC0, 0x0C, 0x00, 0xBF, 0x8B, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 641 | 0xC0, 0x6C, 0x06, 0xBF, 0xA7, 0xFC, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 642 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x02, 0x00, 0x60, 0x06, 643 | 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x20, 0x7F, 0xCB, 0xFA, 0xC0, 644 | 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xAB, 0xFA, 0xC0, 645 | 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xA7, 0xFC, 0x7F, 646 | 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 647 | 0xA3, 0xFA, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x3F, 648 | 0xA7, 0xFC, 0x9A, 0x00, 0x00, 0xD8, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 649 | 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 650 | 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 651 | 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 652 | 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 653 | 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 654 | 0xBF, 0xAB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 655 | 0x80, 0x20, 0x80, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 656 | 0x0B, 0xF8, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 657 | 0x6B, 0xFA, 0x7F, 0xC0, 0x3F, 0x97, 0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 658 | 0x30, 0x06, 0x00, 0xBF, 0x8F, 0xF8, 0x00, 0x20, 0x06, 0x00, 0x60, 0x06, 659 | 0x00, 0x60, 0x06, 0x00, 0x63, 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 660 | 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x7F, 0xD7, 0xF3, 0x00, 661 | 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x97, 0xF3, 0x00, 0x60, 662 | 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x8F, 0xF8, 0x7F, 0xD7, 0xF3, 663 | 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x97, 0xF3, 0x00, 664 | 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0x80, 0x00, 0x7F, 0xCB, 0xF8, 665 | 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x80, 0x08, 0x02, 666 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xA7, 0xFC, 667 | 0x80, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0B, 0xF8, 668 | 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x68, 0x02, 669 | 0x5B, 0x6D, 0xB2, 0x00, 0x20, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 670 | 0x00, 0x60, 0x02, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 671 | 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x7F, 0xCB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 672 | 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xBF, 0x8B, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 673 | 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x80, 0x18, 0x03, 0x00, 0x60, 674 | 0x0C, 0x01, 0x80, 0x30, 0x04, 0x00, 0x80, 0x18, 0x03, 0x00, 0x60, 0x0C, 675 | 0x01, 0x80, 0x30, 0x05, 0xFC, 0x7F, 0xC0, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 676 | 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x28, 0x02, 0xC0, 0x6C, 677 | 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x3F, 0x8B, 0xFA, 678 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x3F, 679 | 0x8B, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 680 | 0xA7, 0xFC, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 681 | 0x6C, 0x06, 0xBF, 0xAB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 682 | 0x0C, 0x00, 0x80, 0x00, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 683 | 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xA3, 0xFA, 0x00, 0x60, 0x06, 0x00, 0x60, 684 | 0x06, 0x00, 0x60, 0x06, 0x00, 0x20, 0x3F, 0x97, 0xF3, 0x00, 0x60, 0x0C, 685 | 0x01, 0x80, 0x30, 0x06, 0x00, 0x80, 0x00, 0x80, 0x0C, 0x00, 0xC0, 0x0C, 686 | 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0B, 0xF8, 0x3F, 0xA0, 0x06, 0x00, 0x60, 687 | 0x06, 0x00, 0x60, 0x06, 0x00, 0x63, 0xFA, 0x7F, 0xC0, 0x80, 0x18, 0x03, 688 | 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x05, 0xFC, 0xBF, 0x98, 0x03, 0x00, 689 | 0x60, 0x0C, 0x01, 0x80, 0x30, 0x05, 0xFC, 0x7F, 0xC0, 0x80, 0x2C, 0x06, 690 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x80, 691 | 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x68, 0x02, 0x80, 692 | 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 693 | 0xC0, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 694 | 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 695 | 0xFA, 0x7F, 0xC0, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 696 | 0xC0, 0x6B, 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 697 | 0xC0, 0x68, 0x02, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 698 | 0xC0, 0x6B, 0xFA, 0x3F, 0xA0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 699 | 0x00, 0x63, 0xFA, 0x7F, 0xC0, 0x7F, 0xC3, 0xFA, 0x00, 0x60, 0x06, 0x00, 700 | 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x28, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 701 | 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xBF, 0x87, 0xFC, 0xFA, 0x28, 0xA2, 0x8A, 702 | 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 703 | 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 704 | 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 705 | 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 706 | 0x28, 0xBE, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 707 | 0x6C, 0x06, 0xBF, 0xAB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 708 | 0x6C, 0x06, 0x80, 0x20, 0x80, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 709 | 0x00, 0xC0, 0x0B, 0xF8, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 710 | 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x3F, 0x97, 0xF3, 0x00, 0x60, 0x0C, 711 | 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x8F, 0xF8, 0x00, 0x20, 0x06, 0x00, 712 | 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x63, 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 713 | 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x7F, 0xD7, 714 | 0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x97, 0xF3, 715 | 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x8F, 0xF8, 0x7F, 716 | 0xD7, 0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xBF, 0x97, 717 | 0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0x80, 0x00, 0x7F, 718 | 0xCB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x80, 719 | 0x08, 0x02, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 720 | 0xA7, 0xFC, 0x80, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 721 | 0x0B, 0xF8, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 722 | 0x68, 0x02, 0x5B, 0x6D, 0xB2, 0x00, 0x20, 0x06, 0x00, 0x60, 0x06, 0x00, 723 | 0x60, 0x06, 0x00, 0x60, 0x02, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 724 | 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x7F, 0xCB, 0xF8, 0xC0, 0x0C, 725 | 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xBF, 0x8B, 0xFA, 0xC0, 0x6C, 726 | 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x80, 0x18, 0x03, 727 | 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x04, 0x00, 0x80, 0x18, 0x03, 0x00, 728 | 0x60, 0x0C, 0x01, 0x80, 0x30, 0x05, 0xFC, 0x7F, 0xC0, 0x7F, 0xCB, 0xFA, 729 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x28, 0x02, 730 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 0x20, 0x3F, 731 | 0x8B, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0x80, 732 | 0x20, 0x3F, 0x8B, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 733 | 0x06, 0xBF, 0xA7, 0xFC, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 734 | 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xAB, 0xF8, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 735 | 0x00, 0xC0, 0x0C, 0x00, 0x80, 0x00, 0x7F, 0xCB, 0xFA, 0xC0, 0x6C, 0x06, 736 | 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xBF, 0xA3, 0xFA, 0x00, 0x60, 0x06, 737 | 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x20, 0x3F, 0x97, 0xF3, 0x00, 738 | 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0x80, 0x00, 0x80, 0x0C, 0x00, 739 | 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0B, 0xF8, 0x3F, 0xA0, 0x06, 740 | 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x63, 0xFA, 0x7F, 0xC0, 0x80, 741 | 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x05, 0xFC, 0xBF, 0x98, 742 | 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x05, 0xFC, 0x7F, 0xC0, 0x80, 743 | 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x7F, 744 | 0xC0, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x68, 745 | 0x02, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6B, 746 | 0xFA, 0x7F, 0xC0, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 747 | 0xC0, 0x6B, 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 748 | 0xC0, 0x6B, 0xFA, 0x7F, 0xC0, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 749 | 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0xBF, 0xAC, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 750 | 0x6C, 0x06, 0xC0, 0x68, 0x02, 0x80, 0x2C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 751 | 0x6C, 0x06, 0xC0, 0x6B, 0xFA, 0x3F, 0xA0, 0x06, 0x00, 0x60, 0x06, 0x00, 752 | 0x60, 0x06, 0x00, 0x63, 0xFA, 0x7F, 0xC0, 0x7F, 0xC3, 0xFA, 0x00, 0x60, 753 | 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x28, 0x00, 0xC0, 0x0C, 754 | 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xBF, 0x87, 0xFC, 0xFA, 0x28, 755 | 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 756 | 0xA2, 0x8A, 0x28, 0xBE, 0xFA, 0x28, 0xA2, 0x8A, 0x28, 0xA2, 0x8A, 0x28, 757 | 0xBE 758 | }; 759 | 760 | const GFXglyph DSEG7_Classic_Bold_18Glyphs[] PROGMEM = { 761 | { 0, 1, 1, 5, 0, 0 } // ' ' 762 | ,{ 1, 1, 1, 16, 0, 0 } // '!' 763 | ,{ 2, 6, 12, 8, 1, -12 } // '"' 764 | ,{ 11, 6, 12, 8, 1, -12 } // '#' 765 | ,{ 20, 6, 12, 8, 1, -12 } // '$' 766 | ,{ 29, 8, 18, 8, 0, -17 } // '%' 767 | ,{ 47, 6, 12, 8, 1, -12 } // '&' 768 | ,{ 56, 4, 4, 8, 0, -18 } // ''' 769 | ,{ 58, 6, 12, 8, 1, -12 } // '(' 770 | ,{ 67, 6, 12, 8, 1, -12 } // ')' 771 | ,{ 76, 6, 12, 8, 1, -12 } // '*' 772 | ,{ 85, 6, 12, 8, 1, -12 } // '+' 773 | ,{ 94, 6, 12, 8, 1, -12 } // ',' 774 | ,{ 103, 10, 2, 16, 3, -10 } // '-' 775 | ,{ 106, 3, 2, 1, -1, -2 } // '.' 776 | ,{ 107, 6, 16, 8, 1, -16 } // '/' 777 | ,{ 119, 12, 18, 16, 2, -18 } // '0' 778 | ,{ 146, 3, 16, 16, 11, -17 } // '1' 779 | ,{ 152, 12, 18, 16, 2, -18 } // '2' 780 | ,{ 179, 11, 18, 16, 3, -18 } // '3' 781 | ,{ 204, 12, 16, 16, 2, -17 } // '4' 782 | ,{ 228, 12, 18, 16, 2, -18 } // '5' 783 | ,{ 255, 12, 18, 16, 2, -18 } // '6' 784 | ,{ 282, 12, 17, 16, 2, -18 } // '7' 785 | ,{ 308, 12, 18, 16, 2, -18 } // '8' 786 | ,{ 335, 12, 18, 16, 2, -18 } // '9' 787 | ,{ 362, 3, 10, 5, 1, -14 } // ':' 788 | ,{ 366, 6, 12, 8, 1, -12 } // ';' 789 | ,{ 375, 6, 12, 8, 1, -12 } // '<' 790 | ,{ 384, 6, 12, 8, 1, -12 } // '=' 791 | ,{ 393, 6, 12, 8, 1, -12 } // '>' 792 | ,{ 402, 6, 12, 8, 1, -12 } // '?' 793 | ,{ 411, 6, 12, 8, 1, -12 } // '@' 794 | ,{ 420, 12, 17, 16, 2, -18 } // 'A' 795 | ,{ 446, 12, 17, 16, 2, -17 } // 'B' 796 | ,{ 472, 11, 10, 16, 2, -10 } // 'C' 797 | ,{ 486, 12, 17, 16, 2, -17 } // 'D' 798 | ,{ 512, 11, 18, 16, 2, -18 } // 'E' 799 | ,{ 537, 11, 17, 16, 2, -18 } // 'F' 800 | ,{ 561, 12, 18, 16, 2, -18 } // 'G' 801 | ,{ 588, 12, 16, 16, 2, -17 } // 'H' 802 | ,{ 612, 3, 8, 16, 11, -9 } // 'I' 803 | ,{ 615, 12, 17, 16, 2, -17 } // 'J' 804 | ,{ 641, 12, 17, 16, 2, -18 } // 'K' 805 | ,{ 667, 11, 17, 16, 2, -17 } // 'L' 806 | ,{ 691, 12, 17, 16, 2, -18 } // 'M' 807 | ,{ 717, 12, 9, 16, 2, -10 } // 'N' 808 | ,{ 731, 12, 10, 16, 2, -10 } // 'O' 809 | ,{ 746, 12, 17, 16, 2, -18 } // 'P' 810 | ,{ 772, 12, 17, 16, 2, -18 } // 'Q' 811 | ,{ 798, 11, 9, 16, 2, -10 } // 'R' 812 | ,{ 811, 12, 17, 16, 2, -17 } // 'S' 813 | ,{ 837, 11, 17, 16, 2, -17 } // 'T' 814 | ,{ 861, 12, 9, 16, 2, -9 } // 'U' 815 | ,{ 875, 12, 17, 16, 2, -17 } // 'V' 816 | ,{ 901, 12, 17, 16, 2, -17 } // 'W' 817 | ,{ 927, 12, 16, 16, 2, -17 } // 'X' 818 | ,{ 951, 12, 17, 16, 2, -17 } // 'Y' 819 | ,{ 977, 12, 18, 16, 2, -18 } // 'Z' 820 | ,{ 1004, 6, 12, 8, 1, -12 } // '[' 821 | ,{ 1013, 6, 12, 8, 1, -12 } // '\' 822 | ,{ 1022, 6, 12, 8, 1, -12 } // ']' 823 | ,{ 1031, 6, 12, 8, 1, -12 } // '^' 824 | ,{ 1040, 6, 12, 8, 1, -12 } // '_' 825 | ,{ 1049, 6, 12, 8, 1, -12 } // '`' 826 | ,{ 1058, 12, 17, 16, 2, -18 } // 'a' 827 | ,{ 1084, 12, 17, 16, 2, -17 } // 'b' 828 | ,{ 1110, 11, 10, 16, 2, -10 } // 'c' 829 | ,{ 1124, 12, 17, 16, 2, -17 } // 'd' 830 | ,{ 1150, 11, 18, 16, 2, -18 } // 'e' 831 | ,{ 1175, 11, 17, 16, 2, -18 } // 'f' 832 | ,{ 1199, 12, 18, 16, 2, -18 } // 'g' 833 | ,{ 1226, 12, 16, 16, 2, -17 } // 'h' 834 | ,{ 1250, 3, 8, 16, 11, -9 } // 'i' 835 | ,{ 1253, 12, 17, 16, 2, -17 } // 'j' 836 | ,{ 1279, 12, 17, 16, 2, -18 } // 'k' 837 | ,{ 1305, 11, 17, 16, 2, -17 } // 'l' 838 | ,{ 1329, 12, 17, 16, 2, -18 } // 'm' 839 | ,{ 1355, 12, 9, 16, 2, -10 } // 'n' 840 | ,{ 1369, 12, 10, 16, 2, -10 } // 'o' 841 | ,{ 1384, 12, 17, 16, 2, -18 } // 'p' 842 | ,{ 1410, 12, 17, 16, 2, -18 } // 'q' 843 | ,{ 1436, 11, 9, 16, 2, -10 } // 'r' 844 | ,{ 1449, 12, 17, 16, 2, -17 } // 's' 845 | ,{ 1475, 11, 17, 16, 2, -17 } // 't' 846 | ,{ 1499, 12, 9, 16, 2, -9 } // 'u' 847 | ,{ 1513, 12, 17, 16, 2, -17 } // 'v' 848 | ,{ 1539, 12, 17, 16, 2, -17 } // 'w' 849 | ,{ 1565, 12, 16, 16, 2, -17 } // 'x' 850 | ,{ 1589, 12, 17, 16, 2, -17 } // 'y' 851 | ,{ 1615, 12, 18, 16, 2, -18 } // 'z' 852 | ,{ 1642, 6, 12, 8, 1, -12 } // '{' 853 | ,{ 1651, 6, 12, 8, 1, -12 } // '|' 854 | ,{ 1660, 6, 12, 8, 1, -12 } // '}' 855 | }; 856 | 857 | const GFXfont DSEG7_Classic_Bold_18 PROGMEM = { 858 | (uint8_t *)DSEG7_Classic_Bold_18Bitmaps, (GFXglyph *)DSEG7_Classic_Bold_18Glyphs, 0x20, 0x7E, 20 859 | }; 860 | 861 | --------------------------------------------------------------------------------