mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-01-22 19:52:05 +01:00
Add X76F100 driver, fix X76F041/DS2401, add GCA15
This commit is contained in:
parent
ffa70d66fb
commit
36b09d5865
@ -74,14 +74,19 @@ target_compile_definitions(
|
||||
cart_tool PRIVATE
|
||||
VERSION="${PROJECT_VERSION}"
|
||||
$<IF:$<CONFIG:Debug>,
|
||||
#ENABLE_ARGV=1
|
||||
ENABLE_PS1_CONTROLLER=1
|
||||
ENABLE_CART_MENU=1
|
||||
#ENABLE_X76F100_DRIVER=1
|
||||
ENABLE_DUMMY_DRIVER=1
|
||||
ENABLE_I2C_LOGGING=1
|
||||
ENABLE_PS1_CONTROLLER=1
|
||||
,
|
||||
#ENABLE_ARGV=1
|
||||
ENABLE_CART_MENU=1
|
||||
ENABLE_PS1_CONTROLLER=1
|
||||
ENABLE_CART_MENU=1
|
||||
#ENABLE_X76F100_DRIVER=1
|
||||
#ENABLE_DUMMY_DRIVER=1
|
||||
#ENABLE_I2C_LOGGING=1
|
||||
>
|
||||
)
|
||||
|
||||
|
@ -88,7 +88,6 @@ function(ps1_target_incbin
|
||||
)
|
||||
string(MAKE_C_IDENTIFIER "${symbolName}" _symbolName)
|
||||
string(MAKE_C_IDENTIFIER "${sizeSymbolName}" _sizeSymbolName)
|
||||
string(MAKE_C_IDENTIFIER "${section}" _section)
|
||||
|
||||
cmake_path(ABSOLUTE_PATH path OUTPUT_VARIABLE _path)
|
||||
|
||||
@ -101,7 +100,7 @@ function(ps1_target_incbin
|
||||
CONFIGURE
|
||||
OUTPUT "${_assemblyFile}"
|
||||
CONTENT [[
|
||||
.section ${_section}.${_symbolName}, "aw"
|
||||
.section ${section}.${_symbolName}, "aw"
|
||||
.balign 8
|
||||
|
||||
.global ${_symbolName}
|
||||
@ -113,7 +112,7 @@ ${_symbolName}:
|
||||
.incbin "${_path}"
|
||||
${_symbolName}_end:
|
||||
|
||||
.section ${_section}.${_sizeSymbolName}, "aw"
|
||||
.section ${section}.${_sizeSymbolName}, "aw"
|
||||
.balign 4
|
||||
|
||||
.global ${_sizeSymbolName}
|
||||
|
@ -933,7 +933,7 @@
|
||||
"gameCart": null,
|
||||
"ioBoard": "PWB0000073070",
|
||||
"bootloaderVersion": null,
|
||||
"lockedToIOBoard": true
|
||||
"lockedToIOBoard": false
|
||||
},
|
||||
{
|
||||
"id": "hypbbc2p",
|
||||
@ -1295,6 +1295,18 @@
|
||||
"bootloaderVersion": null,
|
||||
"lockedToIOBoard": false
|
||||
},
|
||||
{
|
||||
"id": null,
|
||||
"code": "GCA15",
|
||||
"region": "JAA",
|
||||
"name": "GunMania Zone Plus",
|
||||
"year": 2000,
|
||||
"installCart": null,
|
||||
"gameCart": "X76F041+DS2401",
|
||||
"ioBoard": "PWB0000073070",
|
||||
"bootloaderVersion": null,
|
||||
"lockedToIOBoard": false
|
||||
},
|
||||
{
|
||||
"id": "salarymc",
|
||||
"code": "GCA18",
|
||||
|
@ -22,19 +22,20 @@ bool App::_startupWorker(void) {
|
||||
// Skip the warning screen in debug builds.
|
||||
_workerStatus.setNextScreen(_buttonMappingScreen);
|
||||
#endif
|
||||
_workerStatus.update(0, 3, WSTR("App.startupWorker.initIDE"));
|
||||
|
||||
ide::devices[0].enumerate();
|
||||
ide::devices[1].enumerate();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
_workerStatus.update(i, 4, WSTR("App.startupWorker.initIDE"));
|
||||
ide::devices[i].enumerate();
|
||||
}
|
||||
|
||||
_workerStatus.update(1, 3, WSTR("App.startupWorker.initFAT"));
|
||||
_workerStatus.update(2, 4, WSTR("App.startupWorker.initFAT"));
|
||||
|
||||
// Attempt to mount the secondary drive first, then in case of failure try
|
||||
// mounting the primary drive instead.
|
||||
if (!_fileProvider.init("1:"))
|
||||
_fileProvider.init("0:");
|
||||
|
||||
_workerStatus.update(2, 3, WSTR("App.startupWorker.loadResources"));
|
||||
_workerStatus.update(3, 4, WSTR("App.startupWorker.loadResources"));
|
||||
|
||||
_resourceFile = _fileProvider.openFile(
|
||||
EXTERNAL_DATA_DIR "/resource.zip", file::READ
|
||||
@ -300,6 +301,10 @@ bool App::_cartReflashWorker(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: preserve 0x81 traceid if possible
|
||||
//uint8_t traceID[8];
|
||||
//_parser->getIdentifiers()->traceID.copyTo(traceID);
|
||||
|
||||
if (!_cartEraseWorker())
|
||||
return false;
|
||||
if (_parser)
|
||||
|
133
src/cartio.cpp
133
src/cartio.cpp
@ -74,12 +74,6 @@ DriverError DummyDriver::writeData(void) {
|
||||
}
|
||||
|
||||
DriverError DummyDriver::erase(void) {
|
||||
char buf[128];
|
||||
util::hexToString(buf,_dump.dataKey,8);
|
||||
LOG("got %s",buf);
|
||||
util::hexToString(buf,dummyDriverDump.dataKey,8);
|
||||
LOG("exp %s",buf);
|
||||
|
||||
if (!__builtin_memcmp(
|
||||
_dump.dataKey, dummyDriverDump.dataKey, sizeof(_dump.dataKey)
|
||||
)) {
|
||||
@ -171,7 +165,7 @@ DriverError X76Driver::readCartID(void) {
|
||||
}
|
||||
|
||||
DriverError X76Driver::_x76Command(
|
||||
uint8_t cmd, uint8_t param, uint8_t pollByte
|
||||
uint8_t pollByte, uint8_t cmd, int param
|
||||
) const {
|
||||
delayMicroseconds(_X76_PACKET_DELAY);
|
||||
io::i2cStartWithCS();
|
||||
@ -183,11 +177,13 @@ DriverError X76Driver::_x76Command(
|
||||
return X76_NACK;
|
||||
}
|
||||
|
||||
io::i2cWriteByte(param);
|
||||
if (!io::i2cGetACK()) {
|
||||
io::i2cStopWithCS();
|
||||
LOG("NACK while sending param=0x%02x", param);
|
||||
return X76_NACK;
|
||||
if (param >= 0) {
|
||||
io::i2cWriteByte(param);
|
||||
if (!io::i2cGetACK()) {
|
||||
io::i2cStopWithCS();
|
||||
LOG("NACK while sending param=0x%02x", param);
|
||||
return X76_NACK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!io::i2cWriteBytes(_dump.dataKey, sizeof(_dump.dataKey))) {
|
||||
@ -200,7 +196,10 @@ DriverError X76Driver::_x76Command(
|
||||
char buffer[48];
|
||||
|
||||
util::hexToString(buffer, _dump.dataKey, sizeof(_dump.dataKey), ' ');
|
||||
LOG("S: %02X %02X %s", cmd, param, buffer);
|
||||
if (param >= 0)
|
||||
LOG("S: %02X %02X %s", cmd, param, buffer);
|
||||
else
|
||||
LOG("S: %02X %s", cmd, buffer);
|
||||
#endif
|
||||
|
||||
for (int i = _X76_MAX_ACK_POLLS; i; i--) {
|
||||
@ -237,7 +236,7 @@ DriverError X76F041Driver::readPrivateData(void) {
|
||||
// cross 128-byte block boundaries.
|
||||
for (int i = 0; i < 512; i += 128) {
|
||||
auto error = _x76Command(
|
||||
_X76F041_READ | (i >> 8), i & 0xff, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_READ | (i >> 8), i & 0xff
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -256,8 +255,10 @@ DriverError X76F041Driver::readPrivateData(void) {
|
||||
io::i2cStopWithCS();
|
||||
}
|
||||
|
||||
_dump.flags |= DUMP_PRIVATE_DATA_OK;
|
||||
|
||||
auto error = _x76Command(
|
||||
_X76F041_CONFIG, _X76F041_CFG_READ_CONFIG, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_CONFIG, _X76F041_CFG_READ_CONFIG
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -272,10 +273,10 @@ DriverError X76F041Driver::readPrivateData(void) {
|
||||
return X76_NACK;
|
||||
}
|
||||
|
||||
io::i2cReadBytes(_dump.config, 5);
|
||||
io::i2cReadBytes(_dump.config, 8);
|
||||
io::i2cStopWithCS();
|
||||
|
||||
_dump.flags |= DUMP_PRIVATE_DATA_OK;
|
||||
_dump.flags |= DUMP_CONFIG_OK;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@ -283,7 +284,7 @@ DriverError X76F041Driver::writeData(void) {
|
||||
// Writes can only be done in 8-byte blocks.
|
||||
for (int i = 0; i < 512; i += 8) {
|
||||
auto error = _x76Command(
|
||||
_X76F041_WRITE | (i >> 8), i & 0xff, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_WRITE | (i >> 8), i & 0xff
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -298,7 +299,7 @@ DriverError X76F041Driver::writeData(void) {
|
||||
}
|
||||
|
||||
auto error = _x76Command(
|
||||
_X76F041_CONFIG, _X76F041_CFG_WRITE_CONFIG, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_CONFIG, _X76F041_CFG_WRITE_CONFIG
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -316,7 +317,7 @@ DriverError X76F041Driver::writeData(void) {
|
||||
|
||||
DriverError X76F041Driver::erase(void) {
|
||||
auto error = _x76Command(
|
||||
_X76F041_CONFIG, _X76F041_CFG_MASS_PROGRAM, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_CONFIG, _X76F041_CFG_MASS_PROGRAM
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -329,7 +330,7 @@ DriverError X76F041Driver::erase(void) {
|
||||
|
||||
DriverError X76F041Driver::setDataKey(const uint8_t *key) {
|
||||
auto error = _x76Command(
|
||||
_X76F041_CONFIG, _X76F041_CFG_SET_DATA_KEY, _X76F041_ACK_POLL
|
||||
_X76F041_ACK_POLL, _X76F041_CONFIG, _X76F041_CFG_SET_DATA_KEY
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
@ -353,29 +354,91 @@ DriverError X76F041Driver::setDataKey(const uint8_t *key) {
|
||||
/* X76F100 driver */
|
||||
|
||||
enum X76F100Command : uint8_t {
|
||||
_X76F100_READ = 0x81,
|
||||
_X76F100_WRITE = 0x80,
|
||||
_X76F100_SET_READ_KEY = 0xfe,
|
||||
_X76F100_SET_WRITE_KEY = 0xfc,
|
||||
_X76F100_ACK_POLL = 0x55
|
||||
_X76F100_READ = 0x81,
|
||||
_X76F100_WRITE = 0x80,
|
||||
_X76F100_SET_KEY = 0xfc,
|
||||
_X76F100_ACK_POLL = 0x55
|
||||
};
|
||||
|
||||
// TODO: actually implement this (even though no X76F100 carts were ever made)
|
||||
|
||||
DriverError X76F100Driver::readPrivateData(void) {
|
||||
return UNSUPPORTED_OP;
|
||||
auto error = _x76Command(_X76F100_ACK_POLL, _X76F100_READ);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
//io::i2cStart();
|
||||
io::i2cReadBytes(_dump.data, 112);
|
||||
io::i2cStopWithCS();
|
||||
|
||||
_dump.flags |= DUMP_PRIVATE_DATA_OK;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
DriverError X76F100Driver::writeData(void) {
|
||||
return UNSUPPORTED_OP;
|
||||
// Writes can only be done in 8-byte blocks.
|
||||
for (int i = 0; i < 112; i += 8) {
|
||||
auto error = _x76Command(
|
||||
_X76F100_ACK_POLL, _X76F100_WRITE | (i >> 2)
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!io::i2cWriteBytes(&_dump.data[i], 8)) {
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
LOG("NACK while sending data bytes");
|
||||
return X76_NACK;
|
||||
}
|
||||
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
DriverError X76F100Driver::erase(void) {
|
||||
return UNSUPPORTED_OP;
|
||||
// The chip does not have an erase command, so erasing must be performed
|
||||
// manually one block at a time.
|
||||
uint8_t dummy[8]{ 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
for (int i = 0; i < 112; i += 8) {
|
||||
auto error = _x76Command(
|
||||
_X76F100_ACK_POLL, _X76F100_WRITE | (i >> 2)
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!io::i2cWriteBytes(dummy, 8)) {
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
LOG("NACK while sending data bytes");
|
||||
return X76_NACK;
|
||||
}
|
||||
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
}
|
||||
|
||||
return setDataKey(dummy);
|
||||
}
|
||||
|
||||
DriverError X76F100Driver::setDataKey(const uint8_t *key) {
|
||||
return UNSUPPORTED_OP;
|
||||
// There are two separate keys, one for read commands and one for write
|
||||
// commands.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
auto error = _x76Command(
|
||||
_X76F100_ACK_POLL, _X76F100_SET_KEY | (i << 1)
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!io::i2cWriteBytes(key, sizeof(_dump.dataKey))) {
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
LOG("NACK while setting new data key");
|
||||
return X76_NACK;
|
||||
}
|
||||
|
||||
io::i2cStopWithCS(_X76_WRITE_DELAY);
|
||||
}
|
||||
|
||||
_dump.copyKeyFrom(key);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/* ZS01 driver */
|
||||
@ -597,8 +660,10 @@ CartDriver *newCartDriver(Dump &dump) {
|
||||
case _ID_X76F041:
|
||||
return new X76F041Driver(dump);
|
||||
|
||||
//case _ID_X76F100:
|
||||
//return new X76F100Driver(dump);
|
||||
#ifdef ENABLE_X76F100_DRIVER
|
||||
case _ID_X76F100:
|
||||
return new X76F100Driver(dump);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return new CartDriver(dump);
|
||||
|
@ -89,7 +89,9 @@ public:
|
||||
|
||||
class [[gnu::packed]] X76Driver : public CartDriver {
|
||||
protected:
|
||||
DriverError _x76Command(uint8_t cmd, uint8_t param, uint8_t pollByte) const;
|
||||
DriverError _x76Command(
|
||||
uint8_t pollByte, uint8_t cmd, int param = -1
|
||||
) const;
|
||||
|
||||
public:
|
||||
inline X76Driver(Dump &dump, ChipType chipType)
|
||||
|
13
src/ide.cpp
13
src/ide.cpp
@ -21,8 +21,9 @@
|
||||
|
||||
namespace ide {
|
||||
|
||||
static constexpr int _STATUS_TIMEOUT = 100000;
|
||||
static constexpr int _RESET_STATUS_TIMEOUT = 3000000;
|
||||
static constexpr int _STATUS_TIMEOUT = 1000000;
|
||||
static constexpr int _RESET_STATUS_TIMEOUT = 2000000;
|
||||
static constexpr int _DATA_STATUS_TIMEOUT = 2000000;
|
||||
static constexpr int _DMA_TIMEOUT = 10000;
|
||||
|
||||
/* Utilities */
|
||||
@ -143,7 +144,9 @@ DeviceError Device::_command(uint8_t cmd, bool drdy) {
|
||||
DeviceError Device::_transferPIO(void *data, size_t length, bool write) {
|
||||
util::assertAligned<uint16_t>(data);
|
||||
|
||||
auto error = _waitForStatus(CS0_STATUS_DRQ, CS0_STATUS_DRQ, _STATUS_TIMEOUT);
|
||||
auto error = _waitForStatus(
|
||||
CS0_STATUS_DRQ, CS0_STATUS_DRQ, _DATA_STATUS_TIMEOUT
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -165,7 +168,9 @@ DeviceError Device::_transferDMA(void *data, size_t length, bool write) {
|
||||
|
||||
util::assertAligned<uint32_t>(data);
|
||||
|
||||
auto error = _waitForStatus(CS0_STATUS_DRQ, CS0_STATUS_DRQ, _STATUS_TIMEOUT);
|
||||
auto error = _waitForStatus(
|
||||
CS0_STATUS_DRQ, CS0_STATUS_DRQ, _DATA_STATUS_TIMEOUT
|
||||
);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
73
src/io.cpp
73
src/io.cpp
@ -34,13 +34,9 @@ void init(void) {
|
||||
| BIU_CTRL_DMA_DELAY;
|
||||
|
||||
SYS573_WATCHDOG = 0;
|
||||
SYS573_BANK_CTRL = 0;
|
||||
SYS573_CART_OUT = 0;
|
||||
SYS573_MISC_OUT = 0
|
||||
| SYS573_MISC_OUT_ADC_MOSI
|
||||
| SYS573_MISC_OUT_ADC_CS
|
||||
| SYS573_MISC_OUT_ADC_SCK
|
||||
| SYS573_MISC_OUT_JVS_STAT;
|
||||
SYS573_BANK_CTRL = _bankSwitchReg;
|
||||
SYS573_CART_OUT = _cartOutputReg;
|
||||
SYS573_MISC_OUT = _miscOutputReg;
|
||||
|
||||
// Some of the digital I/O board's light outputs are controlled by the FPGA
|
||||
// and cannot be turned off until the FPGA is initialized.
|
||||
@ -202,11 +198,13 @@ void i2cStart(void) {
|
||||
|
||||
void i2cStartWithCS(int csDelay) {
|
||||
_SDA(true);
|
||||
_SCL(true);
|
||||
_SCL(false);
|
||||
CS(true);
|
||||
|
||||
CS(false);
|
||||
delayMicroseconds(csDelay);
|
||||
SCL(true);
|
||||
|
||||
SDA(false); // START: SDA falling, SCL high
|
||||
SCL(false);
|
||||
}
|
||||
@ -223,6 +221,8 @@ void i2cStopWithCS(int csDelay) {
|
||||
SCL(true);
|
||||
|
||||
SDA(true); // STOP: SDA rising, SCL high
|
||||
|
||||
SCL(false);
|
||||
delayMicroseconds(csDelay);
|
||||
CS(true);
|
||||
}
|
||||
@ -311,8 +311,8 @@ uint32_t i2cResetX76(void) {
|
||||
SCL(false);
|
||||
}
|
||||
|
||||
SCL(true);
|
||||
CS(true);
|
||||
SCL(true);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -347,34 +347,43 @@ uint32_t i2cResetZS01(void) {
|
||||
|
||||
/* 1-wire driver */
|
||||
|
||||
static constexpr int _DS_RESET_DELAY = 480;
|
||||
static constexpr int _DS_RESET_LOW_TIME = 480;
|
||||
static constexpr int _DS_RESET_SAMPLE_DELAY = 70;
|
||||
static constexpr int _DS_RESET_DELAY = 410;
|
||||
|
||||
static constexpr int _DS_READ_LOW_TIME = 3;
|
||||
static constexpr int _DS_READ_SAMPLE_DELAY = 10;
|
||||
static constexpr int _DS_READ_DELAY = 53;
|
||||
|
||||
static constexpr int _DS_ZERO_LOW_TIME = 65;
|
||||
static constexpr int _DS_ZERO_HIGH_TIME = 5;
|
||||
static constexpr int _DS_ONE_LOW_TIME = 10;
|
||||
static constexpr int _DS_ONE_HIGH_TIME = 55;
|
||||
|
||||
#define _CART1WIRE(value) setCartOutput(OUT_1WIRE, !(value))
|
||||
#define _DIO1WIRE(value) setDIO1Wire(value)
|
||||
|
||||
bool dsCartReset(void) {
|
||||
_CART1WIRE(false);
|
||||
delayMicroseconds(_DS_RESET_DELAY);
|
||||
delayMicroseconds(_DS_RESET_LOW_TIME);
|
||||
_CART1WIRE(true);
|
||||
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_RESET_SAMPLE_DELAY);
|
||||
bool present = !getCartInput(IN_1WIRE);
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_RESET_DELAY);
|
||||
|
||||
delayMicroseconds(1000);
|
||||
return present;
|
||||
}
|
||||
|
||||
bool dsDIOReset(void) {
|
||||
_DIO1WIRE(false);
|
||||
delayMicroseconds(_DS_RESET_DELAY);
|
||||
delayMicroseconds(_DS_RESET_LOW_TIME);
|
||||
_DIO1WIRE(true);
|
||||
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_RESET_SAMPLE_DELAY);
|
||||
bool present = !getDIO1Wire();
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_RESET_DELAY);
|
||||
|
||||
delayMicroseconds(1000);
|
||||
return present;
|
||||
}
|
||||
|
||||
@ -383,12 +392,12 @@ uint8_t dsCartReadByte(void) {
|
||||
|
||||
for (int bit = 0; bit < 8; bit++) { // LSB first
|
||||
_CART1WIRE(false);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_READ_LOW_TIME);
|
||||
_CART1WIRE(true);
|
||||
delayMicroseconds(10);
|
||||
delayMicroseconds(_DS_READ_SAMPLE_DELAY);
|
||||
if (getCartInput(IN_1WIRE))
|
||||
value |= (1 << bit);
|
||||
delayMicroseconds(50);
|
||||
delayMicroseconds(_DS_READ_DELAY);
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -399,12 +408,12 @@ uint8_t dsDIOReadByte(void) {
|
||||
|
||||
for (int bit = 0; bit < 8; bit++) { // LSB first
|
||||
_DIO1WIRE(false);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_READ_LOW_TIME);
|
||||
_DIO1WIRE(true);
|
||||
delayMicroseconds(10);
|
||||
delayMicroseconds(_DS_READ_SAMPLE_DELAY);
|
||||
if (getDIO1Wire())
|
||||
value |= (1 << bit);
|
||||
delayMicroseconds(50);
|
||||
delayMicroseconds(_DS_READ_DELAY);
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -414,14 +423,14 @@ void dsCartWriteByte(uint8_t value) {
|
||||
for (int bit = 0; bit < 8; bit++) { // LSB first
|
||||
if (value & (1 << bit)) {
|
||||
_CART1WIRE(false);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_ONE_LOW_TIME);
|
||||
_CART1WIRE(true);
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_ONE_HIGH_TIME);
|
||||
} else {
|
||||
_CART1WIRE(false);
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_ZERO_LOW_TIME);
|
||||
_CART1WIRE(true);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_ZERO_HIGH_TIME);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -430,14 +439,14 @@ void dsDIOWriteByte(uint8_t value) {
|
||||
for (int bit = 0; bit < 8; bit++) { // LSB first
|
||||
if (value & (1 << bit)) {
|
||||
_DIO1WIRE(false);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_ONE_LOW_TIME);
|
||||
_DIO1WIRE(true);
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_ONE_HIGH_TIME);
|
||||
} else {
|
||||
_DIO1WIRE(false);
|
||||
delayMicroseconds(60);
|
||||
delayMicroseconds(_DS_ZERO_LOW_TIME);
|
||||
_DIO1WIRE(true);
|
||||
delayMicroseconds(2);
|
||||
delayMicroseconds(_DS_ZERO_HIGH_TIME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user