main index FIRST OF ALL, did you read all of my P900 notes?

Below, I comment this sample Sony Ericsson P900 application source that features direct-screen writing and P900 keys reading. The "direct screen" application sources are available in the P900 download page.

About IMEI numbers...

The IMEI coding for cellular phones manufactured up to April 1st 2004 was: cc-fac-tac-sn-cd where cc is the country code (two digits), fac is the final assembly code (four digits, identifying the manufacturer), sn is the serial number (six digits), and the last digit cd is a check-digit. The P900 shows two extra check digits ("-01") after the IMEI code, but we do not need to care about them.
After that date, the IMEI format has changed to tac-sn-cd where the first eight digits tac are the type allocation code, then the serial number and check digit follow as before. The P900 and P800 use the first scheme; the latest P900 and all the P910i use the latter.

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

The P900 has a 208×320×65536 screen; this means that its screen memory area is a 133120 bytes buffer (notice that 133120 is exactly 130 kilobytes): two bytes per pixel, and 208×320=66560 total pixels. The two bytes are mapped "RGB 5-6-5": that is, the highest 5 bits are the 32 "red" levels, the following 6 bits are the 64 "green" levels, and the lowest 5 bits are "blue", for a total of 65536 RGB combinations (remember, the P800 had "RGB 4-4-4", that is only 4096 different colors, still mapped in a word of two bytes).

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

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

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

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

Second example. Read a pixel value and copy it onto another pixel:

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

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

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

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

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

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

I just had to ask for screen change events to the operating system, in the construction of the CQikAppUi-derived object:
RWindowGroup& rwg=iCoeEnv->RootWin();

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

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

While constructing the CQikAppUi-derived object, you just have to "capture" those keys with something like:

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

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

I actually DID it, but I am still working on.

A bug that I'm still fighting in this example page: don't let the Communicorder application start after pressing of the camera key.

Er... did you try my OverScan software? And my TimeTables software? And the other P900 software downloads?

The ECam library has a bug: image capturing often fails...!

I tried to use the ECam API on my P900 to capture images. My original program always failed to capture images, both in 64K and in 16M colors bitmap modes in any of the three supported resolutions (VGA:640×480, QVGA:320×240, QQVGA:160×120).

Also, while the ECam API documentation and even the TCameraInfo library resource report that contrast is supported, any call to SetContrastL will fail (even using EContrastAuto), giving out a "Not Supported" error window.

To be 100% sure I tried the TestCameraApp program. I compiled it and installed it on my P900, but found that the menu option "Capture Image" fails to capture (I found later in the source a comment saying that "capture via drop down menu will fail on target but works on the emulator"... but it wasn't explained why!! SHAME ON YOU, SonyEricsson guys!).

But here the TestCameraApp fails to capture images also with the camera button. It was able to capture images only sometimes, when I activated the program's viewfinder. It seems that capturing worked only on half the times I pressed the camera button.

This actually seems an application bug. Anyways, I am not that happy with the need of having the viewfinder active to shoot a photo! (this is a SonyEricsson ecam library bug!)

I recently did a master reset of my P900; I use only English language on it, and I installed only a few third-party softwares (no camera-related softwares).

In the TestCameraApp I placed an InfoPrint() of the reported error from ImageReady() and I surprisingly found KErrInUse; my own program always reported KErrInUse (the error -14). According to the documentation, this error means that either Reserve() or PowerOn() failed, but I double-checked that this didn't happen (except when I combined things to explicitly get the Reserve() called after the CommuniCorder already reserved the camera: in this case only my Reserve() failed). No changes if I use only the Reserve() call (this seems legal because in the API description they said that "the camera is powered-on when reserving it").

Well, it seems that for some strange reason (a BUG in the ecam library?!?) image capturing doesn't work if the viewfinder is not activated. And, in my case, on half the times capturing still fails (as if the viewfinder wasn't active).

Currently I still didn't work out a viewfinder on my own program (I now want first see a correctly running TestCameraApp); after thousands of tries it still wasn't able to capture even an image (in any of the 6 supported modes, 64k or 16M colors in VGA, QVGA, QQVGA resolutions): the ImageReady() always reported NULL for CFbsBitmap pointer and HBufC8 pointer...!

Since the ECam library/API relase date (Nov'2003) there were no useful information on the net about it. I read all "camera api" related messages on the Developer/SonyEricsson forum; there was someone talking about these problems, but their development team didn't answer anything... :-(
Also, an user reported to me that the same problems apply when you try to use the camera from AppForge library calls. I do not know AppForge, I only use C++.

BIG UPDATE: I released my first C++ camera-oriented P900 software, and the weird BUGS of the ecam library were used to do some nice tricks... have a look in the P900 download page!

Asynchronous services, lots of headaches...

One of the things that I most hate of the Symbian programming is the massive use of asynchronous services.

That is, even if you want to read an image from a file you have to:

All these things make me quite angry. Oh, well, I write software in "imperative programming" since twenty years. And even on some event-driven style systems (most notably Xfree86) you have full control, without needing such a mess of startservice-wait-getanswer logic.

Symbian guidelines state that since their installed systems will have little memory and other discomforts like low batteries, then a different "programming philosophy" is required. But... while their method is "philosophically correct" (they love to call "Symbian C++" their weird programming approach), it's quite a hell for us who were born in "imperative programming" world and now find that we NEVER get some direct control without a lot of pain...

Worse, the above scheme is recursive. The "open a file" operation consists in a nested scheme like that: start a call on the file server, give control to the system, expect a callback somewhere with the error status, etc. Even such an operation is "asynchronous"! (well, the estlib.lib features a fairly useable libc-standard library, but its use is not even remotely encouraged...!)

In my humble opinion this is the main reason why the Symbian is so slow even on a good processor, the 32bit ARM/920T clocked at respectable 156MHz. When men were men, a 120MHz Intel '486 machine could do stunning things at an excellent speed (then Win95 came out and wasted every thing which you could call "resource"...).

No, don't think I'm just angry today. Think instead to those Symbian people, who implemented a huge and complex graphical object client/server class hierarchy. Hey, how many windows can you keep open on your 208×320 display? surely less than on your 1024×768 home desktop, don't you? not even comparable, eh?

Also, let me tell you that the Symbian/UIQ font server on the P900 only has two fonts. A standard font (in three sizes only, plus - rarely, at least in the standard programs - italics and bold) and a "Courier-like" font (single size) which probably you did see only in one or two console-like third-party applications...

Actually there's something more, but stays there, unused. If you try the FontShell application, you will find some little extras, but neither the Calculator nor other standard applications will ever use them...

Yep, for these TWO fonts there is a (rather complex) font server. No other fonts added, even some simple bitmapped font. And yes, it doesn't support TrueType fonts. If you want TrueType support, you would need a file only - the FREETYPE.DLL library (which Symbian distributed in a .SIS format but without any warranty/support!!!): less than 80k of diskspace (whoa! 80k?! yes, eighty tiny kilobytes!), excellent, stable since years, distributed in GPL source... oh, no, Symbian development team does like only that single MicrosoftWindows-like font! :-(

Well, this was actually done by the SMan 1.3 software, which allows to "change the system font" (provided you installed the appropriate FREETYPE.DLL and reboot the P900), even with antialiasing support.

Well, my next smartphone/PDA will be a Linux-based one. A Symbian/UIQ machine like this P900 is user-friendly (like a Linux one, anyways) but very hard to learn to write software...!

Some other hints...

Beware: as above, all things below are tested only on the P900: I cannot guarantee they are valid on other Symbian platforms.

Someone asked me about compiling OPIE on the P900.

While Symbian is an operating system capable of some decent multitasking and multithreading, it's not an Unix-style system. In the Symbian you can start some "EXE" programs (actually .EXE extension) and dynamically linkable libraries (actually .DLL and .APP and a number of other extensions). They are subject to a number of limitations, for example, allocable memory (heap) limit, stack space limit, etc, stricter than the most common Unix-style systems around. Also, "forking" and starting a new executable is very time-consuming in respect of Unix-style systems. And, final issue, you have to connect to Symbian firmware "servers" to get the most common services (sockets, reading the keyboard, etc) in an asynchronous manner.

I think that OPIE would require a huge effort to be ported on the P900, and final performance will be very low due to Symbian constraints. Most of the work will be converting Unix-style methods (for example, "open a socket", "fork this process", etc) to Symbian conventions. Opie was born for Zaurus-style machines equipped with Linux.

I am trying to set up a standard library for simplifying the most common tasks (e.g., use standard C library plus a few graphical and user I/O) to develop onto a Linux box and the recompile for P900. But this is only a compromise solution... My next smartphone will be a Linux one!

Sometimes, compiling a .APP, you get the error: ...
ERROR: Dll 'TESTPROG[00200FFF].APP' has uninitialised data.
make: *** [] Error 254

You cannot use global variables. The above error was triggered because in one of the sources there were declared some variables like:
const static TInt maxcount=253;
int count;
void MyClass::Func()

  static TInt x;  char n;

That count global variable and that x static variable are not allowed in the .APP file (the n variable is allowed because it's stack-space data).
To get variable names out of an object file (say, testprog.o), you need to use the supplied nm utility program:
/usr/local/er6/bin/arm-epoc-pe-nm --demangle --line-numbers --print-file-name --no-sort *.o | grep -v " [rRtTU] "
(all in one line!!!). Example output:
main.o:00000000 B count
main.o:00000004 b x.213

This must be read as: global variable count defined, and static variable x (which was defined on line 213 of the source file).

Latest releases of the Symbian real-time kernel (EKA2) will introduce support for DLL global writeable static data (WSD). Duh, it seems that they read this complain section of my P900 pages (but we won't see it on the P900)... :-) They always avoided to implement WSD because they said "wastage of memory" (weird, eh?), and also because the minimum allocable memory chunk (by the system, not by the user) is 4096 bytes (ouch!).

Another note about strict stack limits when allocating core memory... If you declare some "large" array like this in your function:
void func() { TInt values[16384]; // 64k local memory needed
then it will be correctly compiled, but at run-time you will get a "kernel panic 3". I did not yet investigate the maximum size of local stack (it seems anyways somewhere near 12-16 kbytes), but for every array larger than 200-300 bytes I always allocate it in the heap (for example with malloc/free standard functions) checking for out-of-memory status (the malloc function returns NULL if insufficient heap space available).

I've been told that the current default stack limit is 12 kilobytes: beware!
Also, remember to set the maximum heap space of a thread to a reasonable value. In one of my latest test programs, I need to allocate one entire megabyte of tables, so I declared 1300*1024 bytes maximum heap size for the task (remember that the Symbian .APP programs cannot have "global data" or even "initialized data"; only read-only const static data objects are allowed).

If you enclose an image larger than 20×16 pixels as application icon, then only the rightmost part will be displayed on the P900 screen.

Brain-damaged Symbian's libc... I am often unable to use the opendir/readdir functions, even in the "wide" (wchar_t) version. It seems that opendir and wopendir raise an E32User-Cbase panic 69 without a true reason.

Privacy issue (eh, eh!): if you go look into the (binary) log file C:\SYSTEM\INSTALL\INSTALL.LOG you will see the latest installing operations (even multiple consecutive applications of the same package!).

The getcwd() function, if called at the beginning of your .APP application, will answer that the current working directory is (most notably) Z:\SYSTEM\PROGRAMS\

Yes, I finally found a bug even in the libc function vsprintf (which I simply happen to love) of the UIQ 2.1 SDK libraries. The Symbian's vsprintf library function considers the italian accented "o" vowel ("ò", char 0xf2) as a string terminator (like '\0'). I did not test everything, but I suspect that other characters may show the same behaviour. Thus, invoking vsprintf with a format string containing the "ò" character, it stops outputting formatted characters before there: sigh!!! 15 years of vsprintf in a number of different operating systems and C/C++ compilers, and finally I have to write a format-string cleaner/wrapper to get it again in my Symbian C++ code...

The RApaLsSession bug...
SonyEricsson/Developer site published in March 2003 (and updated at least in June 2004) a page about "how to start a specified page in the P800/P900 browser". Sadly, the given example (which uses an RApaLsSession session) gives out a weird "Corrupt" error without starting the browser. If you do not specify an URL or filename, the browser still does not start (the given application UID 0x100066de is associated to the correct browser viewer DLL on the Z: drive).

It's highly annoying the waste of hours in tracking Symbian bugs and Symbian documentation bugs. I spent some hours tracking this bug and trying to get a work-around for it because I saw a third-party application which was able to correctly launch the internal browser. No one of the called functions gives out an error, and it does run when launching some other software. But, when calling the browser, the result is an ugly "Corrupt" error box instead of starting it...!
Well, this is just another SAD consequence of Symbian's WEIRD programming approach. The "Symbian C++" style, even starting from some good intuitions, shows lots of inconsistencies and bugs. On the "human" side, any programmer that spends more than a few minutes to solve problems like the one shown above, gets quickly angry and tired. Development of the first Symbian-based application program will require at least WEEKS of full-time working and debugging; and an inconsistency like the one above will require HOURS to test and solve (when actually possible to solve or get around it!)
Result: many freeware developers will LEAVE because it's better to work on other simpler and well documented and more reliable platforms (for example, Linux). And, even if they continue to work on a Symbian platform, they will be HIGHLY TEMPTED to not to show how to solve that problem because of the undesired waste of time!!
...and finally I found a workaround! (phew!)

The UIQ 2.1 actually supports the "double click", which can be read into the "modifiers" field of a TPointerEvent in any RWsSession connection. Yeah, I just tested it, and it ran fine! (too hard to explain how to do in a few lines... go search for EItemDoubleClicked and EModifierDoubleClick in the standard UIQ include files).

If you get a CONE Error 14 then you surely reduced too much the resource file. I found that a number of applications who don't need extra resources need always at least these five first lines (to place in the .RSS resource source):
#include <eikon.rh>
#include <eikcore.rsg>
RESOURCE TBUF { buf = ""; }

Another important thing. When the .AIF file is present in the application package, then the operating system checks on the UIDs are stricter. For example, if you declare an UID for the program and use a different UID in the code (AppDllUid), the presence of the .AIF file triggers a weird "Corrupt" error when starting the program.

Again UIDs... this table is found into the official SonyEricsson document "Developers Guidelines - UIQ and personal-Java for P800/P900" released in October 2003:
101f617b:  UIQ 2.0 compatibility (currently P800 only);
101f80be:  P800, P900 and P910 platforms;
101f61ce:  UIQ 2.1 compatibility (currently P900 only);
101fbb35:  P900 and P910 platforms only.

Also, if you use the "0x101f80be" UID, then you can check what machine is running your program including the hardware abstraction layer functions like here:
#include <hal.h>
TInt n;
HAL::Get(HALData::EMachineUid, n);
if(n==0x101f408b) then it's a P800; if(n==0x101fb2ae) then it's a P900.


Below, a great shot to celebrate this work: Cicciotto's pizza with sausage, mushrooms, cream, ham, and chips!

SonyEricsson P900 with mushroom-ham-sausage-cream-chips pizza!

Sony Ericsson P900 index - send e-mail - home page