@@ -292,6 +292,112 @@ namespace DcsBios {
292292 };
293293 typedef MatRotaryEncoderT<> MatRotaryEncoder;
294294
295+ // To emulate dual concentric rotary encoders/resolvers/potentiometers using a rotary encoder with a push button.
296+ // Secondary message is used when push button or switch is enabled.
297+
298+ template <unsigned long pollIntervalMs = POLL_EVERY_TIME, StepsPerDetent stepsPerDetent = ONE_STEP_PER_DETENT>
299+ class EmulatedConcentricRotaryEncoderT : PollingInput, public ResettableInput {
300+ private:
301+ const char * msg1_; // Function 1 (default)
302+ const char * decArg1_;
303+ const char * incArg1_;
304+ const char * msg2_; // Function 2
305+ const char * decArg2_;
306+ const char * incArg2_;
307+ char pinA_;
308+ char pinB_;
309+ char pinC_; // Integrated button pin
310+ bool msg1Mode_;
311+ char prevMode_;
312+ char lastState_;
313+ signed char delta_;
314+
315+ char readState () {
316+ return (digitalRead (pinA_) << 1 ) | digitalRead (pinB_);
317+ }
318+
319+ void checkPress () {
320+ char currentMode;
321+ msg1Mode_ = ((currentMode = digitalRead (pinC_)) != prevMode_)?!msg1Mode_:msg1Mode_;
322+ prevMode_ = currentMode;
323+ }
324+
325+ void resetState () {
326+ lastState_ = (lastState_==0 )?-1 :0 ;
327+ }
328+
329+ void pollInput () {
330+ char state = readState ();
331+ checkPress ();
332+ switch (lastState_) {
333+ case 0 :
334+ if (state == 2 ) delta_--;
335+ if (state == 1 ) delta_++;
336+ break ;
337+ case 1 :
338+ if (state == 0 ) delta_--;
339+ if (state == 3 ) delta_++;
340+ break ;
341+ case 2 :
342+ if (state == 3 ) delta_--;
343+ if (state == 0 ) delta_++;
344+ break ;
345+ case 3 :
346+ if (state == 1 ) delta_--;
347+ if (state == 2 ) delta_++;
348+ break ;
349+ }
350+ lastState_ = state;
351+
352+ if ((delta_ >= stepsPerDetent) && (msg1Mode_)) {
353+ if (tryToSendDcsBiosMessage (msg1_, incArg1_))
354+ delta_ -= stepsPerDetent;
355+ }
356+ if ((delta_ <= -stepsPerDetent) && (msg1Mode_)) {
357+ if (tryToSendDcsBiosMessage (msg1_, decArg1_))
358+ delta_ += stepsPerDetent;
359+ }
360+ if ((delta_ >= stepsPerDetent) && (!msg1Mode_)) {
361+ if (tryToSendDcsBiosMessage (msg2_, incArg2_))
362+ delta_ -= stepsPerDetent;
363+ }
364+ if ((delta_ <= -stepsPerDetent) && (!msg1Mode_)) {
365+ if (tryToSendDcsBiosMessage (msg2_, decArg2_))
366+ delta_ += stepsPerDetent;
367+ }
368+ }
369+ public:
370+ EmulatedConcentricRotaryEncoderT (const char * msg1, const char * decArg1, const char * incArg1, const char * msg2, const char * decArg2, const char * incArg2, char pinA, char pinB, char pinC) :
371+ PollingInput (pollIntervalMs) {
372+ msg1_ = msg1;
373+ decArg1_ = decArg1;
374+ incArg1_ = incArg1;
375+ msg2_ = msg2;
376+ decArg2_ = decArg2;
377+ incArg2_ = incArg2;
378+ pinA_ = pinA;
379+ pinB_ = pinB;
380+ pinC_ = pinC;
381+ msg1Mode_ = true ;
382+ prevMode_ = 1 ;
383+ pinMode (pinA_, INPUT_PULLUP);
384+ pinMode (pinB_, INPUT_PULLUP);
385+ pinMode (pinC_, INPUT_PULLUP);
386+ prevMode_ = digitalRead (pinC_); // Prevents defaulting to secondary action on initialization
387+ delta_ = 0 ;
388+ lastState_ = readState ();
389+ }
390+
391+ void SetControl (const char * msg) {
392+ msg1_ = msg;
393+ }
394+
395+
396+ void resetThisState () {
397+ this ->resetState ();
398+ }
399+ };
400+ typedef EmulatedConcentricRotaryEncoderT<> EmulatedConcentricRotaryEncoder;
295401}
296402
297403#endif
0 commit comments