BizHawk/libsnes/bsnes/snes/controller/usart/usart.cpp

104 lines
1.8 KiB
C++

#ifdef CONTROLLER_CPP
//Synchronous serial communications cable emulation
//Hardware:
//Teensy++ 2.0 USB
//AT90USB1286
//Connection Diagram:
//[SNES] [Teensy]
// +5v ---
// Clock D5
// Latch D2
// Data1 D3
// Data2 ---
// IOBit ---
// GND GND
void USART::enter() {
if(init && main) {
init({ &USART::usleep, this }, { &USART::read, this }, { &USART::write, this });
main();
}
while(true) step(1000000); //fallback; main should never return
}
void USART::usleep(unsigned milliseconds) {
step(milliseconds);
}
//SNES -> USART
uint8 USART::read() {
while(txbuffer.size() == 0) step(1);
uint8 data = txbuffer[0];
txbuffer.remove(0);
return data;
}
//USART -> SNES
void USART::write(uint8 data) {
rxbuffer.append(data ^ 0xff);
}
//clock
uint2 USART::data() {
//SNES -> USART
if(txlength == 0) {
if(latched == 0) txlength++;
} else if(txlength <= 8) {
txdata = (latched << 7) | (txdata >> 1);
txlength++;
} else {
if(latched == 1) txbuffer.append(txdata);
txlength = 0;
}
//USART -> SNES
if(rxlength == 0 && rxbuffer.size()) {
data1 = 1;
rxdata = rxbuffer[0];
rxbuffer.remove(0);
rxlength++;
} else if(rxlength <= 8) {
data1 = rxdata & 1;
rxdata >>= 1;
rxlength++;
} else {
data1 = 0;
rxlength = 0;
}
return (data2 << 1) | (data1 << 0);
}
//latch
void USART::latch(bool data) {
latched = data;
}
USART::USART(bool port) : Controller(port) {
latched = 0;
data1 = 0;
data2 = 0;
rxlength = 0;
rxdata = 0;
txlength = 0;
txdata = 0;
string filename = interface->path(Cartridge::Slot::Base, "usart.so");
if(open_absolute(filename)) {
init = sym("usart_init");
main = sym("usart_main");
if(init && main) create(Controller::Enter, 1000000);
}
}
USART::~USART() {
if(opened()) close();
}
#endif