mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][FW][SW] Added option to set and read century when updating RTC datetime
This commit is contained in:
parent
6bbfee44e7
commit
e4af127e55
@ -329,17 +329,17 @@ _This command does not require arguments or data._
|
||||
|
||||
#### `response` (time)
|
||||
| offset | type | description |
|
||||
| ------ | ------- | ------------------------------------ |
|
||||
| ------ | ------- | ----------------------------------------- |
|
||||
| `0` | uint8_t | Weekday (1 - 7), 1 represents Monday |
|
||||
| `1` | uint8_t | Hours (0 - 23) |
|
||||
| `2` | uint8_t | Minutes (0 - 59) |
|
||||
| `3` | uint8_t | Seconds (0 - 59) |
|
||||
| `4` | uint8_t | _Unused_ (returns zero) |
|
||||
| `4` | uint8_t | Century (0 - 255), 0 represents year 1900 |
|
||||
| `5` | uint8_t | Year (0 - 99) |
|
||||
| `6` | uint8_t | Month (1 - 12) |
|
||||
| `7` | uint8_t | Day (1 - 31) |
|
||||
|
||||
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format.
|
||||
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format, except for the century field.
|
||||
|
||||
---
|
||||
|
||||
@ -357,15 +357,15 @@ Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decima
|
||||
|
||||
#### `arg1` (time_1)
|
||||
| bits | description |
|
||||
| --------- | -------------- |
|
||||
| `[31:24]` | _Unused_ |
|
||||
| --------- | ----------------------------------------- |
|
||||
| `[31:24]` | Century (0 - 255), 0 represents year 1900 |
|
||||
| `[23:16]` | Year (0 - 99) |
|
||||
| `[15:8]` | Month (1 - 12) |
|
||||
| `[7:0]` | Day (1 - 31) |
|
||||
|
||||
_This command does not send response data._
|
||||
|
||||
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format.
|
||||
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format, except for the century field.
|
||||
|
||||
---
|
||||
|
||||
|
@ -506,7 +506,7 @@ module mcu_top (
|
||||
|
||||
REG_RTC_TIME_1: begin
|
||||
reg_rdata <= {
|
||||
8'd0,
|
||||
7'd0, n64_scb.rtc_rdata[42],
|
||||
n64_scb.rtc_rdata[41:34],
|
||||
3'd0, n64_scb.rtc_rdata[33:29],
|
||||
2'd0, n64_scb.rtc_rdata[25:20]
|
||||
@ -849,6 +849,7 @@ module mcu_top (
|
||||
|
||||
REG_RTC_TIME_1: begin
|
||||
n64_scb.rtc_wdata_valid <= 1'b1;
|
||||
n64_scb.rtc_wdata[42] <= reg_wdata[24];
|
||||
n64_scb.rtc_wdata[41:34] <= reg_wdata[23:16];
|
||||
n64_scb.rtc_wdata[33:29] <= reg_wdata[12:8];
|
||||
n64_scb.rtc_wdata[25:20] <= reg_wdata[5:0];
|
||||
|
@ -40,8 +40,8 @@ interface n64_scb ();
|
||||
logic rtc_pending;
|
||||
logic rtc_done;
|
||||
logic rtc_wdata_valid;
|
||||
logic [41:0] rtc_rdata;
|
||||
logic [41:0] rtc_wdata;
|
||||
logic [42:0] rtc_rdata;
|
||||
logic [42:0] rtc_wdata;
|
||||
|
||||
logic cfg_unlock;
|
||||
logic cfg_pending;
|
||||
|
@ -362,6 +362,7 @@ module n64_si (
|
||||
logic [2:0] rtc_time_weekday;
|
||||
logic [4:0] rtc_time_month;
|
||||
logic [7:0] rtc_time_year;
|
||||
logic rtc_time_century;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
@ -377,6 +378,7 @@ module n64_si (
|
||||
|
||||
if (!(|rtc_stopped) && !n64_scb.rtc_pending && n64_scb.rtc_wdata_valid && (tx_state != TX_STATE_DATA)) begin
|
||||
{
|
||||
rtc_time_century,
|
||||
rtc_time_year,
|
||||
rtc_time_month,
|
||||
rtc_time_weekday,
|
||||
@ -408,6 +410,7 @@ module n64_si (
|
||||
4'd5: rtc_time_weekday <= rx_byte_data[2:0];
|
||||
4'd6: rtc_time_month <= rx_byte_data[4:0];
|
||||
4'd7: rtc_time_year <= rx_byte_data;
|
||||
4'd8: rtc_time_century <= rx_byte_data[0];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
@ -415,6 +418,7 @@ module n64_si (
|
||||
|
||||
always_comb begin
|
||||
n64_scb.rtc_rdata = {
|
||||
rtc_time_century,
|
||||
rtc_time_year,
|
||||
rtc_time_month,
|
||||
rtc_time_weekday,
|
||||
@ -469,7 +473,7 @@ module n64_si (
|
||||
4'd4: tx_byte_data = {5'd0, rtc_time_weekday};
|
||||
4'd5: tx_byte_data = {3'd0, rtc_time_month};
|
||||
4'd6: tx_byte_data = rtc_time_year;
|
||||
4'd7: tx_byte_data = 8'h01;
|
||||
4'd7: tx_byte_data = {7'd0, rtc_time_century};
|
||||
4'd8: tx_byte_data = {(|rtc_stopped), 7'd0};
|
||||
endcase
|
||||
end
|
||||
|
@ -263,10 +263,11 @@ sc64_error_t sc64_get_time (sc64_rtc_time_t *t) {
|
||||
.id = CMD_ID_TIME_GET
|
||||
};
|
||||
sc64_error_t error = sc64_execute_cmd(&cmd);
|
||||
t->weekday = ((cmd.rsp[0] >> 24) & 0xFF);
|
||||
t->hour = ((cmd.rsp[0] >> 16) & 0xFF);
|
||||
t->minute = ((cmd.rsp[0] >> 8) & 0xFF);
|
||||
t->second = (cmd.rsp[0] & 0xFF);
|
||||
t->weekday = ((cmd.rsp[1] >> 24) & 0xFF);
|
||||
t->century = ((cmd.rsp[1] >> 24) & 0xFF);
|
||||
t->year = ((cmd.rsp[1] >> 16) & 0xFF);
|
||||
t->month = ((cmd.rsp[1] >> 8) & 0xFF);
|
||||
t->day = (cmd.rsp[1] & 0xFF);
|
||||
@ -275,11 +276,12 @@ sc64_error_t sc64_get_time (sc64_rtc_time_t *t) {
|
||||
|
||||
sc64_error_t sc64_set_time (sc64_rtc_time_t *t) {
|
||||
uint32_t time[2] = {(
|
||||
((t->weekday << 24) & 0xFF) |
|
||||
((t->hour << 16) & 0xFF) |
|
||||
((t->minute << 8) & 0xFF) |
|
||||
(t->second & 0xFF)
|
||||
), (
|
||||
((t->weekday << 24) & 0xFF) |
|
||||
((t->century << 24) & 0xFF) |
|
||||
((t->year << 16) & 0xFF) |
|
||||
((t->month << 8) & 0xFF) |
|
||||
(t->day & 0xFF)
|
||||
|
@ -149,6 +149,7 @@ typedef struct {
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
uint8_t century;
|
||||
} sc64_rtc_time_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -110,7 +110,7 @@ static void test_sc64_cfg (void) {
|
||||
}
|
||||
|
||||
display_printf("RTC current time:\n ");
|
||||
display_printf("%04d-%02d-%02d", 2000 + FROM_BCD(t.year), FROM_BCD(t.month), FROM_BCD(t.day));
|
||||
display_printf("%04d-%02d-%02d", 1900 + (t.century * 100) + FROM_BCD(t.year), FROM_BCD(t.month), FROM_BCD(t.day));
|
||||
display_printf("T");
|
||||
display_printf("%02d:%02d:%02d", FROM_BCD(t.hour), FROM_BCD(t.minute), FROM_BCD(t.second));
|
||||
display_printf(" (%s)", weekdays[FROM_BCD(t.weekday)]);
|
||||
|
@ -437,8 +437,8 @@ save_type_t cfg_get_save_type (void) {
|
||||
void cfg_get_time (uint32_t *args) {
|
||||
rtc_time_t t;
|
||||
rtc_get_time(&t);
|
||||
args[0] = ((t.hour << 16) | (t.minute << 8) | t.second);
|
||||
args[1] = ((t.weekday << 24) | (t.year << 16) | (t.month << 8) | t.day);
|
||||
args[0] = ((t.weekday << 24) | (t.hour << 16) | (t.minute << 8) | t.second);
|
||||
args[1] = ((t.century << 24) | (t.year << 16) | (t.month << 8) | t.day);
|
||||
}
|
||||
|
||||
void cfg_set_time (uint32_t *args) {
|
||||
@ -450,6 +450,7 @@ void cfg_set_time (uint32_t *args) {
|
||||
t.day = (args[1] & 0xFF);
|
||||
t.month = ((args[1] >> 8) & 0xFF);
|
||||
t.year = ((args[1] >> 16) & 0xFF);
|
||||
t.century = ((args[1] >> 24) & 0xFF);
|
||||
rtc_set_time(&t);
|
||||
}
|
||||
|
||||
|
@ -365,6 +365,7 @@ void dd_process (void) {
|
||||
case DD_CMD_SET_RTC_MINUTE_SECOND:
|
||||
p.time.minute = ((data >> 8) & 0xFF);
|
||||
p.time.second = (data & 0xFF);
|
||||
p.time.century = (p.time.year >= 0x96) ? 0 : 1;
|
||||
rtc_set_time(&p.time);
|
||||
break;
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#define RTC_ADDRESS_SRAM_REGION (0x24)
|
||||
#define RTC_ADDRESS_SRAM_VERSION (0x28)
|
||||
#define RTC_ADDRESS_SRAM_SETTINGS (0x2C)
|
||||
#define RTC_ADDRESS_SRAM_CENTURY (0x40)
|
||||
#define RTC_ADDRESS_SRAM_LAST_YEAR (0x41)
|
||||
|
||||
#define RTC_RTCSEC_ST (1 << 7)
|
||||
|
||||
@ -37,8 +39,9 @@ static rtc_time_t rtc_time = {
|
||||
.hour = 0x12,
|
||||
.weekday = 0x01,
|
||||
.day = 0x01,
|
||||
.month = 0x01,
|
||||
.year = 0x24
|
||||
.month = 0x06,
|
||||
.year = 0x24,
|
||||
.century = 0x01,
|
||||
};
|
||||
static bool rtc_time_pending = false;
|
||||
|
||||
@ -102,10 +105,17 @@ static void rtc_osc_stop (void) {
|
||||
|
||||
static void rtc_read_time (void) {
|
||||
uint8_t regs[7];
|
||||
uint8_t last_year;
|
||||
|
||||
if (rtc_read(RTC_ADDRESS_RTCSEC, regs, 7)) {
|
||||
return;
|
||||
}
|
||||
if (rtc_read(RTC_ADDRESS_SRAM_CENTURY, &rtc_time.century, 1)) {
|
||||
return;
|
||||
}
|
||||
if (rtc_read(RTC_ADDRESS_SRAM_LAST_YEAR, &last_year, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rtc_sanitize_time(regs);
|
||||
|
||||
@ -116,6 +126,15 @@ static void rtc_read_time (void) {
|
||||
rtc_time.day = regs[4];
|
||||
rtc_time.month = regs[5];
|
||||
rtc_time.year = regs[6];
|
||||
|
||||
if (rtc_time.year < last_year) {
|
||||
rtc_time.century += 1;
|
||||
rtc_write(RTC_ADDRESS_SRAM_CENTURY, &rtc_time.century, 1);
|
||||
}
|
||||
|
||||
if (rtc_time.year != last_year) {
|
||||
rtc_write(RTC_ADDRESS_SRAM_LAST_YEAR, &rtc_time.year, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_write_time (void) {
|
||||
@ -136,8 +155,12 @@ static void rtc_write_time (void) {
|
||||
regs[0] |= RTC_RTCSEC_ST;
|
||||
regs[3] |= RTC_RTCWKDAY_VBATEN;
|
||||
|
||||
rtc_write(RTC_ADDRESS_SRAM_CENTURY, &rtc_time.century, 1);
|
||||
rtc_write(RTC_ADDRESS_SRAM_LAST_YEAR, &rtc_time.year, 1);
|
||||
rtc_write(RTC_ADDRESS_RTCMIN, ®s[1], 6);
|
||||
rtc_write(RTC_ADDRESS_RTCSEC, ®s[0], 1);
|
||||
|
||||
rtc_read_time();
|
||||
}
|
||||
|
||||
static void rtc_read_region (void) {
|
||||
@ -165,6 +188,7 @@ void rtc_get_time (rtc_time_t *time) {
|
||||
time->day = rtc_time.day;
|
||||
time->month = rtc_time.month;
|
||||
time->year = rtc_time.year;
|
||||
time->century = rtc_time.century;
|
||||
}
|
||||
|
||||
void rtc_set_time (rtc_time_t *time) {
|
||||
@ -175,6 +199,7 @@ void rtc_set_time (rtc_time_t *time) {
|
||||
rtc_time.day = time->day;
|
||||
rtc_time.month = time->month;
|
||||
rtc_time.year = time->year;
|
||||
rtc_time.century = time->century;
|
||||
rtc_time_pending = true;
|
||||
}
|
||||
|
||||
@ -254,6 +279,7 @@ void rtc_process (void) {
|
||||
rtc_time.hour = ((data[0] >> 16) & 0xFF);
|
||||
rtc_time.minute = ((data[0] >> 8) & 0xFF);
|
||||
rtc_time.second = ((data[0] >> 0) & 0xFF);
|
||||
rtc_time.century = ((data[1] >> 24) & 0xFF);
|
||||
rtc_time.year = ((data[1] >> 16) & 0xFF);
|
||||
rtc_time.month = ((data[1] >> 8) & 0xFF);
|
||||
rtc_time.day = ((data[1] >> 0) & 0xFF);
|
||||
@ -293,6 +319,7 @@ void rtc_process (void) {
|
||||
(rtc_time.second << 0)
|
||||
);
|
||||
data[1] = (
|
||||
(rtc_time.century << 24) |
|
||||
(rtc_time.year << 16) |
|
||||
(rtc_time.month << 8) |
|
||||
(rtc_time.day << 0)
|
||||
|
@ -14,6 +14,7 @@ typedef struct {
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
uint8_t century;
|
||||
} rtc_time_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -781,7 +781,7 @@ fn handle_set_command(connection: Connection, command: &SetCommands) -> Result<(
|
||||
|
||||
match command {
|
||||
SetCommands::Rtc => {
|
||||
let datetime = Local::now();
|
||||
let datetime = Local::now().naive_local();
|
||||
sc64.set_datetime(datetime)?;
|
||||
println!(
|
||||
"SC64 RTC datetime synchronized to: {}",
|
||||
|
@ -25,7 +25,7 @@ use self::{
|
||||
get_config, get_setting, Config, ConfigId, FirmwareStatus, Setting, SettingId, UpdateStatus,
|
||||
},
|
||||
};
|
||||
use chrono::{DateTime, Local};
|
||||
use chrono::NaiveDateTime;
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
cmp::min,
|
||||
@ -55,7 +55,7 @@ pub struct DeviceState {
|
||||
pub button_mode: ButtonMode,
|
||||
pub rom_extended_enable: Switch,
|
||||
pub led_enable: Switch,
|
||||
pub datetime: DateTime<Local>,
|
||||
pub datetime: NaiveDateTime,
|
||||
pub fpga_debug_data: FpgaDebugData,
|
||||
pub diagnostic_data: DiagnosticData,
|
||||
}
|
||||
@ -210,7 +210,7 @@ impl SC64 {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn command_time_get(&mut self) -> Result<DateTime<Local>, Error> {
|
||||
fn command_time_get(&mut self) -> Result<NaiveDateTime, Error> {
|
||||
let data = self.link.execute_command(&Command {
|
||||
id: b't',
|
||||
args: [0, 0],
|
||||
@ -224,7 +224,7 @@ impl SC64 {
|
||||
Ok(convert_to_datetime(&data[0..8].try_into().unwrap())?)
|
||||
}
|
||||
|
||||
fn command_time_set(&mut self, datetime: DateTime<Local>) -> Result<(), Error> {
|
||||
fn command_time_set(&mut self, datetime: NaiveDateTime) -> Result<(), Error> {
|
||||
self.link.execute_command(&Command {
|
||||
id: b'T',
|
||||
args: convert_from_datetime(datetime),
|
||||
@ -529,11 +529,11 @@ impl SC64 {
|
||||
self.command_config_set(Config::TvType(tv_type))
|
||||
}
|
||||
|
||||
pub fn get_datetime(&mut self) -> Result<DateTime<Local>, Error> {
|
||||
pub fn get_datetime(&mut self) -> Result<NaiveDateTime, Error> {
|
||||
self.command_time_get()
|
||||
}
|
||||
|
||||
pub fn set_datetime(&mut self, datetime: DateTime<Local>) -> Result<(), Error> {
|
||||
pub fn set_datetime(&mut self, datetime: NaiveDateTime) -> Result<(), Error> {
|
||||
self.command_time_set(datetime)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::Error;
|
||||
use chrono::{DateTime, Datelike, Local, NaiveDateTime, TimeZone, Timelike};
|
||||
use chrono::{Datelike, NaiveDateTime, Timelike};
|
||||
|
||||
pub fn u8_from_bcd(value: u8) -> u8 {
|
||||
(((value & 0xF0) >> 4) * 10) + (value & 0x0F)
|
||||
@ -9,31 +9,31 @@ pub fn bcd_from_u8(value: u8) -> u8 {
|
||||
(((value / 10) & 0x0F) << 4) | ((value % 10) & 0x0F)
|
||||
}
|
||||
|
||||
pub fn convert_to_datetime(data: &[u8; 8]) -> Result<DateTime<Local>, Error> {
|
||||
let hour = u8_from_bcd(data[1]);
|
||||
let minute = u8_from_bcd(data[2]);
|
||||
pub fn convert_to_datetime(data: &[u8; 8]) -> Result<NaiveDateTime, Error> {
|
||||
let second = u8_from_bcd(data[3]);
|
||||
let year = u8_from_bcd(data[5]) as u32 + 2000;
|
||||
let month = u8_from_bcd(data[6]);
|
||||
let minute = u8_from_bcd(data[2]);
|
||||
let hour = u8_from_bcd(data[1]);
|
||||
let day = u8_from_bcd(data[7]);
|
||||
let native = &NaiveDateTime::parse_from_str(
|
||||
&format!("{year:02}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"),
|
||||
let month = u8_from_bcd(data[6]);
|
||||
let year = 1900u32 + (data[4] as u32 * 100) + u8_from_bcd(data[5]) as u32;
|
||||
NaiveDateTime::parse_from_str(
|
||||
&format!("{year:4}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"),
|
||||
"%Y-%m-%dT%H:%M:%S",
|
||||
)
|
||||
.map_err(|_| Error::new("Couldn't convert from bytes to DateTime<Local>"))?;
|
||||
Ok(Local.from_local_datetime(native).unwrap())
|
||||
.map_err(|_| Error::new("Couldn't convert from bytes to NaiveDateTime"))
|
||||
}
|
||||
|
||||
pub fn convert_from_datetime(datetime: DateTime<Local>) -> [u32; 2] {
|
||||
let weekday = bcd_from_u8((datetime.weekday() as u8) + 1);
|
||||
let hour = bcd_from_u8(datetime.hour() as u8);
|
||||
let minute = bcd_from_u8(datetime.minute() as u8);
|
||||
pub fn convert_from_datetime(datetime: NaiveDateTime) -> [u32; 2] {
|
||||
let second = bcd_from_u8(datetime.second() as u8);
|
||||
let year = bcd_from_u8((datetime.year() - 2000) as u8);
|
||||
let month = bcd_from_u8(datetime.month() as u8);
|
||||
let minute = bcd_from_u8(datetime.minute() as u8);
|
||||
let hour = bcd_from_u8(datetime.hour() as u8);
|
||||
let weekday = bcd_from_u8((datetime.weekday() as u8) + 1);
|
||||
let day = bcd_from_u8(datetime.day() as u8);
|
||||
let month = bcd_from_u8(datetime.month() as u8);
|
||||
let year = bcd_from_u8((datetime.year() % 100) as u8);
|
||||
let century = ((datetime.year() - 1900) / 100) as u8;
|
||||
[
|
||||
u32::from_be_bytes([weekday, hour, minute, second]),
|
||||
u32::from_be_bytes([0, year, month, day]),
|
||||
u32::from_be_bytes([century, year, month, day]),
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user