Skip to content

Commit 3ea820d

Browse files
Merge pull request #25 from AerialElectron/EmulatedConcentricRotaryEncoder
Added concentric rotary encoder emulation
2 parents a0a709e + bdef06b commit 3ea820d

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/internal/Encoders.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)