@@ -6,6 +6,9 @@ namespace MobiFlight.Joysticks.Octavi
66{
77 internal class OctaviHandler
88 {
9+ private const string Shift_VButton_Name = "Button_SHIFT_SW" ;
10+ private const string Unshift_VButton_Name = "Button_UNSHIFT_SW" ;
11+
912 private bool isInShiftMode = false ;
1013 private OctaviReport lastReport = new OctaviReport ( ) ;
1114 private readonly List < string > buttons = new List < string > ( ) ;
@@ -54,6 +57,16 @@ public OctaviHandler(JoystickDefinition definition = null)
5457 var context = new Context ( state , true , stateName + "^" ) ;
5558 this . contexts . Add ( context ) ;
5659 }
60+
61+ /* create at least one instance for the Buttons for the virtual (un)shift events on context change.
62+ * always created first to keep them together in the Button list.
63+ * (shift button will only be called from the buttonmapping later,
64+ * unshift either virtually without context or from the mapping)
65+ */
66+ _ = ToButton ( Shift_VButton_Name ) ;
67+ _ = ToButton ( Unshift_VButton_Name ) ;
68+
69+
5770 foreach ( var context in contexts )
5871 {
5972 // Encoders
@@ -69,6 +82,22 @@ public OctaviHandler(JoystickDefinition definition = null)
6982 if ( ! definition . Inputs . Any ( JoystickInput => JoystickInput . Id == ( int ) context . state ) )
7083 {
7184 buttonMappings . Add ( ( context . state , context . isShifted , OctaviReport . OctaviButtons . HID_ENC_SW ) , ToButton ( $ "Button_{ context . name } _CRSR") ) ;
85+
86+ /* do not create the unshift button in the mapping, will be a duplicate key in the dictionary.
87+ * will be called with the buttons.IndexOf method later in this "virtual" case.
88+ */
89+ //buttonMappings.Add((context.state, context.isShifted, OctaviReport.OctaviButtons.HID_ENC_SW), ToButton(Unshift_VButton_Name));
90+ }
91+ else
92+ {
93+ /* Will be used to raise the "we are shifted now" flag
94+ * Can be used to control a "shifted" variable that turns output pin 7 on/off
95+ * We need two buttons, because context switching forces "unshifting",
96+ * so the shift state always has to be sent explicitly
97+ * (i.e. not a variable that will be toggled when a single button is pressed can be used)
98+ * States that do not support a shift mode will always be "unshifted".
99+ */
100+ buttonMappings . Add ( ( context . state , context . isShifted , OctaviReport . OctaviButtons . HID_ENC_SW ) , ToButton ( context . isShifted ? Shift_VButton_Name : Unshift_VButton_Name ) ) ;
72101 }
73102
74103 // DCT, MENU, CLR, ENT, CDI, OBS, MSG, FLP, VNAV, PROC
@@ -86,6 +115,9 @@ public OctaviHandler(JoystickDefinition definition = null)
86115 buttonMappings . Add ( ( context . state , context . isShifted , OctaviReport . OctaviButtons . HID_BTN_AP_ALT ) , ToButton ( $ "Button_{ context . name } _VNAV") ) ;
87116 buttonMappings . Add ( ( context . state , context . isShifted , OctaviReport . OctaviButtons . HID_BTN_AP_VS ) , ToButton ( $ "Button_{ context . name } _PROC") ) ;
88117 }
118+ /* else: why can't we use these buttons out of FMS-States?
119+ * e.g. Context COM1 Button -D-> could be used to set the radio to VATSIM Unicom "122.800"
120+ */
89121
90122 // AP, HDG, NAV, APR, ALT, VS (AP context only for now to not mess up the ordering of buttons)
91123 if ( context . state == OctaviReport . OctaviState . STATE_AP )
@@ -137,10 +169,20 @@ private int ToButton(string buttonName)
137169 // "Shift Mode" for supported contexts
138170 if ( report . contextState != lastReport . contextState )
139171 {
140- isInShiftMode = false ; // reset shift mode on context change
172+ // reset shift mode on context changes (and synthesize unshift press/release)
173+ int unshift_vButton = buttons . IndexOf ( Unshift_VButton_Name ) ;
174+
175+ if ( unshift_vButton >= 0 )
176+ {
177+ buttonEvents . Add ( ( unshift_vButton , MobiFlightButton . InputEvent . PRESS ) ) ;
178+ buttonEvents . Add ( ( unshift_vButton , MobiFlightButton . InputEvent . RELEASE ) ) ;
179+ }
180+
181+ isInShiftMode = false ;
141182 }
142183 else if ( pressed . HasFlag ( OctaviReport . OctaviButtons . HID_ENC_SW ) && this . definition . Inputs . Any ( JoystickInput => JoystickInput . Id == ( int ) report . contextState ) )
143184 {
185+ /* Button events will be generated by finding the corrensponding ButtonMapping in the loop at the end. */
144186 isInShiftMode = ! isInShiftMode ;
145187 }
146188
0 commit comments