-
Notifications
You must be signed in to change notification settings - Fork 1
/
iCalendar.h
170 lines (161 loc) · 15.8 KB
/
iCalendar.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
1-й блок картинок 01-31: обычные дни ПН-ПТ
2-й блок картинок 32-62: обычные СБ-ВС
3-й блок картинок 63-93: ПН-ПТ - сегодня
4-й блок картинок 94-124: СБ-ВС - сегодня
5-й блок картинок 125-156: дни других месяцев (хвосты)
ДАНО: Задаем год для вычисления возможного високосного февраля int Year
ДАНО: Задаем значение месяца int Month
ДАНО: текущее число int Today
ДАНО: Текущий день недели int Today_w
*/
void Calendar() {
// CYear Входящие данные: год для расчета
// CMonth Входящие данные: месяц для расчета
// CDay Входящие данные: день для расчета
//int change_data[43] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Массив для изменения текущей даты touch screen
byte dwin_day[] = { 0x5A, 0xA5, 0x05, 0x82, 0X57, 0x00, 0x00, 0x00 }; // Расчетное значение день месяца
byte dwin_month[] = { 0x5A, 0xA5, 0x05, 0x82, 0X58, 0x00, 0x00, 0x00 }; // Расчетное значение номера месяца
byte dwin_year[] = { 0x5A, 0xA5, 0x05, 0x82, 0X59, 0x00, 0x00, 0x00 }; // Расчетное значение год
int dwin_year_v;
int dwin_month_v;
rtc.DSread(); // Чтение модуля RTC
int AD = 1; // Переменная указывает на то, является ли искомый год годом нашей эры (AD=1), либо годом до н.э. (AD=0). Вычисляется из положительного, либо отрицательного CYear
int MFD = 0; // Переменная для хранения дня недели первого числа искомого месяца (Month First Day)
int V1 = 0; // Количество накопившихся до искомой даты исключений из следования високосных лет Григорианского календаря. Год кратный 100, но не кратный 400 - не високосный. Первый тип исключений
int V2 = 0; // Количество накопившихся до искомой даты исключений из следования високосных лет Григорианского календаря. Год кратный 400 - високосный. Второй тип исключений
int Offset = 6; // Порядковый номер дня недели даты отсчета, то есть 01.01.0001 года, то есть суббота (6). Это точка отсчета для определения 1-го января искомого года
int Cal[41]; // Массив календаря. С 0-го до 41-го значения, то есть всего 42 значения для 6-и рядов из 7-и столбцов (сетка календаря)
int Cal_10_1582[] = { 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Календарь октября 1582 - исключение;
int Cal_11_1582[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0 }; // Календарь ноября 1582 - исключение;
int Cal_12_1582[] = { 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 0, 0, 0, 0, 0, 0, 0 }; // Календарь декабря 1582 - исключение;
int M[]{ 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // Количество дней в месяцах года. Ряд массива смещен для удобства расчетов m[0]=31 - условный "январь" предыдущего года
char str_hex[10]; // Служебные переменные для перевода из HEX в DEC
unsigned char A[] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x00, 0x00, 0x00 }; // Передаваемый в порт массив
int Registr_ID = 6000 - 10; // Начальное значение регистра адресов, куда будут вписываться числа месяца
int Registr = 0; // Вычисляемое значение регистра (переменной), в который будет записано значение даты
float FirstDay; // Переменная дня недели 01 января искомого года
int CEnd = 0; // Переменная определяет, когда перестать печатать дни предстоящего месяца (загасить лишнюю строку)
double xxx;
//Serial.println("debug4");
if (CYear==1582 && (CMonth==10 || CMonth==11 || CMonth==12)) goto Iskl; // Пропускаем расчет, если октябрь-декабрь 1582 года, то есть исключения
// ### Вычисление эры ###
if (CYear < 0) {
CYear = abs(CYear);
AD = 0;
}
// ### Вычисление дня недели первого числа искомого месяца ###
for (int i = 2; i <= CMonth; i++) {
//Serial.println(i);
MFD += M[i - 1]; // Накапливаем смещение дня недели по каждому из прошедших в году месяцев
}
if ((int(CYear) > 1582 && ((int(CYear) % 4 == 0 && int(CYear) % 100 != 0) || int(CYear) % 400 == 0)) && AD == 1) {
M[2] = 29; // Прибавляем 29 февраля в високосных годах Григорианского календаря и смещаем один день с марта
if (CMonth > 2) MFD++;
}
if ((int(CYear) < 1583 && int(CYear) % 4 == 0) && AD == 1) {
M[2] = 29; // Прибавляем 29 февраля в високосных годах Юлианского календаря н.э. и смещаем один день с марта
if (CMonth > 2) MFD++;
}
if (((int(CYear - 1) % 4 == 0) && AD == 0) || (CYear == 1 && AD == 0)) {
M[2] = 29; // Прибавляем 29 февраля в високосных годах Юлианского календаря до н.э. и смещаем один день с марта
if (CMonth > 2) MFD++;
}
if (CYear > 1582 && AD == 1) {
Offset = 10; // Изменение параметров для лет, после введения Григорианского календаря в октябре 1582 года. Меняется Offset и из расчета накопленных високосных лет уходят два типа исключений (V1 и V2)
V1 = (CYear - 1582) / 100;
V2 = (CYear - 1582) / 400;
}
// ### Главный расчет ###
if (AD == 1) { // Блок вычислений для определения дня недели 01 января лет н.э.
//FirstDay = round(modf(((CYear - 1 + (ceil(CYear / 4) - 1 - (V1 - V2))) + MFD) / 7, &xxx) * 7) + Offset; // Расчет дня недели 1-го января искомого года. ПН-1, ВТ-2, и т.д.
FirstDay = round(modf(((CYear - 1 + (ceil(CYear / 4) - 1 - (V1 - V2))) + MFD) / 7, &xxx) * 7) + Offset;
if (FirstDay > 7) FirstDay = roundf(modf(float(FirstDay / 7), &xxx) * 7);
if (FirstDay == 0) FirstDay = 7; // Корректировка значения если число вышло за 7, возвращение его в диапазон 1-7
}
if (AD == 0 && CYear < 5) {
FirstDay = round((modf(float((5 - CYear + MFD) / 7), &xxx)) * 7); // день недели искомого месяца первых 4-х лет до нашей эры
if (FirstDay == 0) FirstDay = 7;
}
if (AD == 0 && CYear >= 5) {
FirstDay = (7 - abs(round(modf((4 - floor((CYear - 1) / 4) - CYear + 1) / 7, &xxx) * 7))) + round(modf(float(MFD) / 7, &xxx) * 7); // день недели искомого месяца с 5-го года до нашей эры и далее
if (FirstDay > 7) FirstDay = round(modf(float(FirstDay / 7), &xxx) * 7);
}
// ### Публикация ###
for (int i = 1; i < FirstDay; i++) {
Cal[i - 1] = M[CMonth - 1] - (FirstDay - 1) + i; // Цикл заполнения календаря предыдущего месяца
}
for (int i = 0; i < 43; i++) change_data[i] = 0;
for (int i = 1; i <= M[CMonth]; i++) {
Cal[i - 1 + int(FirstDay) - 1] = i; // Цикл заполнения календаря текущего месяца
change_data[int(FirstDay) + i - 1] = i; // Заполнение глобального массива для изменения текущего числа
}
//for (int d = 0; d < 43; d++) Serial.println(change_data[d]); // Печать массива, который для изменения даты в модуле часов
for (int i = M[CMonth] + FirstDay - 1; i <= 41; i++) {
if (CEnd != 1) Cal[i] = i - (M[CMonth] - 1) - (FirstDay - 1); // Цикл заполнения календаря предстоящего месяца
else Cal[i] = 0;
if (i == 28 || i == 35) {
Cal[i] = 0;
CEnd = 1;
}
}
// ### Исключения 1582 года ###
Iskl: // Метка, куда переходит выполнение программы если 10, 11, 12 месяц 1582 года
if (CYear == 1582 && CMonth == 10) { // Если октябрь 1982
for (int i = 0; i <= 41; i++) Cal[i] = Cal_10_1582[i]; // Перезаполняем массив исходя из массива исключений
M[10] = 21; // Дней тогда было всего 21
FirstDay = 1; // Начинался с понедельника
}
if (CYear == 1582 && CMonth == 11) { // Если ноябрь 1982
for (int i = 0; i <= 41; i++) Cal[i] = Cal_11_1582[i]; // Перезаполняем массив исходя из массива исключений
FirstDay = 1; // Начинался с понедельника
}
if (CYear == 1582 && CMonth == 12) { // Если декабрь 1982
for (int i = 0; i <= 41; i++) Cal[i] = Cal_12_1582[i]; // Перезаполняем массив исходя из массива исключений
FirstDay = 3; // Начинался со среды
}
//for (int i=0; i<=41; i++) {Serial.print(Cal[i]);Serial.print("#");} //Печать для проверки правильности расчетов HEX
//Serial.println();Serial.print("01.");Serial.print(CMonth);Serial.print(".");Serial.print(CYear, 0);Serial.print(" = ");Serial.print(int(FirstDay));Serial.print(" AD=");Serial.println(AD); // Печать дня недели первого января искомого года для контроля
// ### Цикл печати ###
for (int i = 1; i <= 42; i++) {
itoa(Registr_ID + i * 10, str_hex, 10); // Преобразуем int в строку в DEC. Будем считать, что это HEX
Registr = (int)strtol(str_hex, NULL, 16); // Получаем из HEX-строки новое число. Присваиваем переведенное из HEX в DEC число
A[4] = highByte(Registr); // Меняем значение регистра и числа в массиве
A[5] = lowByte(Registr);
/* Выбор блока иконок
1-й блок картинок 01-31: обычные дни ПН-ПТ - по умолчанию
2-й блок картинок 32-62: обычные СБ-ВС
3-й блок картинок 63-93: ПН-ПТ - сегодня
4-й блок картинок 94-124: СБ-ВС - сегодня
5-й блок картинок 125-156: дни других месяцев (хвосты) */
int Blok = 0; // Переменная, которая определяет первый файл типа иконки числа, соответствующих определенному дню месяца календаря
if (i % 7 == 0 || (i + 1) % 7 == 0) {
Blok = 31; // 2-й блок иконок: обычные Сб и Вс
/*
Serial.print("CYear: ");
Serial.println(CYear);
Serial.print("rtc.year: ");
Serial.println(float(rtc.year)+2000);
*/
if ((Cal[i - 1] == CDay) && (CMonth == (rtc.month) && CYear == float(rtc.year) + 2000)) Blok = 93; // 4-й блок: Сб и Вс - текущая дата
} else if ((Cal[i - 1] == CDay) && (CMonth == (rtc.month) && CYear == float(rtc.year) + 2000)) {
Blok = 62; // 3-й блок иконок: ПН-ПТ - текущая дата
}
if (i < FirstDay || i > FirstDay - 1 + M[CMonth]) Blok = 124; // 5-й блок. Даты соседних месяцев
if (Cal[i - 1] == 0) Blok = 0;
A[7] = Cal[i - 1] + Blok; // Значение + выбор блока картинок
//Serial.println(A[7]);
//Serial.println("Calendar send");
Serial2.write(A, 8); // Выгружаем в порт
//Serial2.flush(); // Ждем до завершения передачи
//Serial.print(Registr);Serial.print(":");Serial.print(A[7]);Serial.println("#"); //Печать для проверки правильности расчетов HEX
}
dwin_year_v = (CYear);
dwin_year[6] = highByte(dwin_year_v);
dwin_year[7] = lowByte(dwin_year_v);
Serial2.write(dwin_year, 8);
dwin_month_v = (CMonth);
dwin_month[6] = highByte(dwin_month_v);
dwin_month[7] = lowByte(dwin_month_v);
Serial2.write(dwin_month, 8);
}