cdc: get TOC
This commit is contained in:
parent
8f9fb2c7d7
commit
063699b4b3
209
cdc/cdc.cpp
Normal file
209
cdc/cdc.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
#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);
|
||||||
|
}
|
50
cdc/serial.c
Normal file
50
cdc/serial.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include "sh2.h"
|
||||||
|
|
||||||
|
void serial_char(const char c)
|
||||||
|
{
|
||||||
|
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
|
||||||
|
sh2.reg.TDR = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_string(const char * s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
|
||||||
|
sh2.reg.TDR = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_bytes(const char * s, uint32_t length)
|
||||||
|
{
|
||||||
|
while (length > 0) {
|
||||||
|
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
|
||||||
|
sh2.reg.TDR = *s++;
|
||||||
|
length -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hex(char * c, uint32_t len, uint32_t n)
|
||||||
|
{
|
||||||
|
while (len > 0) {
|
||||||
|
uint32_t nib = n & 0xf;
|
||||||
|
n = n >> 4;
|
||||||
|
if (nib > 9) {
|
||||||
|
nib += (97 - 10);
|
||||||
|
} else {
|
||||||
|
nib += (48 - 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
c[--len] = nib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_integer(const uint32_t n, const uint32_t length, const char end)
|
||||||
|
{
|
||||||
|
char num_buf[length];
|
||||||
|
hex(num_buf, length, n);
|
||||||
|
serial_string("0x");
|
||||||
|
serial_bytes(num_buf, length);
|
||||||
|
serial_char(end);
|
||||||
|
}
|
16
cdc/serial.h
Normal file
16
cdc/serial.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void serial_char(const char c);
|
||||||
|
void serial_string(const char * s);
|
||||||
|
void serial_bytes(const char * s, uint32_t length);
|
||||||
|
void serial_integer(const uint32_t n, const uint32_t length, const char end);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
44
cdc/toc.h
Normal file
44
cdc/toc.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct track {
|
||||||
|
const uint8_t control_adr;
|
||||||
|
const uint8_t fad[3];
|
||||||
|
};
|
||||||
|
static_assert((sizeof (track)) == 4);
|
||||||
|
|
||||||
|
struct start_track {
|
||||||
|
const uint8_t control_adr;
|
||||||
|
const uint8_t start_track_number;
|
||||||
|
const uint8_t _zero[2];
|
||||||
|
};
|
||||||
|
static_assert((sizeof (start_track)) == 4);
|
||||||
|
|
||||||
|
struct end_track {
|
||||||
|
const uint8_t control_adr;
|
||||||
|
const uint8_t end_track_number;
|
||||||
|
const uint8_t _zero[2];
|
||||||
|
};
|
||||||
|
static_assert((sizeof (end_track)) == 4);
|
||||||
|
|
||||||
|
struct toc {
|
||||||
|
struct track track[99];
|
||||||
|
struct start_track start_track;
|
||||||
|
struct end_track end_track;
|
||||||
|
struct track lead_out;
|
||||||
|
};
|
||||||
|
static_assert((sizeof (toc)) == 408);
|
||||||
|
|
||||||
|
uint32_t track_fad(struct track * t) const
|
||||||
|
{
|
||||||
|
return (t->fad[0] << 16) | (t->fad[1] << 8) | (t->fad[2] << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t track_control(struct track * t) const
|
||||||
|
{
|
||||||
|
return (t->control_adr >> 4) & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t track_adr(struct track * t) const
|
||||||
|
{
|
||||||
|
return (t->control_adr >> 0) & 0xf;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user