Subversion Repositories group.NITPanels

Rev

Rev 5 | Rev 7 | 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
 
74
            this.simStatus = 0;
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();
114
            this.blankDisplay();
5 pfowler 115
            this.inputTimer.Enabled = false;
3 pfowler 116
        }
117
 
118
        public void powerUp() {
5 pfowler 119
            this.simStatus = 0;
3 pfowler 120
            this.resetAllRotary();
5 pfowler 121
            this.inputTimer.Enabled = true;
3 pfowler 122
 
123
            if (this.assigned == 1)
124
                this.fsx.requestNavComm1Data();
125
            else if (this.assigned == 2)
126
                this.fsx.requestNavComm2Data();
127
        }
128
 
129
        public void blankDisplay() {
130
            byte[] blank = { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a };
131
            for (byte i = 0; i < 4; i++)
132
                setFreq(i, ref blank);
133
            this.points[0] = 0x0000;
134
            this.points[1] = 0x0000;
135
            this.UpdateDisplay();
136
        }
137
 
138
        public byte[] getFreq(byte freq) {
139
            byte[] ret = new byte[5];
140
            switch (freq) {
141
                case 0:
142
                    for (byte i = 0; i < 5; i++)
143
                        ret[i] = display[0, i];
144
                    break;
145
                case 1:
146
                    for (byte i = 0; i < 5; i++)
147
                        ret[i] = display[0, i + 5];
148
                    break;
149
                case 2:
150
                    for (byte i = 0; i < 5; i++)
151
                        ret[i] = display[1, i];
152
                    break;
153
                case 3:
154
                    for (byte i = 0; i < 5; i++)
155
                        ret[i] = display[1, i + 5];
156
                    break;
157
            }
158
            return ret;
159
        }
160
 
161
        public void setFreq(byte freq, ref byte[] data) {
162
            switch (freq) {
163
                case 0:
164
                    for (byte i = 0; i < 5; i++)
165
                        display[0, i] = data[i];
166
                    break;
167
                case 1:
168
                    for (byte i = 0; i < 5; i++)
169
                        display[0, i+5] = data[i];
170
                    break;
171
                case 2:
172
                    for (byte i = 0; i < 5; i++)
173
                        display[1, i] = data[i];
174
                    break;
175
                case 3:
176
                    for (byte i = 0; i < 5; i++)
177
                        display[1, i + 5] = data[i];
178
                    break;
179
            }
180
        }
181
 
182
        public void setNavComFreqs(FSXObject.NavCom_Data data) {
183
            byte[] freq0 = this.charArrayToBytes(data.Freq0.ToString().ToCharArray());
184
            byte[] freq1 = this.charArrayToBytes(data.Freq1.ToString().ToCharArray());
185
            byte[] freq2 = this.charArrayToBytes(data.Freq2.ToString().ToCharArray());
186
            byte[] freq3 = this.charArrayToBytes(data.Freq3.ToString().ToCharArray());
187
 
188
            this.setFreq(0, ref freq0);
189
            this.setFreq(1, ref freq1);
190
            this.setFreq(2, ref freq2);
191
            this.setFreq(3, ref freq3);
192
 
193
            this.UpdateDisplay();
194
        }
195
 
196
        private byte[] charArrayToBytes(char[] digits) {
197
            byte[] bytes = new byte[5];
198
            for (byte i = 0; i < 5; i++) {
199
                bytes[i] = (byte)(digits[i] - '0');
200
            }
201
            return bytes;
202
        }
203
 
204
        public void setDisplay(byte dis, ref byte[] data) {
205
            for (byte i = 0; i < data.Length; i++) {
206
                display[dis, i] = data[i];
207
            }
208
        }
209
 
210
        private void sendDigit(byte dis, byte dig, byte val, byte dp) {
211
            ushort wxValue = (ushort)(dis <<8);
212
            wxValue |= dig;
213
            ushort wxIndex = (ushort)(dp << 8);
214
            wxIndex |= val;
215
 
216
            base.SendCommand(21, (short)wxValue, (short)wxIndex);
217
        }
218
 
219
        private void sendLatch(byte dis) {
220
            if (!this.isOpen())
221
                return;
222
 
223
            base.SendCommand(20, (short)dis, 0);
224
        }
225
 
226
        public void updateInput() {
227
            byte[] data = new byte[8];
228
            int transferred;
229
            base.SendCommand(30, 0, 0, data, out transferred);
230
            this.buttons[0] = data[0];
231
            this.rotary[0, 0] += (sbyte)data[1];
232
            this.buttons[1] = data[2];
233
            this.rotary[1, 0] += (sbyte)data[3];
234
        }
235
 
236
        public bool isSwapSet(byte dis) {
237
            if ((this.buttons[dis] & 0x01)>0)
238
                return true;
239
            return false;
240
        }
241
 
242
        public bool isFlipSet(byte dis) {
243
            if ((this.buttons[dis] & 0x02) > 0)
244
                return true;
245
            return false;
246
        }
247
 
248
        public sbyte getRotary(byte dis, byte rotary) {
249
            return this.rotary[dis, rotary];
250
        }
251
 
252
        public void resetRotary(byte display, byte rotary) {
253
            this.rotary[display, rotary] = 0x00;
254
        }
255
 
256
        public void resetAllRotary() {
257
            this.rotary[0, 0] = 0x00;
258
            this.rotary[0, 1] = 0x00;
259
            this.rotary[1, 0] = 0x00;
260
            this.rotary[1, 1] = 0x00;
261
        }
262
 
263
        private void sendData(byte dis) {
264
            for (byte i = 0; i < 10; i++) {
265
                //this.sendDigit(dis, i, display[dis, i], this.GetBit(this.points[dis], i));
266
                this.sendDigit(dis, i, display[dis, i], 0);
267
            }            
268
        }
269
 
270
        public void UpdateDisplay() {
271
            this.sendData(0);
6 pfowler 272
            this.latchDisplay(0);
3 pfowler 273
            this.sendData(1);
274
            this.latchDisplay(1);
275
        }
276
 
277
        public void UpdateDisplay(byte dis) {
278
            this.sendData(dis);
279
            this.latchDisplay(dis);
280
        }
281
 
282
        private byte GetBit(ushort b, byte bitNumber) {
283
            if ((b & (1 << bitNumber)) != 0)
284
                return 1;
285
            return 0;
286
        }
287
 
288
        private void latchDisplay(byte dis) {
289
            this.sendLatch(dis);
290
        }
291
 
292
        public void swapFreq(byte display) {
293
            if (display == 0) {
294
                byte[] left = this.getFreq(0);
295
                byte[] right = this.getFreq(1);
296
                this.setFreq(0, ref right);
297
                this.setFreq(1, ref left);
298
            } else if (display == 1) {
299
                byte[] left = this.getFreq(2);
300
                byte[] right = this.getFreq(3);
301
                this.setFreq(2, ref right);
302
                this.setFreq(3, ref left);
303
            }
304
        }
305
 
5 pfowler 306
        // @TODO: Remove these, not unneeded
3 pfowler 307
        public override void FsxInit() { }
5 pfowler 308
        public override void MapEvents() { }
3 pfowler 309
 
5 pfowler 310
        public override void FsxReady() {
311
            this.powerUp();
3 pfowler 312
        }
313
 
5 pfowler 314
        //public override void FsxClose() {
315
        //    this.powerDown();
316
        //}
317
 
3 pfowler 318
        public override void FsxEvent(SIMCONNECT_RECV_SIMOBJECT_DATA data) {
319
 
320
            if (data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.AVIONICS) {
321
 
322
                FSXObject.Avionics_Data avionics = (FSXObject.Avionics_Data)data.dwData[0];
323
 
324
                this.avionicsMaster = avionics.avionics_master;
325
                if (this.assigned == 1)
326
                    this.comStatus = (int)avionics.com1_status;
327
                else
328
                    this.comStatus = (int)avionics.com2_status;
329
 
330
                if (this.assigned == 1)
331
                    this.navAvailable = avionics.nav1_available;
332
                else if (this.assigned == 2)
333
                    this.navAvailable = avionics.nav2_available;
334
 
335
                if (!this.avionicsMaster || this.comStatus != 0) {
336
                    this.powerDown();
337
                    return;
338
                }
339
 
340
                if (this.avionicsMaster && this.comStatus == 0 && this.simStatus != 0) {
341
                    this.powerUp();
342
                    return;
343
                }
344
            }
345
 
346
            if (this.simStatus != 0)
347
                return;
348
 
349
            if (this.assigned == 1 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM1_REQ) {
350
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
351
                this.setNavComFreqs(navcomdata);
4 pfowler 352
            } 
353
 
354
            if (this.assigned == 2 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM2_REQ) {
3 pfowler 355
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
356
                this.setNavComFreqs(navcomdata);
357
            }
358
 
5 pfowler 359
        }     
3 pfowler 360
 
361
        public override void SimButtons() {
362
 
363
            if (this.simStatus != 0)
364
                return;
365
 
366
            this.updateInput();
367
 
368
            if (!timers[TIMER_COMMSWAP].Enabled && this.isSwapSet(0)) {
369
                if (this.assigned == 1)
370
                    fsx.Comm1SwapFreq();
371
                else
372
                    fsx.Comm2SwapFreq();
373
                timers[TIMER_COMMSWAP].Enabled = true;
374
            }
375
 
376
            if (!timers[TIMER_NAVSWAP].Enabled && this.isSwapSet(1)) {
377
                if (this.assigned == 1)
378
                    fsx.Nav1SwapFreq();
379
                else
380
                    fsx.Nav2SwapFreq();
381
 
382
                timers[TIMER_NAVSWAP].Enabled = true;
383
            }
384
 
385
            // Check if the MHz/KHz has been pressed
386
            if (!timers[TIMER_COMMFLIP].Enabled && this.isFlipSet(0)) {
387
                this.flipcomm = 1 - this.flipcomm;
388
                timers[TIMER_COMMFLIP].Enabled = true;
389
            }
390
 
391
            if (!timers[TIMER_NAVFLIP].Enabled && this.isFlipSet(1)) {
392
                this.flipnav = 1 - this.flipnav;
393
                timers[TIMER_NAVFLIP].Enabled = true;
394
            }
395
 
396
            // Process the rotary encoders COMM1
397
            sbyte delta = this.getRotary(0, 0);
398
            this.resetRotary(0, 0);
399
            if (delta != 0) {
400
                if (delta < 0) {
401
                    delta = (sbyte)-delta;
402
 
403
                    if (this.flipcomm == 1)
404
                        if (this.assigned == 1)
405
                            fsx.Comm1DecFract();
406
                        else
407
                            fsx.Comm2DecFract();
408
                    else
409
                        if (this.assigned == 1)
410
                            fsx.Comm1DecWhole();
411
                        else
412
                            fsx.Comm2DecWhole();
413
                } else {
414
 
415
                    if (this.flipcomm == 1)
416
                        if (this.assigned == 1)
417
                            fsx.Comm1IncFract();
418
                        else
419
                            fsx.Comm2IncFract();
420
                    else
421
                        if (this.assigned == 1)
422
                            fsx.Comm1IncWhole();
423
                        else
424
                            fsx.Comm2IncWhole();
425
                }
426
            }
427
 
428
            // Process the rotary encoders NAV1
429
            delta = this.getRotary(1, 0);
430
            this.resetRotary(1, 0);
431
            if (delta != 0) {
432
                if (delta < 0) {
433
                    delta = (sbyte)-delta;
434
 
435
                    if (this.flipnav == 1)
436
                        if (this.assigned == 1)
437
                            fsx.Nav1DecFract();
438
                        else
439
                            fsx.Nav2DecFract();
440
                    else
441
                        if (this.assigned == 1)
442
                            fsx.Nav1DecWhole();
443
                        else
444
                            fsx.Nav2DecWhole();
445
                } else {
446
 
447
                    if (this.flipcomm == 1)
448
                        if (this.assigned == 1)
449
                            fsx.Nav1IncFract();
450
                        else
451
                            fsx.Nav2IncFract();
452
                    else
453
                        if (this.assigned == 1)
454
                            fsx.Nav1IncWhole();
455
                        else
456
                            fsx.Nav2IncWhole();
457
                }
458
            }
459
 
460
        }
461
    }
462
}