Subversion Repositories group.electronics

Rev

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