This is my personal blog. I also have a professional blog at http://siliconsparrow.com/

15 November 2007

Moving a DirectShow window while paused

Filed under: Nerd Notes — adam @ 2:26 pm

directshowmoveproblem.jpegI’ve been writing a lot of DirectX / DirectShow stuff lately and I’ve come across a problem if I pause a video replay and then move the containing window. The playback window becomes separated from the containing window even though I am handling the WM_MOVE event.

You’d think that the following code would work:

void CMyWindow::OnMove()
{
    CRect r;
    GetClientRect(r);

// _piWindow is a pointer to my filtergraph's IVideoWindow interface.
    _piWindow->SetWindowPosition(r.left, r.top, r.Width(), r.Height());
}

It works fine if the video is playing but if the replay is paused, the active movie window will ignore the window move commands.

The solution was to trick DirectShow into thinking that you want to resize the window like so:

void CMyWindow::OnMove()
{
    CRect r;
    GetClientRect(r);

    _piWindow->SetWindowPosition(r.left, r.top, r.Width() + 4, r.Height());
    _piWindow->SetWindowPosition(r.left, r.top, r.Width(), r.Height());
}

28 September 2007

Updates to ARM tutorials

Filed under: Nerd Notes — adam @ 10:08 pm

Dan Ashbrook has noticed a mistake in my example code.

If you try and modify the Flash Memory or the Hello World example code to send the output to the 2nd serial port, it does not work due to some incorrect port assignments in Board.h. I have replaced the original example code with the corrected version so you can download it again.

Thanks Dan for not only spotting the problem, but also for fixing it and sending me the fix!


19 September 2007

Primary interface not eth0

Filed under: Nerd Notes — adam @ 4:11 pm

I’ve seen this happen a couple of times with a Debian 4 “Etch” install where the primary Ethernet interface is eth2 or eth3 instead of eth0. I’ve worked out what it is now.

It can happen when you move a hard drive from one system to another, replace the motherboard or ethernet card, clone a drive or in any way cause the MAC address of the Ethernet interface to change.

You see, there is a script which assigns the device numbers based on the MAC address so that in a machine with multiple cards, the numbers will never change. So if you remove an Ethernet interface, it will reserve its device number in case that card ever re-appears.

So how to fix it ? Very simple. Just delete the MAC address cache and reboot. This command will do it:

rm /etc/udev/rules.d/z25_persistent-net.rules

reboot

8 September 2007

MythTV and the TwinHan remote

Filed under: Nerd Notes — adam @ 12:04 am

TwinHan remote controlToday’s challenge – getting this gizmo to work with MythTV. It turned out to be quite a pain so I am documenting it here in case I need to do it again in the future. Note that I am running Ubuntu 7.04 (Feisty Fawn). The procedure may be slightly different for other platforms.


UPDATE: This article is somewhat out of date now. I have re-written it for the latest version of Mythbuntu, you can read the updated guide here.



STEP 1 – Locate the device node for the remote
This remote has a very nifty USB receiver which presents itself to the PC as a HID keyboard. It is mapped to a device in /dev/input but we need to figure out which one. Type this command:

cat /proc/bus/input/devices

Now look for the TwinHan keyboard device. Beware, it also creates a mouse device which you do not want. The entry will look like this:

I: Bus=0003 Vendor=6253 Product=0100 Version=0110
N: Name="Twinhan Tech Remote Control"
P: Phys=usb-0000:00:11.2-1/input0
S: Sysfs=/class/input/input3
H: Handlers=kbd event3
B: EV=120003
B: KEY=800000 0 e0b0ffdf 1cfffff ffffffff fffffffe
B: LED=1f

Note the Sysfs entry. We will need this for the next step…

STEP 2 – Create a symlink to the device node
Even though we saw the remote was on /class/input/input3, It is not guaranteed to stay there. Next time you reboot it may be a different device so we need to create some method of referring to it which will work every time. We can use UDEV for this. Type this command (replacing inputX with the appropriate event device of course):

 udevinfo -a -p /class/input/inputX

You will get lots of output. We are interested in the first {modalias} line.

  looking at parent device '/class/input/input3':
    KERNELS=="input3"
    SUBSYSTEMS=="input"
    DRIVERS==""
    ATTRS{modalias}=="input:b0003v6253p0100e0110-e0,1,11,14,k74,75,77,7D,7E,7F,B7,raml0,1,2,3,4,sfw"
    ATTRS{uniq}=="1111111"
    ATTRS{phys}=="usb-0000:00:11.2-1/input0"
    ATTRS{name}=="Twinhan Tech Remote Control"

Create a new file /etc/udev/rules.d/10-local.rules and paste that line into it so it looks like this (this is supposed to be all on one line BTW):

KERNEL=="event*",ATTRS{modalias}=="input:b0003v6253p0100e0110-e0,1,11,14,
k74,75,77,7D,7E,7F,B7,raml0,1,2,3,4,sfw",SYMLINK="input/irremote"

Then simply unplug the USB device and plug it back in again. You should now see a new device called /dev/input/irremote. We can test it by typing the following. You should see data arrive whenever you press a button on the remote. Press Ctrl-C when you are done testing.

hexdump -C /dev/input/irremote

STEP 3 – Configure LIRC
You need to set up /etc/lirc/hardware.conf and lircd.conf. Both of these files are located in /etc/lirc. To save you the trouble of working out all the settings, I have posted mine here:

hardware.conf

lircd.conf

Once you have these files in place, restart the lirc daemon with this command:

/etc/init.d/lirc restart

You can test that it is working by typing this:

irw

Now every time you press a key, you should see it printed on the screen. Press Ctrl-C when you are done.

STEP 4 – Configure MythTV commands
We are getting closer now. The next step is to set up a file called /home/mythtv/.mythtv/lircrc which contains the mappings between the keys on the remote and the functions in MythTV. Once again, I have already prepared this file which you can download here:

lircrc-mythtv

Rename this file to lircrc and move it to /home/mythtv/.mythtv/. Once that is done, restart MythTV. Here are the key mappings you will end up with:

Key Function
REC Record
TELETEXT OSD
RECALL MENU
PREVIEW INFO
REW/FFWD Forward/backward in MythMusic
CAPTURE Previous playlist item in MythMusic
RECORDLIST Next playlist item in MythMusic

STEP 5 – Configure MPlayer
The final step is to configure the mapping between the remote and the commands in MPlayer. Since MPlayer is a separate program, it needs to be configured separately to MythTV. To configure it, we need another lircrc file but this time is has to be called /home/mythtv/.lircrc. Download it from here:

lircrc-mplayer

Rename it to .lircrc and put it in /home/mythtv and that should be that! Here are the key mappings for MPlayer:

Key Function
MUTE Mute
VOL+/- Adjust volume
CH+/- Skip fwd/back 60 seconds
REW/FFWD Skip fwd/back 10 seconds
PREVIEW Show/hide subtitles
TELETEXT Show/hide OSD
TAB Cycle through audio tracks

If you do not like the key mappings I have chosen, you may edit the lircrc files. The format should be fairly easy to follow.


28 August 2007

NetGear WG311v2 Wireless LAN and Ubuntu Feisty

Filed under: Nerd Notes — adam @ 1:44 pm

I wrote a while back on getting my ACX based wireless LAN card working in Ubuntu version 6.06. Now I have upgraded my machine and find that it is a bit different getting it to work under Ubuntu 7.04 (A.K.A. “Feisty Fawn”).

Essentially, the built-in ACX100 driver now correctly loads the firmware so you don’t need to fiddle with its parameters any more.

However, Fiesty introduces a new tool called “Network Manager” which does not get along with this driver. Network manager is installed by default so the first thing we need to do is get rid of it:

sudo dpkg -P network-manager network-manager-gnome

Then the card can be configured by editing the interfaces file:

sudo gedit /etc/network/interfaces

Here is my file. WEP keys have been changed to protect the innocent.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# Wireless network
auto wlan0
iface wlan0 inet dhcp
        wireless-mode Managed
        wireless-essid MyNetwork # Replace with the name of your wireless network.
        wireless-key 23BA7823B4  # Replace with your own key or omit if not using WEP.

Then reboot and you should be good to go!

One more thing before I finish. Be aware that although this card supports WEP authentication, it does not support WPA so make sure your wireless router is not set to WPA.

 Update

I have just replaced this card with a TP-Link one. It is sooo much faster and more reliable than the NetGear card. Read my article on setting up the TP-Link.


21 July 2007

Concatenating AVI files

Filed under: Nerd Notes — adam @ 6:10 pm

Here’s a small but useful shell script to concatenate any number of AVI files. It works great on Ubuntu and should also work on other UNIX-based systems as long as you have mencoder installed.

To use it, just put the name of each file on the command line in order and they will be all joined together into one big file called joined.avi

#!/bin/sh

# catavi - Script to concatenate multiple AVI files.
# by Adam Pierce http://www.doctort.org/adam
#
# Note: The AVI files must be of the same format (eg. same codec, frame size etc).
#
# This script is freeware. You can use it, copy it, change it, whatever.

TEMPFILE=/tmp/avitmp

cat "$@" > $TEMPFILE

mencoder -forceidx -oac copy -ovc copy $TEMPFILE -o joined.avi

rm $TEMPFILE

Usage example:

./catavi movie-part1.avi movie-part2.avi


18 July 2007

NCURSES Weirdness on Linux Console

Filed under: Nerd Notes — adam @ 5:15 pm

I’ve been writing an application using ncurses under Linux. Everything was going fine until I tried to run it on the Linux console (all my testing had been in an xterm). Suddenly all my borders and fields were all over the place and stuff was not being rendered correctly.

After a lot of research, I found that there are some problems with the Linux TERM settings. To cut a long story short, there is a real simple fix. you just need to print a certain magic escape code and the problem goes away.

So as the first line of my program, I put this:

cout << "\\033c";

In C, that would be:

printf("\\033c");

You can even do it from a script:

echo -ne "\\033c"

It took a lot of Googling to figure that out. I'm not sure exactly why it works but there you go.

For the record, I am using Debian "stable" with kernel 2.6.18.


13 June 2007

Tunneling rdesktop via SSH

Filed under: Nerd Notes — adam @ 5:08 pm

Tunnel.pngI have a Linux (Debian Etch) server which I am maintaining for a customer up in Queensland. A couple of Windows servers have been added to the network and I want to maintain them also.

I have an existing connection to the Linux server via SSH. There is a hole in the customer’s firewall to allow me to connect to it via SSH but not with any other protocol.

Here is how I can connect through my SSH connection to the Windows machine and remotely operate it on my local Linux PC.


1. On the Linux server, edit the file /etc/ssh/sshd_config and add the following line:

    PermitTunnel yes

Don’t forget to restart the SSH daemon on the server after this (I just rebooted it).

2. Install some basic X11 packages and rdesktop onto the Linux server:

apt-get install xbase-clients xterm rdesktop

3. On your local Linux machine, edit the file /etc/ssh/ssh_config and add the following line:

    Tunnel yes

You can now log in to the Linux server using the following command. Let’s say for example, the Linux server is tux.customer.net

ssh -X root@tux.customer.net

Finally bounce across to the Windows box like so. Let’s say the Windows box is called bill.customer.net

rdesktop -u Administrator bill.customer.net

You could even do it in one step like this:

ssh -X root@tux.customer.net "rdesktop -u Administrator bill.customer.net"

15 April 2007

ARM Flash Memory

Filed under: Nerd Notes — adam @ 10:45 pm

This post describes how to store data in the flash memory of the AT91SAM7S256 microprocessor. I wrote it because I could not find a straight-forward description on the net and also because I am bored and have nothing much else to write about today.

The Flash memory is mapped into the chip’s address space from address 0×00100000 to 0x0013FFFF. To read it, you can simply read bytes from that area of memory.

Writing to the flash is a little more complex of course. Firstly you need to set up the flash write cycle timer. This needs to be initialized with the number of CPU clock cycles required to cause a 1.5 microsecond delay. On my Olimex board with an 18.432MHz oscillator, that number works out to be 27.648 – I round it up to 28. The following line of code calculates the correct value based on the clock frequency (MCK) and programs that into the ARM memory controller.

mc->MC_FMR = AT91C_MC_FWS_1FWS | (1 + (((MCK * 15) / 10000000)) << 16);

Once that is done, we are ready to write. The chip writes one page at a time. The page size for this particular chip is 256 bytes. So that means a 256 byte section of Flash memory will be erased and completely overwritten.

Overwritten by what though? Well, you need to write your data to the section of memory where it is to be stored. You must keep your writes within the 256 byte page and you must only use 32 bit writes according to the official Atmel documentation.

Once you have written your data, it goes into an invisible RAM buffer and can then be transferred to the Flash memory by writing to the command register like so:

mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | (page << 8 );

That will begin the write process. It will take some time (up to 6 milliseconds!) and you will not be able to read the data or write to any other Flash page until it is complete. You can detect when the write is complete by monitoring the FRDY bit in the status register.

The value AT91C_MC_WRITE_KEY is 0x5A000000. This is a magic number which is required for the chip to accept the flash write command (to prevent accidental overwriting I suppose).

As usual, I have prepared some example code which will compile and run on the Olimex SAM7-P256 board. Download it here:

ArmFlashTest.tar.bz2

To compile and run, type the following. You will need to have the toolchain and C library set up as described in my previous articles here and here.

tar jxvf ArmFlashTest.tar.bz2

cd FlashTest

make

./startarm

./runram

As with my last example, the program is accessed via the serial port at 9600bps. Start your terminal program (I use GtkTerm) before you run the program. You will be prompted to type in a line of text. Once you press ENTER, your text will be stored in Flash. You may now run the program again and you should see your line retrieved from the Flash.

You could use this example code to store configuration data in your own ARM-based applications. This code is free to use for any purpose.


UPDATE: Dan Ashbrook kindly pointed out that my port assignments for the second serial port are incorrect in Board.h. I have now corrected the file, you can download it here: ArmFlashTest.tar.bz2


5 April 2007

Adding a C library to the arm-gcc toolchain

Filed under: Nerd Notes — adam @ 9:04 pm

This is a sequel to my previous article Getting Started with the Olimex SAM7-P256. Flashing lights are all very well but I want to add a C library so I can use functions like printf().

There is a streamlined version of the standard C library available for embedded systems called newlib which you can download from the files section at http://www.gnuarm.com/. Here’s how you build it to fit in with the toolchain in my previous article:

First you need to have makeinfo. On Ubuntu, install it like this:

sudo apt-get install texinfo

Now we can build and install the library:

tar xzvf newlib-1.14.0.tar.gz

mkdir build-newlib

cd build-newlib

../newlib-1.14.0/configure --target=arm-elf --prefix=/usr/local/arm7

sudo make all install info

Documentation for newlib can be found at http://sourceware.org/newlib/.

Now we have a C library, how about writing Hello World! That was not as easy as it sounds, mainly because I wanted printf() to send its output to the serial port. It took me a lot of documentation-reading and hair-pulling to work out how to do that.

To redirect STDOUT, you need to override the syscalls.o module which is part of libc. Copy the syscalls.c and swi.h files from the newlib source into your project directory and modify the _write() function to send its data to the serial port.

I’ve got some example code to demonstrate this. You can download it by clicking the link here:

ArmHelloWorld.tar.bz2

I’ve tried to keep the code as simple and readable as possible. I’ve also included a couple of shell scripts to make it easier to download and run the code. Here is how you would compile and run it:

tar jxvf ArmHelloWorld.tar.bz2

cd HelloWorld

make

./startarm

Next you need to connect a serial cable and start up a serial terminal on your PC at 9600,n,8,1. Once that is running, launch the example code by typing this:

./runram

If all goes well, you should see “Hello World.” appear on your serial terminal.

If not, well then happy debugging !


UPDATE: Dan Ashbrook kindly pointed out that my port assignments for the 2nd serial port are incorrect in Board.h. I have now corrected the file, you can download it here: ArmHelloWorld.tar.bz2

UPDATE: I recently tried to do this on Ubuntu 8.04 and it didn’t work until I applied this patch to the newlib configure script.


« Previous PageNext Page »

Powered by WordPress