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, &field_second,
&text_weekday, &text_weekday,
&text_day_of_year, &text_day_of_year,
&text_in_dst_range,
&checkbox_dst_enable, &checkbox_dst_enable,
&options_dst_start_which, &options_dst_start_which,
&options_dst_start_weekday, &options_dst_start_weekday,
@ -100,18 +101,25 @@ SetDateTimeView::SetDateTimeView(
options_dst_start_month.set_options(month_options); options_dst_start_month.set_options(month_options);
options_dst_end_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) { const auto date_changed_fn = [this](int32_t) {
auto weekday = rtc_time::day_of_week(field_year.value(), field_month.value(), field_day.value()); handle_date_field_update();
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) : "-");
}; };
field_year.on_change = date_changed_fn; field_year.on_change = date_changed_fn;
field_month.on_change = date_changed_fn; field_month.on_change = date_changed_fn;
field_day.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::RTC datetime;
rtc_time::now(datetime); rtc_time::now(datetime);
SetDateTimeModel model{ SetDateTimeModel model{
@ -146,6 +154,17 @@ void SetDateTimeView::form_init(const SetDateTimeModel& model) {
} }
SetDateTimeModel SetDateTimeView::form_collect() { 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; pmem::dst_config_t dst;
dst.b.dst_enabled = static_cast<uint8_t>(checkbox_dst_enable.value()); 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()); 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_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_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()); dst.b.end_month = static_cast<uint8_t>(options_dst_end_month.selected_index_value());
return { return dst;
.year = static_cast<uint16_t>(field_year.value()), }
.month = static_cast<uint8_t>(field_month.value()),
.day = static_cast<uint8_t>(field_day.value()), void SetDateTimeView::handle_date_field_update() {
.hour = static_cast<uint8_t>(field_hour.value()), auto weekday = rtc_time::day_of_week(field_year.value(), field_month.value(), field_day.value());
.minute = static_cast<uint8_t>(field_minute.value()), auto doy = rtc_time::day_of_year(field_year.value(), field_month.value(), field_day.value());
.second = static_cast<uint8_t>(field_second.value()), bool valid_date = (field_day.value() <= rtc_time::days_per_month(field_year.value(), field_month.value()));
.dst = dst}; 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 ******************************************/ /* SetRadioView ******************************************/

View File

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

View File

@ -21,9 +21,10 @@
*/ */
#include "rtc_time.hpp" #include "rtc_time.hpp"
#include "portapack_persistent_memory.hpp"
using namespace lpc43xx;
using namespace portapack; using namespace portapack;
namespace pmem = portapack::persistent_memory; namespace pmem = portapack::persistent_memory;
namespace rtc_time { namespace rtc_time {
@ -77,8 +78,10 @@ rtc::RTC dst_adjust_returned_time(rtc::RTC& datetime) {
if (doy != dst_current_doy) { if (doy != dst_current_doy) {
if (datetime.year() != dst_current_year) if (datetime.year() != dst_current_year)
dst_update_date_range(datetime.year(), doy); dst_update_date_range(datetime.year(), doy);
else else {
dst_check_date_range(doy); dst_current_doy = doy;
dst_in_range = dst_check_date_range(doy, dst_start_doy, dst_end_doy);
}
} }
// Not in DST date range // 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) // Check if current date is within the DST range (called when date changes)
void dst_check_date_range(uint16_t doy) { bool dst_check_date_range(uint16_t doy, uint16_t start_doy, uint16_t end_doy) {
dst_current_doy = doy;
// Check if date is within DST range // Check if date is within DST range
// (note that dates are reversed in Southern hemisphere because Summer starts in December) // (note that dates are reversed in Southern hemisphere because Summer starts in December)
if (dst_start_doy <= dst_end_doy) if (start_doy <= end_doy)
dst_in_range = ((doy >= dst_start_doy) && (doy < dst_end_doy)); return ((doy >= start_doy) && (doy < end_doy));
else 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) // 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_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_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 { } else {
dst_in_range = false; 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. // 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. // 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. // 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 "signal.hpp"
#include "lpc43xx_cpp.hpp" #include "lpc43xx_cpp.hpp"
using namespace lpc43xx; #include "portapack_persistent_memory.hpp"
namespace rtc_time { namespace rtc_time {
@ -45,8 +45,9 @@ rtc::RTC now(rtc::RTC& out_datetime);
/* Daylight Savings Time functions */ /* Daylight Savings Time functions */
void dst_init(); void dst_init();
rtc::RTC dst_adjust_returned_time(rtc::RTC& datetime); 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); 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 days_per_month(uint16_t year, uint8_t month);
uint8_t current_day_of_week(); uint8_t current_day_of_week();
uint8_t day_of_week(uint16_t year, uint8_t month, uint8_t day); uint8_t day_of_week(uint16_t year, uint8_t month, uint8_t day);