When setting Time & Date indicate if in DST range (#1851)

This commit is contained in:
Mark Thompson 2024-02-06 14:25:44 -06:00 committed by GitHub
parent 5ea1bff1e6
commit 61d9c051de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 25 deletions

View File

@ -81,6 +81,7 @@ SetDateTimeView::SetDateTimeView(
&field_second,
&text_weekday,
&text_day_of_year,
&text_in_dst_range,
&checkbox_dst_enable,
&options_dst_start_which,
&options_dst_start_weekday,
@ -100,18 +101,25 @@ SetDateTimeView::SetDateTimeView(
options_dst_start_month.set_options(month_options);
options_dst_end_month.set_options(month_options);
const auto dst_changed_fn = [this](size_t, uint32_t) {
handle_date_field_update();
};
const auto date_changed_fn = [this](int32_t) {
auto weekday = rtc_time::day_of_week(field_year.value(), field_month.value(), field_day.value());
auto doy = rtc_time::day_of_year(field_year.value(), field_month.value(), field_day.value());
bool valid_date = (field_day.value() <= rtc_time::days_per_month(field_year.value(), field_month.value()));
text_weekday.set(valid_date ? weekday_options[weekday].first : "-");
text_day_of_year.set(valid_date ? to_string_dec_uint(doy, 3) : "-");
handle_date_field_update();
};
field_year.on_change = date_changed_fn;
field_month.on_change = date_changed_fn;
field_day.on_change = date_changed_fn;
options_dst_start_which.on_change = dst_changed_fn;
options_dst_start_weekday.on_change = dst_changed_fn;
options_dst_start_month.on_change = dst_changed_fn;
options_dst_end_which.on_change = dst_changed_fn;
options_dst_end_weekday.on_change = dst_changed_fn;
options_dst_end_month.on_change = dst_changed_fn;
rtc::RTC datetime;
rtc_time::now(datetime);
SetDateTimeModel model{
@ -146,6 +154,17 @@ void SetDateTimeView::form_init(const SetDateTimeModel& model) {
}
SetDateTimeModel SetDateTimeView::form_collect() {
return {
.year = static_cast<uint16_t>(field_year.value()),
.month = static_cast<uint8_t>(field_month.value()),
.day = static_cast<uint8_t>(field_day.value()),
.hour = static_cast<uint8_t>(field_hour.value()),
.minute = static_cast<uint8_t>(field_minute.value()),
.second = static_cast<uint8_t>(field_second.value()),
.dst = dst_collect()};
}
pmem::dst_config_t SetDateTimeView::dst_collect() {
pmem::dst_config_t dst;
dst.b.dst_enabled = static_cast<uint8_t>(checkbox_dst_enable.value());
dst.b.start_which = static_cast<uint8_t>(options_dst_start_which.selected_index_value());
@ -154,14 +173,16 @@ SetDateTimeModel SetDateTimeView::form_collect() {
dst.b.end_which = static_cast<uint8_t>(options_dst_end_which.selected_index_value());
dst.b.end_weekday = static_cast<uint8_t>(options_dst_end_weekday.selected_index_value());
dst.b.end_month = static_cast<uint8_t>(options_dst_end_month.selected_index_value());
return {
.year = static_cast<uint16_t>(field_year.value()),
.month = static_cast<uint8_t>(field_month.value()),
.day = static_cast<uint8_t>(field_day.value()),
.hour = static_cast<uint8_t>(field_hour.value()),
.minute = static_cast<uint8_t>(field_minute.value()),
.second = static_cast<uint8_t>(field_second.value()),
.dst = dst};
return dst;
}
void SetDateTimeView::handle_date_field_update() {
auto weekday = rtc_time::day_of_week(field_year.value(), field_month.value(), field_day.value());
auto doy = rtc_time::day_of_year(field_year.value(), field_month.value(), field_day.value());
bool valid_date = (field_day.value() <= rtc_time::days_per_month(field_year.value(), field_month.value()));
text_weekday.set(valid_date ? weekday_options[weekday].first : "-");
text_day_of_year.set(valid_date ? to_string_dec_uint(doy, 3) : "-");
text_in_dst_range.set(checkbox_dst_enable.value() && rtc_time::dst_test_date_range(field_year.value(), doy, dst_collect()) ? "DST" : "");
}
/* SetRadioView ******************************************/

View File

@ -126,6 +126,9 @@ class SetDateTimeView : public View {
Text text_day_of_year{
{26 * 8, 6 * 16, 3 * 8, 16},
""};
Text text_in_dst_range{
{17 * 8, 7 * 16, 3 * 8, 16},
""};
Checkbox checkbox_dst_enable{
{2 * 8, 9 * 16},
@ -171,6 +174,8 @@ class SetDateTimeView : public View {
void form_init(const SetDateTimeModel& model);
SetDateTimeModel form_collect();
portapack::persistent_memory::dst_config_t dst_collect();
void handle_date_field_update();
};
struct SetFrequencyCorrectionModel {

View File

@ -21,9 +21,10 @@
*/
#include "rtc_time.hpp"
#include "portapack_persistent_memory.hpp"
using namespace lpc43xx;
using namespace portapack;
namespace pmem = portapack::persistent_memory;
namespace rtc_time {
@ -77,8 +78,10 @@ rtc::RTC dst_adjust_returned_time(rtc::RTC& datetime) {
if (doy != dst_current_doy) {
if (datetime.year() != dst_current_year)
dst_update_date_range(datetime.year(), doy);
else
dst_check_date_range(doy);
else {
dst_current_doy = doy;
dst_in_range = dst_check_date_range(doy, dst_start_doy, dst_end_doy);
}
}
// Not in DST date range
@ -105,15 +108,13 @@ rtc::RTC dst_adjust_returned_time(rtc::RTC& datetime) {
}
// Check if current date is within the DST range (called when date changes)
void dst_check_date_range(uint16_t doy) {
dst_current_doy = doy;
bool dst_check_date_range(uint16_t doy, uint16_t start_doy, uint16_t end_doy) {
// Check if date is within DST range
// (note that dates are reversed in Southern hemisphere because Summer starts in December)
if (dst_start_doy <= dst_end_doy)
dst_in_range = ((doy >= dst_start_doy) && (doy < dst_end_doy));
if (start_doy <= end_doy)
return ((doy >= start_doy) && (doy < end_doy));
else
dst_in_range = ((doy >= dst_start_doy) || (doy < dst_end_doy));
return ((doy >= start_doy) || (doy < end_doy));
}
// Update DST parameters (called at power-up, when year changes, or DST settings are changed)
@ -125,12 +126,20 @@ void dst_update_date_range(uint16_t year, uint16_t doy) {
dst_start_doy = day_of_year_of_nth_weekday(dst_current_year, dst.b.start_month, dst.b.start_which, dst.b.start_weekday);
dst_end_doy = day_of_year_of_nth_weekday(dst_current_year, dst.b.end_month, dst.b.end_which, dst.b.end_weekday);
dst_check_date_range(doy);
dst_current_doy = doy;
dst_in_range = dst_check_date_range(doy, dst_start_doy, dst_end_doy);
} else {
dst_in_range = false;
}
}
// Test date range for display purposes only when setting Time
bool dst_test_date_range(uint16_t year, uint16_t doy, pmem::dst_config_t dst) {
uint16_t start_doy = day_of_year_of_nth_weekday(year, dst.b.start_month, dst.b.start_which, dst.b.start_weekday);
uint16_t end_doy = day_of_year_of_nth_weekday(year, dst.b.end_month, dst.b.end_which, dst.b.end_weekday);
return dst_check_date_range(doy, start_doy, end_doy);
}
// Set RTC clock.
// If the user has enabled DST, the time entered and passed to this function is interpreted as having been adjusted for DST.
// When DST functionality is enabled in pmem, the value stored in the RTC hardware is non-DST time, and we only fudge the time when read.

View File

@ -25,7 +25,7 @@
#include "signal.hpp"
#include "lpc43xx_cpp.hpp"
using namespace lpc43xx;
#include "portapack_persistent_memory.hpp"
namespace rtc_time {
@ -45,8 +45,9 @@ rtc::RTC now(rtc::RTC& out_datetime);
/* Daylight Savings Time functions */
void dst_init();
rtc::RTC dst_adjust_returned_time(rtc::RTC& datetime);
void dst_check_date_range(uint16_t doy);
bool dst_check_date_range(uint16_t doy, uint16_t start_doy, uint16_t end_doy);
void dst_update_date_range(uint16_t year, uint16_t doy);
bool dst_test_date_range(uint16_t year, uint16_t doy, portapack::persistent_memory::dst_config_t dst);
uint8_t days_per_month(uint16_t year, uint8_t month);
uint8_t current_day_of_week();
uint8_t day_of_week(uint16_t year, uint8_t month, uint8_t day);