Connecting a Color lcd (MI0283QT-2) to the raspberry pi.

I started to look at the SPI interface of the raspberry pi for only one purpose, to be able to to use it as a control panel for some hacking project.
I had a LCD Screen laying around that I bought at watterrott so I decided to connect it to my raspberry pi.

MI0283QT-2

The MI0283QT-2 module is a nice 2.8” Color LCD with a resolution of 320×240 controlled by a hx8347 controller and a touchscreen based on the ADS7846 controller.
Since the spi interface is 3.3 – 5 V tolerant, it is directly compatible with the raspberry pi, cool.

Connection to the raspberry-pi

C++ Library

The guy from watteroot is providing an ardurino library for controlling the LCD. I decided to start from it to quicly have some working code.
In fact, it was not so easy to implemented since I have barly no experience in C/C++ and the spidev was a huge mystery at that time.
Hopefully, I managed to make it working, and here is the result of my work. The code is available from github.
At this time only the LCD library is implemented, I will work on the touch screen library as soon as this come as a priority to me
As usual feel free to check the code, and use as you wish. You will quickly see it is really a quick port.

Tips :

  • You need a kernel with a SPI library. I only tested on Chris boot kernel
  • For performance reason, some functions are sending quite big SPI command. Make sure to load the spidev with a buffer big enough.
    modprobe spidev bufsiz=256000
    

Finding that I need that parameter was not easy, the only symptom was that all screen was not clearing. After couple of hours I noticed that only function which was sending less that 4096 bytes were working.

The library does not directly support to set the led light level. However if you connect the led pin to the GPIO18 you can control it using the WiringPI gpio tools.

gpio -g mode 18 pwm
gpio -g pwm 18 100
gpio -g pwm 18 300
gpio -g pwm 18 500
gpio -g pwm 18 1000

Building instructions

git clone https://github.com/dgallot/MI0283QT2-pi
cd MI0283QT2-pi/demo
gcc -lstdc++ -iquote ../MI0283QT2 BMPDemo.cpp ../MI0283QT2/MI0283QT2.cpp ../MI0283QT2/font*.c -o BMPDemo
gcc -lstdc++ -iquote ../MI0283QT2 demo1.cpp  ../MI0283QT2/MI0283QT2.cpp ../MI0283QT2/font*.c -o demo1
gcc -lstdc++ -iquote ../MI0283QT2 gameoflife.cpp  ../MI0283QT2/MI0283QT2.cpp ../MI0283QT2/font*.c -o gameoflife

In actions

Wirings

Demo of the lib functionalities

Game of life

What next

For the moment I am trying to implements a framebufffer driver for this device. This will allows any king of gui application to work on this lcd, including the console at the boot time.
The current status is that I am able to clear the sceen. I have to admit that it is not easy task, mainly because I am lacking of C experiences, linux kernel development experiences and I do not know the kernel SPI interfaces at well. But that really challanging job.


Edit 15 March 2013
The information in this blog entry is rather oudated.
Here some informations about using a framebuffer based on my code, with support for the touch screen. MI0283QT2-pi Github project of Dronus
The model of LCD sold by Watteroot changed, and it is not compatible anymore with this code.
On the lallafa blog, you can find the appropirate frame buffer for this new LCD Watterott MI0283QT-9A Display for the Rasbperry Pi.
You can also find a true framebuffer for the old version of LCD on the same blog Watterott Display on Raspberry Pi

Raspberry pi and i2c. Connecting a 24Cxx eeprom.

If you followed my previous blog entry, you have a nice raspberry pi system with support for i2c.

Now it is time to test if the i2c bus and the driver is working.
Let’s try to connect a i2c eeprom to the raspberry, since it is the only i2c device that I have in my drawer.

This code has been tested with a 24C16. It will probably work with smaller one, and bigger with code changes ( page size, and page number )

Connect the device

Easy, just connect the 3,3v, the gnd, the SCL and the SDA pins.


Load the i2c driver

modprob i2c-dev

You can also add the line i2c-dev to the /dev/modules file

Detecting the device.

root@raspberrypi:~# i2cdetect -y -a 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

Reading the eeprom

For testing the reading I am using a test program from i2ctools

root# wget http://www.lm-sensors.org/browser/i2c-tools/trunk/eepromer/eeprom.c?format=txt
root# gcc –o eeprom eeprom.c
root# ./eeprom –r –f data
base-address of eeproms       : 0x50
number of pages to read       : 8 (0x50 .. 0x57)
file opened for writing       : d
            on filedescriptor : 3
i2c-devicenode is             : /dev/i2c-0
            on filedescriptor : 4

Read 16 bytes from eeprom at 0x50, offset 00000000
...
Read 16 bytes from eeprom at 0x57, offset 000000f0

The program should work out of the box, and the content of the eeprom must be save into data.
If you are using a 24C16 the file should be 2048 bytes length.

Writing the eeprom.

The program provided by lmsensor seems to be bugged, basically when it write to the eeprom, we must way until the content has been written before continuing.
This is well documented in the datasheet (http://www.bookly.com/images/24C64-BM.pdf ) as Acknowledge (ACK) Polling
Is it a bug in the driver, or in the application level ?
Anyway, I find a solution, I simply reposition the eeprom read-pointer until it succeded.
If you have a more elegant solution, I will be glad to hear about it.

root# wget https://raw.github.com/dgallot/i2c-tools/master/eepromer/eeprom.c
root# gcc –o eeprom eeprom.c
root# ./eeprom -f data -w
base-address of eeproms       : 0x50
number of pages to read       : 8 (0x50 .. 0x57)
file opened for reading       : data
            on filedescriptor : 3
i2c-devicenode is             : /dev/i2c-0
            on filedescriptor : 4

**WARNING**
 - 	You have chosen to WRITE to this eeprom.
	Make sure that this tiny chip is *NOT* vital to the
	operation of your computer as you can easily corrupt
	the configuration memory of your SDRAM-memory-module,
	your IBM ThinkPad or whatnot...! Fixing these errors can be
	a time-consuming and very costly process!

Things to consider:
 - 	You can have more than one i2c-bus, check in /proc/bus/i2c
	and specify the correct one with -d
	right now you have chosen to use '/dev/i2c-0'
 - 	A eeprom can occupy several i2c-addresses (one per page)
	so please make sure that there is no vital eeprom in your computer
	sitting at addresses between 0x50 and 0x57
Enter 'yes' to continue:yes

Wrote 16 bytes to eeprom at 0x50, offset 00000000
... acked 
Wrote 16 bytes to eeprom at 0x50, offset 00000010
..... acked 
Wrote 16 bytes to eeprom at 0x50, offset 00000020
...... acked 
Wrote 16 bytes to eeprom at 0x50, offset 00000030
...... acked 
Wrote 16 bytes to eeprom at 0x57, offset 000000f0
....... acked 

Credits:

http://elinux.org/RPi_Low-level_peripherals
http://www.lm-sensors.org/browser/i2c-tools/trunk/eepromer/eeprom.c

Building a new kernel for the raspberry pi, including support for i2c, spi and working version of the driver rtl8192cu.

This guide will show you the entire step that I had to do in order to produce my custom kernel. I wanted to have the latest kernel of Chris boot, which include support for spi and i2c, but I also need to include the latest realtek driver for my wifi dongle.

The Chris Boot’s website contains a lot of information, but it does not contains this information required to build his kernel from scratch by real beginner. I will try to fill the gap.

Prerequisits

First install Ubuntu 12.04 LTS

Since I have a mac, I installed it on Parallels and it is working like a charm.

install the cross compiler and the dev tools

sudo apt-get install git-core gcc-4.6-arm-linux-gnueabi
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-4.6 /usr/bin/arm-linux-gnueabi-gcc
sudo apt-get install git-core gcc-4.6-arm-linux-gnueabi

Build the kernel

Download the source code

cd
mkdir rpi-3.2.20
cd rpi-3.2.20
git clone https://github.com/raspberrypi/firmware
git clone -b rpi-3.2.20 https://github.com/bootc/linux.git

Download the realtek driver RTL819xCU, and copy it ro the rpi-3.2.20 directory

Copy the default config from the previous kernel.

There are several way of doing that, you can start simply download the Chris Boot images, and install his latest kernel.
The config is located in /boot/config-3.2.20-rpi1+, or you can simply download it from my site config-3.2.20-rpi1+
Copy this to your ubuntu system as .config

cd ~/rpi-3.2.20/linux
wget http://www.gallot.be/resources/config-3.2.20-rpi1+
cp config-3.2.20-rpi1+ .config

Change the kernel name, so it will not conflict with any other one.

Edit the Makefile and change the first line from :

EXTRAVERSION =
To :
EXTRAVERSION=-spi-i2c-rpi1

Import the config and disable the old rlt8192 module

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig

Open the following menu :
Device Drivers
Network device support
Wireless LAN
And unselect the driver by typing [space]
Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter
Hit [Tab] to select exit multiple time, and save the configuration.

Build the kernel.

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k -j5

Prepare the file to be copied to the system.

mkdir -p ~/rpi-3.2.20/install/boot
make ARCH=arm INSTALL_MOD_PATH=~/rpi-3.2.20/install CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- modules_install
make INSTALL_PATH=~/rpi-3.2.20/install/boot ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- INSTALLKERNEL=none install

Build the 8192cu kernel driver.

Copy and unpack the driver.

cd ~/rpi-3.2.20
wget http://www.gallot.be/resources/RTL819xCU_USB_linux_v3.4.2_3727.20120404.zip
unzip RTL819xCU_USB_linux_v3.4.2_3727.20120404.zip
cd RTL8188C_8192C_8192D_USB_linux_v3.4.2_3727.20120404/driver
tar -xvzf rtl8188C_8192C_8192D_usb_linux_v3.4.2_3727.20120404.tar.gz

Build the 8192cu kernel driver.

cd ~/rpi-3.2.20/RTL8188C_8192C_8192D_USB_linux_v3.4.2_3727.20120404/driver/rtl8188C_8192C_8192D_usb_linux_v3.4.2_3727.20120404
make KSRC=~/rpi-3.2.20/linux ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k -j5

Copy the 8192cu to the modules tree.

cp 8192cu.ko ~/rpi-3.2.20/install/lib/modules/3.2.20-spi-i2c-rpi1+/kernel/drivers/net/wireless

Install the new kernel

Now you simply need to install the new files to you sd card.
Plug you sd card, and if you are working from a virtual machine connect the sd card reader to the ubuntu vm.
The boot partition will be the fat partition, on my system it is mount into /media/00D7-4C15
The system partition is the ext2 partition, on my system it is mount into /media/1bee6d88-1731-433f-8f74-49a7c1ce1035

df -T
/dev/sdb1      vfat        102182   41764     60418  41% /media/00D7-4C15
/dev/sdb2      ext4       1824112 1054740    677980  61% /media/1bee6d88-1731-433f-8f74-49a7c1ce1035

Copy the new firmware

cp ~/rpi-3.2.20/firmware/boot/* /media/00D7-4C15

Copy the kernel and the modules

I really do not know if it is required to install the kernel in the boot partition and in the system partition ( in the /boot ).
But since it does not harm, I copy it on both location.

cp ~/rpi-3.2.20/install/boot/* /media/00D7-4C15
cp ~/rpi-3.2.20/install/boot/* /media/1bee6d88-1731-433f-8f74-49a7c1ce1035/boot
cp -R ~/rpi-3.2.20/install/lib/modules/* /media/1bee6d88-1731-433f-8f74-49a7c1ce1035/lib/modules

Activate the kernel

The latest firmware is not able to directly start the linux image, you do not need to create a disk image anymore.
So to activate it, simply override the kernel.img file with the new kernel.

cp /media/00D7-4C15/vmlinux-3.2.20-spi-i2c-rpi1+ /media/00D7-4C15/kernel.img

Final step

The only remaining step required to start you raspberry pi, and connect a keybord and a screen to it !

And issue a simple depmod command and reboot.

depmod -a
Reboot

I delibered choosed to not merge the RTL819x driver to the kernel source tree.
Doing so slighly complicate the process, but if you want to do it check the website of lumux which explain how to do it.
If you do so, this step is not required :)

The next article will explain how to modify this image make it usable without a keyboard by doing

  • Run the depmod -a on the first boot
  • Do an offline configuration of the wifi
  • Unattented installation of the required package like ssh

Credits:

http://blog.kmp.or.at/2012/05/build-your-own-raspberry-pi-image/
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=28&t=7585
http://www.bootc.net/archives/2012/05/11/updated-raspberry-pi-wheezy-image/
http://www.bootc.net/projects/raspberry-pi-kernel/
http://lumux.co.uk/2012/06/07/realtek-rtl8192curtl8192c-wifi-on-raspberrypi/
http://elinux.org/RPi_Kernel_Compilation

Ovh mcloud soap api. Utilitaire ligne de commande.

Voici mon utilitaire pour dialoguer avec les API Soap du mini cloud.

Mais ca sert à quoi ?

  • Ca permet d’interagir afin de démarrer les instances via la ligne de commande, plutôt que via le manager.
  • on peut facilement avoir les infos sur l’instance, son IP
  • L’utilitaire est facilement interfaçable dans les scripts.

Installation

>apt-get install libsoap-lite-perl

Et accepter toutes les dépendances.
Il suffit après de copier le fichier ovh.pm et ovh.pl dans n’importe quel répertoire.

>wget http://svn.gallot.be/blog/ovh-cloud-api/ovh.pm
>wget http://svn.gallot.be/blog/ovh-cloud-api/ovh.pl
>chmod a+x ovh.pl

Une petite vérification des fichiers n’est pas superflue.

>md5sum ovh.pl ovh.pm
62bdf222e4bffc594afd694615072619  ovh.pl
243f87546259223f7490f8b40870e548  ovh.pm

Utilisation

Lister les projets

>ovh.pl –u username –p password –a listservice

Lister les vms du projet ‘AppScale’

ovj.pl –u username –p password –a listvm –s AppScale

Démarrer une vm

ovj.pl –u username –p password –a startvm –m vm-01

Arrêter une vm

ovj.pl –u username –p password –a stopvm –m vm-01

Rebooter une vm

ovj.pl –u username –p password –a rebootvm –m vm-01

Voici quelques exemples d’utilisation

Shutdown amélioré.

http://svn.gallot.be/blog/ovh-cloud-api/shutdown.sh

Ce script, détecte l’ip de l’hôte. Recherche le nom de la vm dans le cloud et arrête la vm ! Il faut bien entendu mettre les bons paramètres pour username et password.

#!/bin/sh
USERNAME=$1
PASSWORD=$2
MYIP=`ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'`
VMNAME=`./ovh.pl -u $USERNAME -p $PASSWORD -q -a listvm | grep $MYIP | awk '{ print $1}'`
./ovh.pl -u $USERNAME -p $PASSWORD -a stopvm -m $VMNAME

Démarrer tous les vm d’un projet

http://svn.gallot.be/blog/ovh-cloud-api/startall.sh

#!/bin/sh
USERNAME=$1
PASSWORD=$2
PROJECT=$3
./ovh.pl -u $USERNAME -p $PASSWORD -q -a listvm –s $PROJECT | grep stopped | awk '{ print $1}' | while read vm ; do
  echo Starting $vm
  ./ovh.pl -u $USERNAME -p $PASSWORD -a startvm -m $vm
done

Arrêter tous les vm d’un projet

http://svn.gallot.be/blog/ovh-cloud-api/stopall.sh

#!/bin/sh
USERNAME=$1
PASSWORD=$2
PROJECT=$3
./ovh.pl -u $USERNAME -p $PASSWORD -q -a listvm –s $PROJECT | grep running | awk '{ print $1}' | while read vm ; do
  echo Stopping $vm
  ./ovh.pl -u $USERNAME -p $PASSWORD -a stopvm -m $vm
done

Forcing garbage collection.

First, why do you want to force the garbage collection? According to me, you probably never need to do it !
So we should never do it, but then, why do I implement it ?  Well, in my case , it makes sense :)
Ok, the title of the article is misleading you. I am not really able to force the garbage collection, but I am able to detect when the garbage collection works.
At work, we are developing an application server. It allows to dynamically add applications, and of course also allows to uninstall it, more or less as any other application server.
But even for this, you do not need to force the garbage collection; yes and no.
The problems come when you are installing code requiring some JNI libraries.
JNI implementation has some limitations that makes the loaded DLL highly linked with the current Class Loader.

It means that if you do the following steps :

  • Deploy an application which uses a dll
  • Undeploy this application
  • And deploy it again

You will get a UnsatisfiedLinkError with the message : Native Library already loaded in another classloader.
This is weird (IMHO) ! Once a DLL has been loaded, you cannot load it until the ClassLoader object has been reclaimed by the garbage collection.
Let’s check the JVM code to see how it is working.

First when you load a library, the loadLibrary code checks if the dll is not already loaded.
Let’s check the code of java.lang.ClassLoader.loadLibrary code.

private static boolean loadLibrary0(Class fromClass, final File file) {
  …
  synchronized (loadedLibraryNames) {
    if (loadedLibraryNames.contains(name)) {
      throw new UnsatisfiedLinkError ("Native Library " +
      name + " already loaded in another classloader");
    };
  …
}

As you can see, it is checking the list of loaded libraries, if the library is already associated with an otherclassloader. If it is, the load will fail.
Only when the ClassLoader.finalize is called, you will be able to load the library again.

protected void finalize() {
  ...
  for (int i = 0; i < size; i++) {
    if (name.equals(loadedLibraryNames.elementAt(i))) {
    loadedLibraryNames.removeElementAt(i);
    break;
  }
  ...
}

Then, how can we force the garbage collection to allow the finalized to be run, or at least how do we know when the class loader has been completely finalized.

During my experiments, I try just to call the method “System.gc”
It does work, but it is unpredictable. I sometimes need to call it twice, or even more. It is really not easy to be sure that the garbage collection has been executed.
I therefore developed this small piece of code:

    public static void waitGc( long timeout ) {
    	final boolean[] wait = new boolean[1];
    	
    	@SuppressWarnings("unused")
    	// create a small graph of object
        Object graph = new Object() {
    	    private Object leaf = new Object() {
	    	    protected void finalize() throws Throwable {
	    	    	synchronized( wait ) {
	    	    		logger.finest("leaf finalize called");
	    	    		wait[0] = true;
	    	    		wait.notify();
	    	    	}
	    	    }
    		};
    	    protected void finalize() throws Throwable {
    	    	logger.finest("graph finalize called");
    	    }
    	};
    	long start = System.currentTimeMillis();
    	graph = null;
    	while ( System.currentTimeMillis() < start + timeout ) {
    		// defer a little bit the gc
    		try {
    			if ( wait[0] ) {
    				logger.finest("finalize Called on object graph, gc has been executed");
    				break;
    			}
			System.gc();
			System.runFinalization(); 
			logger.finest("finalize not (yet) called");
    			synchronized( wait ) {
				wait.wait(timeout / 10);
    			}
		} catch (InterruptedException e) {
			// do not care 
		}
    	}
    }

The code is not really easy to understand. Here is how it works.
First I create an object graph, two objects which hold a reference to another object.
These objects have been singly modified to notify when the object are finalized.
The rest of the code is a simple loop, which runs System.gc and System.runFinization until it receives the notification that the object graph has been finalized.
For more security, the code does not wait indefinitely, but only for a predefined time.

Inside the container we do two things:

  • When a application is undeployed, we check if it has loaded some dynamic library
  • If not, we just undeploy it. If yes, we wait until the ClassLoader has been finalized using the same technique than above.

Even if the System.gc does nothing, we will be notified that the ClassLoader is not yet finalized, and return to the user a message stating that the component has been undeployed. But for some reasons, which will probably a memory leak on the application, the loaded dynamic library is not released yet.

Do not forget that there are some jvm options which disable the System.gc() calls.

-XX:-DisableExplicitGCDisable calls to System.gc(), JVM still performs garbage collection when necessary.

In a next article
I will explain  how to dig into the native library info, which is not available by any public way.  In that purpose, I will use a class that you probably do not know, sun.misc.Unsafe the modern java peek and poke library!