Subversion Repositories group.NITPanels

Rev

Rev 7 | Rev 12 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 pfowler 1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using System.Timers;
7
 
8
using Microsoft.FlightSimulator.SimConnect;
9
 
10
using LibUsbDotNet;
11
using LibUsbDotNet.Main;
12
using LibUsbDotNet.DeviceNotify;
13
 
14
namespace NITNavComm {
15
    public class NITNavCommDevice : NITDevice  {
16
 
17
        enum UsbCommands : byte {
18
            CMD_LATCH_DISPLAY = 20,
19
            CMD_SET_DISPLAY = 21,
20
        };
21
 
22
        private byte[,] display { get; set; }
23
        private byte[] buttons {get; set; }
24
        private sbyte[,] rotary;
25
        private ushort[] points { get; set; }
26
 
27
        public int flipcomm { get; set; }
28
        public int flipnav { get; set; }
29
 
30
        public uint simStatus { get; set; }
31
 
32
        public int comStatus { get; set; }
33
        public bool navAvailable { get; set; }
34
        public bool avionicsMaster { get; set; }
35
 
36
 
37
        private const int TIMER_COUNT = 4;
38
        private const int TIMER_COMMSWAP = 0;
39
        private const int TIMER_COMMFLIP = 1;
40
        private const int TIMER_NAVSWAP = 2;
41
        private const int TIMER_NAVFLIP = 3;
42
        Timer[] timers = new Timer[TIMER_COUNT];
43
 
5 pfowler 44
        Timer inputTimer = new Timer();
45
 
3 pfowler 46
        public NITNavCommDevice(NITDevice nitDevice) :
47
            base(nitDevice.usbRegistry, "NITNavComm", nitDevice.vid, nitDevice.pid) {
48
            this.init();
49
        }
50
 
51
        public NITNavCommDevice(UsbRegistry usbRegistry, string type, int vid, int pid) :
52
            base(usbRegistry, "NITNavComm", 0x20a0, 0x4236) {
53
            this.init();
54
        }
55
 
56
        private void init()
57
        {
58
            base.Open();
59
 
60
            this.display = new byte[2, 10];
61
            this.points = new ushort[2];
62
            this.blankDisplay();
63
 
64
            this.buttons = new byte[2];
65
            this.buttons[0] = 0x00;
66
            this.buttons[1] = 0x00;
67
 
68
            this.rotary = new sbyte[2, 2];
69
            this.resetAllRotary();
70
 
71
            this.flipcomm = 0;
72
            this.flipnav = 0;
73
 
11 pfowler 74
            this.simStatus = 2;
3 pfowler 75
            this.assigned = 1;
76
 
77
            this.comStatus = 0;
78
            this.navAvailable = true;
79
            this.avionicsMaster = false;
80
 
81
            for (int i = 0; i < TIMER_COUNT; i++) {
82
                Timer timer = new Timer();
83
                timer.Enabled = false;
84
                timer.AutoReset = false;
85
                timer.Interval = NITPanels.CFG_BUTTON_DEBOUNCE_TIME;
86
                timer.Elapsed += OnDebounceTimer;
87
                timers[i] = timer;
88
            }
5 pfowler 89
 
90
            inputTimer.Enabled = false;
91
            inputTimer.AutoReset = true;
92
            inputTimer.Interval = NITPanels.CFG_INPUT_TIMER_INTERVAL;
93
            inputTimer.Elapsed += inputTimer_Elapsed;
3 pfowler 94
 
95
        }
96
 
5 pfowler 97
        void inputTimer_Elapsed(object sender, ElapsedEventArgs e) {
98
            this.SimButtons();
99
        }
100
 
3 pfowler 101
        private static void OnDebounceTimer(Object source, ElapsedEventArgs e) {
102
            Timer timer = (Timer)source;
103
            timer.Enabled = false;
104
        }
105
 
106
        public override bool Close() {
5 pfowler 107
            this.powerDown();
3 pfowler 108
            return base.Close();
109
        }
110
 
111
        public void powerDown() {
5 pfowler 112
            this.simStatus = 2;
3 pfowler 113
            this.resetAllRotary();
11 pfowler 114
 
3 pfowler 115
            this.blankDisplay();
5 pfowler 116
            this.inputTimer.Enabled = false;
3 pfowler 117
        }
118
 
119
        public void powerUp() {
5 pfowler 120
            this.simStatus = 0;
3 pfowler 121
            this.resetAllRotary();
5 pfowler 122
            this.inputTimer.Enabled = true;
11 pfowler 123
 
124
            this.points[0] = 0x0084;
125
            this.points[1] = 0x0084;
126
 
127
            this.sendPoints();
128
 
3 pfowler 129
            if (this.assigned == 1)
130
                this.fsx.requestNavComm1Data();
131
            else if (this.assigned == 2)
132
                this.fsx.requestNavComm2Data();
133
        }
134
 
135
        public void blankDisplay() {
136
            byte[] blank = { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a };
137
            for (byte i = 0; i < 4; i++)
138
                setFreq(i, ref blank);
139
            this.points[0] = 0x0000;
140
            this.points[1] = 0x0000;
11 pfowler 141
            this.sendPoints();
3 pfowler 142
            this.UpdateDisplay();
143
        }
144
 
145
        public byte[] getFreq(byte freq) {
146
            byte[] ret = new byte[5];
147
            switch (freq) {
148
                case 0:
149
                    for (byte i = 0; i < 5; i++)
150
                        ret[i] = display[0, i];
151
                    break;
152
                case 1:
153
                    for (byte i = 0; i < 5; i++)
154
                        ret[i] = display[0, i + 5];
155
                    break;
156
                case 2:
157
                    for (byte i = 0; i < 5; i++)
158
                        ret[i] = display[1, i];
159
                    break;
160
                case 3:
161
                    for (byte i = 0; i < 5; i++)
162
                        ret[i] = display[1, i + 5];
163
                    break;
164
            }
165
            return ret;
166
        }
167
 
168
        public void setFreq(byte freq, ref byte[] data) {
169
            switch (freq) {
170
                case 0:
171
                    for (byte i = 0; i < 5; i++)
172
                        display[0, i] = data[i];
173
                    break;
174
                case 1:
175
                    for (byte i = 0; i < 5; i++)
176
                        display[0, i+5] = data[i];
177
                    break;
178
                case 2:
179
                    for (byte i = 0; i < 5; i++)
180
                        display[1, i] = data[i];
181
                    break;
182
                case 3:
183
                    for (byte i = 0; i < 5; i++)
184
                        display[1, i + 5] = data[i];
185
                    break;
186
            }
187
        }
188
 
189
        public void setNavComFreqs(FSXObject.NavCom_Data data) {
190
            byte[] freq0 = this.charArrayToBytes(data.Freq0.ToString().ToCharArray());
191
            byte[] freq1 = this.charArrayToBytes(data.Freq1.ToString().ToCharArray());
192
            byte[] freq2 = this.charArrayToBytes(data.Freq2.ToString().ToCharArray());
193
            byte[] freq3 = this.charArrayToBytes(data.Freq3.ToString().ToCharArray());
194
 
195
            this.setFreq(0, ref freq0);
196
            this.setFreq(1, ref freq1);
197
            this.setFreq(2, ref freq2);
198
            this.setFreq(3, ref freq3);
199
 
200
            this.UpdateDisplay();
201
        }
202
 
203
        private byte[] charArrayToBytes(char[] digits) {
204
            byte[] bytes = new byte[5];
205
            for (byte i = 0; i < 5; i++) {
206
                bytes[i] = (byte)(digits[i] - '0');
207
            }
208
            return bytes;
209
        }
210
 
11 pfowler 211
        private void sendData(byte dis) {
212
            for (byte i = 0; i < 10; i++) {
213
                this.sendDigit(dis, i, display[dis, i]);
214
            }
215
        }
216
 
217
        public void UpdateDisplay() {
218
            this.sendData(0);
219
            this.latchDisplay(0);
220
            this.sendData(1);
221
            this.latchDisplay(1);
222
 
223
        }
224
 
225
        public void UpdateDisplay(byte dis) {
226
            this.sendData(dis);
227
            this.latchDisplay(dis);
228
        }
229
 
3 pfowler 230
        public void setDisplay(byte dis, ref byte[] data) {
231
            for (byte i = 0; i < data.Length; i++) {
232
                display[dis, i] = data[i];
233
            }
234
        }
235
 
11 pfowler 236
        private void sendDigit(byte dis, byte dig, byte val) {
3 pfowler 237
            ushort wxValue = (ushort)(dis <<8);
238
            wxValue |= dig;
11 pfowler 239
            ushort wxIndex = val;
3 pfowler 240
 
241
            base.SendCommand(21, (short)wxValue, (short)wxIndex);
242
        }
243
 
11 pfowler 244
        private void sendPoints() {
245
            //ushort wxValue = (ushort)();
246
            //ushort wxIndex = (ushort)();
247
 
248
            base.SendCommand(23, (short)this.points[0], (short)this.points[1]);
249
        }
250
 
3 pfowler 251
        private void sendLatch(byte dis) {
252
            if (!this.isOpen())
253
                return;
254
 
255
            base.SendCommand(20, (short)dis, 0);
256
        }
257
 
258
        public void updateInput() {
259
            byte[] data = new byte[8];
260
            int transferred;
261
            base.SendCommand(30, 0, 0, data, out transferred);
262
            this.buttons[0] = data[0];
263
            this.rotary[0, 0] += (sbyte)data[1];
264
            this.buttons[1] = data[2];
265
            this.rotary[1, 0] += (sbyte)data[3];
266
        }
267
 
268
        public bool isSwapSet(byte dis) {
269
            if ((this.buttons[dis] & 0x01)>0)
270
                return true;
271
            return false;
272
        }
273
 
274
        public bool isFlipSet(byte dis) {
275
            if ((this.buttons[dis] & 0x02) > 0)
276
                return true;
277
            return false;
278
        }
279
 
280
        public sbyte getRotary(byte dis, byte rotary) {
281
            return this.rotary[dis, rotary];
282
        }
283
 
284
        public void resetRotary(byte display, byte rotary) {
285
            this.rotary[display, rotary] = 0x00;
286
        }
287
 
288
        public void resetAllRotary() {
289
            this.rotary[0, 0] = 0x00;
290
            this.rotary[0, 1] = 0x00;
291
            this.rotary[1, 0] = 0x00;
292
            this.rotary[1, 1] = 0x00;
293
        }
294
 
295
        private byte GetBit(ushort b, byte bitNumber) {
296
            if ((b & (1 << bitNumber)) != 0)
297
                return 1;
298
            return 0;
299
        }
300
 
301
        private void latchDisplay(byte dis) {
302
            this.sendLatch(dis);
303
        }
304
 
305
        public void swapFreq(byte display) {
306
            if (display == 0) {
307
                byte[] left = this.getFreq(0);
308
                byte[] right = this.getFreq(1);
309
                this.setFreq(0, ref right);
310
                this.setFreq(1, ref left);
311
            } else if (display == 1) {
312
                byte[] left = this.getFreq(2);
313
                byte[] right = this.getFreq(3);
314
                this.setFreq(2, ref right);
315
                this.setFreq(3, ref left);
316
            }
317
        }
318
 
5 pfowler 319
        public override void FsxReady() {
320
            this.powerUp();
3 pfowler 321
        }
322
 
7 pfowler 323
        public override void reAssign() {
324
            if (this.simStatus != 0)
325
                return;
326
 
327
            if (this.assigned == 1)
328
                this.fsx.requestNavComm1Data();
329
            else
330
                this.fsx.requestNavComm2Data();
331
        }
332
 
5 pfowler 333
        //public override void FsxClose() {
334
        //    this.powerDown();
335
        //}
336
 
3 pfowler 337
        public override void FsxEvent(SIMCONNECT_RECV_SIMOBJECT_DATA data) {
338
            if (data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.AVIONICS) {
339
 
340
                FSXObject.Avionics_Data avionics = (FSXObject.Avionics_Data)data.dwData[0];
341
 
342
                this.avionicsMaster = avionics.avionics_master;
343
                if (this.assigned == 1)
344
                    this.comStatus = (int)avionics.com1_status;
345
                else
346
                    this.comStatus = (int)avionics.com2_status;
347
 
348
                if (this.assigned == 1)
349
                    this.navAvailable = avionics.nav1_available;
350
                else if (this.assigned == 2)
351
                    this.navAvailable = avionics.nav2_available;
352
 
353
                if (!this.avionicsMaster || this.comStatus != 0) {
354
                    this.powerDown();
355
                    return;
356
                }
357
 
358
                if (this.avionicsMaster && this.comStatus == 0 && this.simStatus != 0) {
359
                    this.powerUp();
360
                    return;
361
                }
362
            }
363
 
364
            if (this.simStatus != 0)
365
                return;
366
 
367
            if (this.assigned == 1 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM1_REQ) {
368
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
369
                this.setNavComFreqs(navcomdata);
4 pfowler 370
            } 
371
 
372
            if (this.assigned == 2 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM2_REQ) {
3 pfowler 373
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
374
                this.setNavComFreqs(navcomdata);
375
            }
376
 
11 pfowler 377
 
5 pfowler 378
        }     
3 pfowler 379
 
380
        public override void SimButtons() {
11 pfowler 381
            this.inputTimer.Enabled = false;
3 pfowler 382
            if (this.simStatus != 0)
383
                return;
384
 
385
            this.updateInput();
386
 
387
            if (!timers[TIMER_COMMSWAP].Enabled && this.isSwapSet(0)) {
388
                if (this.assigned == 1)
389
                    fsx.Comm1SwapFreq();
390
                else
391
                    fsx.Comm2SwapFreq();
392
                timers[TIMER_COMMSWAP].Enabled = true;
393
            }
394
 
395
            if (!timers[TIMER_NAVSWAP].Enabled && this.isSwapSet(1)) {
396
                if (this.assigned == 1)
397
                    fsx.Nav1SwapFreq();
398
                else
399
                    fsx.Nav2SwapFreq();
400
 
401
                timers[TIMER_NAVSWAP].Enabled = true;
402
            }
403
 
404
            // Check if the MHz/KHz has been pressed
405
            if (!timers[TIMER_COMMFLIP].Enabled && this.isFlipSet(0)) {
406
                this.flipcomm = 1 - this.flipcomm;
407
                timers[TIMER_COMMFLIP].Enabled = true;
408
            }
409
 
410
            if (!timers[TIMER_NAVFLIP].Enabled && this.isFlipSet(1)) {
411
                this.flipnav = 1 - this.flipnav;
412
                timers[TIMER_NAVFLIP].Enabled = true;
413
            }
414
 
415
            // Process the rotary encoders COMM1
416
            sbyte delta = this.getRotary(0, 0);
417
            this.resetRotary(0, 0);
418
            if (delta != 0) {
419
                if (delta < 0) {
420
                    delta = (sbyte)-delta;
421
 
422
                    if (this.flipcomm == 1)
423
                        if (this.assigned == 1)
424
                            fsx.Comm1DecFract();
425
                        else
426
                            fsx.Comm2DecFract();
427
                    else
428
                        if (this.assigned == 1)
429
                            fsx.Comm1DecWhole();
430
                        else
431
                            fsx.Comm2DecWhole();
432
                } else {
433
 
434
                    if (this.flipcomm == 1)
435
                        if (this.assigned == 1)
436
                            fsx.Comm1IncFract();
437
                        else
438
                            fsx.Comm2IncFract();
439
                    else
440
                        if (this.assigned == 1)
441
                            fsx.Comm1IncWhole();
442
                        else
443
                            fsx.Comm2IncWhole();
444
                }
445
            }
446
 
447
            // Process the rotary encoders NAV1
448
            delta = this.getRotary(1, 0);
449
            this.resetRotary(1, 0);
450
            if (delta != 0) {
451
                if (delta < 0) {
452
                    delta = (sbyte)-delta;
453
 
454
                    if (this.flipnav == 1)
455
                        if (this.assigned == 1)
456
                            fsx.Nav1DecFract();
457
                        else
458
                            fsx.Nav2DecFract();
459
                    else
460
                        if (this.assigned == 1)
461
                            fsx.Nav1DecWhole();
462
                        else
463
                            fsx.Nav2DecWhole();
464
                } else {
11 pfowler 465
                        if (this.flipnav == 1)
466
                            if (this.assigned == 1)
467
                                fsx.Nav1IncFract();
468
                            else
469
                                fsx.Nav2IncFract();
3 pfowler 470
                        else
11 pfowler 471
                            if (this.assigned == 1)
472
                                fsx.Nav1IncWhole();
473
                            else
474
                                fsx.Nav2IncWhole();
3 pfowler 475
                }
476
            }
11 pfowler 477
            this.inputTimer.Enabled = true;
478
        } // End SimButtons
3 pfowler 479
    }
480
}