1 /*
2 * CRRCsim - the Charles River Radio Control Club Flight Simulator Project
3 * Copyright (C) 2005, 2008 - Jens Wilhelm Wulf (original author)
4 * Copyright (C) 2005, 2008, 2009, 2010 - Jan Reucker
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 */
21 #include "inputdev_software.h"
22 #include <SDL.h>
23 #include "../../defines.h"
24
25 #include "../../mod_misc/lib_conversions.h"
26
T_TX_InterfaceSoftware(int method,int axesnum)27 T_TX_InterfaceSoftware::T_TX_InterfaceSoftware(int method, int axesnum)
28 : input_method(method),
29 numberOfAxes(axesnum)
30 {
31 #if DEBUG_TX_INTERFACE > 0
32 printf("T_TX_InterfaceSoftware::T_TX_InterfaceSoftware(int method)\n");
33 #endif
34
35 mixer = new T_TX_Mixer(this);
36
37 switch (input_method)
38 {
39 case eIM_joystick:
40 map = new T_AxisMapper(this);
41 calib = new T_Calibration(this);
42 break;
43
44 case eIM_mouse:
45 map = new T_AxisMapper(this);
46 break;
47
48 default:
49 break;
50 }
51
52 for (int i = 0; i < TX_MAXAXIS; i++)
53 {
54 input_raw_data[i] = 0.0;
55 }
56 }
57
~T_TX_InterfaceSoftware()58 T_TX_InterfaceSoftware::~T_TX_InterfaceSoftware()
59 {
60 #if DEBUG_TX_INTERFACE > 0
61 printf("T_TX_InterfaceSoftware::~T_TX_InterfaceSoftware()\n");
62 #endif
63 delete map;
64 delete calib;
65 delete mixer;
66 }
67
init(SimpleXMLTransfer * config)68 int T_TX_InterfaceSoftware::init(SimpleXMLTransfer* config)
69 {
70 #if DEBUG_TX_INTERFACE > 0
71 printf("int T_TX_InterfaceSoftware::init(SimpleXMLTransfer* config)\n");
72 #endif
73
74 int ret = 0;
75
76 // initialize generic stuff
77 T_TX_Interface::init(config);
78
79 // initialize mixer
80 switch (input_method)
81 {
82 case eIM_mouse:
83 ret = mixer->init(config, "inputMethod.mouse");
84 map->init(config, "inputMethod.mouse");
85 break;
86
87 case eIM_joystick:
88 ret = mixer->init(config, "inputMethod.joystick");
89 map->init(config, "inputMethod.joystick");
90 calib->init(config, "inputMethod.joystick");
91 break;
92
93 case eIM_keyboard:
94 default:
95 ret = mixer->init(config, "inputMethod.keyboard");
96 break;
97 }
98
99 return ret;
100 }
101
putBackIntoCfg(SimpleXMLTransfer * config)102 void T_TX_InterfaceSoftware::putBackIntoCfg(SimpleXMLTransfer* config)
103 {
104 #if DEBUG_TX_INTERFACE > 0
105 printf("int T_TX_InterfaceSoftware::putBackIntoCfg(SimpleXMLTransfer* config)\n");
106 #endif
107 T_TX_Interface::putBackIntoCfg(config);
108
109 if (usesMixer())
110 {
111 mixer->putBackIntoCfg(config);
112 }
113 if (usesMapper())
114 {
115 map->putBackIntoCfg(config);
116 }
117 if (usesCalibration())
118 {
119 calib->putBackIntoCfg(config);
120 }
121 }
122
getInputData(TSimInputs * inputs)123 void T_TX_InterfaceSoftware::getInputData(TSimInputs* inputs)
124 {
125 #if DEBUG_TX_INTERFACE > 1
126 printf("void T_TX_InterfaceSoftware::getInputData(TSimInputs* inputs)\n");
127 #endif
128
129 float calibrated[T_AxisMapper::NUM_AXISFUNCS];
130 int axisnum;
131
132 // pre-initialize all axes with the values from the keyboard interface
133 preInitFromKeyboard(inputs);
134
135 calibrated[T_AxisMapper::NOTHING] = 0.0;
136 calibrated[T_AxisMapper::ELEVATOR] = inputs->elevator;
137 calibrated[T_AxisMapper::AILERON] = inputs->aileron;
138 calibrated[T_AxisMapper::RUDDER] = inputs->rudder;
139 calibrated[T_AxisMapper::THROTTLE] = inputs->throttle;
140 calibrated[T_AxisMapper::FLAP] = inputs->flap;
141 calibrated[T_AxisMapper::SPOILER] = inputs->spoiler;
142 calibrated[T_AxisMapper::RETRACT] = inputs->retract;
143 calibrated[T_AxisMapper::PITCH] = inputs->pitch;
144
145 // now override all axes that are mapped to a "real" controller
146
147 // evaluate calibrated input for all axis
148
149 if (input_method != eIM_keyboard)
150 {
151 if (usesCalibration())
152 {
153 axisnum = map->func[T_AxisMapper::ELEVATOR];
154 if (axisnum >= 0)
155 calibrated[T_AxisMapper::ELEVATOR] =
156 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::ELEVATOR];
157
158 axisnum = map->func[T_AxisMapper::AILERON];
159 if (axisnum >= 0)
160 calibrated[T_AxisMapper::AILERON] =
161 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::AILERON];
162
163 axisnum = map->func[T_AxisMapper::RUDDER];
164 if (axisnum >= 0)
165 calibrated[T_AxisMapper::RUDDER] =
166 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::RUDDER];
167
168 axisnum = map->func[T_AxisMapper::THROTTLE];
169 if (axisnum >= 0)
170 calibrated[T_AxisMapper::THROTTLE] =
171 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::THROTTLE];
172
173 axisnum = map->func[T_AxisMapper::FLAP];
174 if (axisnum >= 0)
175 calibrated[T_AxisMapper::FLAP] =
176 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::FLAP];
177
178 axisnum = map->func[T_AxisMapper::SPOILER];
179 if (axisnum >= 0)
180 calibrated[T_AxisMapper::SPOILER] =
181 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::SPOILER];
182
183 axisnum = map->func[T_AxisMapper::RETRACT];
184 if (axisnum >= 0)
185 calibrated[T_AxisMapper::RETRACT] =
186 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::RETRACT];
187
188 axisnum = map->func[T_AxisMapper::PITCH];
189 if (axisnum >= 0)
190 calibrated[T_AxisMapper::PITCH] =
191 calib->calibrate(axisnum, input_raw_data[axisnum]) * map->inv[T_AxisMapper::PITCH];
192 }
193 else // doesn't use calibration
194 {
195 axisnum = map->func[T_AxisMapper::ELEVATOR];
196 if (axisnum >= 0)
197 calibrated[T_AxisMapper::ELEVATOR] =
198 input_raw_data[axisnum] * map->inv[T_AxisMapper::ELEVATOR];
199
200 axisnum = map->func[T_AxisMapper::AILERON];
201 if (axisnum >= 0)
202 calibrated[T_AxisMapper::AILERON] =
203 input_raw_data[axisnum] * map->inv[T_AxisMapper::AILERON];
204
205 axisnum = map->func[T_AxisMapper::RUDDER];
206 if (axisnum >= 0)
207 calibrated[T_AxisMapper::RUDDER] =
208 input_raw_data[axisnum] * map->inv[T_AxisMapper::RUDDER];
209
210 axisnum = map->func[T_AxisMapper::THROTTLE];
211 if (axisnum >= 0)
212 calibrated[T_AxisMapper::THROTTLE] =
213 input_raw_data[axisnum] * map->inv[T_AxisMapper::THROTTLE];
214
215 axisnum = map->func[T_AxisMapper::FLAP];
216 if (axisnum >= 0)
217 calibrated[T_AxisMapper::FLAP] =
218 input_raw_data[axisnum] * map->inv[T_AxisMapper::FLAP];
219
220 axisnum = map->func[T_AxisMapper::SPOILER];
221 if (axisnum >= 0)
222 calibrated[T_AxisMapper::SPOILER] =
223 input_raw_data[axisnum] * map->inv[T_AxisMapper::SPOILER];
224
225 axisnum = map->func[T_AxisMapper::RETRACT];
226 if (axisnum >= 0)
227 calibrated[T_AxisMapper::RETRACT] =
228 input_raw_data[axisnum] * map->inv[T_AxisMapper::RETRACT];
229
230 axisnum = map->func[T_AxisMapper::PITCH];
231 if (axisnum >= 0)
232 calibrated[T_AxisMapper::PITCH] =
233 input_raw_data[axisnum] * map->inv[T_AxisMapper::PITCH];
234 }
235 }
236
237 // apply expo, scaling and trim
238 calibrated[T_AxisMapper::ELEVATOR] = limit(mixer->mix_signed(
239 calibrated[T_AxisMapper::ELEVATOR], T_AxisMapper::ELEVATOR));
240 calibrated[T_AxisMapper::AILERON] = limit(mixer->mix_signed(
241 calibrated[T_AxisMapper::AILERON], T_AxisMapper::AILERON));
242 calibrated[T_AxisMapper::RUDDER] = limit(mixer->mix_signed(
243 calibrated[T_AxisMapper::RUDDER], T_AxisMapper::RUDDER));
244 calibrated[T_AxisMapper::THROTTLE] = limit_unsigned(mixer->mix_unsigned(
245 calibrated[T_AxisMapper::THROTTLE], T_AxisMapper::THROTTLE));
246 calibrated[T_AxisMapper::FLAP] = limit(mixer->mix_signed(
247 calibrated[T_AxisMapper::FLAP], T_AxisMapper::FLAP));
248 calibrated[T_AxisMapper::SPOILER] = limit_unsigned(mixer->mix_unsigned(
249 calibrated[T_AxisMapper::SPOILER], T_AxisMapper::SPOILER));
250 calibrated[T_AxisMapper::RETRACT] = limit_unsigned(mixer->mix_unsigned(
251 calibrated[T_AxisMapper::RETRACT], T_AxisMapper::RETRACT));
252 calibrated[T_AxisMapper::PITCH] = limit(mixer->mix_signed(
253 calibrated[T_AxisMapper::PITCH], T_AxisMapper::PITCH));
254
255 // further apply mixers
256 inputs->elevator = limit(mixer->mix_mixer(calibrated, T_AxisMapper::ELEVATOR));
257 inputs->aileron = limit(mixer->mix_mixer(calibrated, T_AxisMapper::AILERON));
258 inputs->rudder = limit(mixer->mix_mixer(calibrated, T_AxisMapper::RUDDER));
259 inputs->throttle = limit_unsigned(mixer->mix_mixer(calibrated, T_AxisMapper::THROTTLE));
260 inputs->flap = limit(mixer->mix_mixer(calibrated, T_AxisMapper::FLAP));
261 inputs->spoiler = limit_unsigned(mixer->mix_mixer(calibrated, T_AxisMapper::SPOILER));
262 inputs->retract = limit_unsigned(mixer->mix_mixer(calibrated, T_AxisMapper::RETRACT));
263 inputs->pitch = limit(mixer->mix_mixer(calibrated, T_AxisMapper::PITCH));
264 }
265
266
getRawData(float * dest)267 void T_TX_InterfaceSoftware::getRawData(float *dest)
268 {
269 int axes = getNumAxes();
270
271 if (axes > TX_MAXAXIS)
272 {
273 axes = TX_MAXAXIS;
274 }
275 for (int i = 0; i < axes; i++)
276 {
277 *(dest + i) = input_raw_data[i];
278 }
279 }
280
setAxis(int axis,const float x)281 void T_TX_InterfaceSoftware::setAxis(int axis, const float x)
282 {
283 input_raw_data[axis] = limit(x);
284 }
285
286
getDeviceList(std::vector<std::string> & Devices)287 int T_TX_InterfaceSoftware::getDeviceList(std::vector<std::string>& Devices)
288 {
289 Devices.erase(Devices.begin(), Devices.end());
290
291 #if TEST_WITHOUT_JOYSTICK > 0
292 for (int i = 0; i < TEST_WITHOUT_JOYSTICK; i++)
293 {
294 char number[7];
295 std::string name;
296
297 snprintf(number, 6, "%2d - ", i);
298 name = number;
299 name += "fake joystick";
300 Devices.push_back(name);
301 }
302 #else
303 for (int i = 0; i < SDL_NumJoysticks(); i++)
304 {
305 std::string name;
306
307 if (SDL_JoystickName(i) != NULL)
308 {
309 name = SDL_JoystickName(i);
310 }
311 else
312 {
313 name = "not available (removed?)";
314 std::cerr << "CGUICtrlGeneralDialog::rebuildJoystickComboBox(): error:" << std::endl;
315 std::cerr << " Joystick " << i << " is no longer available (removed after starting CRRCsim?)." << std::endl;
316 }
317 Devices.push_back(name);
318 }
319 #endif
320
321 return Devices.size();
322 }
323
324