mirror of https://github.com/stella-emu/stella.git
Properly model analog input.
This commit is contained in:
parent
c7d3a43f58
commit
8aa14d8c75
|
@ -18,7 +18,7 @@
|
|||
#ifndef STATE_MANAGER_HXX
|
||||
#define STATE_MANAGER_HXX
|
||||
|
||||
#define STATE_HEADER "06020100state"
|
||||
#define STATE_HEADER "06050300state"
|
||||
|
||||
class OSystem;
|
||||
class RewindManager;
|
||||
|
|
|
@ -93,9 +93,9 @@ void BoosterWidget::loadConfig()
|
|||
myPins[kJFire]->setState(!getPin(ourPinNo[kJFire]));
|
||||
|
||||
myPins[kJBooster]->setState(
|
||||
getPin(Controller::AnalogPin::Five) == Controller::MIN_RESISTANCE);
|
||||
getPin(Controller::AnalogPin::Five) == AnalogReadout::connectToVcc());
|
||||
myPins[kJTrigger]->setState(
|
||||
getPin(Controller::AnalogPin::Nine) == Controller::MIN_RESISTANCE);
|
||||
getPin(Controller::AnalogPin::Nine) == AnalogReadout::connectToVcc());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -115,13 +115,13 @@ void BoosterWidget::handleCommand(
|
|||
break;
|
||||
case kJBooster:
|
||||
setPin(Controller::AnalogPin::Five,
|
||||
myPins[id]->getState() ? Controller::MIN_RESISTANCE :
|
||||
Controller::MAX_RESISTANCE);
|
||||
myPins[id]->getState() ? AnalogReadout::connectToVcc() :
|
||||
AnalogReadout::disconnect());
|
||||
break;
|
||||
case kJTrigger:
|
||||
setPin(Controller::AnalogPin::Nine,
|
||||
myPins[id]->getState() ? Controller::MIN_RESISTANCE :
|
||||
Controller::MAX_RESISTANCE);
|
||||
myPins[id]->getState() ? AnalogReadout::connectToVcc() :
|
||||
AnalogReadout::disconnect());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -86,7 +86,7 @@ void GenesisWidget::loadConfig()
|
|||
myPins[kJBbtn]->setState(!getPin(ourPinNo[kJBbtn]));
|
||||
|
||||
myPins[kJCbtn]->setState(
|
||||
getPin(Controller::AnalogPin::Five) == Controller::MAX_RESISTANCE);
|
||||
getPin(Controller::AnalogPin::Five) == AnalogReadout::disconnect());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -106,8 +106,8 @@ void GenesisWidget::handleCommand(
|
|||
break;
|
||||
case kJCbtn:
|
||||
setPin(Controller::AnalogPin::Five,
|
||||
myPins[id]->getState() ? Controller::MAX_RESISTANCE :
|
||||
Controller::MIN_RESISTANCE);
|
||||
myPins[id]->getState() ? AnalogReadout::disconnect() :
|
||||
AnalogReadout::connectToVcc());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -109,9 +109,9 @@ PaddleWidget::PaddleWidget(GuiObject* boss, const GUI::Font& font, int x, int y,
|
|||
void PaddleWidget::loadConfig()
|
||||
{
|
||||
myP0Resistance->setValue(Int32(Paddles::MAX_RESISTANCE -
|
||||
getPin(Controller::AnalogPin::Nine)));
|
||||
getPin(Controller::AnalogPin::Nine).resistance));
|
||||
myP1Resistance->setValue(Int32(Paddles::MAX_RESISTANCE -
|
||||
getPin(Controller::AnalogPin::Five)));
|
||||
getPin(Controller::AnalogPin::Five).resistance));
|
||||
myP0Fire->setState(!getPin(Controller::DigitalPin::Four));
|
||||
myP1Fire->setState(!getPin(Controller::DigitalPin::Three));
|
||||
}
|
||||
|
@ -124,11 +124,11 @@ void PaddleWidget::handleCommand(
|
|||
{
|
||||
case kP0Changed:
|
||||
setPin(Controller::AnalogPin::Nine,
|
||||
static_cast<Int32>(Paddles::MAX_RESISTANCE - myP0Resistance->getValue()));
|
||||
AnalogReadout::connectToVcc(Paddles::MAX_RESISTANCE - myP0Resistance->getValue()));
|
||||
break;
|
||||
case kP1Changed:
|
||||
setPin(Controller::AnalogPin::Five,
|
||||
static_cast<Int32>(Paddles::MAX_RESISTANCE - myP1Resistance->getValue()));
|
||||
AnalogReadout::connectToVcc(Paddles::MAX_RESISTANCE - myP1Resistance->getValue()));
|
||||
break;
|
||||
case kP0Fire:
|
||||
setPin(Controller::DigitalPin::Four, !myP0Fire->getState());
|
||||
|
|
|
@ -32,8 +32,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
|
|||
myBoosterEvent = Event::JoystickOneFire9;
|
||||
}
|
||||
|
||||
setPin(AnalogPin::Five, MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Nine, MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Five, AnalogReadout::disconnect());
|
||||
setPin(AnalogPin::Nine, AnalogReadout::disconnect());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -48,6 +48,7 @@ void BoosterGrip::updateButtons()
|
|||
updateMouseButtons(firePressed, boosterPressed);
|
||||
|
||||
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
|
||||
setPin(AnalogPin::Five, triggerPressed ? MIN_RESISTANCE : MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Nine, boosterPressed ? MIN_RESISTANCE : MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Five, triggerPressed ? AnalogReadout::connectToVcc() : AnalogReadout::disconnect());
|
||||
setPin(AnalogPin::Nine, boosterPressed ? AnalogReadout::connectToVcc() : AnalogReadout::disconnect());
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,10 @@ CompuMate::CompuMate(const Console& console, const Event& event,
|
|||
myLeftController = make_unique<CMControl>(*this, Controller::Jack::Left, event, system);
|
||||
myRightController = make_unique<CMControl>(*this, Controller::Jack::Right, event, system);
|
||||
|
||||
myLeftController->setPin(Controller::AnalogPin::Nine, Controller::MAX_RESISTANCE);
|
||||
myLeftController->setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
myRightController->setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
|
||||
myRightController->setPin(Controller::AnalogPin::Five, Controller::MAX_RESISTANCE);
|
||||
myLeftController->setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToGround());
|
||||
myLeftController->setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
myRightController->setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||
myRightController->setPin(Controller::AnalogPin::Five, AnalogReadout::connectToGround());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -44,17 +44,17 @@ void CompuMate::update()
|
|||
Controller& lp = myConsole.leftController();
|
||||
Controller& rp = myConsole.rightController();
|
||||
|
||||
lp.setPin(Controller::AnalogPin::Nine, Controller::MAX_RESISTANCE);
|
||||
lp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
lp.setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToGround());
|
||||
lp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, true);
|
||||
rp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MAX_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToGround());
|
||||
rp.setPin(Controller::DigitalPin::Six, true);
|
||||
|
||||
if (myEvent.get(Event::CompuMateShift))
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
if (myEvent.get(Event::CompuMateFunc))
|
||||
lp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
|
||||
lp.setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||
|
||||
rp.setPin(Controller::DigitalPin::Three, true);
|
||||
rp.setPin(Controller::DigitalPin::Four, true);
|
||||
|
@ -72,7 +72,7 @@ void CompuMate::update()
|
|||
// Emulate the '?' character (Shift-6) with the actual question key
|
||||
if (myEvent.get(Event::CompuMateQuestion))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateY)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -84,7 +84,7 @@ void CompuMate::update()
|
|||
// Emulate the '[' character (Shift-8) with the actual key
|
||||
if (myEvent.get(Event::CompuMateLeftBracket))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateI)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -96,7 +96,7 @@ void CompuMate::update()
|
|||
// Emulate the '-' character (Shift-2) with the actual minus key
|
||||
if (myEvent.get(Event::CompuMateMinus))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateW)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -114,7 +114,7 @@ void CompuMate::update()
|
|||
// Emulate the quote character (Shift-0) with the actual quote key
|
||||
if (myEvent.get(Event::CompuMateQuote))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateP)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -123,7 +123,7 @@ void CompuMate::update()
|
|||
// Emulate Ctrl-space (aka backspace) with the actual Backspace key
|
||||
if (myEvent.get(Event::CompuMateBackspace))
|
||||
{
|
||||
lp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
|
||||
lp.setPin(Controller::AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||
rp.setPin(Controller::DigitalPin::Four, false);
|
||||
}
|
||||
break;
|
||||
|
@ -132,7 +132,7 @@ void CompuMate::update()
|
|||
// Emulate the ']' character (Shift-9) with the actual key
|
||||
if (myEvent.get(Event::CompuMateRightBracket))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateO)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -144,7 +144,7 @@ void CompuMate::update()
|
|||
// Emulate the '=' character (Shift-5) with the actual equals key
|
||||
if (myEvent.get(Event::CompuMateEquals))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateT)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -156,7 +156,7 @@ void CompuMate::update()
|
|||
// Emulate the '+' character (Shift-1) with the actual plus key (Shift-=)
|
||||
if (myEvent.get(Event::CompuMatePlus))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateQ)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
@ -168,7 +168,7 @@ void CompuMate::update()
|
|||
// Emulate the '/' character (Shift-4) with the actual slash key
|
||||
if (myEvent.get(Event::CompuMateSlash))
|
||||
{
|
||||
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
|
||||
rp.setPin(Controller::AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
lp.setPin(Controller::DigitalPin::Six, false);
|
||||
}
|
||||
if (myEvent.get(Event::CompuMateR)) rp.setPin(Controller::DigitalPin::Three, false);
|
||||
|
|
|
@ -48,7 +48,7 @@ bool Controller::read(DigitalPin pin)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Int32 Controller::read(AnalogPin pin)
|
||||
AnalogReadout::Connection Controller::read(AnalogPin pin)
|
||||
{
|
||||
return getPin(pin);
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ bool Controller::save(Serializer& out) const
|
|||
out.putBool(getPin(DigitalPin::Six));
|
||||
|
||||
// Output the analog pins
|
||||
out.putInt(getPin(AnalogPin::Five));
|
||||
out.putInt(getPin(AnalogPin::Nine));
|
||||
getPin(AnalogPin::Five).save(out);
|
||||
getPin(AnalogPin::Nine).save(out);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -90,8 +90,8 @@ bool Controller::load(Serializer& in)
|
|||
setPin(DigitalPin::Six, in.getBool());
|
||||
|
||||
// Input the analog pins
|
||||
setPin(AnalogPin::Five, in.getInt());
|
||||
setPin(AnalogPin::Nine, in.getInt());
|
||||
getPin(AnalogPin::Five).load(in);
|
||||
getPin(AnalogPin::Nine).load(in);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ class System;
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "Serializable.hxx"
|
||||
#include "AnalogReadout.hxx"
|
||||
|
||||
/**
|
||||
A controller is a device that plugs into either the left or right
|
||||
|
@ -154,7 +155,7 @@ class Controller : public Serializable
|
|||
@param pin The pin of the controller jack to read
|
||||
@return The resistance at the specified pin
|
||||
*/
|
||||
virtual Int32 read(AnalogPin pin);
|
||||
virtual AnalogReadout::Connection read(AnalogPin pin);
|
||||
|
||||
/**
|
||||
Write the given value to the specified digital pin for this
|
||||
|
@ -280,13 +281,6 @@ class Controller : public Serializable
|
|||
*/
|
||||
static void setAutoFireRate(int rate, bool isNTSC = true);
|
||||
|
||||
public:
|
||||
/// Constant which represents maximum resistance for analog pins
|
||||
static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF;
|
||||
|
||||
/// Constant which represents minimum resistance for analog pins
|
||||
static constexpr Int32 MIN_RESISTANCE = 0x00000000;
|
||||
|
||||
protected:
|
||||
/**
|
||||
Derived classes *must* use these accessor/mutator methods.
|
||||
|
@ -298,12 +292,12 @@ class Controller : public Serializable
|
|||
inline bool getPin(DigitalPin pin) const {
|
||||
return myDigitalPinState[static_cast<int>(pin)];
|
||||
}
|
||||
inline void setPin(AnalogPin pin, Int32 value) {
|
||||
inline void setPin(AnalogPin pin, AnalogReadout::Connection value) {
|
||||
myAnalogPinValue[static_cast<int>(pin)] = value;
|
||||
if(myOnAnalogPinUpdateCallback)
|
||||
myOnAnalogPinUpdateCallback(pin);
|
||||
}
|
||||
inline Int32 getPin(AnalogPin pin) const {
|
||||
inline AnalogReadout::Connection getPin(AnalogPin pin) const {
|
||||
return myAnalogPinValue[static_cast<int>(pin)];
|
||||
}
|
||||
inline void resetDigitalPins() {
|
||||
|
@ -314,8 +308,8 @@ class Controller : public Serializable
|
|||
setPin(DigitalPin::Six, true);
|
||||
}
|
||||
inline void resetAnalogPins() {
|
||||
setPin(AnalogPin::Five, MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Nine, MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Five, AnalogReadout::disconnect());
|
||||
setPin(AnalogPin::Nine, AnalogReadout::disconnect());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -384,7 +378,8 @@ class Controller : public Serializable
|
|||
std::array<bool, 5> myDigitalPinState{true, true, true, true, true};
|
||||
|
||||
/// The analog value on each analog pin
|
||||
std::array<Int32, 2> myAnalogPinValue{MAX_RESISTANCE, MAX_RESISTANCE};
|
||||
std::array<AnalogReadout::Connection, 2>
|
||||
myAnalogPinValue{AnalogReadout::disconnect(), AnalogReadout::disconnect()};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -44,10 +44,10 @@ class ControllerLowLevel
|
|||
inline bool getPin(Controller::DigitalPin pin) const {
|
||||
return myController.getPin(pin);
|
||||
}
|
||||
inline void setPin(Controller::AnalogPin pin, Int32 value) {
|
||||
inline void setPin(Controller::AnalogPin pin, AnalogReadout::Connection value) {
|
||||
myController.setPin(pin, value);
|
||||
}
|
||||
inline Int32 getPin(Controller::AnalogPin pin) const {
|
||||
inline AnalogReadout::Connection getPin(Controller::AnalogPin pin) const {
|
||||
return myController.getPin(pin);
|
||||
}
|
||||
inline void resetDigitalPins() {
|
||||
|
|
|
@ -26,7 +26,7 @@ Genesis::Genesis(Jack jack, const Event& event, const System& system)
|
|||
else
|
||||
myButtonCEvent = Event::JoystickOneFire5;
|
||||
|
||||
setPin(AnalogPin::Five, MIN_RESISTANCE);
|
||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -41,5 +41,5 @@ void Genesis::updateButtons()
|
|||
updateMouseButtons(firePressed, buttonCPressed);
|
||||
|
||||
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
|
||||
setPin(AnalogPin::Five, buttonCPressed ? MAX_RESISTANCE : MIN_RESISTANCE);
|
||||
setPin(AnalogPin::Five, buttonCPressed ? AnalogReadout::disconnect() : AnalogReadout::connectToVcc());
|
||||
}
|
||||
|
|
|
@ -67,16 +67,16 @@ Keyboard::ColumnState Keyboard::processColumn(const Event::Type buttons[]) {
|
|||
return ColumnState::notConnected;
|
||||
}
|
||||
|
||||
Int32 Keyboard::columnStateToAnalogSignal(ColumnState state) const {
|
||||
AnalogReadout::Connection Keyboard::columnStateToAnalogSignal(ColumnState state) const {
|
||||
switch (state) {
|
||||
case ColumnState::gnd:
|
||||
return MAX_RESISTANCE;
|
||||
return AnalogReadout::connectToGround();
|
||||
|
||||
case ColumnState::vcc:
|
||||
return 0;
|
||||
return AnalogReadout::connectToVcc();
|
||||
|
||||
case ColumnState::notConnected:
|
||||
return INTERNAL_RESISTANCE;
|
||||
return AnalogReadout::connectToVcc(INTERNAL_RESISTANCE);
|
||||
|
||||
default:
|
||||
throw runtime_error("unreachable");
|
||||
|
|
|
@ -70,7 +70,7 @@ class Keyboard : public Controller
|
|||
private:
|
||||
ColumnState processColumn(const Event::Type buttons[]);
|
||||
|
||||
Int32 columnStateToAnalogSignal(ColumnState state) const;
|
||||
AnalogReadout::Connection columnStateToAnalogSignal(ColumnState state) const;
|
||||
|
||||
private:
|
||||
// Pre-compute the events we care about based on given port
|
||||
|
|
|
@ -27,8 +27,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
|
|||
{
|
||||
// We must start with minimum resistance; see commit
|
||||
// 38b452e1a047a0dca38c5bcce7c271d40f76736e for more information
|
||||
setPin(AnalogPin::Five, MIN_RESISTANCE);
|
||||
setPin(AnalogPin::Nine, MIN_RESISTANCE);
|
||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
setPin(AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||
|
||||
// The following logic reflects that mapping paddles to different
|
||||
// devices can be extremely complex
|
||||
|
@ -181,12 +181,12 @@ void Paddles::update()
|
|||
// Only change state if the charge has actually changed
|
||||
if(myCharge[1] != myLastCharge[1])
|
||||
{
|
||||
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * (myCharge[1] / double(TRIGMAX))));
|
||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc(MAX_RESISTANCE * (myCharge[1] / double(TRIGMAX))));
|
||||
myLastCharge[1] = myCharge[1];
|
||||
}
|
||||
if(myCharge[0] != myLastCharge[0])
|
||||
{
|
||||
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * (myCharge[0] / double(TRIGMAX))));
|
||||
setPin(AnalogPin::Nine, AnalogReadout::connectToVcc(MAX_RESISTANCE * (myCharge[0] / double(TRIGMAX))));
|
||||
myLastCharge[0] = myCharge[0];
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ bool Paddles::updateAnalogAxes()
|
|||
if(abs(new_val - sa_xaxis) > 10)
|
||||
sa_xaxis = new_val;
|
||||
|
||||
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE *
|
||||
setPin(AnalogPin::Nine, AnalogReadout::connectToVcc(MAX_RESISTANCE *
|
||||
(BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + XCENTER), 0, 65536) / 65536.0)));
|
||||
sa_changed = true;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ bool Paddles::updateAnalogAxes()
|
|||
if(abs(new_val - sa_yaxis) > 10)
|
||||
sa_yaxis = new_val;
|
||||
|
||||
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE *
|
||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc(MAX_RESISTANCE *
|
||||
(BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + YCENTER), 0, 65536) / 65536.0)));
|
||||
sa_changed = true;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,8 @@ class Paddles : public Controller
|
|||
*/
|
||||
static void setDigitalPaddleRange(int range);
|
||||
|
||||
static constexpr double MAX_RESISTANCE = 1000000.0;
|
||||
// The maximum value of the paddle pot = 1MOhm
|
||||
static constexpr uInt32 MAX_RESISTANCE = 1000000;
|
||||
|
||||
private:
|
||||
// Range of values over which digital and mouse movement is scaled
|
||||
|
|
|
@ -61,8 +61,8 @@ QuadTari::QuadTari(Jack jack, const OSystem& osystem, const System& system,
|
|||
mySecondController = addController(secondType, true);
|
||||
|
||||
// QuadTari auto detection setting
|
||||
setPin(AnalogPin::Five, MIN_RESISTANCE);
|
||||
setPin(AnalogPin::Nine, MAX_RESISTANCE);
|
||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||
setPin(AnalogPin::Nine, AnalogReadout::connectToGround());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -31,7 +31,7 @@ void AnalogReadout::reset(uInt64 timestamp)
|
|||
myU = 0;
|
||||
myIsDumped = false;
|
||||
|
||||
myValue = 0;
|
||||
myConnection = disconnect();
|
||||
myTimestamp = timestamp;
|
||||
|
||||
setConsoleTiming(ConsoleTiming::ntsc);
|
||||
|
@ -64,14 +64,14 @@ uInt8 AnalogReadout::inpt(uInt64 timestamp)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AnalogReadout::update(double value, uInt64 timestamp, ConsoleTiming consoleTiming)
|
||||
void AnalogReadout::update(Connection connection, uInt64 timestamp, ConsoleTiming consoleTiming)
|
||||
{
|
||||
if (consoleTiming != myConsoleTiming) {
|
||||
setConsoleTiming(consoleTiming);
|
||||
}
|
||||
|
||||
if (value != myValue) {
|
||||
myValue = value;
|
||||
if (connection != myConnection) {
|
||||
myConnection = connection;
|
||||
|
||||
updateCharge(timestamp);
|
||||
}
|
||||
|
@ -89,11 +89,28 @@ void AnalogReadout::setConsoleTiming(ConsoleTiming consoleTiming)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AnalogReadout::updateCharge(uInt64 timestamp)
|
||||
{
|
||||
if (myValue >= 0 && !myIsDumped)
|
||||
myU = U_SUPP * (1 - (1 - myU / U_SUPP) *
|
||||
exp(-static_cast<double>(timestamp - myTimestamp) / (myValue * R_POT + R0) / C / myClockFreq));
|
||||
else
|
||||
myU *= exp(-static_cast<double>(timestamp - myTimestamp) / (myIsDumped ? R_DUMP : R0) / C / myClockFreq);
|
||||
if (myIsDumped) {
|
||||
myU *= exp(-static_cast<double>(timestamp - myTimestamp) / R_DUMP / C / myClockFreq);
|
||||
} else {
|
||||
switch (myConnection.type) {
|
||||
case ConnectionType::vcc:
|
||||
myU = U_SUPP * (1 - (1 - myU / U_SUPP) *
|
||||
exp(-static_cast<double>(timestamp - myTimestamp) / (myConnection.resistance + R0) / C / myClockFreq));
|
||||
|
||||
break;
|
||||
|
||||
case ConnectionType::ground:
|
||||
myU *= exp(-static_cast<double>(timestamp - myTimestamp) / (myConnection.resistance + R0) / C / myClockFreq);
|
||||
|
||||
break;
|
||||
|
||||
case ConnectionType::disconnected:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
myTimestamp = timestamp;
|
||||
}
|
||||
|
@ -106,7 +123,7 @@ bool AnalogReadout::save(Serializer& out) const
|
|||
out.putDouble(myUThresh);
|
||||
out.putDouble(myU);
|
||||
|
||||
out.putDouble(myValue);
|
||||
myConnection.save(out);
|
||||
out.putLong(myTimestamp);
|
||||
|
||||
out.putInt(int(myConsoleTiming));
|
||||
|
@ -131,7 +148,7 @@ bool AnalogReadout::load(Serializer& in)
|
|||
myUThresh = in.getDouble();
|
||||
myU = in.getDouble();
|
||||
|
||||
myValue = in.getDouble();
|
||||
myConnection.load(in);
|
||||
myTimestamp = in.getLong();
|
||||
|
||||
myConsoleTiming = ConsoleTiming(in.getInt());
|
||||
|
@ -147,3 +164,63 @@ bool AnalogReadout::load(Serializer& in)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
AnalogReadout::Connection AnalogReadout::connectToGround(uInt32 resistance)
|
||||
{
|
||||
return Connection{ConnectionType::ground, resistance};
|
||||
}
|
||||
|
||||
AnalogReadout::Connection AnalogReadout::connectToVcc(uInt32 resistance)
|
||||
{
|
||||
return Connection{ConnectionType::vcc, resistance};
|
||||
}
|
||||
|
||||
AnalogReadout::Connection AnalogReadout::disconnect()
|
||||
{
|
||||
return Connection{ConnectionType::disconnected, 0};
|
||||
}
|
||||
|
||||
bool AnalogReadout::Connection::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putInt(static_cast<uInt8>(type));
|
||||
out.putInt(resistance);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: AnalogReadout::Connection::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnalogReadout::Connection::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
type = ConnectionType(in.getInt());
|
||||
resistance = in.getInt();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: AnalogReadout::Connection::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const AnalogReadout::Connection& c1, const AnalogReadout::Connection& c2)
|
||||
{
|
||||
if (c1.type == AnalogReadout::ConnectionType::disconnected)
|
||||
return c2.type == AnalogReadout::ConnectionType::disconnected;
|
||||
|
||||
return c1.type == c2.type && c1.resistance == c2.resistance;
|
||||
}
|
||||
|
||||
bool operator!=(const AnalogReadout::Connection& c1, const AnalogReadout::Connection& c2)
|
||||
{
|
||||
return !(c1 == c2);
|
||||
}
|
||||
|
|
|
@ -26,10 +26,24 @@ class AnalogReadout : public Serializable
|
|||
{
|
||||
public:
|
||||
|
||||
AnalogReadout();
|
||||
enum class ConnectionType : uInt8 {
|
||||
ground = 0, vcc = 1, disconnected = 2
|
||||
};
|
||||
|
||||
struct Connection {
|
||||
ConnectionType type;
|
||||
uInt32 resistance;
|
||||
|
||||
bool save(Serializer& out) const;
|
||||
bool load(Serializer& in);
|
||||
|
||||
friend bool operator==(const AnalogReadout::Connection& c1, const AnalogReadout::Connection& c2);
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
AnalogReadout();
|
||||
|
||||
void reset(uInt64 timestamp);
|
||||
|
||||
void vblank(uInt8 value, uInt64 timestamp);
|
||||
|
@ -37,7 +51,7 @@ class AnalogReadout : public Serializable
|
|||
|
||||
uInt8 inpt(uInt64 timestamp);
|
||||
|
||||
void update(double value, uInt64 timestamp, ConsoleTiming consoleTiming);
|
||||
void update(Connection connection, uInt64 timestamp, ConsoleTiming consoleTiming);
|
||||
|
||||
/**
|
||||
Serializable methods (see that class for more information).
|
||||
|
@ -45,6 +59,14 @@ class AnalogReadout : public Serializable
|
|||
bool save(Serializer& out) const override;
|
||||
bool load(Serializer& in) override;
|
||||
|
||||
public:
|
||||
|
||||
static Connection connectToGround(uInt32 resistance = 0);
|
||||
|
||||
static Connection connectToVcc(uInt32 resistance = 0);
|
||||
|
||||
static Connection disconnect();
|
||||
|
||||
private:
|
||||
|
||||
void setConsoleTiming(ConsoleTiming timing);
|
||||
|
@ -56,7 +78,7 @@ class AnalogReadout : public Serializable
|
|||
double myUThresh{0.0};
|
||||
double myU{0.0};
|
||||
|
||||
double myValue{0.0};
|
||||
Connection myConnection{ConnectionType::disconnected, 0};
|
||||
uInt64 myTimestamp{0};
|
||||
|
||||
ConsoleTiming myConsoleTiming;
|
||||
|
@ -80,4 +102,7 @@ class AnalogReadout : public Serializable
|
|||
AnalogReadout& operator=(AnalogReadout&&) = delete;
|
||||
};
|
||||
|
||||
bool operator==(const AnalogReadout::Connection& c1, const AnalogReadout::Connection& c2);
|
||||
bool operator!=(const AnalogReadout::Connection& c1, const AnalogReadout::Connection& c2);
|
||||
|
||||
#endif // TIA_ANALOG_READOUT
|
||||
|
|
|
@ -391,11 +391,11 @@ void TIA::bindToControllers()
|
|||
|
||||
switch (pin) {
|
||||
case Controller::AnalogPin::Five:
|
||||
updatePaddle(1);
|
||||
updateAnalogReadout(1);
|
||||
break;
|
||||
|
||||
case Controller::AnalogPin::Nine:
|
||||
updatePaddle(0);
|
||||
updateAnalogReadout(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -407,18 +407,18 @@ void TIA::bindToControllers()
|
|||
|
||||
switch (pin) {
|
||||
case Controller::AnalogPin::Five:
|
||||
updatePaddle(3);
|
||||
updateAnalogReadout(3);
|
||||
break;
|
||||
|
||||
case Controller::AnalogPin::Nine:
|
||||
updatePaddle(2);
|
||||
updateAnalogReadout(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
for (uInt8 i = 0; i < 4; ++i)
|
||||
updatePaddle(i);
|
||||
updateAnalogReadout(i);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -464,22 +464,22 @@ uInt8 TIA::peek(uInt16 address)
|
|||
break;
|
||||
|
||||
case INPT0:
|
||||
updatePaddle(0);
|
||||
updateAnalogReadout(0);
|
||||
result = myAnalogReadouts[0].inpt(myTimestamp) & 0b10000000;
|
||||
break;
|
||||
|
||||
case INPT1:
|
||||
updatePaddle(1);
|
||||
updateAnalogReadout(1);
|
||||
result = myAnalogReadouts[1].inpt(myTimestamp) & 0b10000000;
|
||||
break;
|
||||
|
||||
case INPT2:
|
||||
updatePaddle(2);
|
||||
updateAnalogReadout(2);
|
||||
result = myAnalogReadouts[2].inpt(myTimestamp) & 0b10000000;
|
||||
break;
|
||||
|
||||
case INPT3:
|
||||
updatePaddle(3);
|
||||
updateAnalogReadout(3);
|
||||
result = myAnalogReadouts[3].inpt(myTimestamp) & 0b10000000;
|
||||
break;
|
||||
|
||||
|
@ -1804,32 +1804,32 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::updatePaddle(uInt8 idx)
|
||||
void TIA::updateAnalogReadout(uInt8 idx)
|
||||
{
|
||||
Int32 resistance;
|
||||
AnalogReadout::Connection connection;
|
||||
switch (idx) {
|
||||
case 0:
|
||||
resistance = myConsole.leftController().read(Controller::AnalogPin::Nine);
|
||||
connection = myConsole.leftController().read(Controller::AnalogPin::Nine);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
resistance = myConsole.leftController().read(Controller::AnalogPin::Five);
|
||||
connection = myConsole.leftController().read(Controller::AnalogPin::Five);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
resistance = myConsole.rightController().read(Controller::AnalogPin::Nine);
|
||||
connection = myConsole.rightController().read(Controller::AnalogPin::Nine);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
resistance = myConsole.rightController().read(Controller::AnalogPin::Five);
|
||||
connection = myConsole.rightController().read(Controller::AnalogPin::Five);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("invalid paddle index");
|
||||
throw runtime_error("invalid analog input");
|
||||
}
|
||||
|
||||
myAnalogReadouts[idx].update(
|
||||
(resistance == Controller::MAX_RESISTANCE) ? -1 : (double(resistance) / Paddles::MAX_RESISTANCE),
|
||||
connection,
|
||||
myTimestamp,
|
||||
myTimingProvider()
|
||||
);
|
||||
|
|
|
@ -663,9 +663,9 @@ class TIA : public Device
|
|||
void delayedWrite(uInt8 address, uInt8 value);
|
||||
|
||||
/**
|
||||
* Update all paddle readout circuits to the current controller state.
|
||||
* Update analog readout circuit to the current controller state.
|
||||
*/
|
||||
void updatePaddle(uInt8 idx);
|
||||
void updateAnalogReadout(uInt8 idx);
|
||||
|
||||
/**
|
||||
* Get the target counter value during a RESx. This essentially depends on
|
||||
|
|
Loading…
Reference in New Issue