1 //============================================================================
2 //
3 //   SSSS    tt          lll  lll
4 //  SS  SS   tt           ll   ll
5 //  SS     tttttt  eeee   ll   ll   aaaa
6 //   SSSS    tt   ee  ee  ll   ll      aa
7 //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
8 //  SS  SS   tt   ee      ll   ll  aa  aa
9 //   SSSS     ttt  eeeee llll llll  aaaaa
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17 
18 #ifndef PADDLES_HXX
19 #define PADDLES_HXX
20 
21 #include "bspf.hxx"
22 #include "Control.hxx"
23 #include "Event.hxx"
24 
25 /**
26   The standard Atari 2600 pair of paddle controllers.
27 
28   @author  Bradford W. Mott
29 */
30 class Paddles : public Controller
31 {
32   public:
33     /**
34       Create a new pair of paddle controllers plugged into the specified jack
35 
36       @param jack   The jack the controller is plugged into
37       @param event  The event object to use for events
38       @param system The system using this controller
39 
40       @param swappaddle Whether to swap the paddles plugged into this jack
41       @param swapaxis   Whether to swap the axis on the paddle (x <-> y)
42       @param swapdir    Whether to swap the direction for which an axis
43                         causes movement (lesser axis values cause paddle
44                         resistance to decrease instead of increase)
45     */
46     Paddles(Jack jack, const Event& event, const System& system,
47             bool swappaddle, bool swapaxis, bool swapdir, bool altmap = false);
48     ~Paddles() override = default;
49 
50   public:
51     static constexpr int ANALOG_MIN_VALUE = -32768;
52     static constexpr int ANALOG_MAX_VALUE = 32767;
53     static constexpr int ANALOG_RANGE = ANALOG_MAX_VALUE - ANALOG_MIN_VALUE + 1;
54     static constexpr float BASE_ANALOG_SENSE = 0.148643628F;
55     static constexpr int MIN_ANALOG_SENSE = 0;
56     static constexpr int MAX_ANALOG_SENSE = 30;
57     static constexpr int MIN_ANALOG_LINEARITY = 25;
58     static constexpr int MAX_ANALOG_LINEARITY = 100;
59     static constexpr int MIN_ANALOG_CENTER = -10;
60     static constexpr int MAX_ANALOG_CENTER = 30;
61     static constexpr int MIN_DIGITAL_SENSE = 1;
62     static constexpr int MAX_DIGITAL_SENSE = 20;
63     static constexpr int MIN_DEJITTER = 0;
64     static constexpr int MAX_DEJITTER = 10;
65     static constexpr int MIN_MOUSE_RANGE = 1;
66     static constexpr int MAX_MOUSE_RANGE = 100;
67 
68     /**
69       Update the entire digital and analog pin state according to the
70       events currently set.
71     */
72     void update() override;
73 
74     /**
75       Returns the name of this controller.
76     */
name() const77     string name() const override { return "Paddles"; }
78 
79     /**
80       Answers whether the controller is intrinsically an analog controller.
81     */
isAnalog() const82     bool isAnalog() const override { return true; }
83 
84     /**
85       Determines how this controller will treat values received from the
86       X/Y axis and left/right buttons of the mouse.  Since not all controllers
87       use the mouse the same way (or at all), it's up to the specific class to
88       decide how to use this data.
89 
90       In the current implementation, the left button is tied to the X axis,
91       and the right one tied to the Y axis.
92 
93       @param xtype  The controller to use for x-axis data
94       @param xid    The controller ID to use for x-axis data (-1 for no id)
95       @param ytype  The controller to use for y-axis data
96       @param yid    The controller ID to use for y-axis data (-1 for no id)
97 
98       @return  Whether the controller supports using the mouse
99     */
100     bool setMouseControl(Controller::Type xtype, int xid,
101                          Controller::Type ytype, int yid) override;
102 
103     /**
104       Sets the x-center for analog paddles.
105 
106       @param xcenter  Value from -10 to 30, representing the center offset/860
107     */
108     static void setAnalogXCenter(int xcenter);
109 
110     /**
111       Sets the y-center for analog paddles.
112 
113       @param ycenter  Value from -10 to 30, representing the center offset/860
114     */
115     static void setAnalogYCenter(int ycenter);
116 
117     /**
118       Sets the linearity of analog paddles.
119 
120       @param linearity Value from 25 to 100
121     */
122     static void setAnalogLinearity(int linearity);
123 
124     /**
125       Sets the sensitivity for analog paddles.
126 
127       @param sensitivity  Value from 0 to 30, where 20 equals 1
128       @return  Resulting sensitivity
129     */
130     static float setAnalogSensitivity(int sensitivity);
131 
132     static float analogSensitivityValue(int sensitivity);
133 
134 
135     /**
136       @param strength  Value from 0 to 10
137     */
138     static void setDejitterBase(int strength);
139 
140     /**
141       @param strength  Value from 0 to 10
142     */
143     static void setDejitterDiff(int strength);
144 
145     /**
146       Sets the sensitivity for digital emulation of paddle movement.
147       This is only used for *digital* events (ie, buttons or keys,
148       or digital joystick axis events); Stelladaptors or the mouse are
149       not modified.
150 
151       @param sensitivity  Value from 1 to MAX_DIGITAL_SENSE, with larger
152                           values causing more movement
153     */
154     static void setDigitalSensitivity(int sensitivity);
155 
156     /**
157       Sets the maximum upper range for digital/mouse emulation of paddle
158       movement (ie, a value of 50 means to only use 50% of the possible
159       range of movement).  Note that this specfically does not apply to
160       Stelladaptor-like devices, which uses an absolute value range.
161 
162       @param range  Value from 1 to 100, representing the percentage
163                     of the range to use
164     */
165     static void setDigitalPaddleRange(int range);
166 
167     // The maximum value of the paddle pot = 1MOhm
168     static constexpr uInt32 MAX_RESISTANCE = 1000000;
169 
170   private:
171     // Range of values over which digital and mouse movement is scaled
172     // to paddle resistance
173     static constexpr int TRIGMIN = 1;
174     static constexpr int TRIGMAX = 4096;
175     static int TRIGRANGE;  // This one is variable for the upper range
176 
177     // Pre-compute the events we care about based on given port
178     // This will eliminate test for left or right port in update()
179     Event::Type myAAxisValue, myBAxisValue,
180                 myLeftADecEvent, myLeftAIncEvent,
181                 myLeftBDecEvent, myLeftBIncEvent,
182                 myLeftAFireEvent, myLeftBFireEvent,
183                 myAxisMouseMotion;
184 
185     // The following are used for the various mouse-axis modes
186     int myMPaddleID{-1};                    // paddle to emulate in 'automatic' mode
187     int myMPaddleIDX{-1}, myMPaddleIDY{-1}; // paddles to emulate in 'specific axis' mode
188 
189     bool myKeyRepeatA{false}, myKeyRepeatB{false};
190     int myPaddleRepeatA{0}, myPaddleRepeatB{0};
191     std::array<int, 2> myCharge{TRIGRANGE/2, TRIGRANGE/2}, myLastCharge{0};
192     int myLastAxisX{0}, myLastAxisY{0};
193     int myAxisDigitalZero{0}, myAxisDigitalOne{0};
194 
195     static int XCENTER;
196     static int YCENTER;
197     static float SENSITIVITY, LINEARITY;
198 
199     static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE;
200     static int DEJITTER_BASE, DEJITTER_DIFF;
201 
202     /**
203       Swap two events.
204     */
205     void swapEvents(Event::Type& event1, Event::Type& event2);
206 
207     AnalogReadout::Connection getReadOut(int lastAxis, int& newAxis, int center);
208 
209     /**
210       Update the axes pin state according to the events currently set.
211     */
212     bool updateAnalogAxes();
213 
214     /**
215       Update the entire state according to mouse events currently set.
216     */
217     void updateMouse(bool& firePressedA, bool& firePressedB);
218 
219     /**
220       Update the axes pin state according to the keyboard events currently set.
221     */
222     void updateDigitalAxes();
223 
224   private:
225     // Following constructors and assignment operators not supported
226     Paddles() = delete;
227     Paddles(const Paddles&) = delete;
228     Paddles(Paddles&&) = delete;
229     Paddles& operator=(const Paddles&) = delete;
230     Paddles& operator=(Paddles&&) = delete;
231 };
232 
233 #endif
234