void convertUnixTimeToDate(time_t t, DateTime *date) { uint32_t a; uint32_t b; uint32_t c; uint32_t d; uint32_t e; uint32_t f; //Negative Unix time values are not supported if(t < 1) t = 0; //Clear milliseconds date->milliseconds = 0; //Retrieve hours, minutes and seconds date->seconds = t % 60; t /= 60; date->minutes = t % 60; t /= 60; date->hours = t % 24; t /= 24; //Convert Unix time to date a = (uint32_t) ((4 * t + 102032) / 146097 + 15); b = (uint32_t) (t + 2442113 + a - (a / 4)); c = (20 * b - 2442) / 7305; d = b - 365 * c - (c / 4); e = d * 1000 / 30601; f = d - e * 30 - e * 601 / 1000; //January and February are counted as months 13 and 14 of the previous year if(e <= 13) { c -= 4716; e -= 1; } else { c -= 4715; e -= 13; } //Retrieve year, month and day date->year = c; date->month = e; date->day = f; //Calculate day of week date->dayOfWeek = computeDayOfWeek(c, e, f); }
void menuEditMonth(uint8_t flags) { if (flags & INTERFACE_MENU_INITIALIZE) { s_schoolYearForThisMonth = (uint16_t)controllerSettingsGetPointer()->schoolYear + 1900; if (s_editingMonth <= 7) s_schoolYearForThisMonth++; s_minDay = 1; s_maxDay = monthDays(s_editingMonth + 1, s_schoolYearForThisMonth); internalStorageMonthRead(s_editingMonth, &s_month); s_currentDay = s_minDay; s_multiselectMode = 0; s_multiselectCenter = 0; interfaceMenuTimerReset(0); } if (interfaceMenuTimerGet(0) >= MENU_HIGHLIGHT_TOGGLE_TICKS * 2) interfaceMenuTimerReset(0); if (menuEditMonthReturningMenuIsVisible()) { menuEditMonthWriteSave(); menuEditMonthWriteCancel(); switch(s_currentDay - s_maxDay) { case MENU_EDITMONTH_SAVE: if (menuEditMonthNeedBlink()) interfaceDisplayWriteChars(MENU_EDITMONTH_SAVE_X, MENU_EDITMONTH_SAVE_Y, ' ', 6); break; case MENU_EDITMONTH_CANCEL: if (menuEditMonthNeedBlink()) interfaceDisplayWriteChars(MENU_EDITMONTH_CANCEL_X, MENU_EDITMONTH_CANCEL_Y, ' ', 6); break; } } else { uint8_t dayDisplayStart = (s_currentDay - (MENU_EDITMONTH_DISPLAY_DAYS_COUNT / 2) > 1 ? s_currentDay - (MENU_EDITMONTH_DISPLAY_DAYS_COUNT / 2) : 1); if (dayDisplayStart > s_maxDay - (MENU_EDITMONTH_DISPLAY_DAYS_COUNT - 1)) dayDisplayStart = s_maxDay - (MENU_EDITMONTH_DISPLAY_DAYS_COUNT - 1); for (uint8_t i = 0; i < MENU_EDITMONTH_DISPLAY_DAYS_COUNT; i++) { uint8_t x = MENU_EDITMONTH_TITLE_X + i * MENU_EDITMONTH_TITLE_OFFSET; uint8_t day = dayDisplayStart + i; sprintf(menuBuffer, MENU_DAY_FORMAT, day); interfaceDisplayWrite(x, MENU_EDITMONTH_TITLE_Y, menuBuffer); uint8_t dayOfWeek = computeDayOfWeek(day, s_editingMonth + 1, s_schoolYearForThisMonth); if (dayOfWeek == MONDAY) { interfaceDisplayWriteChar(x - 1, MENU_EDITMONTH_TITLE_Y, MENU_EDITMONTH_WEEK_SEPARATOR_CHAR); interfaceDisplayWriteChar(x - 1, MENU_EDITMONTH_PROFILE_Y, MENU_EDITMONTH_WEEK_SEPARATOR_CHAR); } else if (dayOfWeek == SUNDAY && i == MENU_EDITMONTH_DISPLAY_DAYS_COUNT - 1) { interfaceDisplayWriteChar(x + 2, MENU_EDITMONTH_TITLE_Y, MENU_EDITMONTH_WEEK_SEPARATOR_CHAR); interfaceDisplayWriteChar(x + 2, MENU_EDITMONTH_PROFILE_Y, MENU_EDITMONTH_WEEK_SEPARATOR_CHAR); } } for (uint8_t i = 0; i < MENU_EDITMONTH_DISPLAY_DAYS_COUNT; i++) { uint8_t x = MENU_EDITMONTH_PROFILE_X + i * MENU_EDITMONTH_PROFILE_OFFSET; uint8_t day = dayDisplayStart + i; //if (day == s_currentDay && !s_multiselectMode) continue; interfaceDisplayWriteChar(x, MENU_EDITMONTH_PROFILE_Y, menuGetProfileChar(s_month.days[day])); } if (s_multiselectMode) { if (menuEditMonthNeedBlink()) { uint8_t start = s_multiselectCenter; uint8_t end = s_currentDay; int8_t len = (int8_t)start - (int8_t)end; if (len < 0) len = -len; int8_t minPos, maxPos; if (end > start) { maxPos = menuEditMonthGetCurrentX(); minPos = maxPos - len * MENU_EDITMONTH_PROFILE_OFFSET; maxPos++; // + 1 because profile takes two spaces if (minPos < 0) minPos = 0; } else if (start > end) { minPos = menuEditMonthGetCurrentX(); maxPos = minPos + len * MENU_EDITMONTH_PROFILE_OFFSET; if (maxPos > INTERFACE_DISPLAY_WIDTH) maxPos = INTERFACE_DISPLAY_WIDTH; } else // start == end { minPos = maxPos = menuEditMonthGetCurrentX(); } for (uint8_t i = minPos; i <= maxPos; i++) interfaceDisplayWriteChar(i, MENU_EDITMONTH_PROFILE_Y, 0xFF); } } else { if (menuEditMonthNeedBlink()) interfaceDisplayWriteChar(menuEditMonthGetCurrentX(), MENU_EDITMONTH_PROFILE_Y, ' '); } } s_returningMenuPreviousVisible = menuEditMonthReturningMenuIsVisible(); uint8_t up = interfaceHandleButtonPressed(INTERFACE_BUTTON_UP); uint8_t down = interfaceHandleButtonPressed(INTERFACE_BUTTON_DOWN); if (up && down) { s_multiselectMode ^= 1; // toggle s_multiselectCenter = s_currentDay; interfaceButtonsLock(); } else if (interfaceHandleButtonPulse(INTERFACE_BUTTON_SELECT)) { if (menuEditMonthReturningMenuIsVisible()) { switch(s_currentDay - s_maxDay) { case MENU_EDITMONTH_SAVE: controllerMonthUpdate(s_editingMonth, &s_month); interfaceMenuPrevious(); break; case MENU_EDITMONTH_CANCEL: interfaceMenuPrevious(); break; } } else { if (s_multiselectMode) { uint8_t rangeStart = s_multiselectCenter; uint8_t rangeEnd = s_currentDay; if (rangeStart > rangeEnd) { uint8_t tmp = rangeStart; rangeStart = rangeEnd; rangeEnd = tmp; } uint8_t rangeProfileCount[PROFILE_COUNT + 1]; // plus 1 because of no profile memset(&rangeProfileCount, 0, PROFILE_COUNT + 1); uint8_t bestProfile = 0; uint8_t oneProfileChoosen = 1; for (uint8_t i = rangeStart; i <= rangeEnd; i++) { uint8_t profile = s_month.days[i]; uint8_t tabIndex = (profile == 0xFF ? PROFILE_COUNT : profile); // PROFILE_COUNT is the last index if (profile == 0xFF) rangeProfileCount[tabIndex]++; else rangeProfileCount[tabIndex]++; if (rangeProfileCount[tabIndex] > rangeProfileCount[bestProfile == 0xFF ? PROFILE_COUNT : bestProfile]) { bestProfile = profile; } if (i > rangeStart && s_month.days[i - 1] != profile) oneProfileChoosen = 0; } uint8_t profileForAll = (oneProfileChoosen ? menuEditMonthComputeNextProfile(s_month.days[rangeStart]) : bestProfile); for (uint8_t i = rangeStart; i <= rangeEnd; i++) s_month.days[i] = profileForAll; } else { s_month.days[s_currentDay] = menuEditMonthComputeNextProfile(s_month.days[s_currentDay]); } } } else if (interfaceHandleButtonPulse(INTERFACE_BUTTON_UP) || up) { s_currentDay++; if (s_multiselectMode && s_currentDay > s_maxDay) s_currentDay = s_maxDay; else if (s_currentDay > s_maxDay + MENU_EDITMONTH_COUNT) s_currentDay = s_minDay; if (menuEditMonthReturningMenuIsVisible()) { menuEditMonthWriteSave(); menuEditMonthWriteCancel(); } } else if (interfaceHandleButtonPulse(INTERFACE_BUTTON_DOWN) || down) { s_currentDay--; if (s_multiselectMode && s_currentDay < s_minDay) s_currentDay = s_minDay; if (s_currentDay <= 0) s_currentDay = s_maxDay + MENU_EDITMONTH_COUNT; if (menuEditMonthReturningMenuIsVisible()) { menuEditMonthWriteSave(); menuEditMonthWriteCancel(); } } }