mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 23:24:15 +01:00
joybus rtc fully working with writes
This commit is contained in:
parent
3ab5b7b6c8
commit
ef205d218a
@ -60,7 +60,7 @@ module n64_flashram (
|
|||||||
if (write_buffer_wmask[0]) high_buffer <= bus.wdata;
|
if (write_buffer_wmask[0]) high_buffer <= bus.wdata;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
flashram.rdata <= write_buffer[flashram.address];
|
flashram.rdata <= write_buffer[flashram.address];
|
||||||
if (write_buffer_wmask[1]) write_buffer[bus.address[6:2]] <= {high_buffer, bus.wdata};
|
if (write_buffer_wmask[1]) write_buffer[bus.address[6:2]] <= {high_buffer, bus.wdata};
|
||||||
end
|
end
|
||||||
|
@ -30,6 +30,7 @@ void process_cfg (void);
|
|||||||
void process_flashram (void);
|
void process_flashram (void);
|
||||||
void process_si (void);
|
void process_si (void);
|
||||||
void process_rtc (void);
|
void process_rtc (void);
|
||||||
|
void process_uart (void);
|
||||||
|
|
||||||
|
|
||||||
bool debug_decide (uint32_t *args);
|
bool debug_decide (uint32_t *args);
|
||||||
@ -45,19 +46,14 @@ void main (void) {
|
|||||||
usb_flush_rx();
|
usb_flush_rx();
|
||||||
usb_flush_tx();
|
usb_flush_tx();
|
||||||
si_reset();
|
si_reset();
|
||||||
|
i2c_stop();
|
||||||
|
|
||||||
cfg_set_sdram_switch(true);
|
cfg_set_sdram_switch(true);
|
||||||
cfg_set_save_type(CFG_SAVE_TYPE_NONE);
|
cfg_set_save_type(CFG_SAVE_TYPE_NONE);
|
||||||
cfg_set_dd_offset(CFG_DEFAULT_DD_OFFSET);
|
cfg_set_dd_offset(CFG_DEFAULT_DD_OFFSET);
|
||||||
cfg_set_cpu_ready(true);
|
cfg_set_cpu_ready(true);
|
||||||
|
|
||||||
current_time[0] = 0x10;
|
print("App ready!\r\n");
|
||||||
current_time[1] = 0x30;
|
|
||||||
current_time[2] = 0x90;
|
|
||||||
current_time[3] = 0x06;
|
|
||||||
current_time[4] = 0x01;
|
|
||||||
current_time[5] = 0x09;
|
|
||||||
current_time[6] = 0x21;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
process_usb();
|
process_usb();
|
||||||
@ -65,6 +61,7 @@ void main (void) {
|
|||||||
process_flashram();
|
process_flashram();
|
||||||
process_si();
|
process_si();
|
||||||
process_rtc();
|
process_rtc();
|
||||||
|
process_uart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +235,7 @@ void process_flashram (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process_si (void) {
|
void process_si (void) {
|
||||||
uint8_t rx_data[12];
|
uint8_t rx_data[10];
|
||||||
uint8_t tx_data[12];
|
uint8_t tx_data[12];
|
||||||
uint32_t *save_data;
|
uint32_t *save_data;
|
||||||
uint32_t *data_offset;
|
uint32_t *data_offset;
|
||||||
@ -288,13 +285,10 @@ void process_si (void) {
|
|||||||
if (!rtc_running) {
|
if (!rtc_running) {
|
||||||
tx_data[1] = SI_RTC_ST_MASK;
|
tx_data[1] = SI_RTC_ST_MASK;
|
||||||
}
|
}
|
||||||
} else if (rx_data[1] == 1) {
|
} else if (rx_data[1] == 2) {
|
||||||
// Backup SRAM
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i < 7; i++) {
|
for (size_t i = 0; i < 7; i++) {
|
||||||
tx_data[i] = current_time[i];
|
tx_data[i] = current_time[i];
|
||||||
}
|
}
|
||||||
tx_data[2] |= 0x80;
|
|
||||||
tx_data[7] = SI_RTC_CENTURY_20XX;
|
tx_data[7] = SI_RTC_CENTURY_20XX;
|
||||||
}
|
}
|
||||||
tx_data[8] = SI_RTC_STATUS(rtc_running);
|
tx_data[8] = SI_RTC_STATUS(rtc_running);
|
||||||
@ -305,9 +299,7 @@ void process_si (void) {
|
|||||||
if (rx_data[1] == 0) {
|
if (rx_data[1] == 0) {
|
||||||
rtc_wp_bits = rx_data[2] & SI_RTC_WP_MASK;
|
rtc_wp_bits = rx_data[2] & SI_RTC_WP_MASK;
|
||||||
rtc_running = (!(rx_data[3] & SI_RTC_ST_MASK));
|
rtc_running = (!(rx_data[3] & SI_RTC_ST_MASK));
|
||||||
} else if (rx_data[1] == 1) {
|
} else if (rx_data[1] == 2) {
|
||||||
// Backup SRAM
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i < 7; i++) {
|
for (size_t i = 0; i < 7; i++) {
|
||||||
new_time[i] = rx_data[i + 2];
|
new_time[i] = rx_data[i + 2];
|
||||||
}
|
}
|
||||||
@ -324,11 +316,142 @@ void process_si (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process_rtc (void) {
|
void process_rtc (void) {
|
||||||
|
static e_rtc_state_t state = RTC_STATE_READ;
|
||||||
|
static e_rtc_state_t next_state = RTC_STATE_READ;
|
||||||
|
static uint8_t phase = 0;
|
||||||
|
static uint8_t sub_phase = 0;
|
||||||
|
static uint8_t rtc_current_time[7];
|
||||||
|
static uint8_t rtc_new_time[7];
|
||||||
|
|
||||||
if (new_time_pending) {
|
if (new_time_pending) {
|
||||||
|
new_time_pending = false;
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
for (int i = 0; i < 7; i++) {
|
||||||
current_time[i] = new_time[i];
|
current_time[i] = new_time[i];
|
||||||
}
|
}
|
||||||
new_time_pending = false;
|
|
||||||
|
rtc_convert_from_n64(new_time, rtc_new_time);
|
||||||
|
|
||||||
|
rtc_new_time[RTC_RTCSEC] |= RTC_RTCSEC_ST;
|
||||||
|
rtc_new_time[RTC_RTCWKDAY] |= RTC_RTCWKDAY_VBAT;
|
||||||
|
|
||||||
|
next_state = RTC_STATE_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Rewrite this mess
|
||||||
|
if (!i2c_busy()) {
|
||||||
|
if (state == RTC_STATE_READ) {
|
||||||
|
switch (phase) {
|
||||||
|
case 0: phase++; i2c_start(); break;
|
||||||
|
case 1: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 2: phase++; i2c_begin_trx(RTC_RTCSEC, false); break;
|
||||||
|
case 3: phase++; i2c_start(); break;
|
||||||
|
case 4: phase++; i2c_begin_trx(RTC_ADDR | I2C_ADDR_READ, false); break;
|
||||||
|
case 5:
|
||||||
|
if (sub_phase > 0) {
|
||||||
|
rtc_current_time[sub_phase - 1] = i2c_get_data();
|
||||||
|
}
|
||||||
|
if (sub_phase < 7) {
|
||||||
|
i2c_begin_trx(0xFF, true);
|
||||||
|
}
|
||||||
|
if (sub_phase == 7) {
|
||||||
|
phase++;
|
||||||
|
sub_phase = 0;
|
||||||
|
if (next_state != RTC_STATE_WRITE) {
|
||||||
|
rtc_convert_to_n64(rtc_current_time, current_time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sub_phase++;
|
||||||
|
break;
|
||||||
|
case 6: phase = 0; i2c_stop(); state = next_state; break;
|
||||||
|
}
|
||||||
|
} else if (state == RTC_STATE_WRITE) {
|
||||||
|
switch (phase) {
|
||||||
|
case 0: phase++; break;
|
||||||
|
|
||||||
|
case 1: phase++; i2c_start(); break;
|
||||||
|
case 2: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 3: phase++; i2c_begin_trx(RTC_RTCSEC, false); break;
|
||||||
|
case 4: phase++; i2c_begin_trx(0x00, false); break;
|
||||||
|
case 5: phase++; i2c_stop(); break;
|
||||||
|
|
||||||
|
case 6: phase++; i2c_start(); break;
|
||||||
|
case 7: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 8: phase++; i2c_begin_trx(RTC_RTCWKDAY, false); break;
|
||||||
|
case 9: phase++; i2c_start(); break;
|
||||||
|
case 10: phase++; i2c_begin_trx(RTC_ADDR | I2C_ADDR_READ, false); break;
|
||||||
|
case 11: phase++; i2c_begin_trx(0xFF, false); break;
|
||||||
|
case 12: phase = (i2c_get_data() & RTC_RTCWKDAY_OSCRUN) ? 6 : 13; i2c_stop(); break;
|
||||||
|
|
||||||
|
case 13: phase++; i2c_start(); break;
|
||||||
|
case 14: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 15: phase++; i2c_begin_trx(RTC_RTCMIN, false); break;
|
||||||
|
case 16:
|
||||||
|
if (sub_phase < 6) {
|
||||||
|
i2c_begin_trx(rtc_new_time[RTC_RTCMIN + sub_phase], false);
|
||||||
|
sub_phase++;
|
||||||
|
} else {
|
||||||
|
phase++;
|
||||||
|
sub_phase = 0;
|
||||||
|
i2c_stop();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 17: phase++; i2c_start(); break;
|
||||||
|
case 18: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 19: phase++; i2c_begin_trx(RTC_RTCSEC, false); break;
|
||||||
|
case 20: phase++; i2c_begin_trx(rtc_new_time[RTC_RTCSEC], false); break;
|
||||||
|
case 21: phase++; i2c_stop(); break;
|
||||||
|
|
||||||
|
case 22: phase++; i2c_start(); break;
|
||||||
|
case 23: phase++; i2c_begin_trx(RTC_ADDR, false); break;
|
||||||
|
case 24: phase++; i2c_begin_trx(RTC_RTCWKDAY, false); break;
|
||||||
|
case 25: phase++; i2c_start(); break;
|
||||||
|
case 26: phase++; i2c_begin_trx(RTC_ADDR | I2C_ADDR_READ, false); break;
|
||||||
|
case 27: phase++; i2c_begin_trx(0xFF, false); break;
|
||||||
|
case 28:
|
||||||
|
if (i2c_get_data() & RTC_RTCWKDAY_OSCRUN) {
|
||||||
|
phase = 0;
|
||||||
|
state = RTC_STATE_READ;
|
||||||
|
next_state = RTC_STATE_READ;
|
||||||
|
} else {
|
||||||
|
phase = 22;
|
||||||
|
}
|
||||||
|
i2c_stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state = RTC_STATE_READ;
|
||||||
|
phase = 0;
|
||||||
|
sub_phase = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_uart (void) {
|
||||||
|
if (UART->SCR & USB_SCR_RXNE) {
|
||||||
|
char cmd = UART->DR;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case '/':
|
||||||
|
print("Bootloader reset...\r\n");
|
||||||
|
reset_handler();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
print("App reset...\r\n");
|
||||||
|
app_handler();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
print("Current time: ");
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
print_02hex(current_time[i]);
|
||||||
|
print(" ");
|
||||||
|
}
|
||||||
|
print("\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ typedef enum {
|
|||||||
USB_STATE_PC_TO_N64,
|
USB_STATE_PC_TO_N64,
|
||||||
} e_usb_state_t;
|
} e_usb_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RTC_STATE_READ,
|
||||||
|
RTC_STATE_WRITE,
|
||||||
|
} e_rtc_state_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DEBUG_WRITE_ADDRESS,
|
DEBUG_WRITE_ADDRESS,
|
||||||
DEBUG_WRITE_LENGTH_START,
|
DEBUG_WRITE_LENGTH_START,
|
||||||
|
@ -323,9 +323,50 @@ uint8_t i2c_get_data (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// misc
|
// RTC
|
||||||
|
|
||||||
const char hex_char_map[16] = {
|
static const uint8_t rtc_bit_mask[7] = {
|
||||||
|
0b01111111,
|
||||||
|
0b01111111,
|
||||||
|
0b00111111,
|
||||||
|
0b00000111,
|
||||||
|
0b00111111,
|
||||||
|
0b00011111,
|
||||||
|
0b11111111
|
||||||
|
};
|
||||||
|
|
||||||
|
void rtc_sanitize_time_data (uint8_t *time_data) {
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
time_data[i] &= rtc_bit_mask[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_convert_to_n64 (uint8_t *rtc_data, uint8_t *n64_data) {
|
||||||
|
rtc_sanitize_time_data(rtc_data);
|
||||||
|
n64_data[0] = rtc_data[RTC_RTCSEC];
|
||||||
|
n64_data[1] = rtc_data[RTC_RTCMIN];
|
||||||
|
n64_data[2] = rtc_data[RTC_RTCHOUR] | 0x80;
|
||||||
|
n64_data[4] = rtc_data[RTC_RTCWKDAY] - 1;
|
||||||
|
n64_data[3] = rtc_data[RTC_RTCDATE];
|
||||||
|
n64_data[5] = rtc_data[RTC_RTCMTH];
|
||||||
|
n64_data[6] = rtc_data[RTC_RTCYEAR];
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_convert_from_n64 (uint8_t *n64_data, uint8_t *rtc_data) {
|
||||||
|
rtc_data[RTC_RTCSEC] = n64_data[0];
|
||||||
|
rtc_data[RTC_RTCMIN] = n64_data[1];
|
||||||
|
rtc_data[RTC_RTCHOUR] = n64_data[2];
|
||||||
|
rtc_data[RTC_RTCWKDAY] = n64_data[4] + 1;
|
||||||
|
rtc_data[RTC_RTCDATE] = n64_data[3];
|
||||||
|
rtc_data[RTC_RTCMTH] = n64_data[5];
|
||||||
|
rtc_data[RTC_RTCYEAR] = n64_data[6];
|
||||||
|
rtc_sanitize_time_data(rtc_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
|
||||||
|
static const char hex_char_map[16] = {
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,7 +133,28 @@ void i2c_begin_trx (uint8_t data, bool mack);
|
|||||||
uint8_t i2c_get_data (void);
|
uint8_t i2c_get_data (void);
|
||||||
|
|
||||||
|
|
||||||
// misc
|
// RTC
|
||||||
|
|
||||||
|
#define RTC_ADDR (0xDE)
|
||||||
|
|
||||||
|
#define RTC_RTCSEC (0x00)
|
||||||
|
#define RTC_RTCMIN (0x01)
|
||||||
|
#define RTC_RTCHOUR (0x02)
|
||||||
|
#define RTC_RTCWKDAY (0x03)
|
||||||
|
#define RTC_RTCDATE (0x04)
|
||||||
|
#define RTC_RTCMTH (0x05)
|
||||||
|
#define RTC_RTCYEAR (0x06)
|
||||||
|
|
||||||
|
#define RTC_RTCSEC_ST (1 << 7)
|
||||||
|
#define RTC_RTCWKDAY_OSCRUN (1 << 5)
|
||||||
|
#define RTC_RTCWKDAY_VBAT (1 << 3)
|
||||||
|
|
||||||
|
void rtc_sanitize_time_data(uint8_t *time_data);
|
||||||
|
void rtc_convert_to_n64 (uint8_t *rtc_data, uint8_t *n64_data);
|
||||||
|
void rtc_convert_from_n64 (uint8_t *n64_data, uint8_t *rtc_data);
|
||||||
|
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
|
||||||
void print (const char *text);
|
void print (const char *text);
|
||||||
void print_02hex (uint8_t number);
|
void print_02hex (uint8_t number);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#define BOOT_UART
|
#define BOOT_UART
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((naked, section(".bootloader"))) int reset_handler (void) {
|
__attribute__ ((naked, section(".bootloader"))) void reset_handler (void) {
|
||||||
register uint32_t length = 0;
|
register uint32_t length = 0;
|
||||||
|
|
||||||
#if defined(BOOT_UART)
|
#if defined(BOOT_UART)
|
||||||
|
@ -156,4 +156,8 @@ typedef volatile struct si_regs {
|
|||||||
#define SI_SCR_TX_LENGTH_BIT (16)
|
#define SI_SCR_TX_LENGTH_BIT (16)
|
||||||
|
|
||||||
|
|
||||||
|
void reset_handler (void);
|
||||||
|
void app_handler (void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user