Wednesday 1 December 2010

Why's my Alpha blend not working!!

That was what I was saying as I do an AlphaBlend() of a 32 bit bitmap nicely saved in Photoshop, the result was a bitmap with white as the 'background' instead of a nice transparent edge.

I've seen this before and moving between Desktop and WinCE I seem to have slightly different results with Alpha blending and image factory stuff. Anyhow I found a few people mentioning that you need to pre-multiply any alpha per pixel before using the Alpha blend (which has an alpha on the image as well). Sceptical but tried it and hey presto my bitmaps now render perfectly.

Here is what I do in Win32:

HBITMAP hbmp = CreateDIBSection(hdcScreen, lpbi, DIB_RGB_COLORS, &pvImageBits, NULL, 0);

const UINT cbImage = cbStride * height;
if (FAILED(ipBitmap->CopyPixels(NULL, cbStride, cbImage, static_cast<BYTE *>(pvImageBits))))
{
// couldn't extract image; delete HBITMAP
DeleteObject(hbmp);
hbmp = NULL;
}

// Pre multiply RGB on alpha channels else alpha blit won't work!
//
if (lpbi->bmiHeader.biBitCount == 32)
{
BYTE* linePtr = (BYTE*)pvImageBits;
for(int y=0;y<height;y++)
{
BYTE* ptr = linePtr;

for(int x=0;x<width;x++)
{
BYTE alpha = *(ptr+3);
*(ptr+0)=(*(ptr+0) * alpha) / 255;
*(ptr+1)=(*(ptr+1) * alpha) / 255;
*(ptr+2)=(*(ptr+2) * alpha) / 255;
ptr+=4;
}

linePtr += cbStride;
}
}
Then just AlphaBlend on my bitmap...perfect, but why doesn't AlphaBlend handle the 32 bit bitmaps anyhow that's what I don't understand.... !

Monday 15 November 2010

Adding custom notifications to the WM6.5 lock screen

If you are wondering how your application can add information on the new WM6.5 lock screen, this can be done easily by utilising a few registry entries! There are two OEM lockscreen entries reserved for OEM applications that will allow applications to register an icon to show on the lock screen with an optional number of unread or unhandled events, when the user slides this to the right or left the application is invoked to deal with the unread events.

The regsitry entry all of this appears under is:

HKLM\Software\\Microsoft\\Shell\\LockScreen\\Notifications\\Notif0
HKLM\Software\\Microsoft\\Shell\\LockScreen\\Notifications\\Notif1

Add the settings like this:

"Command Line"="\program files\myapp\myapp.exe"
"Image"="\icon_notclicked.png"
"FocusImage"="\icon_clicked.png"
"Notification Count"=dword:0

The command line should point to your application, this will be executed when the user slides your cusom slider to the right. The Image and Focus image are two icons which are shown on the lock screen with and without you pressing them. The notification count should be more than 0 to show your icon and 0 to hide your item. The number in the noticication count is displayed on the lock screen so this could be the number of unread messages or emails you've received, whatever you are counting in your application.

You should check that Notif0 and 1 aren't already used by another application and use the appropriate one.

Happy screen locking!

Wednesday 27 October 2010

Accessing the phone vibrator

How can I access the vibrate function from my apps you may say...?

Well the vibrate function is part of the NLED (or notification LED) driver. You can use the NLED functions to pulse or turn on/off the motor in the same way as any LED. To find the vibrator search through the list of LEDs until you find one with a cycle time of -1, this indicates the vibrator.

The following code is complete example of searching through the available LEDs and turning on and off only the vibrate function. This should work on any Windows Mobile or Windows CE with a compatible NLED driver:


#include "nled.h"

enum Status
{
OFF = 0,
ON,
BLINK
};

int GetLedCount()
{
int count = 0;
NLED_COUNT_INFO nci;
if (NLedGetDeviceInfo(NLED_COUNT_INFO_ID, &nci))
{
count = nci.cLeds;
}
return count;
}

int ledCount = GetLedCount();

void SetLedStatus(Status status)
{
NLED_SETTINGS_INFO nsi;
NLED_SUPPORTS_INFO nInfo;
nsi.OffOnBlink = (uint)status;
for (int i = 0; i < ledCount; i++)
{
// request information from this led, we're looking for a
// cycleAdjust of -1 which indicates the vibrator
nInfo.LedNum = i;
NLedGetDeviceInfo(NLED_SUPPORTS_INFO_ID, &nInfo);
if (nInfo.lCycleAdjust == -1)
{
nsi.LedNum = (uint)i;
NLedSetDevice(NLED_SETTINGS_INFO_ID, &nsi);
}
}
}

void VibrateOn()
{
SetLedStatus(Status::ON);
}

void VibrateOff()
{
SetLedStatus(Status::OFF);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
VibrateOn();
Sleep(500);
VibrateOff();
}

Tuesday 12 October 2010

Missing Ordinals in Windows CE

If you get the message:

ERROR: function @ Ordinal 297 missing
Please Check your SYSGEN variable!!!


Then the problem is most likely to be a missing funciton in CoreDLL, to check which it is go to the private sources:

\WINCE600\PRIVATE\WINCEOS\COREOS\CORE\DLL>notepad core_common.def

In this you should be able to search for the ordinal number

; @CESYSGEN IF COREDLL_BATTERY
BatteryDrvrGetLevels=BatteryDrvrGetLevels @297
BatteryDrvrSupportsChangeNotification=BatteryDrvrSupportsChangeNotification @298
BatteryGetLifeTimeInfo=BatteryGetLifeTimeInfo @713
BatteryNotifyOfTimeChange=BatteryNotifyOfTimeChange @714
GetSystemPowerStatusEx=GetSystemPowerStatusEx @715
GetSystemPowerStatusEx2=GetSystemPowerStatusEx2 @1358
; @CESYSGEN ENDIF

Wednesday 29 September 2010

Using events and waking devices using CeRunAppAtTime

Want to wake up a CE device at a future time (even if it is suspend), then use the CeRunAppAtTime but instead of running an app use a named event, this allows an application to wake up the device at a set time and also trap the wake event without spawning another process:

SYSTEMTIME time;
CTime nextWakeUpTime;

// get local system time and convert time to CTime for now
GetLocalTime(&time);
CTime now(time);

// 30 minutes in the future
nextWakeUpTime=now;
nextWakeUpTime+=CTimeSpan(0,0,30,0);

// convert to systemtime
nextWakeUpTime.GetAsSystemTime(time);

// set for wake up !
CeRunAppAtTime(TEXT("\\\\.\\Notifications\\NamedEvents\\SCHEDULE_WAKEEVENT_EVENT"), &time);

HANDLE wakeEvent = CreateEvent(NULL, FALSE, FALSE, SCHEDULE_WAKEEVENT_EVENT);

// wait for wake up!
if (WaitForSingleObject(wakeEvent, FALSE, INFINITE) == WAIT_OBJECT_0)
{
// sheduled wake up
}

Friday 10 September 2010

KITL Messages Don't Support Wide Strings

I've just tracked down a minor irritation with KITL_RETAILMSG and KITL_DEBUGMSG under CE 6.0 R3 - they can't print UNICODE or wide strings.

On several platforms I've seen the KITL device name is not printed correctly. The device name is the name member of the OAL_KITL_DEVICE structure and is defined as a LPCWSTR.

Typically OALKitlInit uses KITL_RETAILMSG to report the device name but the name is never displayed correctly. The string is formatted as "%s" but only the first letter is shown - this implies that the wide string is being formatted as a character string. Trying %hs or %S to override the default does not help.

Reviewing the private sources confirms the problem. Only the %s format is supported and this is for character strings only.

Also be aware that formatting such as %08x is not supported either, but %X is fine!

Monday 6 September 2010

Using #include from BIB files



Did you know that inside of Windows CE build system that bib files can #include other bib files. This technique is used on many BSP's to implement individual driver registry entries from the driver directory

platform.reg
#include "$(_TARGETPLATROOT)\SRC\DRIVERS\display\display.reg"

The same can be done for the bib file, I didn't release this before, but its there to use if you want to in CE6.0 for sure!

platform.bib
#include "$(_TARGETPLATROOT)\SRC\DRIVERS\display\display.bib"

Wednesday 18 August 2010

Page faults on resume from suspend with COMPRESSION=on

A short while ago we had a problem on a platform resuming from suspend, a page fault calling a standard function. The function in question was a Registry query function. The fault was tracked down to that fact that when the config.bib specifies compression like:
COMPRESSION=ON
This means that all files are put into the nk.bin image back to back without any space between them, even running the image from RAM most of these files cannot be executed in place as the file aren't aligned on a page boundary, these files need to be copied into ram on a boundary and executed.
In the project above we needed to use the API so a solution was to turn off the COMPRESSION, this increases the NK.BIN size but helps in lower RAM usage and faster response times due to no duplication of files into executable positions. 

Thursday 8 July 2010

Transformations in WindowsCE using SetMapMode

Unfortunately Windows CE doesn't support transformation of the coordinate system using SetMapMode, SetViewPortExt and SetWindowExt even in Windows CE 7.0 which is rather unfortunate as we had an application just this week that would have benefited from this. The application I'm referring to would have been cross compiled for Win32 and CE so basically I had to support scaling for the PC end as well, no point in having two different systems when the app should be seemless across both platforms, maybe in CE8.0 eh?

Wednesday 9 June 2010

Windows CE 7.0 Preview

Microsoft have unveiled a technology preview of Windows Embedded Compact Edition (windows CE) version 7.0, the preview can be downloaded from http://www.microsoft.com/windowsembedded/en-us/products/windowsce/compact7.mspx go check it out now!

Monday 24 May 2010

Summer 2010 EmbeddedSPARK Competition

To all you embedded hobbyists. I Just want to highlight the latest Microsoft embeddedSPARK compitition on this summer. Given the latest release, this round of the competition is focused on Embedded Standard 7.

You can find all the information you need to enter at http://www.embeddedspark.com/

A video about this can also be seen at http://www.embeddedspark.com/public/videos/embeddedSPARKSUMMER_howto.wmv

FYI - Round 1 closes on June 8
Any questions or issues I can help with please let me know.

>> Nigel

Thursday 20 May 2010

Setting up COM buffers

I was pointed to this today to set the size of serial buffers on WinCE:
 BOOL SetupComm(     HANDLE hFile,   DWORD dwInQueue,     DWORD dwOutQueue   );
This should control the internal buffer sizes for the COM port... but the amusing comment in MSDN says:
 Always returns FALSE because the FIFO queue size cannot be changed
Err... so does this work!?

Wednesday 12 May 2010

Realtime CPU calculation for CE debugging

Quite often I've been in the situation where a process or thread has gone rogue and I've been trying to track down why the system has ground to a halt.

One of the things I find most helpful is the SnapShot tools, this allows you to take a snapshot of the system for its current running processes or threads, this can be useful in itself but using the GetThreadTimes API you can then print out any high CPU users, basically creating your own mini-task manager for Windows CE.

Firstly take a snapshot of the system:

HANDLE hSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);

Secondly call Thread32First/Next on the snapshot to retrieve all the thread information:

THREADENTRY32 te[256]; // up to 256 threads
int used = 0;
te[used].dwSize = sizeof(THREADENTRY32);
if ( Thread32First(hSnapshot,&te[used]) )
{
do
{
..
..

used++;
te[used].dwSize = sizeof(THREADENTRY32);
}
while (Thread32Next(hSnapshot,&te[used]));
}

Finally iterate through the threads getting their thread times, creating times etc:


FILETIME creationTime,exitTime;
FILETIME ktTime[256];
FILETIME utTime[256];
GetThreadTimes ((HANDLE)te[used].th32ThreadID,
&creationTime,
&exitTime,
&ktTime[used],
&utTime[used]);

This can be done in the while loop above, you can also use the results from the snapshot over and over with a sleep(1000), compare the results and print out the top XX threads using CPU to give some realtime feedback on the system usage.

Commonly my applications and kernel development use this method to ensure that the system is using the expected CPU time when being developed.


Thursday 6 May 2010

2010 Embedded Market Study shows Microsoft embedded OS's are on the way up...

The 2010 Embedded Market Study from EE Times group is out now, they reviewed 1,574 surveys on embedded designs.

This year we should be expecting the Wind River (VxWorks) to take the top 17% of upcoming embedded designs, followed by 13% for Debian (Linux), then Windows CE closely following at 13% and then Windows (XP Embedded) at 12%.

Windows CE and Windows XP Embedded are up 1% on last years survey, and between them take a whopping 25% of new designs, great news!

Check out the Webinar on http://www.techonline.com/learning/livewebinar/224000228 for on-demand playback.


Snooze using SleepTilTick

A not so well known function, this little API allows a thread to relinquish its hold on the system until the next tick normally 1ms great for polling loops when used in conjunction with high priority threads...

Friday 30 April 2010

Windows Embedded 7 RTM

After months of a CTP version being available the final version has been released to manufacturer. Windows Embedded Standard 7, the successor of Windows XP Embedded was released April 27th 2010 at the ESC West - Silicon Valley

Windows Embedded Standard 7 is the first embedded OS based on the successful desktop o/s Windows 7. Thus the aligned naming.

It is a highly customizable embedded o/s in a componentized form, which allows OEMs to build devices with a control over the memory footprint and the addition of embedded enabling features (HORM etc.) but still get the familiarity and power of Windows 7.

You can find the Windows Embedded Standard 7 RTM press release here.

But if you want to learn more and you’re in the UK why not come to the Microsoft HUB event next Thursday 6th May.
I’ll be there on the Direct Insight booth and in our Windows Embedded CE- Hands on Lab event. So why not register via this link

>> Nigel

Thursday 22 April 2010

OEMReadDebugByte in CE6.0

I quite often run a simple serial terminal using the debug port, having this we can control the platform without active sync, a keybaord or even an LCD, but when running from CE6.0 the application doesn't build because OEMReadDebugByte fails. If you want an app to be able to do the equivalent of OEMReadDebugByte instead use the function InputDebugCharW.

Wednesday 31 March 2010

Waiting for Thread / Process termination

When launching child processes from applications I used to use GetExitCodeProcess on the process handle, checking if STILL_ACTIVE is returned if it is still running.. heres the smart way!

After spawning a process or creating a worker thread the end of the process/thread can be waited on using WaitForSingleObject.

For instance for threads:

HANDLE hThread;
hThread = CreateThread(NULL,0,StartThread,&threadParam,0,NULL);
if(hThread1 != NULL)
{
WaitForSingleObject(hThread,INFINITE);
}


For processes:

PROCESS_INFORMATION pi={0};
if (CreateProcess (parameters, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, &pi))
{
WaitForSingleObject(pi.hProcess,INFINITE);
}


Thursday 25 March 2010

Registry notifications to pass data between kernel to Apps/drivers

This breifly outlines the technique of passing information or state changes between the Windows CE Kernel/OAL and running drivers or applications. Passing events and notification from the kernel to a driver or application can be a little problematic, information flow the other way is straight forward using the kernel IOCtls.

One thing we can use here is the registry and the registry change notifications, for instance, both drivers/applications and kernel can change the registry, the kernel calls are all preceeded by NK, for instance:

Kernel:

NKRegOpenKeyEx
NKRegCreateKeyEx
NKRegSetValueEx

Driver/App:

RegOpenKeyEx
RegCreateKeyEx
RegSetValueEx

So why not set a state or value to pass in the registry, then wait on a particular registry key or value being changed using the following:


// create an event on a particular registry change
HANDLE event = CeFindFirstRegChange(....)

while(1)
{
// wait for notification of a change
WaitForSingleObject(event, INFINITE);

// clear event
CeFindNextRegChange(event);

}

Using this technique small, or large complex data can be shared very easily.

Thursday 11 March 2010

Platform Builder: Remember to enable Multiprocessor Build

A support incident today reminded me that many people have forgotten to enable Multiprocessor Build support.

Enabling this will reduce the overall time it takes to build a platform workspace and it can be autodetected if enabled. But it seems the default is a manual selected number of processors=1


The selection is accessed via Tools / Options with the selection options as captured below:




Hope this is of help. Nigel

Thursday 4 March 2010

Passing data using SetEvent on Windows CE

Martin in the office came across this one, normally SetEvent is used to signal between two threads or even processes that something has happened, a very light weight message queue shall we say, the major limitation is that you can't pass any parameters or data, so you end up having multiple events or storing the parameter information in the registry etc..but using this API you can associate a DWORD of information against an event that is signalled, pretty handy for simple signalling information between drivers and applications...

BOOL SetEventData(   HANDLE hEvent,   DWORD dwData );
For more information look at:

http://msdn.microsoft.com/en-us/library/aa909185.aspx

Enjoy!

Thursday 4 February 2010

Southern Electronics Show

Just a quick note to invite you to come visit me on the ByteSnap Design stand at next week's Southern Electronics show in Farnborough from the 10 - 11 February 2010.

We will be demonstrating a number of customer projects including one from Rotalink, a designer and manufacturer of miniature motors, transmission and controls. This demo hooks up a DC motor speed detector to a mini-fairground wheel to show rotation and angle information via a display using our SnapUI product.

We'll also be showcasing other bespoke embedded electronics designs, embedded firmware and board design services. Come down to have a talk about services we can provide you from PCB design, through Firmware/BSP design to application development.

See you there!