|
10 | 10 | #include "joybus_rtc.h"
|
11 | 11 | #include "libcart/cart.h"
|
12 | 12 | #include "n64sys.h"
|
| 13 | +#include "dma.h" |
| 14 | +#include "utils.h" |
13 | 15 | #include "rtc_internal.h"
|
14 | 16 | #include "rtc_internal.h"
|
15 | 17 |
|
@@ -424,6 +426,97 @@ int joybus_rtc_get_time( time_t *out )
|
424 | 426 | return RTC_ESUCCESS;
|
425 | 427 | }
|
426 | 428 |
|
| 429 | +static const uint32_t ED64X_REG_I2C_CMD = 0x1F800018; |
| 430 | +static const uint32_t ED64X_REG_I2C_DAT = 0x1F80001C; |
| 431 | + |
| 432 | +static int ed64x_i2c_status(void) |
| 433 | +{ |
| 434 | + return io_read(ED64X_REG_I2C_CMD) & 1; |
| 435 | +} |
| 436 | + |
| 437 | +static int ed64x_i2c_cmd(uint8_t cmd) |
| 438 | +{ |
| 439 | + io_write(ED64X_REG_I2C_DAT, cmd); |
| 440 | + while (io_read(ED64X_REG_I2C_CMD) & 0x80) {} |
| 441 | + return ed64x_i2c_status(); |
| 442 | +} |
| 443 | + |
| 444 | +static uint8_t ed64x_i2c_dat(uint8_t cmd) |
| 445 | +{ |
| 446 | + io_write(ED64X_REG_I2C_DAT, cmd); |
| 447 | + while (io_read(ED64X_REG_I2C_CMD) & 0x80) {} |
| 448 | + return io_read(ED64X_REG_I2C_DAT); |
| 449 | +} |
| 450 | + |
| 451 | +static void ed64x_i2c_start(void) |
| 452 | +{ |
| 453 | + uint8_t val = io_read(ED64X_REG_I2C_CMD); |
| 454 | + io_write(ED64X_REG_I2C_CMD, 0x20); |
| 455 | + io_write(ED64X_REG_I2C_DAT, 0xFF); |
| 456 | + while (io_read(ED64X_REG_I2C_CMD) & 0x80) {} |
| 457 | + io_write(ED64X_REG_I2C_CMD, val | 0x11); // set write mode |
| 458 | +} |
| 459 | + |
| 460 | +static void ed64x_i2c_end(void) |
| 461 | +{ |
| 462 | + io_write(ED64X_REG_I2C_CMD, 0x30); |
| 463 | + io_write(ED64X_REG_I2C_DAT, 0xFF); |
| 464 | + while (io_read(ED64X_REG_I2C_CMD) & 0x80) {} |
| 465 | +} |
| 466 | + |
| 467 | +static void ed64x_i2c_setwr(void) |
| 468 | +{ |
| 469 | + io_write(ED64X_REG_I2C_CMD, io_read(ED64X_REG_I2C_CMD) | 0x11); |
| 470 | +} |
| 471 | + |
| 472 | +static void ed64x_i2c_setrd(void) |
| 473 | +{ |
| 474 | + io_write(ED64X_REG_I2C_CMD, io_read(ED64X_REG_I2C_CMD) | 0x10); |
| 475 | +} |
| 476 | + |
| 477 | +static int ed64x_i2c_write(uint16_t addr, const uint8_t* data, int len) |
| 478 | +{ |
| 479 | + uint8_t bus_addr = addr >> 8; |
| 480 | + uint8_t dev_addr = addr & 0xFF; |
| 481 | + |
| 482 | + for (int i=0; i<len; i+=8) { |
| 483 | + int retry = 0; |
| 484 | + while (1) { |
| 485 | + ed64x_i2c_start(); |
| 486 | + if (ed64x_i2c_cmd(bus_addr) == 0) |
| 487 | + break; |
| 488 | + ed64x_i2c_end(); |
| 489 | + if (++retry == 16) |
| 490 | + return -1; |
| 491 | + } |
| 492 | + ed64x_i2c_cmd(dev_addr+i); |
| 493 | + for (int j=0; j<MIN(len, 8); j++) { |
| 494 | + io_write(ED64X_REG_I2C_DAT, data[i+j]); |
| 495 | + while (io_read(ED64X_REG_I2C_CMD) & 0x80) {} |
| 496 | + } |
| 497 | + ed64x_i2c_end(); |
| 498 | + } |
| 499 | + return 0; |
| 500 | +} |
| 501 | + |
| 502 | +static void ed64x_rtc_write( time_t new_time ) |
| 503 | +{ |
| 504 | + struct tm * rtc_time = gmtime( &new_time ); |
| 505 | + uint8_t buf[7]; |
| 506 | + |
| 507 | + // The RTC is a DS1337. Encode time according to its datasheet |
| 508 | + enum { DS1337_BUS_ADDR = 0xD000 }; |
| 509 | + |
| 510 | + buf[0] = bcd_encode( rtc_time->tm_sec ); |
| 511 | + buf[1] = bcd_encode( rtc_time->tm_min ); |
| 512 | + buf[2] = bcd_encode( rtc_time->tm_hour ); // bit 6 toggles 12/24 hour mode |
| 513 | + buf[3] = bcd_encode( rtc_time->tm_wday + 1 ); |
| 514 | + buf[4] = bcd_encode( rtc_time->tm_mday ); |
| 515 | + buf[5] = bcd_encode( rtc_time->tm_mon + 1 ); // bit 7 is the century bit |
| 516 | + buf[6] = bcd_encode( rtc_time->tm_year % 100 ); |
| 517 | + ed64x_i2c_write( DS1337_BUS_ADDR + 0, buf, sizeof(buf) ); |
| 518 | +} |
| 519 | + |
427 | 520 | int joybus_rtc_set_time( time_t new_time )
|
428 | 521 | {
|
429 | 522 | if( new_time < JOYBUS_RTC_TIMESTAMP_MIN || new_time > JOYBUS_RTC_TIMESTAMP_MAX )
|
|
0 commit comments