Compare commits

...

10 Commits

Author SHA1 Message Date
135
fc069bd63e WIP
прошивка по записи RTC для старых часов rally
2024-07-28 20:57:14 +03:00
135
3f97f3f02a WIP
попытка дебажить PPS/SQW.
работа на SWSerial (8,9) вывод в консоль Serial и на LCD
2024-07-27 12:36:14 +03:00
135
7cccb3306c WIP 2024-07-25 10:14:40 +03:00
135
1ae6e04559 WIP
рабочий код. отображение часов согласно часового пояса MSK на LCD. GPS(19200) и RTC работают.
2024-07-22 01:53:34 +03:00
135
b56f705f05 WIP
адаптация. в Serial выводятся PPS/SQW и на LCD печатается время
2024-07-21 20:30:17 +03:00
hdrlux
43a7b6307c Update GPS_com.cpp 2023-08-01 19:05:35 +02:00
hdrlux
6add396b9f Update GPS_RTC_Clock-main.ino 2023-07-27 19:54:08 +02:00
hdrlux
109fb6adb3 Rename GPS_RTC_Clock_33.ino to GPS_RTC_Clock-main.ino 2023-07-24 10:52:22 +02:00
hdrlux
360e231008 Create README.md 2023-07-24 10:38:42 +02:00
hdrlux
db4934d1bc Add files via upload 2023-07-24 10:38:11 +02:00
20 changed files with 1442 additions and 0 deletions

168
Font_Chrono1.h Normal file
View File

@@ -0,0 +1,168 @@
/*
*
* Font_Chrono1
*
* created with FontCreator
* written by F. Maximilian Thiele
*
* http://www.apetech.de/fontCreator
* me@apetech.de
*
* File Name : Font_Chrono1.h
* Date : 10.01.2012
* Font size in bytes : 12422
* Font width : 10
* Font height : 16
* Font first char : 32
* Font last char : 128
* Font used chars : 96
*
* The font data are defined as
*
* struct _FONT_ {
* uint16_t font_Size_in_Bytes_over_all_included_Size_it_self;
* uint8_t font_Width_in_Pixel_for_fixed_drawing;
* uint8_t font_Height_in_Pixel_for_all_characters;
* unit8_t font_First_Char;
* uint8_t font_Char_Count;
*
* uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1];
* // for each character the separate width in pixels,
* // characters < 128 have an implicit virtual right empty row
*
* uint8_t font_data[];
* // bit field of all characters
*/
//#include <inttypes.h>
#ifdef __AVR__
#include <avr/pgmspace.h>
#else
#define PROGMEM
#endif
#ifndef Font_CHRONO1_H
#define Font_CHRONO1_H
#define Font_CHRONO1_WIDTH 10
#define Font_CHRONO1_HEIGHT 16
static const uint8_t Font_Chrono1[] PROGMEM = {
0x30, 0x86, // size
0x0A, // width
0x10, // height
0x20, // first char
0x60, // char count
// char widths
0x00, 0x03, 0x07, 0x0B, 0x09, 0x0E, 0x0B, 0x03, 0x05, 0x05,
0x06, 0x09, 0x03, 0x05, 0x03, 0x04, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x03, 0x09, 0x08,
0x09, 0x08, 0x0C, 0x0C, 0x09, 0x09, 0x09, 0x09, 0x08, 0x0A,
0x0A, 0x03, 0x09, 0x0C, 0x08, 0x0C, 0x0A, 0x0A, 0x09, 0x0A,
0x0A, 0x09, 0x0B, 0x0A, 0x0C, 0x10, 0x0C, 0x0B, 0x09, 0x05,
0x04, 0x05, 0x08, 0x08, 0x03, 0x09, 0x09, 0x09, 0x09, 0x09,
0x06, 0x09, 0x09, 0x03, 0x04, 0x0A, 0x03, 0x0D, 0x09, 0x09,
0x09, 0x09, 0x06, 0x08, 0x06, 0x09, 0x09, 0x0F, 0x0B, 0x09,
0x07, 0x06, 0x02, 0x06, 0x09, 0x08,
// font data
0xFE, 0xFE, 0xFE, 0x1D, 0x1D, 0x1D, // 33
0x1E, 0x1E, 0x1E, 0x00, 0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34
0x30, 0x30, 0xF0, 0xFE, 0x3E, 0x30, 0x30, 0xF0, 0xFE, 0x3E, 0x30, 0x06, 0x1E, 0x1F, 0x07, 0x06, 0x06, 0x1E, 0x1F, 0x07, 0x06, 0x06, // 35
0x38, 0x7C, 0xFE, 0xE6, 0xFF, 0xC6, 0xCE, 0x8C, 0x0C, 0x04, 0x0C, 0x1C, 0x18, 0x3F, 0x19, 0x1F, 0x0F, 0x07, // 36
0x3C, 0x7E, 0x42, 0x42, 0x7E, 0x3C, 0x80, 0x60, 0x10, 0x8C, 0x82, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0C, 0x02, 0x01, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x1F, 0x0F, // 37
0x00, 0x80, 0x9C, 0xFE, 0xFE, 0xE6, 0xBE, 0x3E, 0x9C, 0x80, 0x80, 0x07, 0x0F, 0x1F, 0x19, 0x18, 0x19, 0x1F, 0x0F, 0x0F, 0x1F, 0x1D, // 38
0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, // 39
0xE0, 0xF8, 0xFC, 0x1E, 0x02, 0x0F, 0x3F, 0x7F, 0xF0, 0x80, // 40
0x02, 0x1E, 0xFC, 0xF8, 0xE0, 0x80, 0xF0, 0x7F, 0x3F, 0x0F, // 41
0x08, 0x68, 0x3E, 0x3E, 0x68, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 42
0xC0, 0xC0, 0xC0, 0xF8, 0xF8, 0xF8, 0xC0, 0xC0, 0xC0, 0x01, 0x01, 0x01, 0x0F, 0x0F, 0x0F, 0x01, 0x01, 0x01, // 43
0x00, 0x00, 0x00, 0xDC, 0x7C, 0x3C, // 44
0x80, 0x80, 0x80, 0x80, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, // 45
0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, // 46
0x00, 0x80, 0x78, 0x06, 0x18, 0x07, 0x00, 0x00, // 47
0xFC, 0xFE, 0x07, 0x03, 0x03, 0x07, 0xFE, 0xFC, 0x3F, 0x7F, 0xE0, 0xC0, 0xC0, 0xE0, 0x7F, 0x3F, // 48 (0)
0x0C, 0x0E, 0x06, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, // 49 (1)
0x0E, 0x0F, 0x03, 0x03, 0x83, 0xC3, 0xFF, 0x7E, 0xF8, 0xFC, 0xCE, 0xC7, 0xC3, 0xC1, 0xC0, 0xC0, // 50 (2)
0x0C, 0x0E, 0x07, 0x83, 0x83, 0xC7, 0xFE, 0x7C, 0x38, 0x78, 0xE0, 0xC1, 0xC1, 0xE3, 0x7F, 0x3E, // 51 (3)
0xE0, 0xF8, 0x1C, 0x0E, 0xFF, 0xFF, 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, // 52 (4)
0x7F, 0x7F, 0x63, 0x63, 0x63, 0xE3, 0xE3, 0xC3, 0x78, 0xF8, 0xE0, 0xC0, 0xC0, 0xE0, 0xFF, 0x7F, // 53 (5)
0xFC, 0xFE, 0x87, 0x83, 0x83, 0x87, 0x1E, 0x1C, 0x3F, 0x7F, 0xE3, 0xC1, 0xC1, 0xE3, 0x7F, 0x3E, // 54 (6)
0x1E, 0x1F, 0x03, 0x03, 0x83, 0xE3, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x07, 0x00, 0x00, // 55 (7)
0x1C, 0xBE, 0xE7, 0xC3, 0xC3, 0xE7, 0xBE, 0x1C, 0x3F, 0x7F, 0xE1, 0xC0, 0xC0, 0xE1, 0x7F, 0x3F, // 56 (8)
0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0x67, 0xFE, 0xFC, 0x30, 0x70, 0xE0, 0xC0, 0xC0, 0xE0, 0x7F, 0x3F, // 57 (9)
0x00, 0x30, 0x30, 0x00, 0x00, 0x0C, 0x0C, 0x00, // 58 (:)
0x70, 0x70, 0x70, 0xDC, 0x7C, 0x3C, // 59
0xE0, 0xE0, 0xE0, 0xF0, 0x70, 0x70, 0x70, 0x38, 0x38, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x0E, 0x0E, // 60
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, // 61
0x38, 0x38, 0x70, 0x70, 0x70, 0xF0, 0xE0, 0xE0, 0xE0, 0x0E, 0x0E, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, // 62
0x18, 0x1C, 0x9E, 0xC6, 0xE6, 0xFE, 0x7C, 0x38, 0x00, 0x00, 0x1D, 0x1D, 0x1D, 0x00, 0x00, 0x00, // 63
0xE0, 0x18, 0xC4, 0xF4, 0x3A, 0x0A, 0x0A, 0xF2, 0xFA, 0x7C, 0x08, 0xF0, 0x07, 0x18, 0x27, 0x2F, 0x48, 0x48, 0x4C, 0x4F, 0x4F, 0x28, 0x36, 0x11, // 64
0x00, 0x80, 0xE0, 0xF8, 0xFE, 0x1E, 0xFE, 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x1C, 0x1F, 0x0F, 0x07, 0x06, 0x06, 0x06, 0x07, 0x0F, 0x1F, 0x1C, 0x10, // 65
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xFE, 0xBC, 0x98, 0x00, 0x1F, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x1F, 0x0F, 0x07, // 66
0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x0E, 0x1E, 0x1C, 0x08, 0x03, 0x0F, 0x1F, 0x1C, 0x18, 0x1C, 0x1F, 0x0E, 0x06, // 67
0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x0E, 0xFE, 0xFC, 0xF0, 0x1F, 0x1F, 0x1F, 0x18, 0x18, 0x1C, 0x1F, 0x0F, 0x03, // 68
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x06, 0x1F, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 69
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x06, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, // 70
0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0xC6, 0xCE, 0xDE, 0xDC, 0xC8, 0x03, 0x0F, 0x0F, 0x1C, 0x18, 0x18, 0x1C, 0x1F, 0x0F, 0x0F, // 71
0xFE, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 72
0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, // 73
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x06, 0x0F, 0x1F, 0x1C, 0x18, 0x18, 0x1F, 0x0F, 0x07, // 74
0xFE, 0xFE, 0xFE, 0xC0, 0xE0, 0xF0, 0xF8, 0xDC, 0x0E, 0x06, 0x02, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1F, 0x1E, 0x18, 0x10, // 75
0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, // 76
0xFE, 0xFE, 0xFE, 0x3E, 0xF8, 0x80, 0x80, 0xF8, 0x3E, 0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, 0x00, 0x03, 0x1F, 0x1F, 0x03, 0x00, 0x1F, 0x1F, 0x1F, // 77
0xFE, 0xFE, 0xFE, 0x7C, 0xF0, 0xE0, 0x80, 0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, 0x00, 0x01, 0x03, 0x0F, 0x1F, 0x1F, 0x1F, // 78
0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x06, 0x0E, 0xFC, 0xFC, 0xF0, 0x03, 0x0F, 0x0F, 0x1C, 0x18, 0x18, 0x1C, 0x0F, 0x0F, 0x03, // 79
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x3C, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 80
0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x06, 0x0E, 0xFC, 0xFC, 0xF0, 0x03, 0x0F, 0x0F, 0x1C, 0x18, 0x1E, 0x1C, 0x1F, 0x1F, 0x33, // 81
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x3C, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x1C, 0x10, // 82
0x38, 0x7C, 0xFE, 0xE6, 0xE6, 0xEE, 0xDE, 0xDC, 0x98, 0x06, 0x0E, 0x1E, 0x1C, 0x18, 0x19, 0x1F, 0x0F, 0x07, // 83
0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, // 84
0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x07, 0x0F, 0x1F, 0x1C, 0x18, 0x18, 0x1C, 0x1F, 0x0F, 0x07, // 85
0x1E, 0xFE, 0xFC, 0xF0, 0x80, 0x00, 0x80, 0xF0, 0xFC, 0xFE, 0x1E, 0x02, 0x00, 0x00, 0x03, 0x1F, 0x1F, 0x1C, 0x1F, 0x1F, 0x03, 0x00, 0x00, 0x00, // 86
0xFE, 0xFE, 0xF8, 0x00, 0x80, 0xF8, 0xFE, 0x3E, 0xFE, 0xF8, 0x80, 0x00, 0xF8, 0xFE, 0xFE, 0x06, 0x00, 0x0F, 0x1F, 0x1F, 0x1F, 0x07, 0x01, 0x00, 0x01, 0x07, 0x1F, 0x1F, 0x1F, 0x0F, 0x00, 0x00, // 87
0x06, 0x1E, 0x3C, 0xF8, 0xF0, 0xE0, 0xF0, 0xF8, 0x3C, 0x1E, 0x06, 0x02, 0x18, 0x1E, 0x0F, 0x07, 0x03, 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x18, 0x10, // 88
0x02, 0x0E, 0x1E, 0x7E, 0xF8, 0xE0, 0xF8, 0x7E, 0x1E, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, // 89
0x00, 0x06, 0x06, 0xC6, 0xE6, 0xF6, 0x3E, 0x1E, 0x0E, 0x1C, 0x1E, 0x1F, 0x1B, 0x19, 0x18, 0x18, 0x18, 0x18, // 90
0xFE, 0xFE, 0xFE, 0x06, 0x06, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, // 91
0x06, 0x78, 0x80, 0x00, 0x00, 0x00, 0x07, 0x18, // 92
0x06, 0x06, 0xFE, 0xFE, 0xFE, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, // 93
0x40, 0x70, 0x7C, 0x1E, 0x1E, 0x7C, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 94
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 95
0x02, 0x06, 0x04, 0x00, 0x00, 0x00, // 96
0x40, 0x60, 0x70, 0x30, 0xB0, 0xB0, 0xF0, 0xF0, 0xE0, 0x0E, 0x1F, 0x1F, 0x1B, 0x19, 0x09, 0x1F, 0x1F, 0x1F, // 97
0xFE, 0xFE, 0xFE, 0x60, 0x30, 0x30, 0xF0, 0xE0, 0xC0, 0x1F, 0x1F, 0x1F, 0x0C, 0x18, 0x18, 0x1F, 0x0F, 0x07, // 98
0xC0, 0xE0, 0xF0, 0x70, 0x30, 0x30, 0x70, 0x60, 0x40, 0x07, 0x0F, 0x1F, 0x1C, 0x18, 0x18, 0x1C, 0x0C, 0x04, // 99
0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xFE, 0xFE, 0xFE, 0x07, 0x0F, 0x1F, 0x18, 0x18, 0x0C, 0x1F, 0x1F, 0x1F, // 100
0xC0, 0xE0, 0xF0, 0xB0, 0xB0, 0xB0, 0xF0, 0xE0, 0xC0, 0x07, 0x0F, 0x1F, 0x1D, 0x19, 0x19, 0x1D, 0x0D, 0x05, // 101
0x30, 0xFC, 0xFE, 0xFE, 0x36, 0x36, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, // 102
0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xF0, 0xF0, 0xF0, 0x47, 0xCF, 0xDF, 0xD8, 0xD8, 0xCC, 0xFF, 0x7F, 0x3F, // 103
0xFE, 0xFE, 0xFE, 0x20, 0x30, 0x30, 0xF0, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 104
0xF6, 0xF6, 0xF6, 0x1F, 0x1F, 0x1F, // 105
0x00, 0xF6, 0xF6, 0xF6, 0xC0, 0xFF, 0xFF, 0x7F, // 106
0xFE, 0xFE, 0xFE, 0xC0, 0xE0, 0xF0, 0xF0, 0x30, 0x10, 0x00, 0x1F, 0x1F, 0x1F, 0x03, 0x01, 0x07, 0x1F, 0x1E, 0x1C, 0x10, // 107
0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, // 108
0xF0, 0xF0, 0xF0, 0x20, 0x30, 0xF0, 0xF0, 0xE0, 0x20, 0x30, 0xF0, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 109
0xF0, 0xF0, 0xF0, 0x20, 0x30, 0x30, 0xF0, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 110
0xC0, 0xE0, 0xF0, 0x70, 0x30, 0x70, 0xF0, 0xE0, 0xC0, 0x07, 0x0F, 0x1F, 0x1C, 0x18, 0x1C, 0x1F, 0x0F, 0x07, // 111
0xF0, 0xF0, 0xF0, 0x60, 0x30, 0x70, 0xF0, 0xE0, 0xC0, 0xFF, 0xFF, 0xFF, 0x0C, 0x18, 0x18, 0x1F, 0x0F, 0x07, // 112
0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xF0, 0xF0, 0xF0, 0x07, 0x0F, 0x1F, 0x18, 0x18, 0x0C, 0xFF, 0xFF, 0xFF, // 113
0xF0, 0xF0, 0xF0, 0x20, 0x30, 0x10, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, // 114
0xE0, 0xF0, 0xF0, 0x90, 0x90, 0xB0, 0x30, 0x20, 0x08, 0x19, 0x1B, 0x13, 0x13, 0x1F, 0x1F, 0x0E, // 115
0x30, 0xFC, 0xFC, 0xFE, 0x30, 0x30, 0x00, 0x0F, 0x1F, 0x1F, 0x18, 0x18, // 116
0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0x0F, 0x1F, 0x1F, 0x18, 0x18, 0x08, 0x1F, 0x1F, 0x1F, // 117
0x10, 0xF0, 0xF0, 0xC0, 0x00, 0xE0, 0xF0, 0xF0, 0x10, 0x00, 0x00, 0x07, 0x1F, 0x1C, 0x1F, 0x07, 0x00, 0x00, // 118
0x10, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0x10, 0x00, 0x00, 0x07, 0x1F, 0x1E, 0x0F, 0x03, 0x00, 0x03, 0x0F, 0x1E, 0x1F, 0x07, 0x00, 0x00, // 119
0x10, 0x30, 0x70, 0xE0, 0xC0, 0x80, 0xC0, 0xE0, 0x70, 0x30, 0x10, 0x10, 0x18, 0x1E, 0x0F, 0x07, 0x03, 0x07, 0x0F, 0x1E, 0x18, 0x10, // 120
0x10, 0xF0, 0xF0, 0xC0, 0x00, 0xC0, 0xF0, 0xF0, 0x30, 0xC0, 0xC0, 0xC7, 0xFF, 0xFC, 0x3F, 0x0F, 0x01, 0x00, // 121
0x30, 0x30, 0x30, 0xF0, 0xF0, 0xF0, 0x30, 0x1C, 0x1E, 0x1F, 0x1B, 0x19, 0x18, 0x18, // 122
0x00, 0x00, 0xFC, 0xFE, 0xFE, 0x06, 0x03, 0x03, 0x7F, 0xFF, 0xFC, 0xC0, // 123
0xFE, 0xFE, 0xFF, 0xFF, // 124
0x06, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0x7F, 0x03, 0x03, // 125
0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, // 126
0xF8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F // 127
};
#endif

152
Font_data.h Normal file
View File

@@ -0,0 +1,152 @@
/*
Font_data.h
MIT License
Copyright (c) 2023 hdrlux
This is the data file for custom fonts, as alternative for the sysfont defined in MD_MAX72xx_font.cpp
'fontClock' only has chars 32..126, saving a few bytes of memory
The first number of every line is the width of the char, the number of columns
The following numbers are the columns, each byte for 8 LED on/off
*/
#ifndef Font_data_H
#define Font_data_H
//fontClock is adapted sysfont for better time/date display in Dutch language
MD_MAX72XX::fontType_t fontClock[] PROGMEM =
{
'F', 2, 0, 0, 0, 126, 8,
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
2, 0, 0, // 32 - 'Space'
2, 0, 95, // 33 - '!'
3, 7, 0, 7, // 34 - '"'
5, 20, 127, 20, 127, 20, // 35 - '#'
5, 68, 74, 255, 74, 50, // 36 - '$'
5, 99, 19, 8, 100, 99, // 37 - '%'
5, 54, 73, 73, 54, 72, // 38 - '&'
1, 7, // 39 - '''
3, 62, 65, 65, // 40 - '('
3, 65, 65, 62, // 41 - ')'
//5, 8, 42, 28, 42, 8, // 42 - '*'
3, 2, 5, 2, // 42 - '°' Degree symbol, replacing * char for easy of use'
5, 8, 8, 62, 8, 8, // 43 - '+'
2, 96, 224, // 44 - ','
2, 8, 8, // 45 - '-'
1, 64, // 46 - '.' width 1
5, 96, 16, 8, 4, 3, // 47 - '/'
5, 62, 81, 73, 69, 62, // 48 - '0'
5, 0, 4, 2, 127, 0, // 49 - '1' - width 5
5, 113, 73, 73, 73, 70, // 50 - '2'
5, 65, 73, 73, 73, 54, // 51 - '3'
5, 15, 8, 8, 8, 127, // 52 - '4'
5, 79, 73, 73, 73, 49, // 53 - '5'
5, 62, 73, 73, 73, 48, // 54 - '6'
5, 1, 1, 121, 5, 3, // 55 - european style '7'
5, 54, 73, 73, 73, 54, // 56 - '8'
5, 6, 73, 73, 73, 62, // 57 - '9'
1, 36, // 58 - colon ':' - width 1
2, 108, 236, // 59 - ';'
3, 8, 20, 34, // 60 - '<'
4, 20, 20, 20, 20, // 61 - '='
3, 34, 20, 8, // 62 - '>'
5, 1, 89, 9, 9, 6, // 63 - '?'
5, 62, 65, 93, 89, 78, // 64 - '@'
5, 126, 9, 9, 9, 126, // 65 - 'A'
5, 127, 73, 73, 73, 54, // 66 - 'B'
5, 62, 65, 65, 65, 65, // 67 - 'C'
5, 127, 65, 65, 65, 62, // 68 - 'D'
5, 127, 73, 73, 73, 65, // 69 - 'E'
5, 127, 9, 9, 9, 1, // 70 - 'F'
5, 62, 65, 65, 73, 121, // 71 - 'G'
5, 127, 8, 8, 8, 127, // 72 - 'H'
3, 65, 127, 65, // 73 - 'I'
5, 48, 65, 65, 65, 63, // 74 - 'J'
5, 127, 8, 20, 34, 65, // 75 - 'K'
5, 127, 64, 64, 64, 64, // 76 - 'L'
5, 127, 2, 12, 2, 127, // 77 - 'M'
5, 127, 4, 8, 16, 127, // 78 - 'N'
5, 62, 65, 65, 65, 62, // 79 - 'O'
5, 127, 9, 9, 9, 6, // 80 - 'P'
5, 62, 65, 65, 97, 126, // 81 - 'Q'
5, 127, 9, 25, 41, 70, // 82 - 'R'
5, 70, 73, 73, 73, 49, // 83 - 'S'
5, 1, 1, 127, 1, 1, // 84 - 'T'
5, 63, 64, 64, 64, 63, // 85 - 'U'
5, 31, 32, 64, 32, 31, // 86 - 'V'
5, 63, 64, 56, 64, 63, // 87 - 'W'
5, 99, 20, 8, 20, 99, // 88 - 'X'
5, 3, 4, 120, 4, 3, // 89 - 'Y'
5, 97, 81, 73, 69, 67, // 90 - 'Z'
3, 127, 65, 65, // 91 - '['
5, 3, 4, 8, 16, 96, // 92 - '\'
3, 65, 65, 127, // 93 - ']'
5, 4, 2, 1, 2, 4, // 94 - '^'
4, 128, 128, 128, 128, // 95 - '_'
3, 1, 2, 4, // 96 - '`'
4, 56, 68, 68, 124, // 97 - 'a'
4, 127, 68, 68, 56, // 98 - 'b'
4, 56, 68, 68, 68, // 99 - 'c'
4, 56, 68, 68, 127, // 100 - 'd'
4, 56, 84, 84, 88, // 101 - 'e'
4, 4, 126, 5, 1, // 102 - 'f'
4, 24, 164, 164, 124, // 103 - 'g'
4, 127, 4, 4, 120, // 104 - 'h'
3, 0, 125, 0, // 105 - 'i' width 3
3, 132, 133, 124, // 106 - 'j'
4, 127, 16, 40, 68, // 107 - 'k'
3, 127, 0, 0, // 108 - 'l' width 3
5, 124, 4, 120, 4, 120, // 109 - 'm'
4, 124, 4, 4, 120, // 110 - 'n'
4, 56, 68, 68, 56, // 111 - 'o'
4, 252, 36, 36, 24, // 112 - 'p'
4, 24, 36, 36, 252, // 113 - 'q'
4, 124, 4, 4, 8, // 114 - 'r'
4, 88, 84, 84, 52, // 115 - 's'
4, 4, 127, 68, 0, // 116 - 't' width 4
4, 60, 64, 64, 124, // 117 - 'u'
4, 28, 32, 64, 124, // 118 - 'v'
5, 60, 64, 48, 64, 60, // 119 - 'w'
4, 108, 16, 16, 108, // 120 - 'x'
5, 125, 0, 132, 133, 124, // 121 - 'ij' dutch 'y'
4, 100, 84, 84, 76, // 122 - 'z'
4, 8, 54, 65, 65, // 123 - '{'
1, 127, // 124 - '|'
4, 65, 65, 54, 8, // 125 - '}'
4, 2, 1, 2, 1, // 126 - '~'
};
// option: add multiple fonts definitions
#endif // Font_data_H

72
GPS_RTC_Clock.cpp Normal file
View File

@@ -0,0 +1,72 @@
/*
GPS_RTC_Clock.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include "GPS_RTC_Clock.h"
#include "RTC_com.h"
#include "GPS_com.h"
#include "LocalDateTime.h"
bool NewSec = false;
bool NewMin = false;
bool NewHour = false;
time_t Loc_t = 0;
time_t RTC_t = 0;
byte last_min = -1;
byte last_5min = -1;
byte last_hour = -1;
bool ResetMCU = true;
void GPS_RTC_Clock_setup() {
RTC_LED_setup();
RTC_setup();
GPS_setup();
TZ_setup();
//Serial.println("DEBUG[GPS_RTC_Clock_setup] done");
}
void GPS_RTC_Clock_loop() {
GPS_loop();
RTC_loop();
}
void Sec_Flip(time_t t) { // called from RTC_com
Loc_t = TZ_Sec(t); // convert UTC to Local Time
RTC_t = t;
NewSec = true; // set "Ready to print"
if (ResetMCU) { // set init time
ResetMCU = false;
last_5min = minute(Loc_t) / 5;
last_hour = hour(Loc_t);
}
if (last_min != minute(Loc_t)) { // Check new minute
MinFlip();
}
}
void MinFlip() {
last_min = minute(Loc_t);
if (last_5min != last_min / 5) { // Check new 5-min
Min5Flip();
}
if (last_hour != hour(Loc_t)) { // Check new hour
HourFlip();
}
NewMin = true; // set "Ready to print"
}
void Min5Flip() {
last_5min = last_min / 5;
GPS_ON(); // try sync RTC-GPS
}
void HourFlip() { // do something on the flip of the RTC hour [UTC time]
last_hour = hour(Loc_t);
NewHour = true; // set "Ready to print"
}
//End

63
GPS_RTC_Clock.h Normal file
View File

@@ -0,0 +1,63 @@
/*
GPS_RTC_Clock.h
MIT License
Copyright (c) 2023 hdrlux
main local Lib with Clock control, creating 'long term ±0.1 sec accurate Arduino clock'
tested hardware:
-Arduino Nano 5V ATmega328P
-see local *.h files for other hardware
main functions:
- Sync RTC with GPS in UTC using interrupt
- LED blinking in sync with GPS PPS, to check accuracy
- LED ON if RTC synced in last hours
- Convert to Local Date/Time
- Setting flag for printing new time to display, using interrupt
*/
/***** Notice *******************************************
!! GPS & USB use the same serial port !!
you will have to disconnect the Arduino RX pin 0 from
the GPS TX pin, to upload a new sketch over USB
->remove GPS PCB or Nano PCB from main PCB/breadboard
********************************************************/
#ifndef GPS_RTC_Clock_H
#define GPS_RTC_Clock_H
#include "ISOWeekNumber.h" // pass to main ino
#include "Local_names.h" // pass to main ino
#include "RTC_com.h"
#include <LiquidCrystal_I2C.h>
extern bool NewSec; // pass to main ino = second ready to print
extern bool NewMin; // pass to main ino = minute ready to print
extern bool NewHour; // pass to main ino = Hour ready to print
extern time_t Loc_t, RTC_t; // pass to main ino = Local timestamp
extern bool gps_on;
extern volatile bool GPS_sec, RTC_sec;
extern unsigned long RTCMillis, GPSMillis;// call from main ino, GPS_RTC_Clock.h
extern LiquidCrystal_I2C lcd;
void GPS_RTC_Clock_setup();
// call from main ino, GPS_RTC_Clock.h
void GPS_RTC_Clock_loop();
// process sec from RTC
void Sec_Flip(time_t t);
// do something on reboot & the flip of the RTC minute [timezone independent]
void MinFlip();
// do something every 5 minutes
void Min5Flip();
// do something every hour, on the hour
void HourFlip();
#endif // GPS_RTC_Clock_H

123
GPS_RTC_Clock.ino Normal file
View File

@@ -0,0 +1,123 @@
/* GPS_RTC_Clock
MIT License
Copyright (c) 2023 hdrlux
https://www.instructables.com/01-Sec-Accurate-RTC-GPS-Wall-Clock-Arduino-96x8-LE/
https://github.com/hdrlux/GPS_RTC_Clock
*/
#include <Arduino.h> // needed for Nano Every
#include "GPS_RTC_Clock.h"
//#include "LED_96x8_matrix.h"
#include <DMD2.h>
#include <LiquidCrystal_I2C.h>
#include "Font_Chrono1.h"
#define pin_RTC_SQW 3
#define DEBUG_PORT Serial
SoftDMD dmd(2, 1);
LiquidCrystal_I2C lcd(0x27, 16, 2);
char TempBuf[5] = "99.9"; // demo value
char HumiBuf[3] = "99"; // demo value
unsigned long TMR_FPS;
long FPS;
bool LCD_Simple_clock;
void setup() { // the setup function runs once when you press reset or power the board
// LCD
lcd.init(); // Инициализация дисплея
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("DEBUG[setup()]");
DEBUG_PORT.begin(38400);
DEBUG_PORT.flush();
delay(1000);
DEBUG_PORT.println("DEBUG[setup()]");
//Serial.begin(19200); // = 9600, must be same as GPS for debug
//Serial.println(); // flush serial
//Serial.println("-Arduino Reboot-"); // debug
GPS_RTC_Clock_setup(); // first in setup
//Matrix_setup(); // LED display
//dmd.setBrightness(5);
//dmd.selectFont(Font_Chrono1);
//dmd.begin();
//dmd.clearScreen();
lcd.setCursor(0, 0);
lcd.print(" ");
}
void loop() { // the loop function runs over and over again forever
// if (millis() - tmr_Blink > 500) {
// Serial.println("DEBUG[BLINK] " + int(digitalRead(13)));
// tmr_Blink = millis();
// digitalWrite(13, !digitalRead(13));
// }
GPS_RTC_Clock_loop(); // first in loop
RTCtoLCD();
//chkFPS();
}
/////////////////////
void RTCtoLCD() {
/*if (GPS_sec) {
DEBUG_PORT.println("DEBUG[RTCtoLCD] GPS_sec");
GPS_PPS_LCD = !GPS_PPS_LCD;
lcd.setCursor(2, 0);
lcd.print((GPS_PPS_LCD) ? " " : ":");
}
if (RTC_sec) {
DEBUG_PORT.println("DEBUG[RTCtoLCD] RTC_sec");
RTC_SQW_LCD = !RTC_SQW_LCD;
lcd.setCursor(5, 0);
lcd.print((RTC_SQW_LCD) ? " " : ":");
}*/
//if (!GPS_sec and !RTC_sec) return;
if (!NewSec && !NewMin && !NewHour) return;
char Clock[9];
char segment[3];
char message[50];
if (NewSec) {
DEBUG_PORT.println("DEBUG[RTCtoLCD] newSec");
//DEBUG_PORT.println("DEBUG[RTCtoLCD] RTCMillis: " + String(RTCMillis));
//DEBUG_PORT.println("DEBUG[RTCtoLCD] RTC_sec: " + String(RTC_sec));
//DEBUG_PORT.println("DEBUG[RTCtoLCD] millis: " + String(millis()));
//snprintf(segment, sizeof(segment),"%.2u", second(Loc_t));
snprintf(segment, sizeof(segment),"%.2u", second(RTC_t));
lcd.setCursor(6, 0);
lcd.print(segment);
}
if (NewMin) {
//snprintf(segment, sizeof(segment),"%.2u", minute(Loc_t));
snprintf(segment, sizeof(segment),"%.2u", minute(RTC_t));
lcd.setCursor(3, 0);
lcd.print(segment);
//snprintf(segment, sizeof(segment),"%.2u", hour(Loc_t));
snprintf(segment, sizeof(segment),"%.2u", hour(RTC_t));
lcd.setCursor(0, 0);
lcd.print(segment);
}
}
void chkFPS() {
if (micros() - TMR_FPS > 1000000) {
DEBUG_PORT.println("DEBUG[chkFPS] FPS: " + String(FPS));
//DEBUG_PORT.println("DEBUG[chkFPS] TMR_FPS: " + String(TMR_FPS));
TMR_FPS = micros();
FPS = 0;
return;
}
FPS++;
}
//End

189
GPS_com.cpp Normal file
View File

@@ -0,0 +1,189 @@
/*
GPS_com.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include <NMEAGPS.h> // https://github.com/SlashDevin/NeoGPS
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
#include "GPS_com.h"
#include "RTC_com.h" // to set the RTC
#include "Serial_AdjustBaud.h" // for adjust serial port baudrate
#include "LocalDateTime.h"
#define cfg_pin_GPS_PPS 2
#define cfg_pin_GPS_Rx 8
#define cfg_pin_GPS_Tx 9
// add the static modifier to limit visibility of these variables to just this file
static byte GPS_PPS_PIN = cfg_pin_GPS_PPS; // Pin 2 = NANO INT0, GPS PPS interrupt signal on this Pin
static bool gps_on; // flag for GPS ON/OFF
static int pulse_count = 0;
static time_t gps_seconds_t = 0; // GPS time
static byte gps_sats = 0;
volatile bool GPS_sec = false; // flag for GPS-PPS
unsigned long GPSMillis;
// set interrupt flag
void gps_interrupt() {
GPSMillis = micros();
GPS_sec = true;
}
NMEAGPS gps; // This parses the GPS characters
gps_fix fix; // This holds on to the latest values
//#include <AltSoftSerial.h>
#include <GPSport.h> // use only for soft-serial
//#define gpsPort Serial
//#define GPS_PORT_NAME "Serial"
#define GPS_PORT_NAME "AltSoftSerial"
/***** Notice ********************************************
Edit file \Arduino\libraries\NeoGPS\src\NMEAGPS_cfg.h
UnComment line //#define NMEAGPS_PARSE_ZDA
only process the NMEA sentences GGA, RMC en ZDA
*********************************************************/
/****** Notice *******************************************
Edit file \Arduino\libraries\NeoGPS\src\NeoTime.h
change both instances of the const name 'DAYS_PER_WEEK'
to something else, they conflict with TimeLib.h
*********************************************************/
// Compile check processing for both RMC & ZDA message [both contain date & time]
// Less dependent on GPS chip config
#ifndef NMEAGPS_PARSE_RMC
#error You must define NMEAGPS_PARSE_RMC in NMEAGPS_cfg.h!
#endif
#ifndef NMEAGPS_PARSE_ZDA
#error You must define NMEAGPS_PARSE_ZDA in NMEAGPS_cfg.h!
#endif
#ifndef NMEAGPS_PARSE_GGA
#error You must define NMEAGPS_PARSE_GGA in NMEAGPS_cfg.h!
#endif
const long POSIX_Y2K_offset = 946684800; // = 10957 days = 30 years, NeoTime (GPS) & TimeLib (RTC) library use different Epoch year, 2000 & 1970
const long offset_28y = 883612800; // = 10227 days = 28 years, simple test for 2038 bug
const long offset_26w = 15724800; // = 182 days = 26 weeks, simple test for timezone
const char baud19200 [] PROGMEM = "PUBX,41,1,3,3,19200,0";
const char baud38400 [] PROGMEM = "PUBX,41,1,3,3,38400,0";
const char GGA_off [] PROGMEM = "PUBX,40,GGA,0,0,0,0";
const char GLL_off [] PROGMEM = "PUBX,40,GLL,0,0,0,0";
const char GSA_off [] PROGMEM = "PUBX,40,GSA,0,0,0,0";
const char GSV_off [] PROGMEM = "PUBX,40,GSV,0,0,0,0";
const char VTG_off [] PROGMEM = "PUBX,40,VTG,0,0,0,0";
const char RMC_off [] PROGMEM = "PUBX,40,RMC,0,0,0,0";
const char ZDA_off [] PROGMEM = "PUBX,40,ZDA,0,0,0,0";
const char RMC_on [] PROGMEM = "PUBX,40,RMC,0,1,0,0";
const char ZDA_on [] PROGMEM = "PUBX,40,ZDA,0,1,0,0";
bool GPS_PPS_LCD;
void GPS_setup() {
DEBUG_PORT.println(F("DEBUG[GPS_setup()] start"));
GPS_sec = false;
if (detRate(cfg_pin_GPS_Rx) != 38400) {
DEBUG_PORT.println(F("DEBUG[GPS_setup()] baudrate not 38400"));
gpsPort.begin(detRate(cfg_pin_GPS_Rx)); // set PC to same baudrate for debug messages
gps.send_P(&gpsPort, (const __FlashStringHelper *) baud38400);
gpsPort.flush();
delay(100);
gpsPort.end();
}
else
DEBUG_PORT.println(F("DEBUG[GPS_setup()] baudrate already 38400"));
gpsPort.begin(38400);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) GGA_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) GLL_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) GSA_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) GSV_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) VTG_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) RMC_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) ZDA_off);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) RMC_on);
delay(100);
gps.send_P(&gpsPort, (const __FlashStringHelper *) ZDA_on);
delay(100);
pinMode(GPS_PPS_PIN, INPUT_PULLUP); // enable pullup on interrupt pin
attachInterrupt(digitalPinToInterrupt(GPS_PPS_PIN), gps_interrupt, RISING); // 100ms HIGH at start of second
GPS_ON();
}
void GPS_loop() {
if (GPS_sec) { // do after GPS PPS interrupt
GPS_sec = false; // clear flag
lcd.setCursor(2, 0); GPS_PPS_LCD = !GPS_PPS_LCD;
lcd.print((GPS_PPS_LCD) ? " " : ":");
GPS_PPS();
}
GPS_read_seconds(); // continue reading buffer
}
void GPS_PPS() { // do something on the flip of the GPS second
int32_t drift = (RTCMillis - GPSMillis); // % (4294967295UL);
//DEBUG_PORT.println("DEBUG[GPS_PPS()] Start");
if (drift > 900000)
drift -= 1000000;
else if (drift < -900000)
drift += 1000000;
//DEBUG_PORT.println("DEBUG[GPS_loop()] drift: " + String(drift));
lcd.setCursor((16 - sizeof(String(drift))), 1);
lcd.print(drift);
if (drift > 5000 && !gps_on) GPS_ON();
if (gps_on) { // do only when needed
pulse_count += 1;
if (pulse_count > 2) { // skip first PPS-Pulses, to make shure time is from satellite
if (gps_seconds_t != 0) { // do only if value is set
// gps_seconds_t += offset_28y; // debug & testing only!
// gps_seconds_t += offset_26w; // debug & testing only!
SetRTC(TZ_Sec(gps_seconds_t)); // sync RTC with GPS
GPS_OFF();
}
}
}
}
void GPS_read_seconds() {
//Serial.println("DEBUG[GPS_read_second()] Start");
while (gps.available(gpsPort)) {
fix = gps.read();
if (fix.valid.time && fix.valid.date) {
gps_seconds_t = fix.dateTime + POSIX_Y2K_offset; // convert for different epoch year
}
if (fix.valid.satellites) {
gps_sats = fix.satellites;
}
}
}
void GPS_ON() {
DEBUG_PORT.println("DEBUG[GPS_ON()] Start");
gps_on = true;
gps_seconds_t = 0; // make shure GPS serial is alive before setting
pulse_count = 0;
}
void GPS_OFF() {
if (gps_on) { // only if NOT off
gps_on = false;
//Serial.println("GPS: OFF"); // debug
}
}
//End

49
GPS_com.h Normal file
View File

@@ -0,0 +1,49 @@
/*
GPS_com.h
MIT License
Copyright (c) 2023 hdrlux
all GPS time functions, tested hardware:
- Ublox Neo M8N
- External L1-antenna
- set Pin: PPS Interrupt in file GPS_com.cpp [default: 2 = NANO INT0]
*/
/***** Notice ********************************************
Edit file \Arduino\libraries\NeoGPS\src\NMEAGPS_cfg.h
UnComment line //#define NMEAGPS_PARSE_ZDA
only process the NMEA sentences GGA, RMC en ZDA
*********************************************************/
/****** Notice *******************************************
Edit file \Arduino\libraries\NeoGPS\src\NeoTime.h
change both instances of the const 'DAYS_PER_WEEK'
to something else, they conflict with TimeLib.h
*********************************************************/
#ifndef GPS_com_H
#define GPS_com_H
// handle interrupt
void gps_interrupt();
// setup hardware & interrupt from PseudoPPS
void GPS_setup();
// main GPS loop, GPS_com
void GPS_loop();
// do something on the flip of the GPS second
void GPS_PPS();
// get time & amount of satts in FIX
void GPS_read_seconds();
// turn GPS on
void GPS_ON();
// no hardware OFF, just ignore
void GPS_OFF();
#endif // GPS_com_H

35
ISOWeekNumber.cpp Normal file
View File

@@ -0,0 +1,35 @@
/*
ISOWeekNumber.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include "ISOWeekNumber.h"
byte ISOdayOfWeek(long days) { // TimeLib.h deviates from ISO8601 with Sunday = 1
// ONLY valid for Epoch year 1970
return (((days + 3) % DAYS_PER_WEEK) + 1); // Mon=1..Sun=7
}
byte ISOWeekNumber(time_t t) { // uses TimeLib.h - valid until 2099
// weeknumber ONLY valid for Mon=1..Sun=7 datelibrary
// calculations valid for ANY Epoch year, only relative dates
long NowDay = elapsedDays(t); // days_since_epoch: now
long CloseThu = NowDay - ISOdayOfWeek(NowDay) + 4; // days_since_epoch: closest Thursday from now
int ISOYear = year(CloseThu * SECS_PER_DAY); // Year for closest Thursday, may be different in first or last week
tmElements_t tm;
tm.Hour = 0;
tm.Minute = 0;
tm.Second = 0;
tm.Day = 4; // 4th day according ISO8601
tm.Month = 1; // Jan
tm.Year = CalendarYrToTm(ISOYear);
time_t JanFour = makeTime(tm); // date: Year-Jan-4
long JanFourDay = elapsedDays(JanFour); // days_since_epoch: Year-Jan-4
int ISOYearDay = NowDay - JanFourDay + ISOdayOfWeek(JanFourDay); // Day number in the ISOYear, range [1..371]
return (((ISOYearDay - 1) / 7) + 1); // Convert Day number in the ISOYear to ISOWeek number, range [1..53]
}
//End

22
ISOWeekNumber.h Normal file
View File

@@ -0,0 +1,22 @@
/*
ISOWeekNumber.h
MIT License
Copyright (c) 2023 hdrlux
function:
- provides weeknumber from Unix time, according ISO8601
*/
#ifndef ISOWeekNumber_H
#define ISOWeekNumber_H
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time valid until year 2099, no 2038 bug !
// ISO8601 compliant, 1 = Monday
byte ISOdayOfWeek(long days);
// ISO8601 compliant, ISOWeek number, range [1..53]
byte ISOWeekNumber(time_t t);
#endif // ISOWeekNumber_H

146
LED_96x8_matrix.cpp Normal file
View File

@@ -0,0 +1,146 @@
/*
LED_96x8_matrix.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include <MD_MAX72xx.h> // https://github.com/MajicDesigns/MD_MAX72XX
#include "LED_96x8_matrix.h"
#include "Font_data.h"
#include "RTC_com.h" // for Sync_Err
// Define the number of devices we have in the chain and the hardware interface
#define MAX_DEVICES 12 // total amount of 8x8 LED segments
#define LEFT_DEVICES 5 // amount of 8x8 LED segments in left zone
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // check if you get strange pixel print
#define CLK_PIN 13 // or SCK [is also onboard LED on Nano]
#define DATA_PIN 11 // or MOSI
#define CS_PIN 10 // or SS
#define INIT_BRIGHT 0 // inital intensity
#define DIP1 6 // Scroll DIP switch
#define DIP2 7 // Bright DIP switch
// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Text parameters
#define CHAR_SPACING 1 // pixels between characters
void Matrix_setup() {
mx.begin();
mx.setFont(fontClock); // custom font in Font_data.h
delay(100); // wait init
Bright_time_zone(INIT_BRIGHT);
Bright_date_zone(INIT_BRIGHT);
pinMode(DIP1, INPUT_PULLUP);
pinMode(DIP2, INPUT_PULLUP);
}
void Bright_date_zone(byte value) { // set range 0..15
mx.control(0, MAX_DEVICES - LEFT_DEVICES - 1, MD_MAX72XX::INTENSITY, value);
}
void Bright_time_zone(byte value) { // set range 0..15
mx.control(MAX_DEVICES - LEFT_DEVICES, MAX_DEVICES - 1, MD_MAX72XX::INTENSITY, value);
}
void DIP_Bright() {
if (digitalRead(DIP2) == LOW) {
Bright_time_zone(3);
Bright_date_zone(3);
} else {
Bright_time_zone(INIT_BRIGHT);
Bright_date_zone(INIT_BRIGHT);
}
}
bool DIP_Scroll() {
if (digitalRead(DIP1) == LOW) {
return true;
}
return false;
}
void Print_date_zone(char *my_text) {
char TextBuf[13]; // string buffer, max n-1 char
char err_char;
if (SyncErr) {
err_char = '!'; // sync warning on display
} else {
err_char = ' '; // space
}
snprintf(TextBuf, sizeof(TextBuf), "%c%s", err_char, my_text); // add char before text, 'between' zones
printText(0, MAX_DEVICES - LEFT_DEVICES - 1, TextBuf); // right zone, from input side
}
void Print_time_zone(char *my_text) { // assuming max 8 chars
DIP_Bright();
printText(MAX_DEVICES - LEFT_DEVICES, MAX_DEVICES - 1, my_text); // left zone
}
void printText(uint8_t modStart, uint8_t modEnd, char *pMsg)
/***** HowTo **********************************************
Simple text printing, uses minimal memory
Print the text chars to the LED matrix modules specified.
Message area is padded with blank columns after printing.
**********************************************************/
{
uint8_t state = 0;
uint8_t curLen;
uint16_t showLen;
uint8_t cBuf[8];
int16_t col = ((modEnd + 1) * COL_SIZE) - 1;
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);
do // finite state machine to print the characters in the space available
{
switch (state) {
case 0: // Load the next character from the font table
// if we reached end of message, reset the message pointer
if (*pMsg == '\0') {
showLen = col - (modEnd * COL_SIZE); // padding characters
state = 2;
break;
}
// retrieve the next character form the font file
showLen = mx.getChar(*pMsg++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
curLen = 0;
state++;
// !! deliberately fall through to next state to start displaying
case 1: // display the next part of the character
mx.setColumn(col--, cBuf[curLen++]);
// done with font character, now display the space between chars
if (curLen == showLen) {
showLen = CHAR_SPACING;
state = 2;
}
break;
case 2: // initialize state for displaying empty columns
curLen = 0;
state++;
// fall through
case 3: // display inter-character spacing or end of message padding (blank columns)
mx.setColumn(col--, 0);
curLen++;
if (curLen == showLen)
state = 0;
break;
default:
col = -1; // this definitely ends the do loop
}
} while (col >= (modStart * COL_SIZE));
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}
//End

42
LED_96x8_matrix.h Normal file
View File

@@ -0,0 +1,42 @@
/*
LED_96x8_matrix.h
MIT License
Copyright (c) 2023 hdrlux
all LED Display functions, specific hardware:
- MAX7219 with 8x8 LED segment 32x32mm
- unit FC16 = 4 segments on one PCB
- 3 units in series = chain of 12 segments, making a 96x8 display
- if NOT wired correct, ALL LED's are ON in HIGH brightness, using 9W power -> use 10W 5V/2A power source for project safety
- normal operation uses 0,5W for LED display + 0,5W for control board
*/
#ifndef LED_96x8_matrix_H
#define LED_96x8_matrix_H
// main display setup
void Matrix_setup();
// intensity right
void Bright_date_zone(byte value);
// intensity left
void Bright_time_zone(byte value);
// Check DIP switch for brightness control
void DIP_Bright();
// Check DIP switch for text scrolling
bool DIP_Scroll();
// print right
void Print_date_zone(char *my_text);
// print left
void Print_time_zone(char *my_text);
// print chars to specific segment range, NO animations
void printText(uint8_t modStart, uint8_t modEnd, char *pMsg);
#endif // LED_96x8_matrix_H

74
LocalDateTime.cpp Normal file
View File

@@ -0,0 +1,74 @@
/*
LocalDateTime.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include <Timezone_Generic.h> // https://github.com/khoih-prog/Timezone_Generic [only this one, DO NOT install all dependencies !!]
#include "LocalDateTime.h"
/*** HowTo ****************************************************************
TimeChangeRule myRule = {abbrev, week, dow, month, hour, offset};
abbrev: is a character string abbreviation for the time zone,
it must be no longer than five characters.
week: is the week of the month that the rule starts.
dow: is the day of the week that the rule starts.
hour: is the hour in local time that the rule starts (0-23).
offset: is the UTC offset in minutes for the time zone being defined.
For convenience, the following symbolic names can be used:
week: First, Second, Third, Fourth, Last
dow: Sun, Mon, Tue, Wed, Thu, Fri, Sat
month: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
**************************************************************************/
/*** Instruction ******************************************************************
Select ONE set of TimeChangeRules below, also for non DST zones
Selection NOT possible during runtime, only at compiletime
The timezones are defined by the offset, in minutes, from UTC.
This means the start of a new minute, and the seconds, are timezone independent !
**********************************************************************************/
// Eastern US time zone [Ottawa, New York, Miami, Nassau]
//TimeChangeRule mySTD = { "EST", First, Sun, Nov, 2, -300 }; // change to UTC - 5 hours
//TimeChangeRule myDST = { "EDT", Second, Sun, Mar, 2, -240 }; // change to UTC - 4 hours
// Western European Time Zone [London = GMT/BST, Dublin = GMT/IST, Lisboa = WET/WEST, Canarias]
//TimeChangeRule mySTD = { "WET ", Last, Sun, Oct, 2, 0 }; // change to UTC
//TimeChangeRule myDST = { "WEST", Last, Sun, Mar, 1, 60 }; // change to UTC + 1 hours
// Central European Time Zone, directive 2000/84/EC [Bruxelles, Paris, Madrid, Roma, Beograd, Warszawa, Stockholm, Berlin]
// All 3 European timezones change at the same time: 01:00 UTC
// TimeChangeRule mySTD = { "CET ", Last, Sun, Oct, 3, 60 }; // change to UTC + 1 hours
// TimeChangeRule myDST = { "CEST", Last, Sun, Mar, 2, 120 }; // change to UTC + 2 hours
// Eastern European Time Zone [Helsinki, Rīga, Kyiv, Αθήνα]
//TimeChangeRule mySTD = { "EET ", Last, Sun, Oct, 4, 120 }; // change to UTC + 2 hours
//TimeChangeRule myDST = { "EEST", Last, Sun, Mar, 3, 180 }; // change to UTC + 3 hours
// Australia Eastern Time Zone [Canberra, Brisbane, Sydney, Melbourne, Hobart]
//TimeChangeRule mySTD = { "AEST", First, Sun, Apr, 3, 600 }; // change to UTC + 10 hours
//TimeChangeRule myDST = { "AEDT", First, Sun, Oct, 2, 660 }; // change to UTC + 11 hours
// Москва Standard Time (MSK, does not observe DST)
TimeChangeRule mySTD = {"MSK ", Last, Sun, Oct, 1, 180}; // allways UTC + 3 hours
TimeChangeRule myDST = {"MSK ", Last, Sun, Mar, 1, 180}; // allways UTC + 3 hours
// Universal Time Coordinated [UTC]
//TimeChangeRule mySTD = {"UTC ", Last, Sun, Oct, 1, 0};
//TimeChangeRule myDST = {"UTC ", Last, Sun, Mar, 1, 0};
Timezone* myTZ;
void TZ_setup() {
myTZ = new Timezone(myDST, mySTD);
}
time_t TZ_Sec(time_t t) { // convert UTC to Local-Time
TimeChangeRule* tcr; // pointer to the time change rule, use to get TZ abbrev
return (myTZ->toLocal(t, &tcr));
}
//End

25
LocalDateTime.h Normal file
View File

@@ -0,0 +1,25 @@
/*
LocalDateTime.h
MIT License
Copyright (c) 2023 hdrlux
function:
- Convert UTC timestamp to Local timestamp, including DST detection [=winter/summer time]
usage:
- uncomment ONE timezone in file LocalDateTime.cpp
*/
#ifndef LocalDateTime_H
#define LocalDateTime_H
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time valid until year 2099, no 2038 bug !
// main TZ setup, GPS_RTC_Clock
void TZ_setup();
// convert UTC to Local-Time
time_t TZ_Sec(time_t t);
#endif // LocalDateTime_H

37
Local_names.cpp Normal file
View File

@@ -0,0 +1,37 @@
/*
Local_names.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include "Local_names.h"
#define dt_MAX_STRING_LEN 9
#define dt_SHORT_STR_LEN 3
static char buffer_m[dt_MAX_STRING_LEN + 1];
static char buffer_d[dt_MAX_STRING_LEN + 1];
//const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec"; // Translate to local Language
//const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThuFriSat"; // Translate to local Language
const char monthShortNames_Loc[] PROGMEM = "ErrJanFebMrtAprMeiJunJulAugSepOktNovDec"; // Dutch
const char dayShortNames_Loc[] PROGMEM = "ErrZonMaaDinWoeDonVryZat"; // Dutch
char* monthShortStrLoc(uint8_t month) {
for (int i = 0; i < dt_SHORT_STR_LEN; i++)
buffer_m[i] = pgm_read_byte(&(monthShortNames_Loc[i + (month * dt_SHORT_STR_LEN)]));
buffer_m[dt_SHORT_STR_LEN] = 0;
return buffer_m;
}
char* dayShortStrLoc(uint8_t day) {
uint8_t index = day * dt_SHORT_STR_LEN;
for (int i = 0; i < dt_SHORT_STR_LEN; i++)
buffer_d[i] = pgm_read_byte(&(dayShortNames_Loc[index + i]));
buffer_d[dt_SHORT_STR_LEN] = 0;
return buffer_d;
}
//End

20
Local_names.h Normal file
View File

@@ -0,0 +1,20 @@
/*
Local_names.h
MIT License
Copyright (c) 2023 hdrlux
Convert to short local weekday & month names
Workaround because DateStrings.cpp in TimeLib is english only
*/
#ifndef Local_names_H
#define Local_names_H
// Local short month
char* monthShortStrLoc(uint8_t month);
// Local short weekday
char* dayShortStrLoc(uint8_t day);
#endif // Local_names_H

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# GPS_RTC_Clock
See https://www.instructables.com/01-Sec-Accurate-RTC-GPS-Wall-Clock-Arduino-96x8-LE/

87
RTC_com.cpp Normal file
View File

@@ -0,0 +1,87 @@
/*
RTC_com.cpp
MIT License
Copyright (c) 2023 hdrlux
*/
#include <Arduino.h> // for all the 'standard' Arduino stuff
#include <DS3232RTC.h> // https://github.com/JChristensen/DS3232RTC
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time [valid until year 2099, no 2038 bug]
#include "GPS_RTC_Clock.h"
#include "RTC_com.h"
#define cfg_pin_RTC_SQW 3;
#ifndef DEBUG_PORT
#define DEBUG_PORT Serial
#endif
// add the static modifier to limit visibility of these variables to just this file
static int ledPin_PPS = A6; // Pin for RTC PseudoPPS LED [analog PIN used as digital PIN]
static int ledPin_Sync = A7; // Pin for valid RTC Sync
static byte RTC_1HZ_PIN = cfg_pin_RTC_SQW; // Pin 3 = NANO INT1, RTC provides a 1Hz interrupt signal on this Pin
static time_t last_sync_t = 0; // last sync
static byte sync_err_hours = 4; // set to 4 for DS3231M, may be set to 8 for DS3231SN. Warning if no GPS sync after n hours, possible 0.1 sec error.
bool SyncErr = true, RTC_SQW_LCD;
#include <DS3232RTC.h>
DS3232RTC myRTC(0x68); // cfg_
volatile bool RTC_sec = false; // flag for PseudoPPS
unsigned long RTCMillis; // blinking timer
void rtc_interrupt() {
//Serial.print("DEBUG[INT] RTC interrupt "); Serial.println(micros());
RTCMillis = micros();
RTC_sec = true;
}
void RTC_LED_setup() {
pinMode(ledPin_PPS, OUTPUT);
pinMode(ledPin_Sync, OUTPUT);
digitalWrite(ledPin_PPS, LOW); // LED off
digitalWrite(ledPin_Sync, LOW); // LED off
}
void RTC_setup() {
pinMode(RTC_1HZ_PIN, INPUT_PULLUP); // enable pullup on interrupt pin (RTC SQW pin is open drain)
attachInterrupt(digitalPinToInterrupt(RTC_1HZ_PIN), rtc_interrupt, FALLING); // HIGH 500ms after start of second
myRTC.begin();
myRTC.squareWave(DS3232RTC::SQWAVE_1_HZ); // 1 Hz square wave
RTC_sec = false;
}
void RTC_loop() {
if (RTC_sec) { // do after RTC PseudoPPS interrupt, without interrupt NO time/date to display
//DEBUG_PORT.println("DEBUG[RTC_loop()] RTC_sec: " + String(RTC_sec));
//DEBUG_PORT.println("DEBUG[RTC_loop()] RTCMillis: " + String(RTCMillis));
//DEBUG_PORT.println("DEBUG[RTC_loop()] millis: " + String(millis()));
lcd.setCursor(5, 0); RTC_SQW_LCD = !RTC_SQW_LCD;
lcd.print((RTC_SQW_LCD) ? " " : ":");
RTC_sec = false; // clear flag
digitalWrite(ledPin_PPS, LOW); // LED off
time_t now_t = myRTC.get();
if ((last_sync_t + (sync_err_hours * 3600)) < now_t) {
SyncErr = true;
//digitalWrite(ledPin_Sync, LOW); // LED off
}
Sec_Flip(now_t); // pass current datetime from RTC in UTC
}
else {
NewSec = false;
}
/*if (millis() > (RTCMillis + 100)) { // do 100ms after PseudoPPS interrupt
digitalWrite(ledPin_PPS, HIGH); // LED on
}*/
}
void SetRTC(time_t t) {
myRTC.set(t + 1); // the GPS NMEA output is 1 second behind at PPS !!
last_sync_t = t;
SyncErr = false;
//digitalWrite(ledPin_Sync, HIGH); // LED on
DEBUG_PORT.println("RTC set by GPS"); // debug
}
//End

34
RTC_com.h Normal file
View File

@@ -0,0 +1,34 @@
/*
RTC_com.h
MIT License
Copyright (c) 2023 hdrlux
all RTC functions, tested hardware:
- DS3231SN via I2C, has only 2-digit years, the Epoch is 2000-01-01. Valid until year 2099
- set Pin: PseudoPPS Interrupt in file RTC_com.cpp [default: 3 = NANO INT1]
- set Pin: PseudoPPS LED in file RTC_com.cpp [default: A3]
*/
#ifndef RTC_com_H
#define RTC_com_H
extern bool SyncErr; // RTC not synced in last n hours
#include "GPS_RTC_Clock.h" // for passing new second
// handle interrupt
void rtc_interrupt();
// setup the pin as output
void RTC_LED_setup();
// setup hardware & interrupt from PseudoPPS
void RTC_setup();
// main RTC loop, RTC_com
void RTC_loop();
// sync RTC from GPS
void SetRTC(time_t t);
#endif // RTC_com_H

55
Serial_AdjustBaud.h Normal file
View File

@@ -0,0 +1,55 @@
/**
* Serial_AdjustBaud
*
* Функция для вычисления и возврата скорости передачи данных (baud rate) на основе полученного входного пина.
*
* @param recpin входной пин для определения скорости передачи данных
*
* @return рассчитанная скорость передачи данных на основе измеренной ширины нулевого бита
*/
long detRate(int recpin) {
long baud, x, rate = 10000;
pinMode(recpin, INPUT); // make sure serial in is a input pin
digitalWrite (recpin, HIGH); // pull up enabled just for noise protection
delay(100);
// Цикл для измерения ширины нулевого бита
for (int i = 0; i < 15; i++){
// Ожидание начала низкого бита
while(digitalRead(recpin) == 1) {}
x = pulseIn(recpin, LOW); // Измерение ширины следующего нулевого бита
rate = x < rate ? x : rate; // Обновление минимальной ширины нулевого бита
}
// Определение скорости передачи данных на основе измеренной ширины нулевого бита
if (rate < 12)
baud = 115200;
else if (rate < 20)
baud = 57600;
else if (rate < 29)
baud = 38400;
else if (rate < 40)
baud = 28800;
else if (rate < 60)
baud = 19200;
else if (rate < 80)
baud = 14400;
else if (rate < 150)
baud = 9600;
else if (rate < 300)
baud = 4800;
else if (rate < 600)
baud = 2400;
else if (rate < 1200)
baud = 1200;
else if (rate < 2400)
baud = 600;
else if (rate < 4800)
baud = 300;
else
baud = 0;
return baud; // Возврат рассчитанной скорости передачи данных
}

46
Timezone_Generic.h Normal file
View File

@@ -0,0 +1,46 @@
/*********************************************************************************************************************************
Timezone_Generic.h
For AVR, ESP8266/ESP32, SAMD21/SAMD51, nRF52, STM32, WT32_ETH01 boards
Based on and modified from Arduino Timezone Library (https://github.com/JChristensen/Timezone)
to support other boards such as ESP8266/ESP32, SAMD21, SAMD51, Adafruit's nRF52 boards, etc.
Copyright (C) 2018 by Jack Christensen and licensed under GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
Built by Khoi Hoang https://github.com/khoih-prog/Timezone_Generic
Licensed under MIT license
Version: 1.10.1
Version Modified By Date Comments
------- ----------- ---------- -----------
1.2.4 K Hoang 17/10/2020 Initial porting to support SAM DUE, SAMD21, SAMD51, nRF52, ESP32/ESP8266, STM32, etc. boards
using SPIFFS, LittleFS, EEPROM, FlashStorage, DueFlashStorage.
1.2.5 K Hoang 28/10/2020 Add examples to use STM32 Built-In RTC.
1.2.6 K Hoang 01/11/2020 Allow un-initialized TZ then use begin() method to set the actual TZ (Credit of 6v6gt)
1.3.0 K Hoang 09/01/2021 Add support to ESP32/ESP8266 using LittleFS/SPIFFS, and to AVR, UNO WiFi Rev2, etc.
Fix compiler warnings.
1.4.0 K Hoang 04/06/2021 Add support to RP2040-based boards using RP2040 Arduino-mbed or arduino-pico core
1.5.0 K Hoang 13/06/2021 Add support to ESP32-S2 and ESP32-C3. Fix bug
1.6.0 K Hoang 16/07/2021 Add support to WT32_ETH01
1.7.0 K Hoang 10/08/2021 Add support to Ameba Realtek RTL8720DN, RTL8722DM and RTM8722CSM
1.7.1 K Hoang 10/10/2021 Update `platform.ini` and `library.json`
1.7.2 K Hoang 02/11/2021 Fix crashing issue for new cleared flash
1.7.3 K Hoang 01/12/2021 Auto detect ESP32 core for LittleFS. Fix bug in examples for WT32_ETH01
1.8.0 K Hoang 31/12/2021 Fix `multiple-definitions` linker error
1.9.0 K Hoang 20/01/2022 Make compatible to old code
1.9.1 K Hoang 26/01/2022 Update to be compatible with new FlashStorage libraries. Add support to more SAMD/STM32 boards
1.10.0 K Hoang 06/04/2022 Use Ethernet_Generic library as default. Add support to Portenta_H7 Ethernet and WiFi
1.10.1 K Hoang 25/09/2022 Add support to `RP2040W` using `CYW43439 WiFi` with `arduino-pico` core
**********************************************************************************************************************************/
#pragma once
#ifndef TIMEZONE_GENERIC_H
#define TIMEZONE_GENERIC_H
#include "Timezone_Generic.hpp"
#include "Timezone_Generic_Impl.h"
#endif // TIMEZONE_GENERIC_H