mirror of https://github.com/stella-emu/stella.git
Yet more work on the RIOT SWCHA/SWACNT write functionality. I'm now
almost 100% sure the current RIOT write handling is working correctly, as it works with all ROMs I've tested as well as the SpeakJet portion of the AtariVox. I2C EEPROM handling still isn't working, but at least now it's getting the correct values (in the correct order) from the RIOT. So it should be much easier to finish, now that the RIOT part is taken care of. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1498 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
27441fadbf
commit
44913019b8
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: EquateList.cxx,v 1.31 2008-05-04 17:16:39 stephena Exp $
|
||||
// $Id: EquateList.cxx,v 1.32 2008-05-06 16:39:10 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <fstream>
|
||||
|
@ -71,9 +71,9 @@ void EquateList::addEquate(const string& label, int address)
|
|||
else if((address & 0x1000) == 0x1000)
|
||||
flags = EQF_RW;
|
||||
else
|
||||
{ cerr << "label = " << label << ", address = " << hex << address << " discarded\n";
|
||||
//{ cerr << "label = " << label << ", address = " << hex << address << " discarded\n";
|
||||
return; // don't know what else to do for now
|
||||
}
|
||||
//}
|
||||
|
||||
removeEquate(label);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: AtariVox.cxx,v 1.18 2008-04-29 20:06:14 stephena Exp $
|
||||
// $Id: AtariVox.cxx,v 1.19 2008-05-06 16:39:10 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifdef SPEAKJET_EMULATION
|
||||
|
@ -102,6 +102,7 @@ void AtariVox::write(DigitalPin pin, bool value)
|
|||
// Pin 1: SpeakJet DATA
|
||||
// output serial data to the speakjet
|
||||
case One:
|
||||
myDigitalPinState[One] = value;
|
||||
clockDataIn(value);
|
||||
break;
|
||||
|
||||
|
@ -114,6 +115,7 @@ void AtariVox::write(DigitalPin pin, bool value)
|
|||
<< " written to SDA line at cycle "
|
||||
<< mySystem.cycles()
|
||||
<< endl;
|
||||
myDigitalPinState[Three] = value;
|
||||
myEEPROM->writeSDA(value);
|
||||
break;
|
||||
|
||||
|
@ -126,6 +128,7 @@ void AtariVox::write(DigitalPin pin, bool value)
|
|||
<< " written to SCLK line at cycle "
|
||||
<< mySystem.cycles()
|
||||
<< endl;
|
||||
myDigitalPinState[Four] = value;
|
||||
myEEPROM->writeSCL(value);
|
||||
break;
|
||||
|
||||
|
@ -137,10 +140,6 @@ void AtariVox::write(DigitalPin pin, bool value)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariVox::clockDataIn(bool value)
|
||||
{
|
||||
// Data is normally inverted when sending to the SpeakJet;
|
||||
// we need to reverse that
|
||||
// value = !value;
|
||||
|
||||
uInt32 cycle = mySystem.cycles();
|
||||
if(DEBUG_ATARIVOX)
|
||||
cerr << "AtariVox: value "
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6532.cxx,v 1.23 2008-04-28 21:31:40 stephena Exp $
|
||||
// $Id: M6532.cxx,v 1.24 2008-05-06 16:39:11 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -137,9 +137,11 @@ uInt8 M6532::peek(uInt16 addr)
|
|||
if(port1.read(Controller::Three)) value |= 0x04;
|
||||
if(port1.read(Controller::Four)) value |= 0x08;
|
||||
|
||||
// Return the input bits set by the controller *and* the
|
||||
// output bits set by the last write to SWCHA
|
||||
return (value & ~myDDRA) | (myOutA & myDDRA);
|
||||
// Each pin is high (1) by default and will only go low (0) if either
|
||||
// (a) External device drives the pin low
|
||||
// (b) Corresponding bit in SWACNT = 1 and SWCHA = 0
|
||||
// Thanks to A. Herbert for this info
|
||||
return (myOutA | ~myDDRA) & value;
|
||||
}
|
||||
|
||||
case 0x01: // Port A Data Direction Register
|
||||
|
@ -235,59 +237,20 @@ void M6532::poke(uInt16 addr, uInt8 value)
|
|||
case 0: // Port A I/O Register (Joystick)
|
||||
{
|
||||
myOutA = value;
|
||||
uInt8 a = myOutA & myDDRA;
|
||||
|
||||
Controller& port0 = myConsole.controller(Controller::Left);
|
||||
port0.write(Controller::One, a & 0x10);
|
||||
port0.write(Controller::Two, a & 0x20);
|
||||
port0.write(Controller::Three, a & 0x40);
|
||||
port0.write(Controller::Four, a & 0x80);
|
||||
|
||||
Controller& port1 = myConsole.controller(Controller::Right);
|
||||
port1.write(Controller::One, a & 0x01);
|
||||
port1.write(Controller::Two, a & 0x02);
|
||||
port1.write(Controller::Three, a & 0x04);
|
||||
port1.write(Controller::Four, a & 0x08);
|
||||
setOutputState();
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // Port A Data Direction Register
|
||||
{
|
||||
myDDRA = value;
|
||||
|
||||
/*
|
||||
Undocumented feature used by the AtariVox and SaveKey.
|
||||
When the DDR is changed, the ORA (output register A) cached
|
||||
from a previous write to SWCHA is 'applied' to the controller pins.
|
||||
|
||||
When a bit in the DDR is set as input, +5V is placed on its output
|
||||
pin. When it's set as output, either +5V or 0V (depending on the
|
||||
contents of SWCHA) will be placed on the output pin.
|
||||
The standard macros for the AtariVox use this fact to send data
|
||||
to the port. This is represented by the following algorithm:
|
||||
|
||||
if(DDR bit is input) set output as 1
|
||||
else if(DDR bit is output) set output as bit in ORA
|
||||
*/
|
||||
uInt8 a = myOutA | ~myDDRA;
|
||||
|
||||
Controller& port0 = myConsole.controller(Controller::Left);
|
||||
port0.write(Controller::One, a & 0x10);
|
||||
port0.write(Controller::Two, a & 0x20);
|
||||
port0.write(Controller::Three, a & 0x40);
|
||||
port0.write(Controller::Four, a & 0x80);
|
||||
|
||||
Controller& port1 = myConsole.controller(Controller::Right);
|
||||
port1.write(Controller::One, a & 0x01);
|
||||
port1.write(Controller::Two, a & 0x02);
|
||||
port1.write(Controller::Three, a & 0x04);
|
||||
port1.write(Controller::Four, a & 0x08);
|
||||
setOutputState();
|
||||
break;
|
||||
}
|
||||
|
||||
default: // Port B I/O & DDR Registers (Console switches)
|
||||
break; // hardwired as read-only
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,6 +266,34 @@ void M6532::setTimerRegister(uInt8 value, uInt8 interval)
|
|||
myCyclesWhenTimerSet = mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::setOutputState()
|
||||
{
|
||||
/*
|
||||
When a bit in the DDR is set as input, +5V is placed on its output
|
||||
pin. When it's set as output, either +5V or 0V (depending on the
|
||||
contents of SWCHA) will be placed on the output pin.
|
||||
The standard macros for the AtariVox use this fact to send data
|
||||
to the port. This is represented by the following algorithm:
|
||||
|
||||
if(DDR bit is input) set output as 1
|
||||
else if(DDR bit is output) set output as bit in ORA
|
||||
*/
|
||||
uInt8 a = myOutA | ~myDDRA;
|
||||
|
||||
Controller& port0 = myConsole.controller(Controller::Left);
|
||||
port0.write(Controller::One, a & 0x10);
|
||||
port0.write(Controller::Two, a & 0x20);
|
||||
port0.write(Controller::Three, a & 0x40);
|
||||
port0.write(Controller::Four, a & 0x80);
|
||||
|
||||
Controller& port1 = myConsole.controller(Controller::Right);
|
||||
port1.write(Controller::One, a & 0x01);
|
||||
port1.write(Controller::Two, a & 0x02);
|
||||
port1.write(Controller::Three, a & 0x04);
|
||||
port1.write(Controller::Four, a & 0x08);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6532::save(Serializer& out) const
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6532.hxx,v 1.12 2008-04-23 16:51:11 stephena Exp $
|
||||
// $Id: M6532.hxx,v 1.13 2008-05-06 16:39:11 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef M6532_HXX
|
||||
|
@ -32,7 +32,7 @@ class Deserializer;
|
|||
RIOT
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: M6532.hxx,v 1.12 2008-04-23 16:51:11 stephena Exp $
|
||||
@version $Id: M6532.hxx,v 1.13 2008-05-06 16:39:11 stephena Exp $
|
||||
*/
|
||||
class M6532 : public Device
|
||||
{
|
||||
|
@ -131,6 +131,7 @@ class M6532 : public Device
|
|||
{ return myTimer - (mySystem->cycles() - myCyclesWhenTimerSet); }
|
||||
|
||||
void setTimerRegister(uInt8 data, uInt8 interval);
|
||||
void setOutputState();
|
||||
|
||||
private:
|
||||
// Reference to the console
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: MT24LC256.cxx,v 1.7 2008-04-29 20:06:14 stephena Exp $
|
||||
// $Id: MT24LC256.cxx,v 1.8 2008-05-06 16:39:11 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <cassert>
|
||||
|
@ -48,7 +48,11 @@ char jpee_msg[256];
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
MT24LC256::MT24LC256(const string& filename, const System& system)
|
||||
: mySystem(system),
|
||||
mySDA(false),
|
||||
mySCL(false),
|
||||
myCyclesWhenTimerSet(0),
|
||||
myCyclesWhenSDASet(0),
|
||||
myCyclesWhenSCLSet(0),
|
||||
myDataFile(filename)
|
||||
{
|
||||
// First initialize the I2C state
|
||||
|
@ -93,25 +97,42 @@ bool MT24LC256::readSDA()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::writeSDA(bool state)
|
||||
{
|
||||
//cerr << "writeSDA: " << state << endl;
|
||||
mySDA = state;
|
||||
myCyclesWhenSDASet = mySystem.cycles();
|
||||
|
||||
#define jpee_data(x) ( (x) ? \
|
||||
(!jpee_mdat && jpee_sdat && jpee_mclk && (jpee_data_stop(),1), jpee_mdat = 1) : \
|
||||
(jpee_mdat && jpee_sdat && jpee_mclk && (jpee_data_start(),1), jpee_mdat = 0))
|
||||
|
||||
jpee_data(state);
|
||||
update();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::writeSCL(bool state)
|
||||
{
|
||||
//cerr << "writeSCL: " << state << endl;
|
||||
mySCL = state;
|
||||
myCyclesWhenSCLSet = mySystem.cycles();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::update()
|
||||
{
|
||||
#define jpee_clock(x) ( (x) ? \
|
||||
(jpee_mclk = 1) : \
|
||||
(jpee_mclk && (jpee_clock_fall(),1), jpee_mclk = 0))
|
||||
|
||||
jpee_clock(state);
|
||||
#define jpee_data(x) ( (x) ? \
|
||||
(!jpee_mdat && jpee_sdat && jpee_mclk && (jpee_data_stop(),1), jpee_mdat = 1) : \
|
||||
(jpee_mdat && jpee_sdat && jpee_mclk && (jpee_data_start(),1), jpee_mdat = 0))
|
||||
|
||||
// These pins have to be updated at the same time
|
||||
// However, the there's no guarantee that the writeSDA() and writeSDL()
|
||||
// methods will be called at the same time or in the correct order, so
|
||||
// we only do the write when they have the same 'timestamp'
|
||||
if(myCyclesWhenSDASet == myCyclesWhenSCLSet)
|
||||
{
|
||||
cerr << endl << "--> SCL = " << mySCL << ", SDA = " << mySDA << " @ " << myCyclesWhenSDASet << endl;
|
||||
jpee_clock(mySCL);
|
||||
jpee_data(mySDA);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -127,12 +148,14 @@ void MT24LC256::jpee_init()
|
|||
for(int i = 0; i < 256; i++)
|
||||
for(int j = 0; j < 128; j++)
|
||||
myData[i + j*256] = (i+1)*(j+1);
|
||||
|
||||
// jpee_timercheck(1);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::jpee_data_start()
|
||||
{
|
||||
//cerr << " ==> jpee_data_start()\n";
|
||||
cerr << " ==> jpee_data_start()\n";
|
||||
/* We have a start condition */
|
||||
if (jpee_state == 1 && (jpee_nb != 1 || jpee_pptr != 3))
|
||||
{
|
||||
|
@ -161,7 +184,7 @@ void MT24LC256::jpee_data_start()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::jpee_data_stop()
|
||||
{
|
||||
//cerr << " ==> jpee_data_stop()\n";
|
||||
cerr << " ==> jpee_data_stop()\n";
|
||||
int i;
|
||||
|
||||
if (jpee_state == 1 && jpee_nb != 1)
|
||||
|
@ -186,7 +209,7 @@ void MT24LC256::jpee_data_stop()
|
|||
}
|
||||
for (i=3; i<jpee_pptr; i++)
|
||||
{
|
||||
//cerr << " => writing\n";
|
||||
cerr << " => writing\n";
|
||||
myData[(jpee_address++) & jpee_sizemask] = jpee_packet[i];
|
||||
if (!(jpee_address & jpee_pagemask))
|
||||
break; /* Writes can't cross page boundary! */
|
||||
|
@ -202,7 +225,7 @@ void MT24LC256::jpee_data_stop()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::jpee_clock_fall()
|
||||
{
|
||||
//cerr << " ==> jpee_clock_fall()\n";
|
||||
cerr << " ==> jpee_clock_fall()\n";
|
||||
switch(jpee_state)
|
||||
{
|
||||
case 1:
|
||||
|
@ -318,12 +341,19 @@ bool MT24LC256::jpee_timercheck(int mode)
|
|||
if(mode) // set timer
|
||||
{
|
||||
myCyclesWhenTimerSet = mySystem.cycles();
|
||||
cerr << " --> timer set: " << myCyclesWhenTimerSet << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
else // read timer
|
||||
{
|
||||
uInt32 elapsed = mySystem.cycles() - myCyclesWhenTimerSet;
|
||||
//cerr << " --> elapsed: " << elapsed << endl;
|
||||
|
||||
if(elapsed < (uInt32)(5000000.0 / 838.0))
|
||||
cerr << " --> timer still running: " << elapsed << endl;
|
||||
else
|
||||
cerr << " --> timer expired: " << elapsed << endl;
|
||||
|
||||
return elapsed < (uInt32)(5000000.0 / 838.0);
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +361,7 @@ bool MT24LC256::jpee_timercheck(int mode)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int MT24LC256::jpee_logproc(char const *st)
|
||||
{
|
||||
// cerr << " " << st << endl;
|
||||
cerr << " " << st << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: MT24LC256.hxx,v 1.2 2008-04-13 23:43:14 stephena Exp $
|
||||
// $Id: MT24LC256.hxx,v 1.3 2008-05-06 16:39:12 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef MT24LC256_HXX
|
||||
|
@ -30,7 +30,7 @@ class System;
|
|||
(aka Supercat) for the bulk of this code.
|
||||
|
||||
@author Stephen Anthony & J. Payson
|
||||
@version $Id: MT24LC256.hxx,v 1.2 2008-04-13 23:43:14 stephena Exp $
|
||||
@version $Id: MT24LC256.hxx,v 1.3 2008-05-06 16:39:12 stephena Exp $
|
||||
*/
|
||||
class MT24LC256
|
||||
{
|
||||
|
@ -65,6 +65,8 @@ class MT24LC256
|
|||
int jpee_logproc(char const *st);
|
||||
bool jpee_timercheck(int mode);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
// The system of the parent controller
|
||||
const System& mySystem;
|
||||
|
@ -72,9 +74,15 @@ class MT24LC256
|
|||
// The EEPROM data
|
||||
uInt8 myData[32768];
|
||||
|
||||
// Cached state of the SDA and SCL pins on the last write
|
||||
bool mySDA, mySCL;
|
||||
|
||||
// Indicates when the timer was set
|
||||
uInt32 myCyclesWhenTimerSet;
|
||||
|
||||
// Indicates when the SDA and SCL pins were set/written
|
||||
uInt32 myCyclesWhenSDASet, myCyclesWhenSCLSet;
|
||||
|
||||
// The file containing the EEPROM data
|
||||
string myDataFile;
|
||||
|
||||
|
|
|
@ -13,15 +13,13 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: SaveKey.cxx,v 1.1 2008-04-29 15:49:34 stephena Exp $
|
||||
// $Id: SaveKey.cxx,v 1.2 2008-05-06 16:39:12 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "MT24LC256.hxx"
|
||||
#include "System.hxx"
|
||||
#include "SaveKey.hxx"
|
||||
|
||||
#define DEBUG_SAVEKEY 0
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
|
||||
const string& eepromfile)
|
||||
|
@ -67,24 +65,14 @@ void SaveKey::write(DigitalPin pin, bool value)
|
|||
// Pin 3: EEPROM SDA
|
||||
// output data to the 24LC256 EEPROM using the I2C protocol
|
||||
case Three:
|
||||
if(DEBUG_SAVEKEY)
|
||||
cerr << "SaveKey: value "
|
||||
<< value
|
||||
<< " written to SDA line at cycle "
|
||||
<< mySystem.cycles()
|
||||
<< endl;
|
||||
myDigitalPinState[Three] = value;
|
||||
myEEPROM->writeSDA(value);
|
||||
break;
|
||||
|
||||
// Pin 4: EEPROM SCL
|
||||
// output clock data to the 24LC256 EEPROM using the I2C protocol
|
||||
case Four:
|
||||
if(DEBUG_SAVEKEY)
|
||||
cerr << "SaveKey: value "
|
||||
<< value
|
||||
<< " written to SCLK line at cycle "
|
||||
<< mySystem.cycles()
|
||||
<< endl;
|
||||
myDigitalPinState[Four] = value;
|
||||
myEEPROM->writeSCL(value);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue