using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using AIOWDMNet; // the namespace exposes the AIOWDM Class interface namespace Sample1 { public partial class Form1 : Form { UInt32 Status = 0; // This is the basic data that we will be using to interface with the card: const UInt32 MAX_CARDS = 10; public Int32 NumCards = 0; public Int32 CardNum = 0; // The index of the one card we will be using 0 public UInt32 Offset = 0; // This the offset that will be used based on the base address of the card public bool RunFlag = false; public bool TimerEnabled = false; //public byte[] value = new byte[] { 0, 0, 0 }; // 3 values used for read write public int i = 0; // This will hold the data for the card installed in the system: public struct TCardData { public bool IsValid; public bool IsSelected; public UInt32 DeviceID; public UInt32 Base; // This a result of findcards and the base address of the card }; public TCardData CardData; // only one struct //public UInt32[] PortOffsets = new UInt32[5] { 0, 4, 8, 12, 16 }; // offsets for 5 max ports // Note: This value gets changed on init or Change Quad Count Mode change public ushort ModeCtrlReg = 0x2831; // default value 0x2831 see spec 0010 1000 0011 0001 public const double PI = 3.141593; public Int32[] previous_readings = new Int32[8]; // buffer data for display public Int32[] currentReadings = new Int32[8]; // buffer data for display public UInt32[] currentRes = new UInt32[8]; // buffer data for display public bool[] directionFlag = new bool[8]; // Array of controls for GUI updates: public TextBox[] ChannelData = new TextBox[8]; public TextBox[] FlagData = new TextBox[8]; public ComboBox[] CountMode = new ComboBox[8]; // Interval Timer fou GUI update: // (Note: A Windows Forms timer designed for single threaded environments not a System Timer 55 ms min res) static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); public Form1() { InitializeComponent(); // Initialize default values: // Arrays of the controls: ChannelData[0] = textBoxVolts0; ChannelData[1] = textBoxVolts1; ChannelData[2] = textBoxVolts2; ChannelData[3] = textBoxVolts3; ChannelData[4] = textBoxVolts4; ChannelData[5] = textBoxVolts5; ChannelData[6] = textBoxVolts6; ChannelData[7] = textBoxVolts7; CountMode[0] = comboBoxMulti0; CountMode[1] = comboBoxMulti1; CountMode[2] = comboBoxMulti2; CountMode[3] = comboBoxMulti3; CountMode[4] = comboBoxMulti4; CountMode[5] = comboBoxMulti5; CountMode[6] = comboBoxMulti6; CountMode[7] = comboBoxMulti7; FlagData[0] = textBoxFlag0; FlagData[1] = textBoxFlag1; FlagData[2] = textBoxFlag2; FlagData[3] = textBoxFlag3; FlagData[4] = textBoxFlag4; FlagData[5] = textBoxFlag5; FlagData[6] = textBoxFlag6; FlagData[7] = textBoxFlag7; for (int i = 0; i < 8; i++) { CountMode[i].SelectedIndex = 1; // init flag to match check box state } for (i = 0; i < 8; i++) { directionFlag[i] = false; // init flag to match check box state } // Ping the driver AIOWDM.SYS: // This takes an absolute address not relative offset // This is the one place we actual might use all 16 bits returned for an error code AA55 // otherwise we only use an 8 bit byte of data per read and write: if (AIOWDM.InPortB(0x61) == 0xAA55) { MessageBox.Show(" AIOWDM.SYS not detected.\n Please copy AIOWDM.SYS into [Windows]/system32/drivers and re-run this sample.\n Ensure that a board is installed properly.", "Warning"); } textBoxStatus.Text = "This sample demonstrates basic operation of the board."; // This will get all the card info: FindCardsWDM(); // Add the event and the event handler for the method that will // process the timer event to the timer: myTimer.Tick += new EventHandler(TimerEventProcessor); // Set the timer interval in miliseconds and start 55ms min resolution: myTimer.Interval = 100; } private void Form1_Load(object sender, EventArgs e) { } private void FindCardsWDM() { bool found = false; // Local Vars for QueryCardInfo(): UInt32 DeviceID, Base; UInt32 NameSize = 256; UInt16[] Name = new UInt16[256]; String strname; // Set CardData to 0 as needed: CardData.IsValid = false; CardData.IsSelected = false; CardData.DeviceID = 0; CardData.Base = 0; // Get the total number of cards installed: NumCards = AIOWDM.GetNumCards(); if (NumCards == 0) // no cards present { labelCardName.Text = "No Card Found"; textBoxStatus.Text = "No cards were found!"; textBoxStatus.Text += "This may mean the card is not installed. "; textBoxStatus.Text += "Check Device Manager for a card and its status"; textBoxStatus.Text += "You may consider rebooting your system."; RunFlag = false; } else { // Validate and store card data: Status = AIOWDM.QueryCardInfo(CardNum, out DeviceID, out Base, out NameSize, out strname); // Populate list box with addresse offsets found set flags: switch (DeviceID) { case 0x2230: // PCI-QUAD-8 labelCardName.Text = "PCI-QUAD-8 Quadrature Card"; CardData.IsValid = true; CardData.DeviceID = DeviceID; CardData.Base = Base; found = true; break; default: break; }// end switch }//end else card present // If card(s) are present but no valid cards were found: if ((NumCards != 0) && (found == false) ) { labelCardName.Text = "No Valid Card Found."; textBoxStatus.Text = "No valid card was found!"; textBoxStatus.Text += "This may mean the card is not installed. "; textBoxStatus.Text += "Check Device Manager for a card and its status"; textBoxStatus.Text += "You may consider rebooting your system."; RunFlag = false; } if (RunFlag) { CardData.IsSelected = true; } } private void TimerEventProcessor(Object myObject, EventArgs myEventArgs) { // This is the method that runs when the timer event is raised: myTimer.Stop(); UpdateGUIState(); myTimer.Enabled = true; } private void UpdateGUIState() { // Get data and display: String readString; for (int count = 0; count < 8; count++) { previous_readings[count] = currentReadings[count]; currentReadings[count] = Read_7766(count); if (currentReadings[count] != previous_readings[count]) { //change = true; readString = currentReadings[count].ToString(); ChannelData[count].Text = readString; } } } private void btnInit_Click(object sender, EventArgs e) { // We could get this from the UI for testing but its disabled for now: String strCtrlReg = textBoxCtrlReg.Text; UInt16 CtrlReg = UInt16.Parse(strCtrlReg, System.Globalization.NumberStyles.HexNumber); // Init board: Init_7766(CardNum, CtrlReg); //ctrReg is our default set at startup and used in init func ModeCtrlReg = CtrlReg; // reset global value } private void btnPerformIO_Click(object sender, EventArgs e) { if (TimerEnabled) { TimerEnabled = false; myTimer.Stop(); btnPerformIO.Text = "Perform I/O"; } else { TimerEnabled = true; myTimer.Enabled = true; btnPerformIO.Text = "Stop I/O"; } } private void btnExit_Click(object sender, EventArgs e) { // Right now this is only called on button click not window close ALtF4 etc: // Kill the timer: myTimer.Stop(); myTimer.Enabled = false; myTimer.Dispose(); // Close the form and Application: this.Close(); } private void btnReset_Click(object sender, EventArgs e) { // Button Clicks to reset a channel: // Need to stop the timer change board and GUI: myTimer.Stop(); //Get button sender Tag (index) Int32 iTagindex = 0; Button btnSender = sender as Button; if (btnSender != null) { iTagindex = Convert.ToInt32(btnSender.Tag); } // Toggle local mode value and button display states: ResetCount_7766(iTagindex); // Restart timer thread: myTimer.Enabled = true; } private void comboBoxMulti_SelectedIndexChanged(object sender, EventArgs e) { // Need to stop the timer change board and GUI: myTimer.Stop(); //Get sender Tag (index) Int32 iTagindex = 0; ComboBox cmbSender = sender as ComboBox; if (cmbSender != null) { iTagindex = Convert.ToInt32(cmbSender.Tag); } // Set Mode based on index 0-4: SetQuadCountMode_7766(iTagindex, cmbSender.SelectedIndex); // Restart timer thread: myTimer.Enabled = true; } private void btnReverse_Click(object sender, EventArgs e) { // Reverse all channels (CPLD) however you can also reverse individual channels: // Note: This is for demo purposes you probably should only do this on startup initialization for (int count = 0; count < 8; count++) { if (directionFlag[count]) { AIOWDM.RelOutPortB(CardNum, (uint) (Offset + 7 + (count * 8)), 0x01); // swap inA and inB reverse direction (optional) directionFlag[count] = false; } else { AIOWDM.RelOutPortB(CardNum, (uint) (Offset + 7 + (count * 8)), 0x00); // swap inA and inB reverse direction (optional) directionFlag[count] = true; } } } private void btnReadFlags_Click(object sender, EventArgs e) { // Button Clicks to read flags for a channel: // Need to stop the timer change board and GUI: myTimer.Stop(); //Get button sender Tag (index) Int32 iTagindex = 0; Button btnSender = sender as Button; if (btnSender != null) { iTagindex = Convert.ToInt32(btnSender.Tag); } // Get data and display: byte flags; String readString; flags = ReadFlags_7766(iTagindex); // Hex: //readString = flags.ToString(x2); //FlagData[iTagindex].Text = readString; // Binary: char pad = '0'; readString = Convert.ToString(flags, 2); FlagData[iTagindex].Text = readString.PadLeft(8, pad); // Restart timer thread: myTimer.Enabled = true; } public void Init_7766(int CardNum, UInt16 CtrlReg) { // See spec for control register options etc // for example: MCR0 and MCR1 == 0xA001 == 1010 000 000 0001 == MCR1 B7........MCR0 B0 // Init all 8 channels the same way for free running count mode acquisition: for (int count = 0; count < 8; count++) { //AIOWDM.RelOutPort(CardNum, (uint)(Offset + 0 + (count * 8)), 0xA001); // (no index) //AIOWDM.RelOutPort(CardNum, (uint)(Offset + 0 + (count * 8)), 0x2821); // (reset CNTR at index) AIOWDM.RelOutPort(CardNum, (uint)(Offset + 0 + (count * 8)), CtrlReg); // default 0x2831 init PCI board mode see spec AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 7 + (count * 8)), 0x01); // swap inA and inB reverse direction value: (optional) (CPLD) AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 6 + (count * 8)), 0x09); // reset all flags and counters } } public int Read_7766(int chan) { // The Channel data starts at base address offset 0x02 See the LS7766 spec int data = 0; AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 6 + (chan * 8)), 0x04); // load ODR from CNTR // Read up to 8 channels 32 bits per channel: uint baseOffset = 0x02; uint chanOffset = (uint)chan * 0x08; data = (int)AIOWDM.RelInPortL(CardNum, (uint)(Offset + baseOffset + chanOffset)); return data; } public byte ReadFlags_7766(int chan) { byte flags = 0; // Read Flags at offset + 6: uint chanOffset = (uint)chan * 0x08; flags = (byte)AIOWDM.RelInPortB(CardNum, (uint)(Offset + 6 + chanOffset)); // not base plus 2 start point? return flags; } public void ResetCount_7766(int channel) { // Reset the counters for one channel: AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 6 + (channel * 8)), 0x09); // reset all flags and counters } public void SetQuadCountMode_7766(int channel, int index) { // See spec for options // MCR0 B1B0 == 00 v 01 v 10 v 11 // Use exiting MCR0 value and reinit with new count mode bits: // Set for one channel by index 0-4: // Note: ctrReg is our global default set at startup and used in init func as well ushort mask = ModeCtrlReg; ushort B1B0 = 0x0001; // 00 is Non quadrature mode which is A and B data are count and direction // So this mode wont be appropriate for some encoders switch (index) { case 0: B1B0 = 0x00; break; case 1: B1B0 = 0x01; break; case 2: B1B0 = 0x02; break; case 3: B1B0 = 0x03; break; default: B1B0 = 0x00; break; } //MCR0 and MCR1 mask = (ushort)(ModeCtrlReg & ((0xFFFF) << 2)); // clear 2 right bits ModeCtrlReg = (ushort)(mask | B1B0); // set new value AIOWDM.RelOutPort(CardNum, (uint)(Offset + 0 + (channel * 8)), ModeCtrlReg); // rewrite control register AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 7 + (channel * 8)), 0x01); // swap inA and inB reverse direction value: (optional) (CPLD) AIOWDM.RelOutPortB(CardNum, (uint)(Offset + 6 + (channel * 8)), 0x09); // reset all flags and counters } } }