1//! Seiko S-3511A real-time clock chip 2//! 3//! Used by Pokemon, Boktai, Rockman EXE 4.5, and maybe others 4 5use crate::interrupts::{InterruptRegisters, InterruptType}; 6use bincode::{Decode, Encode}; 7use jgenesis_common::num::{GetBit, U16Ext}; 8use jgenesis_common::{define_bit_enum, timeutils}; 9 10define_bit_enum!(Hours, [Twelve, TwentyFour]); 11define_bit_enum!(BeforeNoon, [Am, Pm]); 12 13impl BeforeNoon { 14 #[must_use] 15 fn toggle(self) -> Self { 16 match self { 17 Self::Am => Self::Pm, 18 Self::Pm => Self::Am, 19 } 20 } 21} 22 23#[derive(Debug, Clone, Encode, Decode)] 24struct Control { 25 power_cycled: bool, // POWER 26 hours: Hours, // 12/24 27 alarm_interrupt: bool, // INTAE 28 per_minute_interrupt: bool, // INTME 29 frequency_interrupt: bool, // INTFE 30} 31 32impl Default for Control { 33 fn default() -> Self { 34 // Per the datasheet, defaults to 0x82 at power-on (POWER and INTFE set) 35 // However, Sennen Kazoku depends on the chip initially being in 24-hour mode, and some games 36 // assume the chip is broken if they ever see the POWER bit set after first boot 37 Self { 38 power_cycled: false, 39 hours: Hours::TwentyFour, 40 alarm_interrupt: false, 41 per_minute_interrupt: false, 42 frequency_interrupt: false, 43 } 44 } 45} 46 47impl Control { 48 fn read(&self) -> u8 { 49 (u8::from(self.power_cycled) << 7) 50 | ((self.hours as u8) << 6) 51 | (u8::from(self.alarm_interrupt) << 5) 52 | (u8::from(self.per_minute_interrupt) << 3) 53 | (u8::from(self.frequency_interrupt) << 1) 54 } 55 56 fn write(&mut self, value: u8) { 57 self.hours = Hours::from_bit(value.bit(6)); 58 self.alarm_interrupt = value.bit(5); 59 self.per_minute_interrupt = value.bit(3); 60 self.frequency_interrupt = value.bit(1); 61 62 log::trace!("Control write: {value:02X}"); 63 log::trace!(" 12/24: {:?}", self.hours); 64 log::trace!(" INTAE: {}", self.alarm_interrupt); 65 log::trace!(" INTME: {}", self.per_minute_interrupt); 66 log::trace!(" INTFE: {}", self.frequency_interrupt); 67 68 if self.frequency_interrupt && !self.per_minute_interrupt { 69 log::error!("Frequency interrupts are not implemented"); 70 } 71 } 72} 73 74#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 75struct DateTime { 76 year: u8, 77 month: u8, 78 day: u8, 79 day_of_week: u8, 80 hour: u8, 81 before_noon: BeforeNoon, 82 minute: u8, 83 second: u8, 84 nanos: u128, 85} 86 87impl Default for DateTime { 88 fn default() -> Self { 89 Self { 90 year: 0, 91 month: 1, 92 day: 1, 93 day_of_week: 0, 94 hour: 0, 95 before_noon: BeforeNoon::Am, 96 minute: 0, 97 second: 0, 98 nanos: 0, 99 } 100 } 101} 102 103define_bit_enum!(CommandDirection, [Write, Read]); 104 105#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 106enum Command { 107 Reset, 108 Status, 109 DataFromYear, 110 DataFromHour, 111 InterruptRegisterLow, 112 InterruptRegisterHigh, 113} 114 115impl Command { 116 fn parse(command_byte: u8) -> Option<Self> { 117 // All command bytes must start with 0110 118 if command_byte >> 4 != 0b0110 { 119 return None; 120 } 121 122 match (command_byte >> 1) & 7 { 123 0b000 => Some(Self::Reset), 124 0b001 => Some(Self::Status), 125 0b010 => Some(Self::DataFromYear), 126 0b011 => Some(Self::DataFromHour), 127 0b100 => Some(Self::InterruptRegisterLow), 128 0b101 => Some(Self::InterruptRegisterHigh), 129 0b110 | 0b111 => { 130 log::error!("RTC test mode not implemented; ignoring command"); 131 None 132 } 133 _ => unreachable!("value & 7 is always 0-7"), 134 } 135 } 136} 137 138#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 139enum ReadTarget { 140 Status, 141 Year, 142 Month, 143 Day, 144 DayOfWeek, 145 Hour, 146 Minute, 147 Second, 148 InterruptLow, 149 InterruptHigh, 150} 151 152impl ReadTarget { 153 fn read(self, rtc: &SeikoRealTimeClock) -> u8 { 154 match self { 155 Self::Status => rtc.control.read(), 156 Self::Year => binary_to_bcd(rtc.datetime.year), 157 Self::Month => binary_to_bcd(rtc.datetime.month), 158 Self::Day => binary_to_bcd(rtc.datetime.day), 159 Self::DayOfWeek => rtc.datetime.day_of_week, 160 Self::Hour => { 161 binary_to_bcd(rtc.datetime.hour) | ((rtc.datetime.before_noon as u8) << 7) 162 } 163 Self::Minute => binary_to_bcd(rtc.datetime.minute), 164 Self::Second => binary_to_bcd(rtc.datetime.second), 165 Self::InterruptLow => rtc.interrupt_register.lsb(), 166 Self::InterruptHigh => rtc.interrupt_register.msb(), 167 } 168 } 169 170 fn next(self) -> Option<Self> { 171 match self { 172 Self::Year => Some(Self::Month), 173 Self::Month => Some(Self::Day), 174 Self::Day => Some(Self::DayOfWeek), 175 Self::DayOfWeek => Some(Self::Hour), 176 Self::Hour => Some(Self::Minute), 177 Self::Minute => Some(Self::Second), 178 // TODO is this right? 179 Self::InterruptLow => Some(Self::InterruptHigh), 180 _ => None, 181 } 182 } 183} 184 185fn binary_to_bcd(value: u8) -> u8 { 186 let low = value % 10; 187 let high = value / 10; 188 low | (high << 4) 189} 190 191#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 192enum WriteTarget { 193 Status, 194 Year, 195 Month, 196 Day, 197 DayOfWeek, 198 Hour, 199 Minute, 200 Second, 201 InterruptLow, 202 InterruptHigh, 203} 204 205impl WriteTarget { 206 fn write(self, rtc: &mut SeikoRealTimeClock, value: u8) { 207 match self { 208 Self::Status => rtc.control.write(value), 209 Self::Year => { 210 let year = bcd_to_binary(value); 211 rtc.datetime.year = if year < 100 { year } else { 0 }; 212 } 213 Self::Month => { 214 let month = bcd_to_binary(value & 0x1F); 215 rtc.datetime.month = if (1..=12).contains(&month) { month } else { 1 }; 216 } 217 Self::Day => { 218 let day = bcd_to_binary(value & 0x3F); 219 if day > timeutils::days_in_month(rtc.datetime.month, rtc.datetime.year) { 220 rtc.tick_month(); 221 rtc.datetime.day = 1; 222 } else if day == 0 { 223 rtc.datetime.day = 1; 224 } else { 225 rtc.datetime.day = day; 226 } 227 } 228 Self::DayOfWeek => { 229 rtc.datetime.day_of_week = value & 0x7; 230 } 231 Self::Hour => { 232 let hour = bcd_to_binary(value & 0x3F); 233 match rtc.control.hours { 234 Hours::Twelve => { 235 let before_noon = BeforeNoon::from_bit(value.bit(7)); 236 rtc.datetime.hour = if hour < 12 { hour } else { 0 }; 237 rtc.datetime.before_noon = before_noon; 238 } 239 Hours::TwentyFour => { 240 rtc.datetime.hour = if hour < 24 { hour } else { 0 }; 241 rtc.datetime.before_noon = BeforeNoon::from_bit(false); 242 } 243 } 244 } 245 Self::Minute => { 246 let minute = bcd_to_binary(value & 0x7F); 247 rtc.datetime.minute = if minute < 60 { minute } else { 0 }; 248 } 249 Self::Second => { 250 rtc.datetime.second = bcd_to_binary(value & 0x7F); 251 // Invalid values will get cleared at the next second tick 252 } 253 Self::InterruptLow => { 254 rtc.interrupt_register.set_lsb(value); 255 } 256 Self::InterruptHigh => { 257 rtc.interrupt_register.set_msb(value); 258 } 259 } 260 } 261 262 fn next(self) -> Option<Self> { 263 match self { 264 Self::Year => Some(Self::Month), 265 Self::Month => Some(Self::Day), 266 Self::Day => Some(Self::DayOfWeek), 267 Self::DayOfWeek => Some(Self::Hour), 268 Self::Hour => Some(Self::Minute), 269 Self::Minute => Some(Self::Second), 270 // TODO is this right? 271 Self::InterruptLow => Some(Self::InterruptHigh), 272 _ => None, 273 } 274 } 275} 276 277fn bcd_to_binary(value: u8) -> u8 { 278 (value & 0xF) + 10 * (value >> 4) 279} 280 281#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 282enum CommandState { 283 Idle, 284 ReceivingCommand { bits: u8, remaining: u8 }, 285 PreparingSend { target: ReadTarget }, 286 SendingData { bits: u8, remaining: u8, next: Option<ReadTarget> }, 287 ReceivingData { destination: WriteTarget, bits: u8, remaining: u8 }, 288 Finished, 289} 290 291pub struct RtcWrite { 292 pub chip_select: bool, 293 pub clock: bool, 294 pub data: bool, 295} 296 297#[derive(Debug, Clone, Encode, Decode)] 298pub struct SeikoRealTimeClock { 299 datetime: DateTime, 300 control: Control, 301 interrupt_register: u16, 302 interrupt_line: bool, 303 last_update_time_nanos: u128, 304 command_state: CommandState, 305 prev_clock: bool, 306} 307 308impl SeikoRealTimeClock { 309 pub fn new() -> Self { 310 Self { 311 datetime: DateTime::default(), 312 control: Control::default(), 313 interrupt_register: 0x8000, 314 interrupt_line: false, 315 last_update_time_nanos: timeutils::current_time_nanos(), 316 command_state: CommandState::Idle, 317 prev_clock: false, 318 } 319 } 320 321 pub fn read(&self) -> bool { 322 log::debug!("RTC read; current command state {:?}", self.command_state); 323 324 match self.command_state { 325 CommandState::SendingData { bits, .. } => bits.bit(0), 326 _ => true, 327 } 328 } 329 330 pub fn write(&mut self, RtcWrite { chip_select, clock, data }: RtcWrite) { 331 log::trace!( 332 "RTC write: CS={}, SCK={}, SIO={}, current state {:?}", 333 u8::from(chip_select), 334 u8::from(clock), 335 u8::from(data), 336 self.command_state 337 ); 338 339 let prev_clock = self.prev_clock; 340 self.prev_clock = clock; 341 342 if !chip_select { 343 self.command_state = CommandState::Idle; 344 return; 345 } 346 347 if self.command_state == CommandState::Finished { 348 return; 349 } 350 351 if self.command_state == CommandState::Idle { 352 self.command_state = CommandState::ReceivingCommand { bits: 0, remaining: 8 }; 353 return; 354 } 355 356 // Data reads/writes only progress on falling clock edges 357 let falling_clock_edge = prev_clock && !clock; 358 if !falling_clock_edge { 359 return; 360 } 361 362 self.command_state = match self.command_state { 363 CommandState::ReceivingCommand { mut bits, remaining: 1 } => { 364 // Command bytes are received MSB first 365 bits = (bits << 1) | u8::from(data); 366 367 match Command::parse(bits) { 368 Some(Command::Reset) => { 369 log::debug!("Received RTC reset command"); 370 371 self.reset(); 372 CommandState::Finished 373 } 374 Some(command) => { 375 let direction = CommandDirection::from_bit(bits.bit(0)); 376 377 log::debug!("Received RTC command {command:?}, direction {direction:?}"); 378 379 match direction { 380 CommandDirection::Read => CommandState::PreparingSend { 381 target: match command { 382 Command::Status => ReadTarget::Status, 383 Command::DataFromYear => ReadTarget::Year, 384 Command::DataFromHour => ReadTarget::Hour, 385 Command::InterruptRegisterLow => ReadTarget::InterruptLow, 386 Command::InterruptRegisterHigh => ReadTarget::InterruptHigh, 387 Command::Reset => unreachable!("already a reset match arm"), 388 }, 389 }, 390 CommandDirection::Write => CommandState::ReceivingData { 391 destination: match command { 392 Command::Status => WriteTarget::Status, 393 Command::DataFromYear => WriteTarget::Year, 394 Command::DataFromHour => WriteTarget::Hour, 395 Command::InterruptRegisterLow => WriteTarget::InterruptLow, 396 Command::InterruptRegisterHigh => WriteTarget::InterruptHigh, 397 Command::Reset => unreachable!("already a reset match arm"), 398 }, 399 bits: 0, 400 remaining: 8, 401 }, 402 } 403 } 404 None => CommandState::Finished, 405 } 406 } 407 CommandState::ReceivingCommand { mut bits, mut remaining } => { 408 // Command bytes are received MSB first 409 bits = (bits << 1) | u8::from(data); 410 remaining -= 1; 411 412 CommandState::ReceivingCommand { bits, remaining } 413 } 414 CommandState::PreparingSend { target } => CommandState::SendingData { 415 bits: target.read(self), 416 remaining: 8, 417 next: target.next(), 418 }, 419 CommandState::SendingData { remaining: 1, next: Some(next), .. } => { 420 let bits = next.read(self); 421 CommandState::SendingData { bits, remaining: 8, next: next.next() } 422 } 423 CommandState::SendingData { remaining: 1, next: None, .. } => CommandState::Finished, 424 CommandState::SendingData { mut bits, mut remaining, next } => { 425 bits >>= 1; 426 remaining -= 1; 427 428 CommandState::SendingData { bits, remaining, next } 429 } 430 CommandState::ReceivingData { destination, mut bits, remaining: 1 } => { 431 // Data is received LSB first 432 bits = (bits >> 1) | (u8::from(data) << 7); 433 434 log::debug!("Applying write {bits:02X} to destination {destination:?}"); 435 436 destination.write(self, bits); 437 438 match destination.next() { 439 Some(next) => { 440 CommandState::ReceivingData { destination: next, bits: 0, remaining: 8 } 441 } 442 None => CommandState::Finished, 443 } 444 } 445 CommandState::ReceivingData { destination, mut bits, mut remaining } => { 446 // Data is received LSB first 447 bits = (bits >> 1) | (u8::from(data) << 7); 448 remaining -= 1; 449 450 CommandState::ReceivingData { destination, bits, remaining } 451 } 452 CommandState::Idle | CommandState::Finished => unreachable!(), 453 }; 454 } 455 456 fn reset(&mut self) { 457 self.control.write(0); 458 self.control.power_cycled = false; 459 self.interrupt_register = 0; 460 self.datetime = DateTime::default(); 461 self.interrupt_line = false; 462 } 463 464 pub fn update_time(&mut self, cycles: u64, interrupts: &mut InterruptRegisters) { 465 let current_time_nanos = timeutils::current_time_nanos(); 466 let elapsed_nanos = current_time_nanos.saturating_sub(self.last_update_time_nanos); 467 self.last_update_time_nanos = current_time_nanos; 468 469 self.update_time_internal(elapsed_nanos); 470 471 let prev_interrupt_line = self.interrupt_line; 472 self.update_interrupt_line(); 473 474 // RTC interrupt line is inverted; raise interrupt when line is de-asserted 475 if prev_interrupt_line && !self.interrupt_line { 476 interrupts.set_flag(InterruptType::GamePak, cycles); 477 } 478 } 479 480 fn update_time_internal(&mut self, elapsed_nanos: u128) { 481 self.datetime.nanos += elapsed_nanos; 482 let mut elapsed_seconds = (self.datetime.nanos / 1_000_000_000) as u64; 483 self.datetime.nanos %= 1_000_000_000; 484 485 if elapsed_seconds == 0 { 486 return; 487 } 488 489 if self.datetime.second >= 60 { 490 // Can happen if software wrote an invalid second 491 self.datetime.second = 0; 492 self.tick_minute(); 493 elapsed_seconds -= 1; 494 } 495 496 let second = u64::from(self.datetime.second) + elapsed_seconds; 497 let elapsed_minutes = second / 60; 498 self.datetime.second = (second % 60) as u8; 499 if elapsed_minutes == 0 { 500 return; 501 } 502 503 let minute = u64::from(self.datetime.minute) + elapsed_minutes; 504 let elapsed_hours = minute / 60; 505 self.datetime.minute = (minute % 60) as u8; 506 507 for _ in 0..elapsed_hours { 508 self.tick_hour(); 509 } 510 } 511 512 fn tick_minute(&mut self) { 513 self.datetime.minute += 1; 514 if self.datetime.minute >= 60 { 515 self.datetime.minute = 0; 516 self.tick_hour(); 517 } 518 } 519 520 fn tick_hour(&mut self) { 521 self.datetime.hour += 1; 522 523 match self.control.hours { 524 Hours::Twelve => { 525 if self.datetime.hour >= 12 { 526 self.datetime.hour = 0; 527 self.datetime.before_noon = self.datetime.before_noon.toggle(); 528 if self.datetime.before_noon == BeforeNoon::Am { 529 self.tick_day(); 530 } 531 } 532 } 533 Hours::TwentyFour => { 534 if self.datetime.hour >= 24 { 535 self.datetime.hour = 0; 536 self.tick_day(); 537 } 538 } 539 } 540 } 541 542 fn tick_day(&mut self) { 543 self.datetime.day_of_week = (self.datetime.day_of_week + 1) % 7; 544 545 self.datetime.day += 1; 546 if self.datetime.day > timeutils::days_in_month(self.datetime.month, self.datetime.year) { 547 self.datetime.day = 1; 548 self.tick_month(); 549 } 550 } 551 552 fn tick_month(&mut self) { 553 self.datetime.month += 1; 554 if self.datetime.month > 12 { 555 self.datetime.month = 1; 556 self.tick_year(); 557 } 558 } 559 560 fn tick_year(&mut self) { 561 // Chip only has a 2-digit year (represents 2000-2099) 562 self.datetime.year = (self.datetime.year + 1) % 100; 563 } 564 565 fn update_interrupt_line(&mut self) { 566 // TODO this is not tested - I don't think any official releases use RTC interrupts 567 if self.control.per_minute_interrupt { 568 if self.control.frequency_interrupt { 569 // Per-minute steady interrupt: goes low at 0sec, goes high at 30sec 570 match self.datetime.second { 571 0 => self.interrupt_line = true, 572 30 => self.interrupt_line = false, 573 _ => {} 574 } 575 } else { 576 // Per-minute edge interrupt: goes low at 0sec, never goes high 577 self.interrupt_line |= self.datetime.second == 0; 578 } 579 } else if self.control.frequency_interrupt { 580 // TODO frequency steady interrupts - does anything use these? 581 } else if self.control.alarm_interrupt { 582 // Alarm interrupt: goes low when hour/minute matches alarm time 583 let alarm_hour = bcd_to_binary(self.interrupt_register.lsb() & 0x3F); 584 let alarm_before_noon = BeforeNoon::from_bit(self.interrupt_register.bit(7)); 585 let alarm_minute = bcd_to_binary(self.interrupt_register.msb() & 0x7F); 586 587 self.interrupt_line = alarm_hour == self.datetime.hour 588 && alarm_before_noon == self.datetime.before_noon 589 && alarm_minute == self.datetime.minute; 590 } else { 591 // No interrupts enabled 592 self.interrupt_line = false; 593 } 594 } 595} 596 597#[cfg(test)] 598mod tests { 599 use super::*; 600 601 #[test] 602 fn everything_overflows_24h() { 603 let mut rtc = SeikoRealTimeClock::new(); 604 rtc.control.hours = Hours::TwentyFour; 605 rtc.datetime = DateTime { 606 year: 99, 607 month: 12, 608 day: 31, 609 day_of_week: 6, 610 hour: 23, 611 before_noon: BeforeNoon::Am, 612 minute: 59, 613 second: 59, 614 nanos: 0, 615 }; 616 617 rtc.update_time_internal(1_000_000_000); 618 619 assert_eq!( 620 rtc.datetime, 621 DateTime { 622 year: 0, 623 month: 1, 624 day: 1, 625 day_of_week: 0, 626 hour: 0, 627 before_noon: BeforeNoon::Am, 628 minute: 0, 629 second: 0, 630 nanos: 0, 631 } 632 ); 633 } 634 635 #[test] 636 fn everything_overflows_12h() { 637 let mut rtc = SeikoRealTimeClock::new(); 638 rtc.control.hours = Hours::Twelve; 639 rtc.datetime = DateTime { 640 year: 99, 641 month: 12, 642 day: 31, 643 day_of_week: 6, 644 hour: 11, 645 before_noon: BeforeNoon::Pm, 646 minute: 59, 647 second: 59, 648 nanos: 0, 649 }; 650 651 rtc.update_time_internal(1_000_000_000); 652 653 assert_eq!( 654 rtc.datetime, 655 DateTime { 656 year: 0, 657 month: 1, 658 day: 1, 659 day_of_week: 0, 660 hour: 0, 661 before_noon: BeforeNoon::Am, 662 minute: 0, 663 second: 0, 664 nanos: 0, 665 } 666 ); 667 } 668 669 #[test] 670 fn am_to_pm_12h() { 671 let mut rtc = SeikoRealTimeClock::new(); 672 rtc.control.hours = Hours::Twelve; 673 rtc.datetime = DateTime { 674 year: 0, 675 month: 1, 676 day: 5, 677 day_of_week: 0, 678 hour: 11, 679 before_noon: BeforeNoon::Am, 680 minute: 59, 681 second: 59, 682 nanos: 0, 683 }; 684 685 rtc.update_time_internal(1_000_000_000); 686 687 assert_eq!( 688 rtc.datetime, 689 DateTime { 690 year: 0, 691 month: 1, 692 day: 5, 693 day_of_week: 0, 694 hour: 0, 695 before_noon: BeforeNoon::Pm, 696 minute: 0, 697 second: 0, 698 nanos: 0, 699 } 700 ); 701 } 702 703 fn leap_year_test(year: u8, expected_day: u8) { 704 let mut rtc = SeikoRealTimeClock::new(); 705 rtc.control.hours = Hours::TwentyFour; 706 rtc.datetime = DateTime { 707 year, 708 month: 2, 709 day: 28, 710 day_of_week: 0, 711 hour: 23, 712 before_noon: BeforeNoon::Am, 713 minute: 59, 714 second: 59, 715 nanos: 1_000_000_000 - 1, 716 }; 717 718 rtc.update_time_internal(1); 719 720 assert_eq!(rtc.datetime.day, expected_day); 721 } 722 723 #[test] 724 #[rustfmt::skip] 725 fn leap_years() { 726 leap_year_test(0, 29); // 2000 727 leap_year_test(3, 1); // 2003 728 leap_year_test(4, 29); // 2004 729 leap_year_test(5, 1); // 2005 730 leap_year_test(95, 1); // 2095 731 leap_year_test(96, 29); // 2096 732 leap_year_test(97, 1); // 2097 733 } 734}