Subversion Repositories group.NITPanels

Rev

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