210 lines
4.6 KiB
C++
210 lines
4.6 KiB
C++
#include <stdint.h>
|
|
|
|
#include "sh2.h"
|
|
#include "serial.h"
|
|
|
|
volatile uint16_t * const DATATRNS = (volatile uint16_t *)0x25890000; // 0
|
|
volatile uint16_t * const DATASTAT = (volatile uint16_t *)0x25890004; // 1 (not implemented in mednafen)
|
|
volatile uint16_t * const HIRQREQ = (volatile uint16_t *)0x25890008; // 2
|
|
volatile uint16_t * const HIRQMSK = (volatile uint16_t *)0x2589000c; // 3
|
|
volatile uint16_t * const CDATA0 = (volatile uint16_t *)0x25890018; // 6
|
|
volatile uint16_t * const CDATA1 = (volatile uint16_t *)0x2589001c; // 7
|
|
volatile uint16_t * const CDATA2 = (volatile uint16_t *)0x25890020; // 8
|
|
volatile uint16_t * const CDATA3 = (volatile uint16_t *)0x25890024; // 9
|
|
volatile uint16_t * const MPEGRGB = (volatile uint16_t *)0x25890028; // a (not implemented in mednafen)
|
|
|
|
/* Bit names of interrupt factor registers (HIRQREQ, HIRQMSK) */
|
|
#define HIRQ__CMOK (1 << 0) /* Command can be issued */
|
|
#define HIRQ__DRDY (1 << 1) /* Data transfer ready */
|
|
#define HIRQ__CSCT (1 << 2) /* 1 sector read completed */
|
|
#define HIRQ__BFUL (1 << 3) /* CD buffer full */
|
|
#define HIRQ__PEND (1 << 4) /* End of CD playback */
|
|
#define HIRQ__DCHG (1 << 5) /* Disk replacement occurrence */
|
|
#define HIRQ__ESEL (1 << 6) /* End of selector setting process */
|
|
#define HIRQ__EHST (1 << 7) /* End of host I/O processing */
|
|
#define HIRQ__ECPY (1 << 8) /* End of copy/move processing */
|
|
#define HIRQ__EFLS (1 << 9) /* End of file system processing */
|
|
#define HIRQ__SCDQ (1 << 10) /* Subcode Q update completed */
|
|
#define HIRQ__MPED (1 << 11) /* End of MPEG-related processing */
|
|
#define HIRQ__MPCM (1 << 12) /* End of MPEG operation undefined interval */
|
|
#define HIRQ__MPST (1 << 13) /* MPEG interrupt status notification */
|
|
|
|
struct cd_command {
|
|
uint16_t CDATA[4];
|
|
};
|
|
|
|
struct cd_response {
|
|
uint16_t CDATA[4];
|
|
};
|
|
|
|
int cd_wait_hirq(uint16_t status)
|
|
{
|
|
for (int i = 0; i < 0x240000; i++) {
|
|
uint16_t hirq_temp = *HIRQREQ;
|
|
if ((hirq_temp & status) != 0) {
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int cd_command_response(cd_command * command, cd_response * response)
|
|
{
|
|
uint16_t hirq = *HIRQREQ;
|
|
serial_string("cd_command_response hirq: ");
|
|
serial_integer(hirq, 8, '\n');
|
|
if ((hirq & HIRQ__CMOK) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
*HIRQREQ &= ~HIRQ__CMOK;
|
|
|
|
*CDATA0 = command->CDATA[0];
|
|
*CDATA1 = command->CDATA[1];
|
|
*CDATA2 = command->CDATA[2];
|
|
*CDATA3 = command->CDATA[3];
|
|
|
|
if (cd_wait_hirq(HIRQ__CMOK) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
response->CDATA[0] = *CDATA0;
|
|
response->CDATA[1] = *CDATA1;
|
|
response->CDATA[2] = *CDATA2;
|
|
response->CDATA[3] = *CDATA3;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cd_data_end()
|
|
{
|
|
struct cd_command command = {{
|
|
0x0600,
|
|
0,
|
|
0,
|
|
0
|
|
}};
|
|
struct cd_response response = {0};
|
|
|
|
int ret = cd_command_response(&command, &response);
|
|
|
|
*HIRQREQ &= ~HIRQ__DRDY;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int cd_wait_data_ready()
|
|
{
|
|
int ret = cd_wait_hirq(HIRQ__DRDY);
|
|
if (ret != 0)
|
|
cd_data_end();
|
|
|
|
*HIRQREQ &= ~HIRQ__DRDY;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int cd_get_data(uint16_t * data, int size)
|
|
{
|
|
int ret;
|
|
|
|
ret = cd_wait_data_ready();
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
while (size > 0) {
|
|
*data = *DATATRNS;
|
|
data += 1;
|
|
size -= 1;
|
|
}
|
|
|
|
ret = cd_data_end();
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cd_get_toc(uint32_t * toc)
|
|
{
|
|
struct cd_command command = {{
|
|
0x0200,
|
|
0,
|
|
0,
|
|
0
|
|
}};
|
|
struct cd_response response = {0};
|
|
|
|
int ret = cd_command_response(&command, &response);
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
int size = ((response.CDATA[0] & 0xff) << 16)
|
|
| ((response.CDATA[1] & 0xffff) << 0);
|
|
ret = cd_get_data((uint16_t *)toc, size);
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cd_init()
|
|
{
|
|
struct cd_command command = {{
|
|
0x0400,
|
|
0,
|
|
0,
|
|
0x040f,
|
|
}};
|
|
struct cd_response response = {0};
|
|
|
|
int ret = cd_command_response(&command, &response);
|
|
return ret;
|
|
}
|
|
|
|
void test_cd()
|
|
{
|
|
int ret;
|
|
ret = cd_init();
|
|
serial_string("cd_init: ");
|
|
serial_integer(ret, 8, '\n');
|
|
if (ret != 0)
|
|
return;
|
|
|
|
uint32_t toc[102];
|
|
ret = cd_get_toc(toc);
|
|
serial_string("cd_get_toc: ");
|
|
serial_integer(ret, 8, '\n');
|
|
if (ret != 0)
|
|
return;
|
|
|
|
for (int i = 0; i < 102; i++) {
|
|
serial_integer(toc[i], 8, '\n');
|
|
}
|
|
}
|
|
|
|
void main()
|
|
{
|
|
// serial mode register
|
|
sh2.reg.SMR = 0
|
|
| SMR__CA__ASYNCHRONOUS_MODE
|
|
| SMR__CHR__EIGHT_BIT_DATA
|
|
| SMR__PE__PARITY_BIT_NOT_ADDED_OR_CHECKED
|
|
| SMR__OE__EVEN_PARITY
|
|
| SMR__STOP__ONE_STOP_BIT
|
|
| SMR__MP__DISABLED
|
|
| SMR__CKS__PHI_4;
|
|
|
|
// actual baud rate at phi_4 = 3579545 / (16 * (5 + 1))
|
|
// 37286.927 ~= 38400
|
|
sh2.reg.BRR = 5;
|
|
|
|
sh2.reg.SCR = SCR__TE__TRANSMITTER_ENABLE | SCR__RE__RECEIVER_ENABLE;
|
|
|
|
sh2.reg.SSR = 0;
|
|
|
|
test_cd();
|
|
|
|
while (1);
|
|
}
|