mirror of https://github.com/stella-emu/stella.git
Add support for 2600-daptor II when flashed as an AVox-USB converter.
Basically, for this device we use software flow control rather than hardware CTS signal.
This commit is contained in:
parent
0ef60c517b
commit
c00fda482d
|
@ -34,8 +34,8 @@
|
||||||
one ZIP file, and distribute just that file.
|
one ZIP file, and distribute just that file.
|
||||||
|
|
||||||
* Extended AtariVox support to handle flow control, so that long phrases
|
* Extended AtariVox support to handle flow control, so that long phrases
|
||||||
are no longer corrupted/cut off. Note that some USB-serial adaptors
|
are no longer corrupted/cut off. This includes properly supporting the
|
||||||
don't support this mode, so there may still be issues with those.
|
2600-daptor II, which is flashable to an AVox-USB converter.
|
||||||
|
|
||||||
* Added option to select the audio device.
|
* Added option to select the audio device.
|
||||||
|
|
||||||
|
|
|
@ -56,10 +56,27 @@ bool AtariVox::read(DigitalPin pin)
|
||||||
switch(pin)
|
switch(pin)
|
||||||
{
|
{
|
||||||
// Pin 2: SpeakJet READY
|
// Pin 2: SpeakJet READY
|
||||||
// CTS (Clear To Send) is sent directly to pin 2
|
// READY signal is sent directly to pin 2
|
||||||
// We also deal with the case where devices send CTS inverted
|
|
||||||
case DigitalPin::Two:
|
case DigitalPin::Two:
|
||||||
return setPin(pin, mySerialPort->isCTS() ^ myCTSFlip);
|
{
|
||||||
|
// Some USB-serial adaptors support only CTS, others support only
|
||||||
|
// software flow control
|
||||||
|
// So we check the state of both then AND the results, on the
|
||||||
|
// assumption that if a mode isn't supported, then it reads as TRUE
|
||||||
|
// and doesn't change the boolean result
|
||||||
|
// Thus the logic is:
|
||||||
|
// READY_SIGNAL = READY_STATE_CTS && READY_STATE_FLOW
|
||||||
|
// Note that we also have to take inverted CTS into account
|
||||||
|
|
||||||
|
// When using software flow control, only update on a state change
|
||||||
|
uInt8 flowCtrl = 0;
|
||||||
|
if(mySerialPort->readByte(flowCtrl))
|
||||||
|
myReadyStateSoftFlow = flowCtrl == 0x11; // XON
|
||||||
|
|
||||||
|
// Now combine the results of CTS and'ed with flow control
|
||||||
|
return setPin(pin,
|
||||||
|
(mySerialPort->isCTS() ^ myCTSFlip) && myReadyStateSoftFlow);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return SaveKey::read(pin);
|
return SaveKey::read(pin);
|
||||||
|
|
|
@ -32,7 +32,7 @@ class FilesystemNode;
|
||||||
This code owes a great debt to Alex Herbert's AtariVox documentation and
|
This code owes a great debt to Alex Herbert's AtariVox documentation and
|
||||||
driver code.
|
driver code.
|
||||||
|
|
||||||
@author B. Watson
|
@author B. Watson, Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class AtariVox : public SaveKey
|
class AtariVox : public SaveKey
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,9 @@ class AtariVox : public SaveKey
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
string about(bool swappedPorts) const override { return Controller::about(swappedPorts) + myAboutString; }
|
string about(bool swappedPorts) const override {
|
||||||
|
return Controller::about(swappedPorts) + myAboutString;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clockDataIn(bool value);
|
void clockDataIn(bool value);
|
||||||
|
@ -117,9 +119,11 @@ class AtariVox : public SaveKey
|
||||||
// "close enough".
|
// "close enough".
|
||||||
uInt64 myLastDataWriteCycle{0};
|
uInt64 myLastDataWriteCycle{0};
|
||||||
|
|
||||||
// Some USB-Serial adaptors either don't support CTS, or send the signal
|
// When using software flow control, assume the device starts in READY mode
|
||||||
// as inverted; we detect that when opening the port, and flip the signal
|
bool myReadyStateSoftFlow{true};
|
||||||
// when necessary
|
|
||||||
|
// Some USB-Serial adaptors send the CTS signal inverted; we detect
|
||||||
|
// that when opening the port, and flip the signal when necessary
|
||||||
bool myCTSFlip{false};
|
bool myCTSFlip{false};
|
||||||
|
|
||||||
// Holds information concerning serial port usage
|
// Holds information concerning serial port usage
|
||||||
|
|
|
@ -43,7 +43,6 @@ class SerialPort
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read a byte from the serial port.
|
Read a byte from the serial port.
|
||||||
NOTE: This is for potential future use; no class currently uses this.
|
|
||||||
|
|
||||||
@param data Destination for the byte read from the port
|
@param data Destination for the byte read from the port
|
||||||
@return True if a byte was read, else false
|
@return True if a byte was read, else false
|
||||||
|
|
|
@ -63,14 +63,21 @@ bool SerialPortMACOS::openPort(const string& device)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool SerialPortMACOS::readByte(uInt8& data)
|
||||||
|
{
|
||||||
|
if(myHandle)
|
||||||
|
return read(myHandle, &data, 1) == 1;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool SerialPortMACOS::writeByte(uInt8 data)
|
bool SerialPortMACOS::writeByte(uInt8 data)
|
||||||
{
|
{
|
||||||
if(myHandle)
|
if(myHandle)
|
||||||
{
|
|
||||||
// cerr << "SerialPortMACOS::writeByte " << int(data) << endl;
|
|
||||||
return write(myHandle, &data, 1) == 1;
|
return write(myHandle, &data, 1) == 1;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,14 @@ class SerialPortMACOS : public SerialPort
|
||||||
*/
|
*/
|
||||||
bool openPort(const string& device) override;
|
bool openPort(const string& device) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read a byte from the serial port.
|
||||||
|
|
||||||
|
@param data Destination for the byte read from the port
|
||||||
|
@return True if a byte was read, else false
|
||||||
|
*/
|
||||||
|
bool readByte(uInt8& data) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write a byte to the serial port.
|
Write a byte to the serial port.
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,9 @@ bool SerialPortUNIX::openPort(const string& device)
|
||||||
if(myHandle <= 0)
|
if(myHandle <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Open the device in nonblocking mode
|
// Clear buffers, then open the device in nonblocking mode
|
||||||
|
tcflush(myHandle, TCOFLUSH);
|
||||||
|
tcflush(myHandle, TCIFLUSH);
|
||||||
fcntl(myHandle, F_SETFL, FNDELAY);
|
fcntl(myHandle, F_SETFL, FNDELAY);
|
||||||
|
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
|
@ -64,14 +66,21 @@ bool SerialPortUNIX::openPort(const string& device)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool SerialPortUNIX::readByte(uInt8& data)
|
||||||
|
{
|
||||||
|
if(myHandle)
|
||||||
|
return read(myHandle, &data, 1) == 1;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool SerialPortUNIX::writeByte(uInt8 data)
|
bool SerialPortUNIX::writeByte(uInt8 data)
|
||||||
{
|
{
|
||||||
if(myHandle)
|
if(myHandle)
|
||||||
{
|
|
||||||
// cerr << "SerialPortUNIX::writeByte " << int(data) << endl;
|
|
||||||
return write(myHandle, &data, 1) == 1;
|
return write(myHandle, &data, 1) == 1;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,14 @@ class SerialPortUNIX : public SerialPort
|
||||||
*/
|
*/
|
||||||
bool openPort(const string& device) override;
|
bool openPort(const string& device) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read a byte from the serial port.
|
||||||
|
|
||||||
|
@param data Destination for the byte read from the port
|
||||||
|
@return True if a byte was read, else false
|
||||||
|
*/
|
||||||
|
bool readByte(uInt8& data) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write a byte to the serial port.
|
Write a byte to the serial port.
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,14 @@ bool SerialPortWINDOWS::openPort(const string& device)
|
||||||
dcb.Parity = NOPARITY;
|
dcb.Parity = NOPARITY;
|
||||||
dcb.StopBits = ONESTOPBIT;
|
dcb.StopBits = ONESTOPBIT;
|
||||||
SetCommState(myHandle, &dcb);
|
SetCommState(myHandle, &dcb);
|
||||||
|
|
||||||
|
COMMTIMEOUTS commtimeouts;
|
||||||
|
commtimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||||
|
commtimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||||
|
commtimeouts.ReadTotalTimeoutConstant = 1;
|
||||||
|
commtimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||||
|
commtimeouts.WriteTotalTimeoutConstant = 0;
|
||||||
|
SetCommTimeouts(myHandle, &commtimeouts);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -69,13 +77,26 @@ bool SerialPortWINDOWS::openPort(const string& device)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool SerialPortWINDOWS::readByte(uInt8& data)
|
||||||
|
{
|
||||||
|
if(myHandle)
|
||||||
|
{
|
||||||
|
DWORD read;
|
||||||
|
ReadFile(myHandle, &data, 1, &read, NULL);
|
||||||
|
return read == 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool SerialPortWINDOWS::writeByte(uInt8 data)
|
bool SerialPortWINDOWS::writeByte(uInt8 data)
|
||||||
{
|
{
|
||||||
if(myHandle)
|
if(myHandle)
|
||||||
{
|
{
|
||||||
DWORD written;
|
DWORD written;
|
||||||
return WriteFile(myHandle, &data, 1, &written, 0) == TRUE;
|
WriteFile(myHandle, &data, 1, &written, NULL);
|
||||||
|
return written == 1;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,14 @@ class SerialPortWINDOWS : public SerialPort
|
||||||
*/
|
*/
|
||||||
bool openPort(const string& device) override;
|
bool openPort(const string& device) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read a byte from the serial port.
|
||||||
|
|
||||||
|
@param data Destination for the byte read from the port
|
||||||
|
@return True if a byte was read, else false
|
||||||
|
*/
|
||||||
|
bool readByte(uInt8& data) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write a byte to the serial port.
|
Write a byte to the serial port.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue