Friday, June 11, 2010

Forget the MCE Extender - just stream the tuner output.


A number of companies that used to make MCE Extenders have stopped making them - I can understand why...you cannot play DVD's from a central server and you cannot access MCE applications like Netflix, Hulu, etc.

My solution to this is to try use the features included with Windows in order to get what you need and just create the rest. Since ATI came out with their firmware upgrade for their cable card tuner it is now possible to play recorded content on other computers on your network (except of course premium content like HBO). Content like videos, pictures, recorded tv, etc. can also be accessed by firstly sharing the folders and then adding the shares to your libraries on other systems. All this leaves is live TV.

There is a solution out there from SiliconDust called HDHomeRun but that will only give you ATSC and Clear QAM - although they have announced a cablecard solution. I bought one of the 2 port devices to play with and it seems pretty decent except for the fact that I need to keep poking holes in my firewall so it can communicate with its driver.

Looking at what is available it becomes obvious that the only solution would be to develop my own tuner streaming solution. I thought about reverse engineering the tuner portion of the extender but that seemed like way to much effort.

Phase 1
I spent 3 months delving into the AVStream class in the WDK during this time I played around with the sample tuner that is included in the DDK hacked out a lot of code and added a lot more. And finally came up with my first alpha solution.

For this I have an application on the 'tuner server' (main MCE box) and a tuner driver on the client system. when you start up a TV application on the client the tuner driver is started which communicates with the server. after that all tune requests are passed to the server and the tuner stream is passed back to the client.

I have included a capture of a Windows 7 x86 session running in VMWare (x86 is faster to kernel debug than x64 with windbg). Media Center is running in the VM communicating with the server (console box) on the left of the screen. My other client box is my Dell XPS notebook running Win 7 x64.

I experiance very little tiling but that could be because I am running on a 1Gbps network. I also spent a lot of time optimizing the network code.
This concludes Phase 1 of the project Phase 2 will include support for multiple simultaneous client and cable card tuners. I am still waiting for my Ceton 4 port tuner which I ordered in April but seems to have been delayed until July.

Part two...

Wednesday, June 9, 2010

Why can't a portable AC just power up automatically?




The problem:
We have a computer room that does not get central air after hours. Its gets pretty toasty by Sunday - to keep the air temperature down we installed a portable unit which vents into the plenum. Everything works fine however until there is a power spike or a blackout. We tried to find an inexpensive unit that would auto-restart but no luck.

The Solution:

The Current AC unit has an IR remote control so how about we just learn the codes and then anyone can terminal into the machine with the IR connected and run the application to send the power on command to the unit. Easy, right...

How will I get there:
I found an old Media Center IR Tranceiver lying around in the office and decided that would be the best way to go about this project. I then hit up Google tried all combinations of IR and infrared learing and programming and found basically nothing. Did find a number of references to Windows DDK.

Browsed the DDK and see what I can find - no client information but a couple of IOCTL_IR_* calls that could be useful if I can determine the device enumeration.

I did some more research on MSDN and found out that the client could communicate via IrBus - using the setupapi and the GUID for IrBus it is easy to get the device path.



Here are the functions for that:



hardwareDeviceInfo = SetupDiGetClassDevs ( &GUID_CLASS_IRBUS,...));
SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,0,&GUID_CLASS_IRBUS,...))

PSP_DEVICE_INTERFACE_DETAIL_DATA pfunctionClassDeviceData = NULL;
// call this next function twice first time to determine buffer size needed
SetupDiGetDeviceInterfaceDetail (...,pfunctionClassDeviceData,...);

hDevice = CreateFile(pfunctionClassDeviceData->DevicePath,...);
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);



Now that I had a handle to the device I could start using the IOCTL_IR commands. However I discovered after many frustrating hours that the driver does not detect if the client application is 32 or 64 bit. I got a lot of funky results until I decided to compile my app as 64 bit.

With the 64 bit application it was easy to capture the power button on the AC remote.

9050 -4400 650 -500 600 -500 600 -500 650 -500 600 -500 600 -1650 600 -550 600 -500 600 -1650 600 -1650 600 -1600 650 -1650 550 -1650 600 -550 600 -1600 600 -1650 600 -550 550 -1650 600 -550 600 -500 600 -550 600 -500 600 -550 550 -550 600 -1650 550 -550 600 -1650 600 -1650 600 -1650 550 -1700 550 -1650 600 -1650 600 -39750 9000 -200 600 -1000000
However sending the command it is not as easy. When the remote learned the command it did not detect the frequency. I am currently trying to decide what the best parameters are for transmitting this block of data.

Why is my transmit not working...

After thinking about this last night and not being able to figure out a reliable way to calculate the carrier frequency with the data I had the only thing left was using pulse mode. To test that the emitter was actually working I learnt a button on my XPS noteboook remote and sent that back to the XPS to see if it worked - I chose an arbitrary pulse of 50 microseconds. This worked but still I could not transmit the power button of the remote control to the AC...I guess this remote is not working in pulsed or DC mode so I need to take more drastic options.

I guess the only option I have now is take it appart :).



This is a pretty simple circuit looks like a IR led/keyboard controler chip with a transistor, two caps and a resistor.
Google search for RSM2221-001 just ended up with a lot of chinese sites - using bing to do the same search I at leat got a 'translate' button. I discovered that this is actaully a knock off of a NEC μPD6121. I managed to fins a datasheet for this chip at http://www.datasheetcatalog.org/datasheet/nec/UPD6122G-002.pdf. The datasheet says the chip operates between 400 and 500 khz. Cool now I can just calculate the carrier frequency which will be the osc freq/12 so between 33 and 41khz. What I thought was a large cap just turns out to be a ceramic oscillator a CRB455E so I guess we are running at 455khz so IR carrier is 38khz. Now I can calculate the carrier period for the IOCTL_IR_TRANSMIT call, everyone knows period = 1/freq so period = 26.31 micro seconds so 26. Lets plug this in and give it a go again. And Eureka it worked - AC switched on just as I had hoped.
Now to get everything back to where it should be and see if I can switch it on remotely.

Further thoughts:
Now that I have everything back in the computer room...it dawned on me that the power is a toggle interface so I would have to know that it is hot (this info I can get from the UPS web interface) and that the AC is not already on. For the latter portion I will need a webcam and a form of illumination - but I will leave that for part 2.