Accessing LEDs and the LCD display on a SpacePilot

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

DavePugh
Posts: 6
Joined: Thu Apr 05, 2007 2:47 am

Accessing LEDs and the LCD display on a SpacePilot

Post by DavePugh » Wed May 30, 2007 6:33 am

Back in early April, I posted a message asking for information about how I would go about writing a vxWorks device driver for the SpacePilot to be used with our 3D digital effect processor. I have now bought a spacepilot and, as predicted by jwick, the sensor and buttons proved to be trivial to get working. :D

I'm now trying to get control of the blue LEDs behind the knob and the LCD bitmap display. :?

For the LEDs, I've been trying to use the SET_REPORT command (similar to the LEDs in my USB keyboard driver) for Report ID 4 which appears to be the LED usage page, but I can't seem to get any change. When I use the GET_REPORT command, it returns 4 in the first byte (report ID) and zero in the second byte, no matter what I have sent in the SET_REPORT command.

I can't seem to find any reference to the LCD bitmap in the HID descriptor information, but there are report IDs 5 through 18 which are "feature" descriptions. I'm assuming that these features allow things like recentering of axes.

I'd be grateful for any assistance that anyone could offer in helping me getting the LEDs and LCD display working, and in finding out what those 14 feature descriptors do.

Thanks

Dave Pugh
Last edited by DavePugh on Wed May 30, 2007 9:01 am, edited 1 time in total.

DavePugh
Posts: 6
Joined: Thu Apr 05, 2007 2:47 am

Partial success

Post by DavePugh » Wed May 30, 2007 9:00 am

:D I was right about the LEDs. They now work. Please ignore that part of the original post. I've still got no idea where to start with writing to the LCD display though. :(

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Thu May 31, 2007 5:32 am

Here is some info and pseudocode on the SpacePilot LCD.

The LCD is 64x240 but is addressed one row of eight bits high at a time.
The LCD is filled 7 columns at a time from left to right in one of the 8 rows.
If the start position is (0,0), the first byte sent fills the following bits:
----------------------------------- ...
|1
|2
|3
|4
|5 ------>
|6
|7
|8
|Start of the second row
...
The next byte fills the column to the right of that one.
If there are less than 7 columns left in the row, you must send a packed structure for the remaining rows.

The packed structure is a count, value structure. You can have up to 3 values that can be repeated up to 255 times.
Of course, there are only 240 columns per row. This can fill patterns or empty space quickly.
We make extensive use of this packet, testing all data to see if it is more efficient to send it packed before sending it unpacked.
This is the relevant data structure.
typedef struct PackedDataState
{
int count[3]; // Count of each pattern in the data array
unsigned char bits[3]; // Up to 3 patterns of data bytes
} PackedDataState;

#define RPTID_LCD_POS 0x0c
#define RPTID_LCD_DATA 0x0d
#define RPTID_LCD_DATA_PACK 0x0e

void LCDStartPos(int row, int column)
/*
* Sets position at which subsequent bits will be filled.
* Note that row is one of 8 rows of 8 bit tall columns.
* There is a problem if you try to start after column 120.
*/
{
unsigned char *buffer = new unsigned char[4];

// Set start position
buffer[0] = RPTID_LCD_POS; // report ID 0x0c for LCD_POS
buffer[1] = row; // 0-7
buffer[2] = column; // 0-239
buffer[3] = 0;

// Send the buffer to the device
EnqueueCommand( buffer, 4 ); // buffer is free'd by EnqueueCommand after it is transmitted
}


LCDSendBitsUnpacked(unsigned char bits[][])
{
unsigned char *buffer = new unsigned char[8];
buffer[0] = RPTID_LCD_DATA; // report ID 0x0d for LCD_DATA
buffer[1] = bits[j++];
buffer[2] = bits[j++];
buffer[3] = bits[j++];
buffer[4] = bits[j++];
buffer[5] = bits[j++];
buffer[6] = bits[j++];
buffer[7] = bits[j++];

EnqueueCommand( buffer, 8 );
}


LCDSendBitsPacked( PackedDataState pds )
{
unsigned char *buffer = new unsigned char[7];

buffer[0] = RPTID_LCD_DATA_PACK; // report ID 0x0e for packed data packet
buffer[1] = pds.count[0];
buffer[2] = pds.bits [0];
buffer[3] = pds.count[1];
buffer[4] = pds.bits [1];
buffer[5] = pds.count[2];
buffer[6] = pds.bits [2];

// Queue up the command for transmission to the device
EnqueueCommand( buffer, 7 );
}

DavePugh
Posts: 6
Joined: Thu Apr 05, 2007 2:47 am

Thanks

Post by DavePugh » Thu May 31, 2007 5:48 am

Thanks Jwick. That looks like exactly what I need. I have spent this morning staring at the output from a USB protocol analyser, trying to work out the syntax. I had correctly assumed that the C, D and E reports were the correct ones, but couldn't work out the data format.

I'll let you know how I get on.

Thanks

Dave

DavePugh
Posts: 6
Joined: Thu Apr 05, 2007 2:47 am

Success

Post by DavePugh » Thu May 31, 2007 6:29 am

:D Many thanks Jwick. I now have full control of the LCD. Hopefully, once I've finished integrating the driver into our product, our customers should start buying lots of them.

Best Wishes

Dave

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Thu May 31, 2007 6:35 am

Terrific. That sounds great.
Let us know what you do with the LCD. Maybe you can send us a photo.

mew
Posts: 4
Joined: Fri Apr 27, 2007 2:33 pm
Location: Austin Texas USA
Contact:

Post by mew » Wed Aug 29, 2007 7:57 am

jwick wrote:void LCDStartPos(int row, int column)
/*
* Sets position at which subsequent bits will be filled.
* Note that row is one of 8 rows of 8 bit tall columns.
* There is a problem if you try to start after column 120.
*/
Hi,

Could you elaborate on the problems of starting after column 120? Is that value a typo?

Thanks
-- mew

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Wed Aug 29, 2007 8:14 am

Hello mew,

There was a small problem in an earlier version of the SP firmware where requests to start drawing at any column after 120 resulted in starting at the next column to the right. That was fixed quite a while ago. I wouldn't worry about it.

Jim
3Dx Software Development

cbeeckler
Posts: 2
Joined: Wed Oct 10, 2007 5:16 pm

Re: Partial success

Post by cbeeckler » Wed Oct 10, 2007 5:20 pm

DavePugh wrote::D I was right about the LEDs. They now work. Please ignore that part of the original post. I've still got no idea where to start with writing to the LCD display though. :(
Is there a way to control the LEDs on the SpaceNavigator using DirectX? I have found the DirectX far easier to implement into software than the COM samples provided.

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Thu Oct 11, 2007 5:59 am

Not that I know of. You may try some of the DX calls if there is something similar for joysticks. Chances are they won't connect up to the same USB messages.
You'll probably need to have a separate connection to the device to do non-DX calls.

Jim
3Dx Software Development

Michel
Posts: 9
Joined: Thu Oct 11, 2007 7:09 am

Post by Michel » Fri Oct 12, 2007 12:24 am

Dave & jwick,

I have the same wish, I'd like to control the LCD from within my application. I saw the pseudo code posted in this thread and I have absolutely no idea how to use it :( Can you give any hint how to communicate to the spacepilot? Dave are you willing to share some of your code? I'm working in (Managed) C++. I'm working on a .NET control wrapping all functions of the spacepilot. If I can get the LCD working I'm willing to share the control so everybody can use it in .NET applications.

Thanks!

Michel

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Fri Oct 12, 2007 10:03 am

Hi Michel,

I don't have any sample code for accessing the SP LCD from managed code...although it is something I am looking at.

Jim
3Dx Software Development

Michel
Posts: 9
Joined: Thu Oct 11, 2007 7:09 am

Post by Michel » Fri Oct 12, 2007 11:14 am

Hi Jim,

Maybe I can help you integrate it in .NET code. It's just that I don't have the slightest idea what you were talking about in the previous posting with the pseudo-code. Should the communication work in a low-level way where a device is opened and messages are send to it?

How comes everything is done through a nice COM except for the LCD?

If you have some non-.NET stuff working please send it to me, I'll see how I can integrate it ...

Thanks!

Michel

jwick
Moderator
Moderator
Posts: 2803
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick » Fri Oct 12, 2007 11:30 am

Hi Michel,

That isn't pseudo-code, it IS the code that manages the LCD (with a lot of synchronization and optimization code left out). The LCD is a bitmap. Everything you see on it is constructed by the driver one bit at a time. There is an interface to the driver to set strings on it via the old C/C++ SDK (GUI Synch API), but that has not yet been ported to the COM API (3DxInput). Why hasn't that been done? Not enough call for it to rise to the top of the priority list.

Also, the LCD was not meant to be an arbitrary bitmap you can scribble on. It was meant to tell the user what the buttons do. If you want to sync in with the latter, it fits in with our scheme. If you want arbitrary control over the LCD, you are going to be fighting with the driver for control over it. In that case, it would be best to turn off the 3DxWare driver and use native MS APIs.

Jim
3Dx Software Development

Michel
Posts: 9
Joined: Thu Oct 11, 2007 7:09 am

Post by Michel » Fri Oct 12, 2007 2:50 pm

Hi Jim,

Well .. I'm not looking for playing AVI's on the LCD or anything, but I would like to change the text (that describes the buttons functions)dynamically, so from withing my program. A workaround could be by changing the configuration but that doesn't seem to work (I posted that issue as well in this forum)

Michel

Post Reply