Rev 158 | Rev 160 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
using MCP2221;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using WindowsInput;
using WindowsInput.Native;
namespace nitdcscore {
public struct devdata {
public uint prev_input;
public uint cur_input;
public ushort cur_adc;
public ushort prev_adc;
public ushort max_adc;
public ushort adc_thres;
public int id;
public string name;
public string function;
}
public class mcp2221 {
DcsBios bios = new DcsBios();
MchpUsbI2c usbi2c = new MchpUsbI2c();
public Boolean hasAHFS { get; set; }
public Boolean hasAAP { get; set; }
int idx { get; set; }
int devcount { get; set; }
long dummy = 0;
public uint speed { get; set; }
Timer refresh = new Timer();
Timer delay = new Timer();
InputSimulator sendkey = new InputSimulator();
private readonly Object lockobject = new object();
public devdata[] devices = new devdata[5];
public mcp2221() {
speed = 400000;
idx = 0;
refresh.Interval = 70;
refresh.AutoReset = true;
refresh.Elapsed += refresh_Elapsed;
refresh.Enabled = false;
delay.Interval = 5;
delay.AutoReset = false;
delay.Elapsed += delay_Elapsed;
delay.Enabled = false;
bios.InitUDP();
usbi2c.Settings.GetConnectionStatus();
devcount = usbi2c.Management.GetDevCount();
Console.WriteLine(devcount.ToString() + " devices found");
for (int i = 0; i < devcount; i++) {
int rslt = usbi2c.Management.SelectDev(i);
usbi2c.Settings.GetConnectionStatus();
string usbDescriptor = this.usbi2c.Settings.GetUsbStringDescriptor();
if (usbDescriptor == "AHCP/FSCP Panel") {
this.hasAHFS = true;
devices[i].cur_input = 0;
devices[i].prev_input = 0;
devices[i].cur_adc = 0;
devices[i].max_adc = 930;
devices[i].adc_thres = 15;
devices[i].id = i;
devices[i].name = "AHCP/FSCP Panel";
devices[i].function = "refresh_ahfs";
init_ahfs(i);
} else if (usbDescriptor == "AAP Panel") {
this.hasAAP = true;
devices[i].cur_input = 0;
devices[i].prev_input = 0;
devices[i].prev_adc = 0;
devices[i].id = i;
devices[i].name = "AAP Panel";
devices[i].function = "refresh_aap";
init_aap(i);
}
}
}
private Boolean enabled;
public Boolean Enabled {
get {
return enabled;
}
set {
if (this.devcount == 0)
return;
this.enabled = true;
refresh.Enabled = true;
}
}
void delay_Elapsed(object sender, ElapsedEventArgs e) {
delay.Enabled = false;
}
void delayms(double ms = 100) {
delay.Interval = ms;
delay.Enabled = true;
dummy = 0;
while (delay.Enabled) { dummy++; }
}
void refresh_Elapsed(object sender, ElapsedEventArgs e) {
if (!Enabled)
return;
devdata dev = devices[idx];
usbi2c.Management.SelectDev(dev.id);
usbi2c.Settings.GetConnectionStatus();
Type type = this.GetType();
MethodInfo callfunc = type.GetMethod(dev.function);
ParameterInfo[] parameters = callfunc.GetParameters();
object[] parms = { idx };
callfunc.Invoke(this, parms);
idx++;
if (idx >= devcount)
idx = 0;
}
public void init_aap(int devid) {
// Enable the mcp23017
WriteGpio(3, 0);
this.delayms(500);
this.WriteGpio(3, 1);
this.delayms();
// Set io dir, pullups and rev polarity
byte[] data;
data = new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff }; // All inputs & polarity
WriteI2cData(0x40, data, 5);
data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
WriteI2cData(0x40, data, 3);
refresh_aap(devid);
devices[devid].prev_input = devices[devid].cur_input;
}
public void refresh_aap(int devid) {
refresh.Enabled = false;
lock (lockobject) {
byte[] data;
data = new byte[] { 0x12 }; // Select GPIOA register
WriteI2cData(0x40, data, 1);
data = new byte[] { 0x00, 0x00 }; // Read two bytes
int rslt = ReadI2CData(0x41, ref data, 2);
// Join all our buttons into a single inputs
uint gpio = (uint)((1 - ReadGpio(0)) | ((1 - ReadGpio(1)) << 1));
devices[devid].cur_input = (uint)gpio << 16;
devices[devid].cur_input |= (uint)data[0] << 8;
devices[devid].cur_input |= (uint)data[1];
if (devices[devid].cur_input != devices[devid].prev_input) {
this.input_aap(devid);
devices[devid].prev_input = devices[devid].cur_input;
}
}
refresh.Enabled = enabled;
}
public void input_aap(int devid) {
//
Switch2Pos(11, "AAP_CDUPWR", devid);
//
Switch2Pos(10, "AAP_EGIPWR", devid);
//
Switch3Pos(9, 8, "AAP_STEER", devid);
//
Selector(new int[] { 6, 5, 4 }, "AAP_STEERPT", devid);
//
Selector(new int[] {0,1,2,3}, "AAP_PAGE", devid);
}
public void init_ahfs(int devid) {
WriteGpio(3, 0);
this.delayms(500);
// Enable the mcp23017
WriteGpio(3, 1);
this.delayms();
// Set io dir, pullups and rev polarity
byte[] data;
// Soldered a couple of inputs wrong, the f0 is to reverse them (fuel boost switches)
data = new byte[] { 0x00, 0xff, 0xff, 0xf0, 0xff }; // All inputs & polarity
WriteI2cData(0x40, data, 5);
data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
WriteI2cData(0x40, data, 3);
data = new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff }; // All inputs & polarity
WriteI2cData(0x42, data, 5);
data = new byte[] { 0x0c, 0xff, 0xff }; // All pullups = on
WriteI2cData(0x42, data, 3);
// Get the initial ADC value
devices[devid].prev_adc = devices[devid].cur_adc = ReadADC(1);
refresh_ahfs(devid);
devices[devid].prev_input = devices[devid].cur_input;
}
public void refresh_ahfs(int devid) {
refresh.Enabled = false;
lock (lockobject) {
byte[] data;
data = new byte[] { 0x12 }; // Select GPIOA register
WriteI2cData(0x40, data, 1);
data = new byte[] { 0x00, 0x00 }; // Read two bytes
int rslt = ReadI2CData(0x41, ref data, 2);
devices[devid].cur_input = (uint)data[0] << 24;
devices[devid].cur_input |= (uint)data[1] << 16;
data = new byte[] { 0x12 }; // Select GPIOA register
WriteI2cData(0x42, data, 1);
data = new byte[] { 0x00, 0x00 }; // Read two bytes
rslt = ReadI2CData(0x43, ref data, 2);
devices[devid].cur_input |= (uint)data[0] << 8;
devices[devid].cur_input |= (uint)data[1];
if (devices[devid].cur_input != devices[devid].prev_input) {
this.input_ahfs(devid);
devices[devid].prev_input = devices[devid].cur_input;
}
// Do the Refueling light adc
devices[devid].cur_adc = ReadADC(1);
if (devices[devid].cur_adc > devices[devid].max_adc)
devices[devid].max_adc = devices[devid].cur_adc;
ushort lowerval = 0;
if (devices[devid].prev_adc >= devices[devid].adc_thres)
lowerval = (ushort)(devices[devid].prev_adc - devices[devid].adc_thres);
ushort upperval = devices[devid].max_adc;
if (devices[devid].prev_adc <= upperval - devices[devid].adc_thres)
upperval = (ushort)(devices[devid].prev_adc + devices[devid].adc_thres);
//Console.WriteLine("ADC: " + devices[devid].cur_adc + " Max: " + devices[devid].max_adc + " Low: " + lowerval + " High: " + upperval);
if ((devices[devid].cur_adc < lowerval) || (devices[devid].cur_adc >= upperval)) {
// Cover our min/max ranges within threshold
if (devices[devid].cur_adc < devices[devid].adc_thres)
devices[devid].cur_adc = 0;
if (devices[devid].cur_adc > devices[devid].max_adc - devices[devid].adc_thres)
devices[devid].cur_adc = devices[devid].max_adc;
devices[devid].prev_adc = devices[devid].cur_adc;
ushort refuellight = map_ushort(devices[devid].cur_adc, 0, devices[devid].max_adc, 0, 0xffff);
bios.SendData("ALCP_RCVR_LTS " + refuellight.ToString() + "\n");
Console.WriteLine("ALCP_RCVR_LTS " + ":" + refuellight.ToString() + "(" + devices[devid].cur_adc + ")");
}
}
refresh.Enabled = enabled;
}
public void input_ahfs(int devid) {
// AHCP
// Train - Safe - Arm
Switch3Pos(8, 9, "AHCP_MASTER_ARM", devid);
// Gunarm - Safe - Arm
Switch3Pos(10, 11, "AHCP_GUNPAC", devid);
// Train - Safe - Arm
Switch3Pos(12, 13, "AHCP_LASER_ARM", devid);
// Off - On
Switch2Pos(14, "AHCP_TGP", devid);
// Radar - Delta - Baro
Switch3Pos(0, 1, "AHCP_ALT_SCE", devid);
// Night - Day
Switch2Pos(2, "AHCP_HUD_DAYNIGHT", devid);
//Stby - Norm
Switch2Pos(15, "AHCP_HUD_MODE", devid);
// Off - On
Switch2Pos(3, "AHCP_CICU", devid);
// Off - On
Switch2Pos(4, "AHCP_JTRS", devid);
//Off - Test - On
Switch3Pos(6, 5, "AHCP_IFFCC", devid);
//
Switch2Pos(7, "HARS_FAST_ERECT", devid);
// Fuel System
//
Switch2Pos(16, "FSCP_AMPL", devid);
//
Switch2Pos(24, "FSCP_BOOST_MAIN_L", devid);
//
Switch2Pos(25, "FSCP_BOOST_MAIN_R", devid);
//
Switch2Pos(26, "FSCP_BOOST_WING_L", devid);
//
Switch2Pos(27, "FSCP_BOOST_WING_R", devid);
//
Switch2Pos(28, "FSCP_CROSSFEED", devid);
//
Switch2Pos(30, "FSCP_EXT_TANKS_FUS", devid);
//
Switch2Pos(31, "FSCP_EXT_TANKS_WING", devid);
//
Switch2Pos(20, "FSCP_FD_MAIN_L",devid, true);
//
Switch2Pos(21, "FSCP_FD_MAIN_R", devid, true);
//
Switch2Pos(18, "FSCP_FD_WING_L", devid, true);
//
Switch2Pos(19, "FSCP_FD_WING_R", devid, true);
//
Switch2Pos(17, "FSCP_LINE_CHECK", devid);
//
Switch2Pos(23, "FSCP_RCVR_LEVER", devid); // Technically a 3pos, but 3rd not needed
//
Switch2Pos(29, "FSCP_TK_GATE", devid);
}
public byte ReadGpio(byte pinNum) {
return Convert.ToByte(usbi2c.Functions.ReadGpioPinValue(pinNum));
}
public ushort ReadADC(byte pinNum) {
ushort[] adcData = { 0, 0, 0, 0, 0, 0 };
int rslt = usbi2c.Functions.GetAdcData(adcData);
return adcData[pinNum];
}
public void WriteGpio(byte pinNum, byte value) {
this.usbi2c.Functions.WriteGpioPinValue(pinNum, value);
}
public int WriteI2cData(byte address, byte[] data, uint count) {
int rslt = this.usbi2c.Functions.WriteI2cData(address, data, count, this.speed);
return rslt;
}
public int ReadI2CData(byte address, ref byte[] data, uint count) {
int rslt = this.usbi2c.Functions.ReadI2cData(address, data, count, this.speed);
return rslt;
}
public uint Switch2Pos(int pin, String cmd, int devid, Boolean invert = false) {
uint chg = (uint)(devices[devid].prev_input >> pin) & 0x01;
uint norm = (uint)(devices[devid].cur_input >> pin) & 0x01;
uint value = 0;
if ((uint)(norm) == 1) {
value = (uint)(invert ? 0 : 1);
} else {
value = (uint)(invert ? 1 : 0);
}
if (norm != chg) {
bios.SendData(cmd + " " + value.ToString() + "\n");
Console.WriteLine(cmd + ":" + value.ToString());
}
return value;
}
public uint Switch3Pos(int pin0, int pin1, String cmd, int devid, Boolean invert = false) {
uint value = 1;
uint chg0 = (uint)(devices[devid].prev_input >> pin0) & 0x01;
uint chg1 = (uint)(devices[devid].prev_input >> pin1) & 0x01;
uint nrm0 = (uint)(devices[devid].cur_input >> pin0) & 0x01;
uint nrm1 = (uint)(devices[devid].cur_input >> pin1) & 0x01;
if ((uint)nrm0 == 1)
value = (uint)(invert ? 2 : 0);
else if ((uint)nrm1 == 1)
value = (uint)(invert ? 0 : 2);
if ((nrm0 != chg0) || (nrm1 != chg1)) {
bios.SendData(cmd + " " + value.ToString() + "\n");
Console.WriteLine(cmd + ":" + value.ToString());
}
return value;
}
public uint Selector(int[] pins, String cmd, int devid) {
uint value = 0;
uint chg = 0;
uint norm = 0;
uint mask = 0;
for (int i = 0; i < pins.Length; i++)
mask |= (uint)1 << i;
for (int i = 0; i < pins.Length; i++) {
chg |= (uint)(devices[devid].prev_input >> (pins[i] - i)) & mask;
norm |= (uint)(devices[devid].cur_input >> (pins[i] - i)) & mask;
if ((uint)((devices[devid].cur_input >> pins[i]) & 0x01) == 1) {
value = (uint)i;
}
}
// This happens when between positions of the selector
if (norm == 0)
return 0;
if (norm != chg) {
bios.SendData(cmd + " " + value.ToString() + "\n");
Console.WriteLine(cmd + ":" + value.ToString());
}
return value;
}
public void send_trackir(VirtualKeyCode key) {
sendkey.Keyboard.KeyDown(VirtualKeyCode.CONTROL);
System.Threading.Thread.Sleep(10);
sendkey.Keyboard.KeyPress(key);
sendkey.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
}
public ushort map_ushort(ushort x, ushort in_min, ushort in_max, ushort out_min, ushort out_max) {
return (ushort)((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
}
}
}