Subversion Repositories group.electronics

Rev

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

Rev Author Line No. Line
158 pfowler 1
using MCP2221;
2
using System;
3
using System.Collections.Generic;
4
using System.Linq;
5
using System.Reflection;
6
using System.Text;
7
using System.Threading.Tasks;
8
using System.Timers;
159 pfowler 9
using WindowsInput;
10
using WindowsInput.Native;
158 pfowler 11
 
12
namespace nitdcscore {
13
    public struct devdata {
14
        public uint prev_input;
15
        public uint cur_input;
159 pfowler 16
        public ushort cur_adc;
17
        public ushort prev_adc;
18
        public ushort max_adc;
19
        public ushort adc_thres;
158 pfowler 20
 
21
        public int id;
22
        public string name;
23
        public string function;
24
    }
25
 
26
 
27
 
159 pfowler 28
 
29
 
158 pfowler 30
    public class mcp2221 {
31
        DcsBios bios = new DcsBios();
32
        MchpUsbI2c usbi2c = new MchpUsbI2c();
33
        public Boolean hasAHFS { get; set; }
34
        public Boolean hasAAP { get; set; }
35
 
36
        int idx { get; set; }
37
        int devcount { get; set; }
159 pfowler 38
        long dummy = 0;
158 pfowler 39
 
40
        public uint speed { get; set; }
41
 
42
        Timer refresh = new Timer();
159 pfowler 43
        Timer delay = new Timer();
44
        InputSimulator sendkey = new InputSimulator();
158 pfowler 45
 
46
        private readonly Object lockobject = new object();
47
 
48
        public devdata[] devices = new devdata[5];
49
 
50
 
51
        public mcp2221() {
52
            speed = 400000;
53
            idx = 0;
54
 
159 pfowler 55
            refresh.Interval = 70;
56
            refresh.AutoReset = true;
57
            refresh.Elapsed += refresh_Elapsed;
58
            refresh.Enabled = false;
59
 
60
            delay.Interval = 5;
61
            delay.AutoReset = false;
62
            delay.Elapsed += delay_Elapsed;
63
            delay.Enabled = false;
64
 
158 pfowler 65
            bios.InitUDP();
66
 
67
            usbi2c.Settings.GetConnectionStatus();
68
            devcount = usbi2c.Management.GetDevCount();
69
            Console.WriteLine(devcount.ToString() + " devices found");
70
            for (int i = 0; i < devcount; i++) {
71
                int rslt = usbi2c.Management.SelectDev(i);
72
                usbi2c.Settings.GetConnectionStatus();
73
                string usbDescriptor = this.usbi2c.Settings.GetUsbStringDescriptor();
74
                if (usbDescriptor == "AHCP/FSCP Panel") {
75
                    this.hasAHFS = true;
76
                    devices[i].cur_input = 0;
77
                    devices[i].prev_input = 0;
159 pfowler 78
                    devices[i].cur_adc = 0;
79
                    devices[i].max_adc = 930;
80
                    devices[i].adc_thres = 15;
158 pfowler 81
                    devices[i].id = i;
82
                    devices[i].name = "AHCP/FSCP Panel";
83
                    devices[i].function = "refresh_ahfs";
84
 
159 pfowler 85
                    init_ahfs(i);
158 pfowler 86
                } else if (usbDescriptor == "AAP Panel") {
87
                    this.hasAAP = true;
88
                    devices[i].cur_input = 0;
89
                    devices[i].prev_input = 0;
159 pfowler 90
                    devices[i].prev_adc = 0;
158 pfowler 91
                    devices[i].id = i;
92
                    devices[i].name = "AAP Panel";
93
                    devices[i].function = "refresh_aap";
94
 
159 pfowler 95
                    init_aap(i);
158 pfowler 96
                }
97
            }
98
 
159 pfowler 99
 
158 pfowler 100
        }
101
 
102
        private Boolean enabled;
103
        public Boolean Enabled {
104
            get {
105
                return enabled;
106
            }
107
            set {
159 pfowler 108
                if (this.devcount == 0)
109
                    return;
110
 
158 pfowler 111
                this.enabled = true;
112
                refresh.Enabled = true;
113
            }
114
        }
115
 
159 pfowler 116
        void delay_Elapsed(object sender, ElapsedEventArgs e) {
117
            delay.Enabled = false;
118
        }
119
 
120
        void delayms(double ms = 100) {
121
            delay.Interval = ms;
122
            delay.Enabled = true;
123
            dummy = 0;
124
            while (delay.Enabled) { dummy++; }
125
        }
126
 
158 pfowler 127
        void refresh_Elapsed(object sender, ElapsedEventArgs e) {
128
            if (!Enabled)
129
                return;
130
            devdata dev = devices[idx];
131
 
132
            usbi2c.Management.SelectDev(dev.id);
159 pfowler 133
            usbi2c.Settings.GetConnectionStatus();
158 pfowler 134
 
135
 
136
            Type type = this.GetType();
137
            MethodInfo callfunc = type.GetMethod(dev.function);
138
            ParameterInfo[] parameters = callfunc.GetParameters();
159 pfowler 139
            object[] parms = { idx };
158 pfowler 140
            callfunc.Invoke(this, parms);
141
 
142
            idx++;
143
            if (idx >= devcount)
144
                idx = 0;
145
        }
146
 
159 pfowler 147
        public void init_aap(int devid) {
158 pfowler 148
            // Enable the mcp23017
159 pfowler 149
            WriteGpio(3, 0);
150
            this.delayms(500);
151
            this.WriteGpio(3, 1);
152
            this.delayms();
158 pfowler 153
 
154
            // Set io dir, pullups and rev polarity
155
            byte[] data;
156
            data = new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff }; // All inputs & polarity
157
            WriteI2cData(0x40, data, 5);
158
            data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
159
            WriteI2cData(0x40, data, 3);
160
 
159 pfowler 161
            refresh_aap(devid);
162
            devices[devid].prev_input = devices[devid].cur_input;
158 pfowler 163
        }
164
 
159 pfowler 165
        public void refresh_aap(int devid) {
166
            refresh.Enabled = false;
167
            lock (lockobject) {
168
                byte[] data;
169
                data = new byte[] { 0x12 }; // Select GPIOA register
170
                WriteI2cData(0x40, data, 1);
171
 
172
                data = new byte[] { 0x00, 0x00 }; // Read two bytes
173
                int rslt = ReadI2CData(0x41, ref data, 2);
174
 
175
                // Join all our buttons into a single inputs
176
                uint gpio = (uint)((1 - ReadGpio(0)) | ((1 - ReadGpio(1)) << 1));
177
                devices[devid].cur_input = (uint)gpio << 16;
178
                devices[devid].cur_input |= (uint)data[0] << 8;
179
                devices[devid].cur_input |= (uint)data[1];
180
 
181
                if (devices[devid].cur_input != devices[devid].prev_input) {
182
                    this.input_aap(devid);
183
                    devices[devid].prev_input = devices[devid].cur_input;
184
                }
185
 
186
            }
187
            refresh.Enabled = enabled;
158 pfowler 188
        }
189
 
159 pfowler 190
        public void input_aap(int devid) {
191
            //
192
            Switch2Pos(11, "AAP_CDUPWR", devid);
193
            //
194
            Switch2Pos(10, "AAP_EGIPWR", devid);
195
            //
196
            Switch3Pos(9, 8, "AAP_STEER", devid);
197
            //
198
            Selector(new int[] { 6, 5, 4 }, "AAP_STEERPT", devid);
199
            //
200
            Selector(new int[] {0,1,2,3}, "AAP_PAGE", devid);
158 pfowler 201
 
159 pfowler 202
 
203
 
204
        }
205
 
206
        public void init_ahfs(int devid) {
207
            WriteGpio(3, 0);
208
            this.delayms(500);
158 pfowler 209
            // Enable the mcp23017
210
            WriteGpio(3, 1);
159 pfowler 211
            this.delayms();
158 pfowler 212
            // Set io dir, pullups and rev polarity
213
            byte[] data;
214
            // Soldered a couple of inputs wrong, the f0 is to reverse them (fuel boost switches)
215
            data = new byte[] { 0x00, 0xff, 0xff, 0xf0, 0xff }; // All inputs & polarity
216
            WriteI2cData(0x40, data, 5);
217
            data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
218
            WriteI2cData(0x40, data, 3);
219
 
220
            data = new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff }; // All inputs & polarity
221
            WriteI2cData(0x42, data, 5);
222
            data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
223
            WriteI2cData(0x42, data, 3);
224
 
159 pfowler 225
            // Get the initial ADC value
226
            devices[devid].prev_adc = devices[devid].cur_adc = ReadADC(1);
227
            refresh_ahfs(devid);
228
            devices[devid].prev_input = devices[devid].cur_input;
158 pfowler 229
        }
230
 
159 pfowler 231
        public void refresh_ahfs(int devid) {
232
            refresh.Enabled = false;
158 pfowler 233
            lock (lockobject) {
159 pfowler 234
                byte[] data;
158 pfowler 235
                data = new byte[] { 0x12 }; // Select GPIOA register
236
                WriteI2cData(0x40, data, 1);
237
 
238
                data = new byte[] { 0x00, 0x00 }; // Read two bytes
239
                int rslt = ReadI2CData(0x41, ref data, 2);
240
 
159 pfowler 241
                devices[devid].cur_input = (uint)data[0] << 24;
242
                devices[devid].cur_input |= (uint)data[1] << 16;
158 pfowler 243
 
244
                data = new byte[] { 0x12 }; // Select GPIOA register
245
                WriteI2cData(0x42, data, 1);
246
 
247
                data = new byte[] { 0x00, 0x00 }; // Read two bytes
248
                rslt = ReadI2CData(0x43, ref data, 2);
249
 
159 pfowler 250
                devices[devid].cur_input |= (uint)data[0] << 8;
251
                devices[devid].cur_input |= (uint)data[1];
252
 
253
 
254
 
255
                if (devices[devid].cur_input != devices[devid].prev_input) {
256
                    this.input_ahfs(devid);
257
                    devices[devid].prev_input = devices[devid].cur_input;
258
                }
259
 
260
 
261
                // Do the Refueling light adc
262
                devices[devid].cur_adc = ReadADC(1);
263
 
264
                if (devices[devid].cur_adc > devices[devid].max_adc)
265
                    devices[devid].max_adc = devices[devid].cur_adc;
266
 
267
                ushort lowerval = 0;
268
                if (devices[devid].prev_adc >= devices[devid].adc_thres)
269
                    lowerval = (ushort)(devices[devid].prev_adc - devices[devid].adc_thres);
270
 
271
                ushort upperval = devices[devid].max_adc;
272
                if (devices[devid].prev_adc <= upperval - devices[devid].adc_thres)
273
                    upperval = (ushort)(devices[devid].prev_adc + devices[devid].adc_thres);
274
 
275
                //Console.WriteLine("ADC: " + devices[devid].cur_adc + " Max: " + devices[devid].max_adc + " Low: " + lowerval + " High: " + upperval);
276
 
277
                if ((devices[devid].cur_adc < lowerval) || (devices[devid].cur_adc >= upperval)) {
278
                    // Cover our min/max ranges within threshold
279
                    if (devices[devid].cur_adc < devices[devid].adc_thres)
280
                        devices[devid].cur_adc = 0;
281
                    if (devices[devid].cur_adc > devices[devid].max_adc - devices[devid].adc_thres)
282
                        devices[devid].cur_adc = devices[devid].max_adc;
283
 
284
                    devices[devid].prev_adc = devices[devid].cur_adc;
285
 
286
                    ushort refuellight = map_ushort(devices[devid].cur_adc, 0, devices[devid].max_adc, 0, 0xffff);
287
                    bios.SendData("ALCP_RCVR_LTS " + refuellight.ToString() + "\n");
288
                    Console.WriteLine("ALCP_RCVR_LTS " + ":" + refuellight.ToString() + "(" + devices[devid].cur_adc + ")");
289
                }
290
 
158 pfowler 291
            }
159 pfowler 292
            refresh.Enabled = enabled;
293
        }
158 pfowler 294
 
159 pfowler 295
        public void input_ahfs(int devid) {
296
            // AHCP
297
 
298
            // Train - Safe - Arm
299
            Switch3Pos(8, 9, "AHCP_MASTER_ARM", devid);
300
            // Gunarm - Safe - Arm
301
            Switch3Pos(10, 11, "AHCP_GUNPAC", devid);
302
            // Train - Safe - Arm
303
            Switch3Pos(12, 13, "AHCP_LASER_ARM", devid);
304
            // Off - On
305
            Switch2Pos(14, "AHCP_TGP", devid);
306
            // Radar  - Delta - Baro
307
            Switch3Pos(0, 1, "AHCP_ALT_SCE", devid);
308
            // Night - Day
309
            Switch2Pos(2, "AHCP_HUD_DAYNIGHT", devid);
310
            //Stby - Norm
311
            Switch2Pos(15, "AHCP_HUD_MODE", devid);
312
            // Off - On
313
            Switch2Pos(3, "AHCP_CICU", devid);
314
            // Off - On
315
            Switch2Pos(4, "AHCP_JTRS", devid);
316
            //Off - Test - On
317
            Switch3Pos(6, 5, "AHCP_IFFCC", devid);
318
            //
319
            Switch2Pos(7, "HARS_FAST_ERECT", devid);
320
 
321
            // Fuel System
322
 
323
            // 
324
            Switch2Pos(16, "FSCP_AMPL", devid);
325
            // 
326
            Switch2Pos(24, "FSCP_BOOST_MAIN_L", devid);
327
            // 
328
            Switch2Pos(25, "FSCP_BOOST_MAIN_R", devid);
329
            // 
330
            Switch2Pos(26, "FSCP_BOOST_WING_L", devid);
331
            // 
332
            Switch2Pos(27, "FSCP_BOOST_WING_R", devid);
333
            // 
334
            Switch2Pos(28, "FSCP_CROSSFEED", devid);
335
            // 
336
            Switch2Pos(30, "FSCP_EXT_TANKS_FUS", devid);
337
            // 
338
            Switch2Pos(31, "FSCP_EXT_TANKS_WING", devid);
339
            // 
340
            Switch2Pos(20, "FSCP_FD_MAIN_L",devid, true);
341
            // 
342
            Switch2Pos(21, "FSCP_FD_MAIN_R", devid, true);
343
            // 
344
            Switch2Pos(18, "FSCP_FD_WING_L", devid, true);
345
            // 
346
            Switch2Pos(19, "FSCP_FD_WING_R", devid, true);
347
            // 
348
            Switch2Pos(17, "FSCP_LINE_CHECK", devid);
349
            // 
350
            Switch2Pos(23, "FSCP_RCVR_LEVER", devid); // Technically a 3pos, but 3rd not needed
351
            // 
352
            Switch2Pos(29, "FSCP_TK_GATE", devid);
158 pfowler 353
        }
354
 
355
 
356
        public byte ReadGpio(byte pinNum) {
357
            return Convert.ToByte(usbi2c.Functions.ReadGpioPinValue(pinNum));
358
        }
359
 
360
        public ushort ReadADC(byte pinNum) {
361
            ushort[] adcData = { 0, 0, 0, 0, 0, 0 };
362
 
363
            int rslt = usbi2c.Functions.GetAdcData(adcData);
364
 
365
            return adcData[pinNum];
366
        }
367
 
368
        public void WriteGpio(byte pinNum, byte value) {
369
            this.usbi2c.Functions.WriteGpioPinValue(pinNum, value);
370
        }
371
 
372
        public int WriteI2cData(byte address, byte[] data, uint count) {
373
            int rslt = this.usbi2c.Functions.WriteI2cData(address, data, count, this.speed);
374
            return rslt;
375
        }
376
 
377
        public int ReadI2CData(byte address, ref byte[] data, uint count) {
378
            int rslt = this.usbi2c.Functions.ReadI2cData(address, data, count, this.speed);
379
            return rslt;
380
        }
381
 
159 pfowler 382
        public uint Switch2Pos(int pin, String cmd, int devid, Boolean invert = false) {
383
            uint chg = (uint)(devices[devid].prev_input >> pin) & 0x01;
384
            uint norm = (uint)(devices[devid].cur_input >> pin) & 0x01;
158 pfowler 385
            uint value = 0;
386
 
387
            if ((uint)(norm) == 1) {
388
                value = (uint)(invert ? 0 : 1);
159 pfowler 389
            } else {
390
                value = (uint)(invert ? 1 : 0);
158 pfowler 391
            }
392
 
393
            if (norm != chg) {
394
                bios.SendData(cmd + " " + value.ToString() + "\n");
395
                Console.WriteLine(cmd + ":" + value.ToString());
396
            }
397
            return value;
398
        }
399
 
159 pfowler 400
        public uint Switch3Pos(int pin0, int pin1, String cmd, int devid, Boolean invert = false) {
158 pfowler 401
            uint value = 1;
159 pfowler 402
            uint chg0 = (uint)(devices[devid].prev_input >> pin0) & 0x01;
403
            uint chg1 = (uint)(devices[devid].prev_input >> pin1) & 0x01;
404
            uint nrm0 = (uint)(devices[devid].cur_input >> pin0) & 0x01;
405
            uint nrm1 = (uint)(devices[devid].cur_input >> pin1) & 0x01;
158 pfowler 406
 
407
            if ((uint)nrm0 == 1)
408
                value = (uint)(invert ? 2 : 0);
409
            else if ((uint)nrm1 == 1)
410
                value = (uint)(invert ? 0 : 2);
411
 
412
            if ((nrm0 != chg0) || (nrm1 != chg1)) {
413
                bios.SendData(cmd + " " + value.ToString() + "\n");
414
                Console.WriteLine(cmd + ":" + value.ToString());
415
            }
416
 
417
            return value;
418
        }
419
 
159 pfowler 420
        public uint Selector(int[] pins, String cmd, int devid) {
421
            uint value = 0;
422
            uint chg = 0;
423
            uint norm = 0;
424
            uint mask = 0;
425
            for (int i = 0; i < pins.Length; i++)
426
                mask |= (uint)1 << i;
427
 
428
            for (int i = 0; i < pins.Length; i++) {
429
                chg |= (uint)(devices[devid].prev_input >> (pins[i] - i)) & mask;
430
                norm |= (uint)(devices[devid].cur_input >> (pins[i] - i)) & mask;
431
 
432
                if ((uint)((devices[devid].cur_input >> pins[i]) & 0x01) == 1) {
433
                    value = (uint)i;
434
                }
435
            }
436
 
437
            // This happens when between positions of the selector
438
            if (norm == 0)
439
                return 0;
440
 
441
 
442
            if (norm != chg) {
443
                bios.SendData(cmd + " " + value.ToString() + "\n");
444
                Console.WriteLine(cmd + ":" + value.ToString());
445
            }
446
 
447
            return value;
448
        }
449
 
450
        public void send_trackir(VirtualKeyCode key) {
451
            sendkey.Keyboard.KeyDown(VirtualKeyCode.CONTROL);
452
            System.Threading.Thread.Sleep(10);
453
            sendkey.Keyboard.KeyPress(key);
454
            sendkey.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
455
        }
456
 
158 pfowler 457
        public ushort map_ushort(ushort x, ushort in_min, ushort in_max, ushort out_min, ushort out_max) {
458
            return (ushort)((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
459
        }
460
 
461
 
462
    }
463
}