Skip to content

Commit 4986b7b

Browse files
Merge pull request #34 from DCSFlightpanels/document-EmulatedConcentricRotaryEncoder
Documentation and some cleanup of the code. No functional changes.
2 parents 3ea820d + 7d52218 commit 4986b7b

File tree

3 files changed

+54
-47
lines changed

3 files changed

+54
-47
lines changed

examples/OneOfEverything/OneOfEverything.ino

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,86 @@
77
*#2 - Provide a very basic testing suite that developers can use to ensure that changes do not break existing sketches
88
*/
99

10+
// Some made-up pin assignments just to make the examples more readable
11+
const int PIN_A = 1;
12+
const int PIN_B = 2;
13+
const int ANALOG_PIN_A = 6;
14+
1015
// Buttons
1116
///////////
1217
// The simplest push button, a single momentary button on a single pin, which sends ARG_0 to MSG_0
13-
DcsBios::ActionButton iffDec("IFF_CODE", "INC", 1);
18+
DcsBios::ActionButton iffDec("IFF_CODE", "INC", PIN_A);
1419

1520
// Used when a physical switch is a momentary button, but needs to sent alternating arguments each time it is pressed
16-
DcsBios::ToggleButton toggleButtonExample("MSG_0", "ARG_0", "ARG_1", 1);
21+
DcsBios::ToggleButton toggleButtonExample("MSG_0", "ARG_0", "ARG_1", PIN_A);
1722

1823
// A dual mode button with a master switch which toggles the function of a physical pit button between two different DCS functions. Think multi-seat aircraft.
19-
DcsBios::DualModeButton dualModeButtonExample(0, 1, "MSG_INMODE0", "MSG_INMODE1");
24+
DcsBios::DualModeButton dualModeButtonExample(PIN_A, PIN_B, "MSG_INMODE0", "MSG_INMODE1");
2025

2126
// Switches
2227
////////////
2328
// A standard two position on/off
24-
DcsBios::Switch2Pos switch2PosExample("MSG_0", 1);
29+
DcsBios::Switch2Pos switch2PosExample("MSG_0", PIN_A);
2530
// A three position on/off/on switch
26-
DcsBios::Switch3Pos switch3PosExample("MSG_0", 1, 2);
31+
DcsBios::Switch3Pos switch3PosExample("MSG_0", PIN_A, PIN_B);
2732
// A multiple position switch, often a rotary switch
2833
const byte multiPosPins[4] = {1,2,3,4};
2934
DcsBios::SwitchMultiPos switchMulitPosExample("MSG_0", multiPosPins, 4);
3035
// A switch that has a cover in DCS that must be opened before the switch itself can be activated
31-
DcsBios::SwitchWithCover2Pos pltLaunchbarAbort("PLT_LAUNCHBAR_ABORT", "PLT_LAUNCHBAR_ABORT_COVER", 6);
36+
DcsBios::SwitchWithCover2Pos pltLaunchbarAbort("PLT_LAUNCHBAR_ABORT", "PLT_LAUNCHBAR_ABORT_COVER", PIN_A);
3237

3338
// Analogs
3439
///////////
35-
// Use an analog input, divided into discrete steps
36-
DcsBios::AnalogMultiPos analogMultiPosExample("MSG_0", 1, 10);
40+
// Use an analog input, divided into (10) discrete steps
41+
DcsBios::AnalogMultiPos analogMultiPosExample("MSG_0", ANALOG_PIN_A, 10);
3742

3843
// Other stuff
3944
// A Binary Coded Decimal wheel usually displaying digits for numeric entry, i.e. IFF code wheels.
40-
DcsBios::BcdWheel bcdWheelExample("MSG_0", 1, 2);
45+
DcsBios::BcdWheel bcdWheelExample("MSG_0", PIN_A, PIN_B);
4146
// A special case of bcdWheel that will send a radio frequency instead of raw digit
4247
DcsBios::RadioPreset radioPresetExample("MSG_0", 1, 2, 3, 4, 5);
4348

4449
// Spinning things
4550
///////////////////
51+
const int DATAPIN = 1;
52+
const int CLKPIN = 2;
53+
const int SWPIN = 3;
54+
4655
// Rotary encoder on two pins to send INC/DEC arguments when rotated
47-
DcsBios::RotaryEncoder rotaryEncoderExample("MSG_0", "ARG_DEC", "ARG_INC", 1, 2);
56+
DcsBios::RotaryEncoder rotaryEncoderExample("MSG_0", "ARG_DEC", "ARG_INC", PIN_A, PIN_B);
4857
// A rotary encoder which will send larger increments when used continuously. Originally written for faster gross adjustments to HSI.
49-
DcsBios::RotaryAcceleratedEncoder rotaryAcceleratedEncoderExample("MSG_0", "ARG_DEC", "ARG_INC", "FAST_INC", "FAST_DEC", 1, 2);
58+
DcsBios::RotaryAcceleratedEncoder rotaryAcceleratedEncoderExample("MSG_0", "ARG_DEC", "ARG_INC", "FAST_INC", "FAST_DEC", PIN_A, PIN_B);
59+
// A rotary with pushbutton, used to emulate a concentric rotary encoder. Pushing the button toggles between two functions
60+
DcsBios::EmulatedConcentricRotaryEncoder ilsRightKnob("ILS_KHZ", "DEC", "INC", "ILS_VOL", "-4500", "+4500", DATAPIN, CLKPIN, SWPIN);
61+
5062
// A linear/analog axis on a single pin
51-
DcsBios::Potentiometer potentiometerExample("MSG_0", 1);
63+
DcsBios::Potentiometer potentiometerExample("MSG_0", ANALOG_PIN_A);
5264
// A linear axis control where the physical or electrical range of the input does utilize the full 0 to 1023 range.
53-
DcsBios::Potentiometer clippedPotentiometerExample("MSG_0", false, 256, 768);
65+
DcsBios::Potentiometer clippedPotentiometerExample("MSG_0", ANALOG_PIN_A, false, 256, 768);
5466

5567
// An inverted version of a linear axis control
56-
DcsBios::Potentiometer invertedPotentiometerExample("MSG_0", 1, true);
68+
DcsBios::Potentiometer invertedPotentiometerExample("MSG_0", ANALOG_PIN_A, true);
5769

5870
// Rotary encoder being used to control something that is an N-pos switch in DCS. 3 represents the number of positions of the switch in DCS.
59-
DcsBios::RotarySwitch rotarySwitchExample("MSG_0", 1, 2, 3);
71+
DcsBios::RotarySwitch rotarySwitchExample("MSG_0", PIN_A, PIN_B, 3);
6072

6173
// Outputs
6274
///////////
75+
const int OUT_PIN_A = 15;
76+
const int ANALOG_OUT_PIN_A = 16;
6377
// A single LED
64-
DcsBios::Dimmer defaultDimmerExample(0x1012, 5);
65-
DcsBios::LED masterCaution(0x1012, 0x0800, 13);
78+
DcsBios::Dimmer defaultDimmerExample(0x1012, OUT_PIN_A);
79+
DcsBios::LED masterCaution(0x1012, 0x0800, OUT_PIN_A);
6680
// An analog output with a value that comes from a DCS address
67-
DcsBios::Dimmer dimmerExample(0x1012, 13);
68-
DcsBios::Dimmer invertedDimmerExample(0x1012, 5, 200, 0);
81+
DcsBios::Dimmer dimmerExample(0x1012, ANALOG_OUT_PIN_A);
82+
DcsBios::Dimmer invertedDimmerExample(0x1012, ANALOG_OUT_PIN_A, 200, 0);
6983
unsigned int myValueMapper(unsigned int dcsValue)
7084
{
7185
return dcsValue % 10;
7286
}
73-
DcsBios::Dimmer mappedDimmerExample(0x1012, 5, myValueMapper);
87+
DcsBios::Dimmer mappedDimmerExample(0x1012, ANALOG_OUT_PIN_A, myValueMapper);
7488
// A servo motor controlleed from DCS, i.e. a guage.
75-
DcsBios::ServoOutput servoExample(0x1012, 13, 544, 2400);
89+
DcsBios::ServoOutput servoExample(0x1012, ANALOG_OUT_PIN_A, 544, 2400);
7690

7791
void setup() {
7892
DcsBios::setup();

releasenotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
- Added input_min and input_max optional parameters to PotentiometerEWMA to allow a user to calibrate their analog inputs if their physical control does not utilize the full range available to the controller.
33
- Fix Switch2Pos state reset logic, and improve it's internal debounce logic for a few edge cases.
44
- Add DualModeButton for first multi-seat support. Originally developed for use in Apache cockpits where one switch toggles the function of a physical button between front and back seat DCS control.
5+
- Included AerialElectron's Concentric Rotary Encoder Emulator. Useful for simpits with a rotary that has a pushbutton, to emulate controlling two different dcs cockpit controls, especially if the dcs controls are dual-ring concentric rotaries. Thanks for the contribution AerialElectron!
56

67
## v0.3.7
78
- Integrate 2 and 3 position Matrix switches, thanks to Dehuman for the starting point!

src/internal/Encoders.h

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ namespace DcsBios {
294294

295295
//To emulate dual concentric rotary encoders/resolvers/potentiometers using a rotary encoder with a push button.
296296
//Secondary message is used when push button or switch is enabled.
297-
298297
template <unsigned long pollIntervalMs = POLL_EVERY_TIME, StepsPerDetent stepsPerDetent = ONE_STEP_PER_DETENT>
299298
class EmulatedConcentricRotaryEncoderT : PollingInput, public ResettableInput {
300299
private:
@@ -306,29 +305,27 @@ namespace DcsBios {
306305
const char* incArg2_;
307306
char pinA_;
308307
char pinB_;
309-
char pinC_; //Integrated button pin
308+
char pinToggle_; //Integrated button pin
310309
bool msg1Mode_;
311310
char prevMode_;
312311
char lastState_;
313312
signed char delta_;
314313

315314
char readState() {
316-
return (digitalRead(pinA_) << 1) | digitalRead(pinB_);
317-
}
318-
319-
void checkPress() {
320315
char currentMode;
321-
msg1Mode_ = ((currentMode = digitalRead(pinC_)) != prevMode_)?!msg1Mode_:msg1Mode_;
316+
msg1Mode_ = ((currentMode = digitalRead(pinToggle_)) != prevMode_)?!msg1Mode_:msg1Mode_;
322317
prevMode_ = currentMode;
318+
319+
return (digitalRead(pinA_) << 1) | digitalRead(pinB_);
323320
}
324321

325322
void resetState() {
323+
msg1Mode_ = !msg1Mode_;
326324
lastState_ = (lastState_==0)?-1:0;
327325
}
328326

329327
void pollInput() {
330328
char state = readState();
331-
checkPress();
332329
switch(lastState_) {
333330
case 0:
334331
if (state == 2) delta_--;
@@ -349,47 +346,42 @@ namespace DcsBios {
349346
}
350347
lastState_ = state;
351348

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_))
349+
if (delta_ >= stepsPerDetent) {
350+
if (tryToSendDcsBiosMessage(msg1Mode_?msg1_:msg2_, msg1Mode_?incArg1_:incArg2_))
362351
delta_ -= stepsPerDetent;
363352
}
364-
if ((delta_ <= -stepsPerDetent) && (!msg1Mode_)) {
365-
if (tryToSendDcsBiosMessage(msg2_, decArg2_))
353+
if (delta_ <= -stepsPerDetent) {
354+
if (tryToSendDcsBiosMessage(msg1Mode_?msg1_:msg2_, msg1Mode_?decArg1_:decArg2_))
366355
delta_ += stepsPerDetent;
367356
}
368357
}
369358
public:
370359
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) {
360+
PollingInput(pollIntervalMs)
361+
{
372362
msg1_ = msg1;
373363
decArg1_ = decArg1;
374364
incArg1_ = incArg1;
375365
msg2_ = msg2;
376366
decArg2_ = decArg2;
377367
incArg2_ = incArg2;
368+
378369
pinA_ = pinA;
379370
pinB_ = pinB;
380-
pinC_ = pinC;
371+
pinToggle_ = pinC;
381372
msg1Mode_ = true;
382-
prevMode_ = 1;
373+
383374
pinMode(pinA_, INPUT_PULLUP);
384375
pinMode(pinB_, INPUT_PULLUP);
385-
pinMode(pinC_, INPUT_PULLUP);
386-
prevMode_ = digitalRead(pinC_); //Prevents defaulting to secondary action on initialization
376+
pinMode(pinToggle_, INPUT_PULLUP);
377+
prevMode_ = digitalRead(pinToggle_); //Prevents defaulting to secondary action on initialization
378+
387379
delta_ = 0;
388380
lastState_ = readState();
389381
}
390382

391383
void SetControl(const char* msg) {
392-
msg1_ = msg;
384+
msg1_ = msg; // Note this won't work to remap the second message
393385
}
394386

395387

0 commit comments

Comments
 (0)