Skip to content

Commit 87b927f

Browse files
committed
Move ED64 X-series i2c into separate file; hook up to RTC subsystem
1 parent 16c460e commit 87b927f

File tree

4 files changed

+151
-98
lines changed

4 files changed

+151
-98
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ LIBDRAGON_OBJS += \
4444
$(BUILD_DIR)/compress/shrinkler_dec_fast.o $(BUILD_DIR)/compress/shrinkler_dec.o \
4545
$(BUILD_DIR)/joybus.o $(BUILD_DIR)/joybus_accessory.o $(BUILD_DIR)/joybus_rtc.o $(BUILD_DIR)/pixelfx.o \
4646
$(BUILD_DIR)/joypad.o $(BUILD_DIR)/joypad_accessory.o \
47-
$(BUILD_DIR)/controller.o $(BUILD_DIR)/rtc.o $(BUILD_DIR)/rtc_internal.o \
47+
$(BUILD_DIR)/controller.o $(BUILD_DIR)/ed64x.o $(BUILD_DIR)/rtc.o $(BUILD_DIR)/rtc_internal.o \
4848
$(BUILD_DIR)/eeprom.o $(BUILD_DIR)/eepromfs.o $(BUILD_DIR)/mempak.o $(BUILD_DIR)/cpak.o \
4949
$(BUILD_DIR)/tpak.o $(BUILD_DIR)/graphics.o $(BUILD_DIR)/rdp.o \
5050
$(BUILD_DIR)/rsp.o $(BUILD_DIR)/rsp_crash.o \

src/ed64x.c

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* @file ed64x.c
3+
* @brief EverDrive 64 X-series utilities
4+
*/
5+
6+
#include "debug.h"
7+
#include "dma.h"
8+
#include "ed64x.h"
9+
#include "rtc_internal.h"
10+
#include "utils.h"
11+
12+
/**
13+
* @addtogroup ed64x
14+
* @{
15+
*/
16+
17+
static const uint32_t ED64X_REG_I2C_CMD = 0x1F800018;
18+
static const uint32_t ED64X_REG_I2C_DAT = 0x1F80001C;
19+
20+
static int ed64x_i2c_status(void)
21+
{
22+
return io_read(ED64X_REG_I2C_CMD) & 1;
23+
}
24+
25+
static int ed64x_i2c_cmd(uint8_t cmd)
26+
{
27+
io_write(ED64X_REG_I2C_DAT, cmd);
28+
while (io_read(ED64X_REG_I2C_CMD) & 0x80) {}
29+
return ed64x_i2c_status();
30+
}
31+
32+
static uint8_t ed64x_i2c_dat(uint8_t cmd)
33+
{
34+
io_write(ED64X_REG_I2C_DAT, cmd);
35+
while (io_read(ED64X_REG_I2C_CMD) & 0x80) {}
36+
return io_read(ED64X_REG_I2C_DAT);
37+
}
38+
39+
static void ed64x_i2c_start(void)
40+
{
41+
uint8_t val = io_read(ED64X_REG_I2C_CMD);
42+
io_write(ED64X_REG_I2C_CMD, 0x20);
43+
io_write(ED64X_REG_I2C_DAT, 0xFF);
44+
while (io_read(ED64X_REG_I2C_CMD) & 0x80) {}
45+
io_write(ED64X_REG_I2C_CMD, val | 0x11); // set write mode
46+
}
47+
48+
static void ed64x_i2c_end(void)
49+
{
50+
io_write(ED64X_REG_I2C_CMD, 0x30);
51+
io_write(ED64X_REG_I2C_DAT, 0xFF);
52+
while (io_read(ED64X_REG_I2C_CMD) & 0x80) {}
53+
}
54+
55+
static void ed64x_i2c_setwr(void)
56+
{
57+
io_write(ED64X_REG_I2C_CMD, io_read(ED64X_REG_I2C_CMD) | 0x11);
58+
}
59+
60+
static void ed64x_i2c_setrd(void)
61+
{
62+
io_write(ED64X_REG_I2C_CMD, io_read(ED64X_REG_I2C_CMD) | 0x10);
63+
}
64+
65+
static int ed64x_i2c_write(uint16_t addr, const uint8_t* data, int len)
66+
{
67+
uint8_t bus_addr = addr >> 8;
68+
uint8_t dev_addr = addr & 0xFF;
69+
70+
for (int i=0; i<len; i+=8) {
71+
int retry = 0;
72+
while (1) {
73+
ed64x_i2c_start();
74+
if (ed64x_i2c_cmd(bus_addr) == 0)
75+
break;
76+
ed64x_i2c_end();
77+
if (++retry == 16)
78+
return -1;
79+
}
80+
ed64x_i2c_cmd(dev_addr+i);
81+
for (int j=0; j<MIN(len, 8); j++) {
82+
io_write(ED64X_REG_I2C_DAT, data[i+j]);
83+
while (io_read(ED64X_REG_I2C_CMD) & 0x80) {}
84+
}
85+
ed64x_i2c_end();
86+
}
87+
return 0;
88+
}
89+
90+
int ed64x_rtc_write( time_t new_time )
91+
{
92+
struct tm * rtc_time = gmtime( &new_time );
93+
uint8_t buf[7];
94+
95+
// The RTC is a DS1337. Encode time according to its datasheet
96+
enum { DS1337_BUS_ADDR = 0xD000 };
97+
98+
buf[0] = bcd_encode( rtc_time->tm_sec );
99+
buf[1] = bcd_encode( rtc_time->tm_min );
100+
buf[2] = bcd_encode( rtc_time->tm_hour ); // bit 6 toggles 12/24 hour mode
101+
buf[3] = bcd_encode( rtc_time->tm_wday + 1 );
102+
buf[4] = bcd_encode( rtc_time->tm_mday );
103+
buf[5] = bcd_encode( rtc_time->tm_mon + 1 ); // bit 7 is the century bit
104+
buf[6] = bcd_encode( rtc_time->tm_year % 100 );
105+
return ed64x_i2c_write( DS1337_BUS_ADDR + 0, buf, sizeof(buf) );
106+
}
107+
108+
/** @} */ /* ed64x */

src/ed64x.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @file ed64x.h
3+
* @brief EverDrive 64 X-Series utilities.
4+
* @ingroup peripherals
5+
*/
6+
7+
#ifndef __LIBDRAGON_ED64X_H
8+
#define __LIBDRAGON_ED64X_H
9+
10+
#include <stdbool.h>
11+
#include <stdint.h>
12+
#include <time.h>
13+
14+
/**
15+
* @defgroup ed64x EverDrive 64 X-series
16+
* @ingroup peripherals
17+
* @brief EverDrive 64 X-series utilities.
18+
*
19+
* @{
20+
*/
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
int ed64x_rtc_write( time_t new_time );
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
/** @} */ /* ed64x */
33+
34+
#endif

src/joybus_rtc.c

+8-97
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
*/
66

77
#include "debug.h"
8+
#include "ed64x.h"
89
#include "joybus_commands.h"
910
#include "joybus_internal.h"
1011
#include "joybus_rtc.h"
1112
#include "libcart/cart.h"
1213
#include "n64sys.h"
13-
#include "dma.h"
14-
#include "utils.h"
15-
#include "rtc_internal.h"
1614
#include "rtc_internal.h"
1715

1816
/**
@@ -426,97 +424,6 @@ int joybus_rtc_get_time( time_t *out )
426424
return RTC_ESUCCESS;
427425
}
428426

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-
520427
int joybus_rtc_set_time( time_t new_time )
521428
{
522429
if( new_time < JOYBUS_RTC_TIMESTAMP_MIN || new_time > JOYBUS_RTC_TIMESTAMP_MAX )
@@ -548,9 +455,13 @@ int joybus_rtc_set_time( time_t new_time )
548455
if (cart_type == CART_EDX)
549456
{
550457
// Joybus RTC write is not supported on EverDrive 64 X7.
551-
debugf("joybus_rtc_set_time: EverDrive 64 X7 not supported!\n");
552-
// TODO: Research and implement ED64 X7-specific RTC write
553-
return RTC_EBADCLOCK;
458+
// Attempt to use the ED64X i2c interface to set the time instead.
459+
if( ed64x_rtc_write( new_time ) != 0 )
460+
{
461+
debugf("joybus_rtc_set_time: EverDrive 64 X7 i2c write failed!\n");
462+
return RTC_EBADCLOCK;
463+
}
464+
return RTC_ESUCCESS;
554465
}
555466

556467
debugf("joybus_rtc_set_time: reading control block\n");

0 commit comments

Comments
 (0)