[p900] some "direct" programming...

  • From: Alfonso Martone <a.martone@xxxxxxxxxxx>
  • To: p900@xxxxxxxxxxxxx
  • Date: Thu, 27 May 2004 13:43:29 +0200

I wrote this "direct screen" software to understand some internals of=20
the P900 in order to write software like The Old Dos Times, when Men=20
were Men and wrote directly in the VGA screen memory. Remember, the VGA=20
mode 320=D7200=D7256 was an array of 64000 bytes (one for each pixel, thus=
=20
having up to 256 different color) located at absolute address 0xa0000.=20
You just needed a pointer to screen memory to do anything.=20

The P900 has a 208=D7320=D765536 screen; this means that its screen memory=
=20
area is a 133120 bytes buffer: two bytes per pixel, and 208=D7320=3D66560=20
total pixels. The two bytes are mapped "RGB 5-6-5": that is, the lowest=20
5 bits are the 32 "red" levels, the following 6 bits are the 64 "green"=20
levels, and the high 5 bits are "blue" (remember, the P800 had "RGB=20
4-4-4", that is only 4096 colors).=20

This means that to convert a canonical "24 bit" color to a "16 bit" you=20
just have to rebuild the pixel clearing unused bits: take the 5 most=20
significant bits of the red component, the 6 most significant of the=20
green, and the 5 from the blue, and "join" together. Since the type=20
unsigned short is recognized as 16-bit unsigned type by the gcc=20
compiler, I just defined the type PIXEL (I could have done a typedef=20
instead, but in this page I want to keep things as simple as possible):
 #define PIXEL unsigned short=20

To get the screen array address mapped as a pointer, one has to use the=20
Symbian's undocumented TScreenInfoV01 structure. I found some=20
information around the net and in some free sources:
 PIXEL *scr;
 TPckgBuf<TScreenInfoV01> i;
 UserSvr::ScreenInfo(i);
 scr=3D(PIXEL*)(i().iScreenAddress);=20

After doing this, the scr pointer can be used to access directly P900=20
screen memory in the fastest possible way, even faster than the "direct=20
screen drawing functions" of the Symbian graphics library.=20

=46irst example. Given a backingstore array of 66560 PIXELs, you can copy=20
it to the screen just copying its contents:
 Mem::Copy(scr, backingstore, 320*208*2)=20

Second example. Read a pixel value and copy it onto another pixel:
 scr[147+208*15]=3Dscr[55+208*312];

The scr[55+208*312] is a reference to a 16-bit memory value (which type=20
we defined as PIXEL); in our case, it's the pixel located at=20
coordinates (x=3D55,y=3D312) (remember, x range from 0 to 207 and y range=20
from 0 to 319; the screen is 320 rows of 208 pixels each).=20

Remember that the Symbian's window manager thinks it has the exclusive=20
use of the screen memory, requiring any graphical widget to have a=20
redraw function... Then you would like to size your application window=20
accordingly: ignore the initial window size passed to the .APP=20
application program, and size it out to the entire screen. You will=20
still write in the screen area (instead of supporting window-based=20
writes via the operating system functions); every window redraw will=20
wipe out your screen contents (oh, now we don't care about it; we will=20
use the official system functions for direct screen drawing only to get=20
informed about when the Symbian window manager is going to "touch" our=20
screen).=20

This said, you have a stunningly fast memory-mapped screen device (you=20
won't be that stupid to write out of those 133120 bytes bounds), which=20
will make you laugh at the weirdly slow Symbian window management (you=20
need to know that all strange methods and flaws come up because, by=20
design issue, the Symbian/UIQ system development kit must allow the=20
programmer to compile and debug in a Windows box the program).=20

Now, let's take the control over the screen tapping. Just add the=20
function HandlePointerEventL to your CCoeControl-based window. You will=20
get the function called every time the user taps the screen (for "drag"=20
support there is some extra work to do, which is not discussed here - I
am still trying to get them in a clean manner).=20

Now we have everything needed to write a minimal user application. But=20
searching the Symbian-related sites I found some little interesting=20
add-ons.=20

=46irst, my P900 has the flip. Every time I open or close the flip, the=20
"screen size" changes (208=D7208 while the flip is "closed" and 208=D7320=20
while the flip is opened or absent; notice that in 208=D7208 mode, you=20
still can write in the "user invisible" screen memory). I chose to use=20
the "close flip" event to close this test application, because when I=20
close the flip, almost always it's because I am putting the P900 in the=20
gunnysack :-)=20

I just had to ask for screen change events to the operating system, in=20
the construction of the CQikAppUi-derived object:
 RWindowGroup& rwg=3DiCoeEnv->RootWin();
 rwg.EnableScreenChangeEvents();
 rwg.AutoForeground(ETrue);=20

and then place in the HandleScreenDeviceChanged function this code:
 CWsScreenDevice& s=3D*(iCoeEnv->ScreenDevice());
 if(s.CurrentScreenMode()!=3D0) Exit(); // if closed flip then exit app

Second, the application keys. I simply like too much rolling the=20
jog-dial while tapping on the screen. I think of the jog-dial press-out=20
and press-in as the equivalent "Esc" and "Space" keys of my PC, while=20
the jog-dial press-into as the equivalent of "Enter"; I named "Net" the=20
browser button, "Cam" the Communicorder button and "Power" the power=20
button.=20

While constructing the CQikAppUi-derived object, you just have to=20
"capture" those keys with something like:
 cap[0]=3DiEikonEnv->RootWin().CaptureKey(NET,0,0,1);=20

(I have defined NET as EStdKeyApplication0 and SPACE as EStdKeyDeviceD=20
because I don't want weird and floating definitions around...)=20

Now, how to use this stuff: the sample application writes a black pixel=20
in the point "tapped" by the pen (yeah! you may find that it's time to=20
recalibrate the screen, go search for this in the P900's control=20
panel!). You may even write an event collector routine, and then=20
program the P900 the same way you would program in X11 under Linux! :-)=20

Last bug that I'm still fighting: don't let the Communicorder
application start after pressing of the camera key.


The full source is here:
http://www.alfonsomartone.itb.it/directvideo.tar.bz2

alf


Other related posts:

  • » [p900] some "direct" programming...