3

I am attempting to change the display of a Delcom USB 7-segment display in Unity (Mono framework) with C#. I am able to find the device and read the serial number, but I am unable to properly send control packets. I'm pretty positive that I am forming and/or sending the data incorrectly, but I have no experience with this type of communication and am at a loss as to what to do.

I cobbled together the following code from a couple of their example programs (both in C++). I'm using InteropServices to use the unmanaged DLL that they supply.



using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

public class DelcomController : MonoBehaviour
{   
    [DllImport("DelcomDLL", EntryPoint="DelcomGetDeviceCount")]
    public static extern int DelcomGetDeviceCount(uint ProductType);

    [DllImport("DelcomDLL", EntryPoint="DelcomGetNthDevice")]
    public static extern int DelcomGetNthDevice(uint ProductType, uint NthDevice, StringBuilder DeviceName);

    [DllImport("DelcomDLL", EntryPoint="DelcomOpenDevice")]
    public static extern uint DelcomOpenDevice(StringBuilder DeviceName, int Mode );

    [DllImport("DelcomDLL", EntryPoint="DelcomCloseDevice")]
    public static extern int DelcomCloseDevice(uint DeviceHandle);

    [DllImport("DelcomDLL", EntryPoint="DelcomReadDeviceSerialNum")]
    public static extern int DelcomReadDeviceSerialNum(StringBuilder DeviceName, uint DeviceHandle);

    [DllImport("DelcomDLL", EntryPoint="DelcomSendPacket")]
    public static extern int DelcomSendPacket(uint DeviceHandle, ref PacketStructure PacketOut);

    [DllImport("DelcomDLL", EntryPoint="DelcomLEDControl")]
    public static extern int DelcomLEDControl(uint DeviceHandle, int Color, int Mode);

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct PacketStructure
    {
        public byte Recipient;
        public byte DeviceModel;
        public byte MajorCmd;
        public byte MinorCmd;
        public byte DataLSB;
        public byte DataMSB;
        public byte Length;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 8 )] 
        public byte[] DATA ;      //Data 1 .. 8
    }

    private uint hUSB;
    private static int DisplaySize = 6;

    PacketStructure packet = new PacketStructure ();

    void Start ()
    {
        int Result = 0;
        StringBuilder DeviceName = new StringBuilder (512);  

        // Serach for the first match USB device, For USB IO Chips use Delcom.USBIODS
        // With Generation 2 HID devices, you can pass a TypeId of 0 to open any Delcom device.
        try
        {
            Result = DelcomGetNthDevice (3, 0, DeviceName);
        }
        catch
        {
            print ("Error in DelcomGetNthDevice ().");  
        }

        if (Result == 0)
        {  // if not found, exit
            print ("Device not found!\n");
            return;
        }

        print ("Device found: "+ DeviceName);   // This prints the GUID properly..

        hUSB = DelcomOpenDevice(DeviceName, 0);

        print ("Device opened: " + hUSB.ToString ());   // This prints the handle fine.

        int serial = DelcomReadDeviceSerialNum (DeviceName, hUSB);

        print ("Device serial: " + serial.ToString ()); // This prints the correct serial.

        // Next, I'm attempting to turn on all of the digits using the example in NDHIDTEST as a reference.
        // The device does nothing. I'm pretty sure I'm not forming the packet properly, but I'm not exactly
        // sure of what changes to make.

        // Enter 8-digit mode.
        DisplaySizeSetup (8);

        // Turn all digits on.
        packet.MajorCmd = 101;
        packet.MinorCmd = 81;
        packet.DataLSB = 0;
        packet.DataMSB = 0;
        DelcomSendPacket (hUSB, ref packet);
        packet.MajorCmd = 101;
        packet.MinorCmd = 80;
        packet.DataLSB = 1;
        packet.DataMSB = 0;
        DelcomSendPacket (hUSB, ref packet);    // blink off

        // I'm doing this just for our test program to make sure we keep the device open for long enough.
        StartCoroutine (CloseDevice ());
    }

    private IEnumerator CloseDevice ()
    {
        yield return new WaitForSeconds (5f);
        DelcomCloseDevice(hUSB);
        print ("Device closed.");
    }
}

So GetNthDevice finds the display, hUSB is populated with the identifier using the resulting DeviceName, and the correct serial is read. Next, I'm attempting to send over a data packet that is used in one of their test programs that is supposed to simply illuminate all of the LEDs on the display, but it doesn't do anything.

Ultimately, what I need is to know how to set each of the four digits on the display.

Steven
  • 166,672
  • 24
  • 332
  • 435
Geo Ego
  • 1,315
  • 7
  • 27
  • 53
  • 1
    Instead of trying to create the structure in C# and pass it to the unmanaged dll, you might want to write a C++ plugin that creates and sends the packet and expose a (simpler) method to use from C#. http://docs.unity3d.com/Documentation/Manual/PluginsForDesktop.html – Calvin Oct 16 '13 at 22:52
  • Thanks for the suggestion. I'm working with Delcom to try and get it going natively, but this is definitely an option if that doesn't work out. – Geo Ego Oct 22 '13 at 18:43

1 Answers1

2

According to the header I found, the Length member should be of type short not byte. Although you don't actually use the extra data, apparently.

They also list c# sample code, except their web server seems to be configured such that .cs files can't be downloaded.

Jester
  • 56,577
  • 4
  • 81
  • 125
  • Thanks for catching that. I did change the data type; of course, it didn't change the outcome, since the data is not used as you pointed out. Also, I did find that file here: https://github.com/bbyars/buildlight/blob/master/buildlight/DelcomDll.cs However, it's just blinking a light on another product they have, which uses an entirely different device family, so it doesn't help much beyond finding the device, unfortunately. – Geo Ego Oct 21 '13 at 13:33