Модуль «Календарь»
C++
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 era_year = 1; // Переменная указывает на то, является ли искомый год годом нашей эры (era_year=1), либо годом до н.э. (era_year=0). Вычисляется из положительного, либо отрицательного CYear
int month_first_day = 0; // Переменная для хранения дня недели первого числа искомого месяца (Month First Day)
int type_1_leap = 0; // Количество накопившихся до искомой даты исключений из следования високосных лет Григорианского календаря. Год кратный 100, но не кратный 400 - не високосный. Первый тип исключений
int type_2_leap = 0; // Количество накопившихся до искомой даты исключений из следования високосных лет Григорианского календаря. Год кратный 400 - високосный. Второй тип исключений
//int start_week_day = 7; // Порядковый номер дня недели даты отсчета, то есть 01.01.0001 года, то есть суббота (6). Это точка отсчета для определения 1-го января искомого года ENG-7 RUS-6
int array_grid[42]; // Массив календаря. С 0-го до 41-го значения, то есть всего 42 значения для 6-и рядов из 7-и столбцов (сетка календаря)
int array_grid_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 array_grid_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 array_grid_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 end_day_month[]{31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Количество дней в месяцах года. Ряд массива смещен для удобства расчетов end_day_month[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);
era_year = 0;
}
// ### Вычисление дня недели первого числа искомого месяца ###
for (int i = cal_lang; i <= CMonth; i++) // было RUS i=2 ENG i=5
{
// Serial.println(i);
month_first_day += end_day_month[i - 1]; // Накапливаем смещение дня недели по каждому из прошедших в году месяцев
}
if ((int(CYear) > 1582 && ((int(CYear) % 4 == 0 && int(CYear) % 100 != 0) || int(CYear) % 400 == 0)) && era_year == 1)
{
end_day_month[2] = 29; // Прибавляем 29 февраля в високосных годах Григорианского календаря и смещаем один день с марта
if (CMonth > 2)
month_first_day++;
}
if ((int(CYear) < 1583 && int(CYear) % 4 == 0) && era_year == 1)
{
end_day_month[2] = 29; // Прибавляем 29 февраля в високосных годах Юлианского календаря н.э. и смещаем один день с марта
if (CMonth > 2)
month_first_day++;
}
if (((int(CYear - 1) % 4 == 0) && era_year == 0) || (CYear == 1 && era_year == 0))
{
end_day_month[2] = 29; // Прибавляем 29 февраля в високосных годах Юлианского календаря до н.э. и смещаем один день с марта
if (CMonth > 2)
month_first_day++;
}
if (CYear > 1582 && era_year == 1)
{
start_week_day = 10; // Изменение параметров для лет, после введения Григорианского календаря в октябре 1582 года. Меняется start_week_day и из расчета накопленных високосных лет уходят два типа исключений (type_1_leap и type_2_leap)
type_1_leap = (CYear - 1582) / 100;
type_2_leap = (CYear - 1582) / 400;
}
// ### Главный расчет ###
if (era_year == 1)
{ // Блок вычислений для определения дня недели 01 января лет н.э.
// FirstDay = round(modf(((CYear - 1 + (ceil(CYear / 4) - 1 - (type_1_leap - type_2_leap))) + month_first_day) / 7, &xxx) * 7) + start_week_day; // Расчет дня недели 1-го января искомого года. ПН-1, ВТ-2, и т.д.
FirstDay = round(modf(((CYear - 1 + (ceil(CYear / 4) - 1 - (type_1_leap - type_2_leap))) + month_first_day) / 7, &xxx) * 7) + start_week_day;
if (FirstDay > 7)
FirstDay = roundf(modf(float(FirstDay / 7), &xxx) * 7);
if (FirstDay == 0)
FirstDay = 7; // Корректировка значения если число вышло за 7, возвращение его в диапазон 1-7
}
if (era_year == 0 && CYear < 5)
{
FirstDay = round((modf(float((5 - CYear + month_first_day) / 7), &xxx)) * 7); // день недели искомого месяца первых 4-х лет до нашей эры
if (FirstDay == 0)
FirstDay = 7;
}
if (era_year == 0 && CYear >= 5)
{
FirstDay = (7 - abs(round(modf((4 - floor((CYear - 1) / 4) - CYear + 1) / 7, &xxx) * 7))) + round(modf(float(month_first_day) / 7, &xxx) * 7); // день недели искомого месяца с 5-го года до нашей эры и далее
if (FirstDay > 7)
FirstDay = round(modf(float(FirstDay / 7), &xxx) * 7);
}
// ### Публикация ###
for (int i = 1; i < FirstDay; i++)
{
array_grid[i - 1] = end_day_month[CMonth - 1] - (FirstDay - 1) + i; // Цикл заполнения календаря предыдущего месяца
}
for (int i = 0; i < 43; i++)
change_data[i] = 0;
for (int i = 1; i <= end_day_month[CMonth]; i++)
{
array_grid[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 = end_day_month[CMonth] + FirstDay - 1; i <= 41; i++)
{
if (CEnd != 1)
array_grid[i] = i - (end_day_month[CMonth] - 1) - (FirstDay - 1); // Цикл заполнения календаря предстоящего месяца
else
array_grid[i] = 0;
if (i == 28 || i == 35)
{
array_grid[i] = 0;
CEnd = 1;
}
}
// ### Исключения 1582 года ###
Iskl: // Метка, куда переходит выполнение программы если 10, 11, 12 месяц 1582 года
if (CYear == 1582 && CMonth == 10)
{ // Если октябрь 1982
for (int i = 0; i <= 41; i++)
array_grid[i] = array_grid_10_1582[i]; // Перезаполняем массив исходя из массива исключений
end_day_month[10] = 21; // Дней тогда было всего 21
FirstDay = 1; // Начинался с понедельника
}
if (CYear == 1582 && CMonth == 11)
{ // Если ноябрь 1982
for (int i = 0; i <= 41; i++)
array_grid[i] = array_grid_11_1582[i]; // Перезаполняем массив исходя из массива исключений
FirstDay = 1; // Начинался с понедельника
}
if (CYear == 1582 && CMonth == 12)
{ // Если декабрь 1982
for (int i = 0; i <= 41; i++)
array_grid[i] = array_grid_12_1582[i]; // Перезаполняем массив исходя из массива исключений
FirstDay = 3; // Начинался со среды
}
// for (int i=0; i<=41; i++) {Serial.print(array_grid[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(" era_year=");Serial.println(era_year); // Печать дня недели первого января искомого года для контроля
// ### Цикл печати ###
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 == cal_block_lang) // RUS (i + 1) % 7 == 0) ENG (i + 1) % 7 == 2)
{
Blok = 31; // 2-й блок иконок: обычные Сб и Вс
if ((array_grid[i - 1] == CDay) && (CMonth == (rtc.month) && CYear == float(rtc.year) + 2000))
Blok = 93; // 4-й блок: Сб и Вс - текущая дата
}
else if ((array_grid[i - 1] == CDay) && (CMonth == (rtc.month) && CYear == float(rtc.year) + 2000))
{
Blok = 62; // 3-й блок иконок: ПН-ПТ - текущая дата
}
if (i < FirstDay || i > FirstDay - 1 + end_day_month[CMonth])
Blok = 124; // 5-й блок. Даты соседних месяцев
if (array_grid[i - 1] == 0)
Blok = 0;
A[7] = array_grid[i-1] + Blok; // Значение + выбор блока картинок
SerialDwin.write(A, 8); // Выгружаем в порт
// Serial.print(Registr);Serial.print(":");Serial.print(A[7]);Serial.println("#"); //Печать для проверки правильности расчетов HEX
}
// Serial.print("№№№№№№№№№№");
dwin_year_v = (CYear);
dwin_year[6] = highByte(dwin_year_v);
dwin_year[7] = lowByte(dwin_year_v);
SerialDwin.write(dwin_year, 8);
// SerialDwin.flush();
dwin_month_v = (CMonth);
dwin_month[6] = highByte(dwin_month_v);
dwin_month[7] = lowByte(dwin_month_v);
SerialDwin.write(dwin_month, 8);
}