Wednesday, February 24, 2010

Optical mouse cam


Optical mouse cam


Are you using an optical mouse right now? Ever wanted to see your desktop through the eye on the bottom of it? Me neither, I already know I have to clean my desktop :-)
People get bored sometimes, and when I get bored I sometimes open up stuff to find out what makes it tick. One time, I did this with an old optical mouse. Well, a mouse only has 2 chips inside: the optical sensor and a chip for the usb/ps2-interfacing. I looked up the datasheet of the optical sensor (which is an ADNS2610) and it told me the sensor has a tiny 18x18 CCD, which can be read out using the serial port (the one which normally interfaces to the PS2/USB-chip).
So I start Visual Basic (I usually do my stuff under Linux, but I'm no star at using anything graphical like QT or GTK, so for this quick'n'dirty project I fell back in my old habits) and hack something up using a few wires to the trusty ole parallel port. The result: crisp lo-res b&w imaging :-)

As you can see, the mouse was over some text with an 'e' in it.
One of the more obvious features of a mouse, however, is that it can detect movement. Combine this with the just-aquired imaging features, and we have a ghetto b&w handscanner. This is a 'scanned' piece of a receipt:
I can understand you can't wait to have such a handy scanner yourself. And now, you can! The software is downloadable here. The software works on mice which use an ADNS-2610 optical sensor, recognisable by the eight pins, the sun-like mark and the text 'A2610'. I've seen this sensor in most cheap optical mice that aren't too old. To hook it up, check out the pinout in the datasheet, then on the PCB cut the traces running from the sensors SCK- and SDIO-pins to the rest of the mouse. Then connect the sensor, using a diode, to a parallel port, like this:
pp:                adns-2610:
25-----------------GND
12----------+------SDIO 5 -----|<|--+
9 -----------------SCK 
Plug in the USB/PS2-plug (or apply 5V to the Vcc-pin of the sensor), run the software and you should be OK.
I got a few questions about whether it would be possible to get the image from the USB or PS/2-port of the mouse, so you can view the image of an unmodified mouse. The answer is: In theory, it could be possible, if the microcontroller between the port and the sensor-IC supports some kind of pass-through-mode so you can use it to talk directly to the sensor. In practice though, I don't know of any chip that supports that kind of mode, so the answer would have to be: Nope, as far as I know, it can't be done.
By the way, if you search for datasheets, it seems that Agilent has spun off their optical division to a new company called Avago.

C# – BinaryFormatter.Deserialize is “Unable to find assembly”

While testing a SQL CLR procedure recently I came across an issue with the binary formatter deserialization failing because it could not find the assembly for the type (even though the type is within the same assembly as the deserialization code).

The database application I have been working on has an initial request object (from a web service or web site) that is serialized using the binary formatter and stored in a Request table. It is then added into a Queue to be processed by one or more Service Broker services at a later time.

The serialization and deserialization of the request object is performed by a SQL CLR procedure, utilising the “System.Runtime.Serialization.Formatters.Binary.BinaryFormatter” formatter.

While testing that the Service Broker was configured correctly I was reusing the same Request table data, where the request object had previously been serialized and saved to the table. However I quickly noticed that after re-deploying the SQL CLR project I was running into an error while deserializing the object (note: the type being serialized/deserialized is in the same assembly as the code that serializes it):

Unable to find assembly 'MyAssembly; Version=1.0.3463.18923; Culture=neutral; PublicKeyToken=40e3171cc8066fe6'.

After a little googling it became apparent that the binary formatter stores the type information within the serialized object so that it knows what type to deserialize it to (that makes sense), however this becomes a big issue if you are storing data for periods of time and need to maintain backwards compatibility with new versions of the assembly containing the type information.

Luckily the guys at MS had thought of this and provided us with the “System.Runtime.Serialization.SerializationBinder” class. By inheriting from this class it is possible to redirect all the requests for types from the binary formatter to the types of your choice.

Here is a sample that will allow the types to be found in the current assembly regardless of which version of the assembly originally created the serialized stream:

01sealed class AllowAllAssemblyVersionsDeserializationBinder : System.Runtime.Serialization.SerializationBinder
02{
03    public override Type BindToType(string assemblyName, stringtypeName)
04    {
05        Type typeToDeserialize = null;
06 
07        String currentAssembly = Assembly.GetExecutingAssembly().FullName;
08 
09        // In this case we are always using the current assembly
10        assemblyName = currentAssembly;
11 
12        // Get the type using the typeName and assemblyName
13        typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
14            typeName, assemblyName));
15 
16        return typeToDeserialize;
17    }
18}
19 
20public static MyRequestObject Deserialize(byte[] b)
21{
22    MyRequestObject mro = null;
23    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = newSystem.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
24    System.IO.MemoryStream ms = new System.IO.MemoryStream(b);
25 
26    // To prevent errors serializing between version number differences (e.g. Version 1 serializes, and Version 2 deserializes)
27    formatter.Binder = new AllowAllVersionsDeserializationBinder();
28 
29    // Allow the exceptions to bubble up
30    // System.ArgumentNullException
31    // System.Runtime.Serialization.SerializationException
32    // System.Security.SecurityException
33    mro = (MyRequestObject)formatter.Deserialize(ms);
34    ms.Close();
35    return mro;
36}

In my case the type itself had not changed between assembly versions, only the assembly version information. However the MSDN link below shows an example of allowing backwards compatibility between different versions of the type where the type itself may have changed significantly.

(http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder(VS.71).aspx)

P.S. this would also be a great solution if you are attempting to deserialize an object that was created in a different assembly that you cannot reference in your own project for some reason – providing you know the structure of the object and create a similar class in your own assembly.