Subversion Repositories group.NITPanels

Rev

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