#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