1.1k views
in Embedded Wizard Studio by

Hi, I have a BMP bitmap stored in a buffer in my native code. I want to read it into the EW  environment. Like in an int16 array. After I have it in a EW memory array, how do I display the bitmap image from the array buffer on a specified Rectangle?

Here is how I want to read the BMP into a buffer.

// Assume, all entries in the array 'SomeDataArray' should be filled with
// contents from the array in the main software/middleware.
var int16 SomeDataArray[156600];
var int32 noOfEntries = SomeDataArray.length;
var int32 i;

// Iterate through all entries of the array. Here the variable 'noOfEntries'
// limits the loop.
for ( i = 0; i < noOfEntries; i = i + 1 )
{
  var uint16 val;

  // Within 'native' code read the value 'i' of the array in your main software
  // or middleware. Store the value in the local variable 'val'.
  native ( i, val )
  {
    /* Declaration of an externally available array. In this manner the
       C compiler can access the array without warnings. */
    extern unsigned int16_t YourDeviceArray[ THE_SIZE_OF_YOUR_ARRAY ];
    
    val = YourDeviceArray[ i ];
  }

  // Again in Chora, copy the value from the variable 'val' to an array
  // member existing in 'this' object
  SomeDataArray[ i ] = val;
}

 

1 Answer

0 votes
by

Hello,

Embedded Wizard provides an infrastructure to display bitmaps with content that is provided during runtime: Extern Bitmap.

The class Resources::ExternBitmap provides the functionality to handle a bitmap loaded dynamically at the runtime from an extern image source. Bitmaps loaded in this manner can be used as regular bitmap resources. Please note, that this class provides only an interface for integrating your own image loader (e.g. PNG, JPG, GIF decoder) - it does not contain the image decoder itself!

The function EwLoadExternBitmap() is part of this interface and has to be implemented by yourself, in order to provide the image data - e.g. provided by your middleware.

Please have a look to the chapter Displaying dynamically loaded images. For details regarding the interface implementation please see the chapter Extern Bitmap interface. It contains also an example for integrating libJPEG as image decoder. Instead of using libJPEG you can adapt your own image provider.

I hope this helps...

Best regards,

Manfred.

by

Hi Manfred,

I read and looked at the Displaying dynamically loaded images here and followed alone the suggestions and even the EW sample Project "using-extern-bitmap-1" project. 

In my project, I dragged the ExternBitmap Resource. In object Resource. ExternalBitmap ---> Name I added "./Res/img_00.jpg" Now I get this error:

[11.3.2021 14:33:52] Error Resources::ExternBitmap.load (37:12) : Call to an unknown method 'EwLoadExternBitmap()'.

Am I missing an #include somewhere. I looked at the EW example code "using-extern-bitmap-1" The same method 'EwLoadExternBitmap()" is being used, but the compiler is okay with it.

Where would this native method be in the EW example?

I included the slot ExternalBitmap.load method below.

 

// slot Resources::ExternBitmap.load
// First dispose the old bitmap
if ( bitmap != null )
{
  $if $prototyper
    EwFreeBitmap( bitmap );
  $endif

  $if !$prototyper && ( $platform != *.WebGL.* )
    var handle handle = bitmap;

    // Free the memory reserved for this resource ...
    native ( handle )
    {
      EwFreeBitmap((XBitmap*)handle );
    }
  $endif

  $if !$prototyper && ( $platform == *.WebGL.* )
    var handle handle = bitmap;

    // Free the memory reserved for this resource ...
    native ( handle )
    {
      _app._FreeBitmap( handle );
    }
  $endif

  // For now no bitmap is available
  bitmap          = null;
  pure FrameSize  = <0,0>;
  pure FrameDelay = 0;
  pure NoOfFrames = 1;
  pure Animated   = false;
}

$if $prototyper
  bitmap = EwLoadExternBitmap( pure Name );
$endif

$if !$prototyper && ( $platform != *.WebGL.* )
  var string name   = pure Name;
  var handle handle = null;

  native ( name, handle )
  {
    extern XBitmap* EwLoadExternBitmap( XString aName );
    handle = (XHandle)EwLoadExternBitmap( name );
  }

  bitmap = handle;
$endif

$if !$prototyper && ( $platform == *.WebGL.* )
  var string name   = pure Name;
  var handle handle = null;

  native ( name, handle )
  {
    handle = _app._LoadExternBitmap( name, this );
  }

  bitmap = handle;
$endif

// Ask the attributes of the loaded bitmap
if ( bitmap != null )
{
  $if $prototyper
    pure NoOfFrames = EwGetBitmapNoOfFrames( bitmap );
    pure FrameSize  = EwGetBitmapFrameSize ( bitmap );
    pure FrameDelay = EwGetBitmapFrameDelay( bitmap );
  $endif

  $if !$prototyper && ( $platform != *.WebGL.* )
    var int32  noOfFrames = 1;
    var point  frameSize  = <0,0>;
    var int32  frameDelay = 0;

    handle = bitmap;

    native ( handle, noOfFrames, frameSize, frameDelay )
    {
      XBitmap* bmp = (XBitmap*)handle;

      noOfFrames = bmp->NoOfVirtFrames;
      frameSize  = bmp->FrameSize;
      frameDelay = bmp->FrameDelay;
    }

    /* Copy the bitmap attributes into the bitmap object */
    pure NoOfFrames = noOfFrames;
    pure FrameSize  = frameSize;
    pure FrameDelay = frameDelay;
  $endif

  $if !$prototyper && ( $platform == *.WebGL.* )
    var int32  noOfFrames = 1;
    var point  frameSize  = <0,0>;
    var int32  frameDelay = 0;

    handle = bitmap;

    native ( handle, noOfFrames, frameSize, frameDelay )
    {
      noOfFrames = handle.NoOfFrames;
      frameSize  = handle.FrameSize;
      frameDelay = handle.FrameDelay;
    }

    /* Copy the bitmap attributes into the bitmap object */
    pure NoOfFrames = noOfFrames;
    pure FrameSize  = frameSize;
    pure FrameDelay = frameDelay;
  $endif

  // Can the bitmap run an animation sequence?
  pure Animated = ( pure FrameDelay > 0 ) && ( pure NoOfFrames > 1 );
}

// Force all affected views to update their aspect
notifyobservers this;

 

 

by

Hello,

the cause of problem is that the function EwLoadExternBitmap() is not available at the prototyping time when you start the application within Embedded Wizard Studio. As its name indicates, it is intended to implement some 'extern' code to load the images.

In practice the function EwLoadExternBitmap() has to be implemented by yourself and adapted to the concrete bitmap storage in your target system. When you build a binary for the target system, the linker can address the function EwLoadExternBitmap() and link with it.

In order to use the function also during prototyping you have to provide the function enclosed within so-called Intrinsic Module. In this manner the 'extern' function can be used directly from Embedded Wizard Studio when you prototype the GUI. The example using-extern-bitmap-1 contains such intrinsics module (named there ExternBitmapLoader.ewi).

How to deal with the problem?

Please take a look at the section Extern Bitmap and Prototyping. It explains the possible options.

Does it help you further?

Best regards

Paul Banach

by

Hi Paul,

 

I tried to look in the using-extern-bitmap-1 example's intrinsic module named  ExternBitmapLoader.ewi and I think it's a binary.

I am working on target specific  STM32f746G-Discovey Platform and the intrinsic method is for windows WGL. For my target specific, can I put my EwLoadExternBitmap() definition in a xxx.c file and put the xxx.c file in the "Makefile" to link it? 

Last time I had to link my own functions, I created bunch of C files and added the C file names to the "Makefile"  added the functions calls in the DeviceDriver.c and used "Device Interface" in EW to hook up these function. Then I used the "outlet" from my slider to call them. For this scenario, do I go through a similar process?

 

Here is the example function definition of EwLoadExternBitmap() from your example here

/* Include necessary header files */
#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
#include "ewextpxl_RGBA8888.h"
#include <string.h>


XBitmap* EwLoadExternBitmap( XString aName )
{
  char          name[32];
  int           width;
  int           height;
  unsigned int  clr_red, clr_green, clr_blue, clr_alpha;
  XBitmap*      bitmap;
  XPoint        frameSize;
  XRect         lockArea;
  XBitmapLock*  lock;
  unsigned int* dest;
  int           ofs;
  int           x, y;

  /* STEP 1 */
  
  /* Convert the 16-bit wide character string in 8-bit ANSI string */
  EwStringToAnsi( aName, name, sizeof( name ), 0 );

  /* STEP 1 and 2 */

  /* The blue bitmap is requested? aName == "BLUE 100x50". Determine
     the size and the color to fill the bitmap. */
  if ( !strcmp( name, "BLUE 100x50" ))
  {
    width      = 100;
    height     = 50;
    clr_red    = 0;
    clr_green  = 0;
    clr_blue   = 255;
    clr_alpha  = 255;
  }
  
  /* The red bitmap is requested? aName == "RED 200x100". Determine
     the size and the color to fill the bitmap. */
  else if !strcmp( name, "SEMI-RED 200x100" ))
  {
    width      = 200;
    height     = 100;
    clr_red    = 255;
    clr_green  = 0;
    clr_blue   = 0;
    clr_alpha  = 128;
  }

  /* The requested image is not available */  
  else
    return NULL;

  /* STEP 3 */

  /* Create a new bitmap with the previously determined size */
  frameSize.X = width;
  frameSize.Y = height;
  bitmap      = EwCreateBitmap( EW_PIXEL_FORMAT_NATIVE, frameSize, 0, 1 );
  
  /* Enough memory to create the bitmap? */
  if ( bitmap == NULL )
    return NULL;
  
  /* STEP 4 */
  
  /* Lock the entire bitmap for write operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 0, 1 );
  
  /* STEP 5 */
  
  /* Get the pointer to the first pixel within the locked bitmap. In the
     RGBA8888 format every pixel is a 32-bit value (unsigned int). 
     Additionally calculate the offset in pixel between the end of one row
     and the begin of the next row. */
  dest   = (unsigned int*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 4 ) - width;

  /* Iterate through the pixel within the locked bitmap area. Do this
     row-by-row and column-by-column. After one row is finished adjust the
     'dest' pointer to refer to the next row. After one column is finished
     increment the 'dest' pointer only. */
  for ( y = 0; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
    {
      /* The color value you want to store in the pixel. Every variable
         is valid in range 0 .. 255. */
      unsigned int red   = clr_red;
      unsigned int green = clr_green;
      unsigned int blue  = clr_blue;
      unsigned int alpha = clr_alpha;

      /* In the color format RGBA8888, the color components 'red', 'green'
         and 'blue' can be premultiplied by 'alpha' component. Should this
         occur in your Platform Package?

         Please note, to optimize the implementation we divide the result
         of the multiplication by 256 (shift right 8) instead of by 255.
         Thus to reduce the calculation errors we increase the alpha value. */
      #ifdef EW_PREMULTIPLY_COLOR_CHANNELS
        red   = (( red   * ( alpha + 1 )) >> 8 );
        green = (( green * ( alpha + 1 )) >> 8 );
        blue  = (( blue  * ( alpha + 1 )) >> 8 );
      #endif

      /* In the color format RGBA8888, the arrangement of the color components
         'red', 'green', 'blue' and 'alpha' can be configured. Ensure, that all
         components are stored at right bit offsets within the 32-bit value of
         the pixel */
      red   <<= EW_COLOR_CHANNEL_BIT_OFFSET_RED;
      green <<= EW_COLOR_CHANNEL_BIT_OFFSET_GREEN;
      blue  <<= EW_COLOR_CHANNEL_BIT_OFFSET_BLUE;
      alpha <<= EW_COLOR_CHANNEL_BIT_OFFSET_ALPHA;
     
      /* Now compose the color components to a single 32-bit value and store
         the result in the bitmap memory ... */
      *dest = red | green | blue | alpha;
    }

  /* STEP 6 */

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
  
  /* STEP 8 */
  
  /* Return the bitmap */
  return bitmap;
}

 

by

Hello,

The Intrinsic Modules exist exclusively for Windows. They allow the user to add some target specific functionality (e.g. dynamic loading of images) to Embedded Wizard Studio. Thereupon this functionality can be used during the design and prototyping when the user works with Embedded Wizard Studio.

For the target system (e.g. STM32f746G), the Intrinsic Modules have no application. As you already deduced, for the target system you create a C file, put there the EwLoadExternBitmap() function and add the C file to the make file. This is similar to what you did with functions in DeviceDriver.c.

Nevertheless, you have to fix the error message 'Call to unknown method EwLoadExternBitmap()'. According to the section Extern Bitmap and Prototyping you have two possibilities:

Option 1: You provide the function EwLoadExternBitmap() within an Intrinsic Module. Then you can display the images even during the design and prototyping phase.

Option 2: You exclude for the prototyping case the code which may trigger the loading of the extern image. Then the images remain empty during the prototyping and design phase but no errors are reported anymore. 

Does it help you further?

Best regards

Paul Banach

by

Hi Paul 

Thanks for the hint on theExternBitmapLoader.ewi.  I was able to get the Error to go away by copying the ExternBitmapLoader.ewi from EW's example project "using-extern-bitmap-1"  into my project. Now the Error goes away and I can display the jpg image in the Prototyper using the ExternBitmap resource. But I'm not out of the woods yet. As you mentioned, I need to write my own EwLoadExternBitmap() function some where which I will get back to you later. But now I need to get teh mechanics of displaying and image from a buffer and do the following.

1. I want to use a buffer and point ExtternBitmap1. So I created an uint16 ImageBufferArray[156600] array and pointed the ExternBitmap1 "Name" attribute in the inspector to it. like this "ImageBufferArray": 

Here is the ImageBufferArray initialization. If puting some patterns in the ImageBufferArray, would theExternBitmapLoader.ewi  make the correct format of RGB888 and display an image?      See ImageBufferArray initialization below.

 

 

2. Can I just put my native code EwLoadExternBitmap() function in the "Inline" Native code Snippet box and have EW generate it in Application.c? 

 

3. BTW, the ImageBufferArray initialization is taking forever in the prototype. I will try to make the array size smaller and see if it goes faster. Any ideas?

Thanks,

mmd

 

by

Hello mmd,

Concerning your first question, I'm afraid your approach won't work. You have to implement the EwLoadExternBitmap() function as C code. There you can create a bitmap and access its pixel memory. Please follow the instructions in the article Extern Bitmap interface.

Concerning your second question, yes you can put the code of the C function within an Inline member so it will be generated. 

Concerning the third question, yes, the array initialization is taken over during prototyping. However, the approach of using an array to store the pixel data is not optimal. To display the data you will need to copy it into a bitmap memory area. Thus I would avoid it. The above mentioned article explains how you create a bitmap and how you lock it in order to access its memory. Then you can access the memory (similarly to how you access array elements) and modify the pixel. The entire implementation is made in C in this case.

Best regards

Paul Banach

by

Hi Paul,

1. If I put the code of C function within an Inline member so it will be generated, then this will only work on None Prototyper mode correct?

2. I have looked at the code in Extern Bitmap interface (See code snipped below), Will this code work in "prototyper" environment since it is  not target specific? The EwLoadExternBitmap() I'm using for now is coming from EW"s Intrinsic Method example"using-extern-bitmap-1" .ewi code for now. 

3. Question is: If the below code can work with the prototyper environment,  The XString parameter in XBitmap* EwLoadExternBitmap( XString aName ) Where the name string should come from, is it in the ExternBitmapx.Name property i.e. "Blue 100x50" as shown in picture below? 

4. Is the name string passed through the ExternBitmap.Load method and passed to the either Prototyper or Non Prototyper function XBitmap* EwLoadExternBitmap( XString aName )?

 

 

 

Because in the "Name" property of ExternBitmap according to EW's instructions in here state that  "Name could be the path to the desired file on the SD card file system. If the image contents are received over the network, the Name could be an URL addressing precisely the file to download from a server" So my question is, if the Name string property is not pointing to a file but merely a string for the code to take action on to determine what type of bitmap to send back as shown in the code snipped below, referenced from the example in  Extern Bitmap interface, why am i getting an error like "Run time  The file "Blue 100x 50" not found"? 

You see in the example code givern in Extern Bitmap interface, the name to the Xsring aName parameter must come from somewhere, and that somewhere, as I understand it, is from the property specified as "Name" in ExternBitmap. But when I put "Blue 100x 50" in the ExternBitmap1 "Name" property, I get a "Run time  The file "Blue 100x 50" not found" error.

My understanding is: the ExternBitmapx resource invokes .Load or .Reload methods. In the .Load method is where the Prototyper or Non Prototyper function "EwLoadExternBitmap()" is called and  I can always write code to assign new string to ExternBitmapx.Name = " xxx" property, hence the EwLoadExternBitmap() function can take different action based on the string name coming from ExternBitmapx.Name = " xxx" property and return different bitmaps. Correct?

/* Include necessary header files */
#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
#include "ewextpxl_RGBA8888.h"
#include <string.h>


XBitmap* EwLoadExternBitmap( XString aName )
{
  char          name[32];
  int           width;
  int           height;
  unsigned int  clr_red, clr_green, clr_blue, clr_alpha;
  XBitmap*      bitmap;
  XPoint        frameSize;
  XRect         lockArea;
  XBitmapLock*  lock;
  unsigned int* dest;
  int           ofs;
  int           x, y;

  /* STEP 1 */
  
  /* Convert the 16-bit wide character string in 8-bit ANSI string */
  EwStringToAnsi( aName, name, sizeof( name ), 0 );

  /* STEP 1 and 2 */

  /* The blue bitmap is requested? aName == "BLUE 100x50". Determine
     the size and the color to fill the bitmap. */
  if ( !strcmp( name, "BLUE 100x50" ))
  {
    width      = 100;
    height     = 50;
    clr_red    = 0;
    clr_green  = 0;
    clr_blue   = 255;
    clr_alpha  = 255;
  }
  
  /* The red bitmap is requested? aName == "RED 200x100". Determine
     the size and the color to fill the bitmap. */
  else if !strcmp( name, "SEMI-RED 200x100" ))
  {
    width      = 200;
    height     = 100;
    clr_red    = 255;
    clr_green  = 0;
    clr_blue   = 0;
    clr_alpha  = 128;
  }

  /* The requested image is not available */  
  else
    return NULL;

  /* STEP 3 */

  /* Create a new bitmap with the previously determined size */
  frameSize.X = width;
  frameSize.Y = height;
  bitmap      = EwCreateBitmap( EW_PIXEL_FORMAT_NATIVE, frameSize, 0, 1 );
  
  /* Enough memory to create the bitmap? */
  if ( bitmap == NULL )
    return NULL;
  
  /* STEP 4 */
  
  /* Lock the entire bitmap for write operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 0, 1 );
  
  /* STEP 5 */
  
  /* Get the pointer to the first pixel within the locked bitmap. In the
     RGBA8888 format every pixel is a 32-bit value (unsigned int). 
     Additionally calculate the offset in pixel between the end of one row
     and the begin of the next row. */
  dest   = (unsigned int*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 4 ) - width;

  /* Iterate through the pixel within the locked bitmap area. Do this
     row-by-row and column-by-column. After one row is finished adjust the
     'dest' pointer to refer to the next row. After one column is finished
     increment the 'dest' pointer only. */
  for ( y = 0; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
    {
      /* The color value you want to store in the pixel. Every variable
         is valid in range 0 .. 255. */
      unsigned int red   = clr_red;
      unsigned int green = clr_green;
      unsigned int blue  = clr_blue;
      unsigned int alpha = clr_alpha;

      /* In the color format RGBA8888, the color components 'red', 'green'
         and 'blue' can be premultiplied by 'alpha' component. Should this
         occur in your Platform Package?

         Please note, to optimize the implementation we divide the result
         of the multiplication by 256 (shift right 8) instead of by 255.
         Thus to reduce the calculation errors we increase the alpha value. */
      #ifdef EW_PREMULTIPLY_COLOR_CHANNELS
        red   = (( red   * ( alpha + 1 )) >> 8 );
        green = (( green * ( alpha + 1 )) >> 8 );
        blue  = (( blue  * ( alpha + 1 )) >> 8 );
      #endif

      /* In the color format RGBA8888, the arrangement of the color components
         'red', 'green', 'blue' and 'alpha' can be configured. Ensure, that all
         components are stored at right bit offsets within the 32-bit value of
         the pixel */
      red   <<= EW_COLOR_CHANNEL_BIT_OFFSET_RED;
      green <<= EW_COLOR_CHANNEL_BIT_OFFSET_GREEN;
      blue  <<= EW_COLOR_CHANNEL_BIT_OFFSET_BLUE;
      alpha <<= EW_COLOR_CHANNEL_BIT_OFFSET_ALPHA;
     
      /* Now compose the color components to a single 32-bit value and store
         the result in the bitmap memory ... */
      *dest = red | green | blue | alpha;
    }

  /* STEP 6 */

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
  
  /* STEP 8 */
  
  /* Return the bitmap */
  return bitmap;
}

T

 

by

Hello,

1. If I put the code of C function within an Inline member so it will be generated, then this will only work on None Prototyper mode correct?

concerning your first question, the content of an Inline member is intended for the target system only. To run the code also within the Prototyper you have to implement a new Intrinsics module and put the code inside it. Or you refrain from using the code during Prototyping. As already mentioned, these both options are explained in the section Extern Bitmap and Prototyping. These section also refers the chapter Implementing Prototyper intrinsics, where further details about the Intrinsic modules is provided. At the end of this chapter you will find a working example of the Intrinsics module implementing EwLoadExternBitmap() to create a QR code.

2. I have looked at the code in Extern Bitmap interface (See code snipped below), Will this code work in "prototyper" environment since it is  not target specific? The EwLoadExternBitmap() I'm using for now is coming from EW"s Intrinsic Method example"using-extern-bitmap-1" .ewi code for now. 

In fact the Intrinsic modules are intended to cover target specific code for the prototyping purpose. The implementation of EwLoadExternBitmap() is so far target specific as it takes care e.g. of the correct color format how the bitmaps are stored in the target. Yes, you should be able to compile the above code within an intrinsics module. I recommend you once more the above mentioned article containing the example of QR code generator.

3. Question is: If the below code can work with the prototyper environment,  The XString parameter in XBitmap* EwLoadExternBitmap( XString aName ) Where the name string should come from, is it in the ExternBitmapx.Name property i.e. "Blue 100x50" as shown in picture below? 

Exact. Please take a look at the chapter Extern Bitmap interface, it explains this dependency.

4. Is the name string passed through the ExternBitmap.Load method and passed to the either Prototyper or Non Prototyper function XBitmap* EwLoadExternBitmap( XString aName )?

Exact. Depending on actual operating mode (code running in target or in the prototyper), the load method invokes the function EwLoadExternBitmap() found in a C module of the target system or implemented within an intrinsics module. This is controlled by the $if .. $endif directives.

So my question is, if the Name string property is not pointing to a file but merely a string for the code to take action on to determine what type of bitmap to send back as shown in the code snipped below, referenced from the example in  Extern Bitmap interface, why am i getting an error like "Run time  The file "Blue 100x 50" not found"? 

This is probably the case because you are using the intrinsics module from the using-extern-bitmap-1 example. This module interprets the name as path to a file and wants to load the file. If the Name does not refer an existing file, you get the error. In your own implementation you are free to interpret Name as you need. It is just a string identifying the content you want to receive from the EwLoadExtwernBitmap(). For example, if you use EwLoadExternBitmap() to receive images from several video cameras, the Name can be used to select the right one, "Camera1", "Camera2", etc. It's completely up to you how to interpret the Name.

My understanding is: the ExternBitmapx resource invokes .Load or .Reload methods. In the .Load method is where the Prototyper or Non Prototyper function "EwLoadExternBitmap()" is called and  I can always write code to assign new string to ExternBitmapx.Name = " xxx" property, hence the EwLoadExternBitmap() function can take different action based on the string name coming from ExternBitmapx.Name = " xxx" property and return different bitmaps. Correct?

Yes, this is the idea. And you can have multiple instances of the Extern Bitmap object at the same time. Each instance initialzed with other string in its Name property and consequently containing other image inside. 

Does it help you further?

Best regards

Paul Banach

by

Hi Paul, thanks for your responses, and clarification, just so that there is no misunderstanding, in your responses below:

Exact. Depending on actual operating mode (code running in target or in the prototyper), the load method invokes the function EwLoadExternBitmap() found in a C module of the target system or implemented within an intrinsics module. This is controlled by the $if .. $endif directives.

Does "Exact" mean Yes?

Thanks,

MMD

by
yes :o)

Best regards

Paul Banach
by

Hello,

Just a further hint: Besides the above discussed 'extern bitmap' approach, Embedded Wizard also supports another concept to integrate external contents. It is called Applet. Especially if your intention is to display dynamic contents (camera images, video player images, etc.) Applet should be the better option. In such case, please take a look at the ask article Embedded Wizard with Camera. See also the related documentation for the Views::Applet class.

Best regards

Paul Banach

 

by

Hi Paul,

I was able to use the EW's example from External Bitmap Interface to write the EwLoadExtenBitmap() function for my target MSP32F746G board. Now I can display in the Image View the Red and the Blue bitmap images byupdating the ExternBitmap1.Name property on the fly as shon in the picture below. The Inline C EW's example code inserted in the Applicaiton.C fills up the dest bitmap pointer locked by the Bitmap buffer from EW.  Then as the example describes, the RGB565 pixel values are loaded (*dest = red | green | blue | alpha;). Right now, I'm going with this, I will make a function and pass this dest pointer to my target function and fill it up with the bitmap image received by the camera sensor. 

But first I am in process of implementing the I2C and SPI and my (ArduCam init and read function) device drivers to link with the EW and my target. 

 

#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
//#include "ewextpxl_RGBA8888.h"
#include "ewextpxl_RGB565.h"
#include <string.h>


XBitmap* EwLoadExternBitmap( XString aName )
{
  char          name[32];
  int           width;
  int           height;
  unsigned int  clr_red, clr_green, clr_blue, clr_alpha;
  XBitmap*      bitmap;
  XPoint        frameSize;
  XRect         lockArea;
  XBitmapLock*  lock;
  unsigned int* dest;
  int           ofs;
  int           x, y;

  /* STEP 1 */
  
  /* Convert the 16-bit wide character string in 8-bit ANSI string */
  EwStringToAnsi( aName, name, sizeof( name ), 0 );

  /* STEP 1 and 2 */

  /* The blue bitmap is requested? aName == "BLUE 100x50". Determine
     the size and the color to fill the bitmap. */
  if ( !strcmp( name, "BLUE 100x50" ))
  {
    width      = 100;
    height     = 50;
    clr_red    = 0;
    clr_green  = 0;
    clr_blue   = 255;
    clr_alpha  = 255;
  }
  
  /* The red bitmap is requested? aName == "RED 200x100". Determine
     the size and the color to fill the bitmap. */
  else if (!strcmp( name, "SEMI-RED 200x100" ))
  {
    width      = 200;
    height     = 100;
    clr_red    = 255;
    clr_green  = 0;
    clr_blue   = 0;
    clr_alpha  = 128;
  }

  /* The requested image is not available */  
  else
    return NULL;

  /* STEP 3 */

  /* Create a new bitmap with the previously determined size */
  frameSize.X = width;
  frameSize.Y = height;
  bitmap      = EwCreateBitmap( EW_PIXEL_FORMAT_NATIVE, frameSize, 0, 1 );
  
  /* Enough memory to create the bitmap? */
  if ( bitmap == NULL )
    return NULL;
  
  /* STEP 4 */
  
  /* Lock the entire bitmap for write operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 0, 1 );
  
  /* STEP 5 */
  
  /* Get the pointer to the first pixel within the locked bitmap. In the
     RGBA8888 format every pixel is a 32-bit value (unsigned int). 
     Additionally calculate the offset in pixel between the end of one row
     and the begin of the next row. */
  dest   = (unsigned int*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 4 ) - width;

  /* Iterate through the pixel within the locked bitmap area. Do this
     row-by-row and column-by-column. After one row is finished adjust the
     'dest' pointer to refer to the next row. After one column is finished
     increment the 'dest' pointer only. */
  for ( y = 0; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
    {
      /* The color value you want to store in the pixel. Every variable
         is valid in range 0 .. 255. */
      unsigned int red   = clr_red;
      unsigned int green = clr_green;
      unsigned int blue  = clr_blue;
      unsigned int alpha = clr_alpha;

      /* In the color format RGBA8888, the color components 'red', 'green'
         and 'blue' can be premultiplied by 'alpha' component. Should this
         occur in your Platform Package?

         Please note, to optimize the implementation we divide the result
         of the multiplication by 256 (shift right 8) instead of by 255.
         Thus to reduce the calculation errors we increase the alpha value. */
      #ifdef EW_PREMULTIPLY_COLOR_CHANNELS
        red   = (( red   * ( alpha + 1 )) >> 8 );
        green = (( green * ( alpha + 1 )) >> 8 );
        blue  = (( blue  * ( alpha + 1 )) >> 8 );
      #endif

      /* In the color format RGBA8888, the arrangement of the color components
         'red', 'green', 'blue' and 'alpha' can be configured. Ensure, that all
         components are stored at right bit offsets within the 32-bit value of
         the pixel */
      red   <<= EW_COLOR_CHANNEL_BIT_OFFSET_RED;
      green <<= EW_COLOR_CHANNEL_BIT_OFFSET_GREEN;
      blue  <<= EW_COLOR_CHANNEL_BIT_OFFSET_BLUE;
      alpha <<= EW_COLOR_CHANNEL_BIT_OFFSET_ALPHA;
     
      /* Now compose the color components to a single 32-bit value and store
         the result in the bitmap memory ... */
      *dest = red | green | blue | alpha;
    }

  /* STEP 6 */

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
  
  /* STEP 8 */
  
  /* Return the bitmap */
  return bitmap;
}

 

by

Hello,

it sounds good! Let us know if you run into any problems. From your description I assume you are using a bitmap in RGB565 color format. The above code example, however, still uses the NATIVE bitmap format. Is that intentional? To use RGB565 adapt:

1. the parameter aFormat in the EwCreateBitmap() invocation.

2. The access to the pixel memory has to be modified. With RGB565 one pixel occupies 16 bit (unsigned short). See also Bitmap color format EW_PIXEL_FORMAT_RGB565 (optional).

Best regards

Paul Banach

by

Hi Paul,

 

Thanks for the info on format EW_PIXEL_FORMAT_RGB565 (optional). I used it to create the bitmap EwCreateBitmap() invocation fr RGB565. 

 I am struggling with UART, SPI and I2C. I need these drivers to read the data from the Camera Sensor.

1. I got the UART to work in my native code  using the UART_HandleTypeDef       UART_Handle; from ew_bsb_console.c. In my native code :

HAL_UART_Transmit(&huart1, data,10,100); Does not work, because huart1 handle I brought it in from Cube MX

 HAL_UART_Transmit( &UART_Handle, data,4,10); Works, using UART_Handle, I can get characters to transmitted on the UART.

 

2. For SPI, I created my own initialization drivers ew_bsp_spi2.c/h I use the SPI read and Write using the : HAL_SPI_Transmit and HAL_SPI_Recieve functions with the handle hspi2. This seems to work and I can read and write an SPI register in my external device. I'm not sure if there is a pre-existing SPI handle and initializer that I should use so I don't change any system settings in EW?.

uint8_t bus_read(int address)
{
	uint8_t value;
	uint8_t spiData1[2];

	 	 	 HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_RESET);
	 	  	  spiData1[0]=  address; //spiData[0][0] ;0x40;
	 	  	  HAL_SPI_Transmit(&hspi2,spiData1, 1, 1);
	 	  	  HAL_SPI_Receive(&hspi2, &spiData1[1], 1, 1);
	 	  	  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_SET);
	 	  	  value = spiData1[1];
	 return value;
}

uint8_t bus_write(int address,int value)
{

	uint8_t spiData1[2];

	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_RESET);
	spiData1[0] = address;
	spiData1[1] = value;
    HAL_SPI_Transmit(&hspi2,  spiData1, 2, 1);
    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_SET);

	return 1;
}

 

3. As for the I2C I have a problem. I created  ew_bsp_I2c_ar.c/h and put it in Makefiel. I got the initialization code from CubeMx and put the initialization routine  in stm32746g_discovery.c. This is definitely NOT Working. The handle I copied for the I2C from CubeMx I put in stm32746g_discovery.c. and it is: I2C_HandleTypeDef  hi2c1; See my code snippets below. After this initialization, I use the HAL functions in my native code to read and write to I2C (See last code snippet). Looking in the  stm32746g_discovery.c.there seems to be already existing initialization with a different handle name for I2C and the handle name which could be one of these two in the code snippet belwo:

This  code below is a section from stm32746g_discovery.c

static void I2Cx_Init(I2C_HandleTypeDef *i2c_handler)
{
  if(HAL_I2C_GetState(i2c_handler) == HAL_I2C_STATE_RESET)
  {
    if (i2c_handler == (I2C_HandleTypeDef*)(&hI2cAudioHandler))
    {
      /* Audio and LCD I2C configuration */
      i2c_handler->Instance = DISCOVERY_AUDIO_I2Cx;
    }
    else
    {
      /* External, camera and Arduino connector  I2C configuration */
      i2c_handler->Instance = DISCOVERY_EXT_I2Cx;
    }
    i2c_handler->Init.Timing           = DISCOVERY_I2Cx_TIMING;
    i2c_handler->Init.OwnAddress1      = 0;
    i2c_handler->Init.AddressingMode   = I2C_ADDRESSINGMODE_7BIT;
    i2c_handler->Init.DualAddressMode  = I2C_DUALADDRESS_DISABLE;
    i2c_handler->Init.OwnAddress2      = 0;
    i2c_handler->Init.GeneralCallMode  = I2C_GENERALCALL_DISABLE;
    i2c_handler->Init.NoStretchMode    = I2C_NOSTRETCH_DISABLE;

    /* Init the I2C */
    I2Cx_MspInit(i2c_handler);
    HAL_I2C_Init(i2c_handler);
  }
}

 

The code below is my own generated code ew_bsp_i2c_ar.h/c

/*******************************************************************************
*
* E M B E D D E D   W I Z A R D   P R O J E C T
*
*                                                Copyright (c) TARA Systems GmbH
*                                    written by Paul Banach and Manfred Schweyer
*
********************************************************************************
*
* This software is delivered "as is" and shows the usage of other software
* components. It is provided as an example software which is intended to be
* modified and extended according to particular requirements.
*
* TARA Systems hereby disclaims all warranties and conditions with regard to the
* software, including all implied warranties and conditions of merchantability
* and non-infringement of any third party IPR or other rights which may result
* from the use or the inability to use the software.
*
********************************************************************************
*
* DESCRIPTION:
*   This file is part of the interface (glue layer) between an Embedded Wizard
*   generated UI application and the board support package (BSP) of a dedicated
*   target.
*   This template provides access to some LEDs and buttons of the board.
* 
*******************************************************************************/
//ew_bsp_i2c_ar.h

#ifndef EW_BSP_I2C_AR_H
#define EW_BSP_I2C_AR_H


#ifdef __cplusplus
  extern "C"
  {
#endif


/*******************************************************************************
* FUNCTION:
*   void EwBspI2c1_ar_Init( void );

*
* DESCRIPTION:
*   Configures one I2C of the board used for  applications.
*
* ARGUMENTS:
*   None
*
* RETURN None:
*   None
*
*******************************************************************************/

// Armen Added

/* ------------------ I2C ---------------- */
void EwBspI2c1_ar_Init( void );
void BSP_I2C1_Init (void );


#ifdef __cplusplus
  }
#endif

#endif /* EW_BSP_I2C_AR_H */


/* msy */
//ew_bsp_adc_ar.c

#include "ewconfig.h"
#include "stm32f7xx_hal.h"
#include "stm32746g_discovery.h"

#include "ew_bsp_i2c_ar.h"


 void EwBspI2c1_ar_Init( void )
{
  //BSP_ADC_Init( EW_ADC );
  BSP_I2C1_Init (  );
}

/* msy */

 

The code below Is my modification of stm32746g_discovery.c where I initialize the I2C with my own hi2c1 instance handler.


// part of stm32746g_discovery.c

// I2C 1 Init
//static void MX_I2C1_Init(void);
void BSP_I2C1_Init( void )
{
   MX_I2C1_Init();
}

// SPI 2 Init
//static void MX_SPI2_Init(void);
void BSP_SPI2_Init( void )
{
  MX_SPI2_Init();
}


void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x00C0EAFF;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief SPI2 Initialization Function
  * @param None
  * @retval None
  */
void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

Here is my native code where I use the I2C HAL read and write functions with the hi2c1 handle.

byte rdSensorReg8_8(uint8_t regID, uint8_t* regDat)
{
	uint8_t i2cData[2];
		i2cData[0] = regID;

	HAL_I2C_Master_Transmit(&hi2c1, I2C_ID, i2cData, 1,1);
	HAL_I2C_Master_Receive(&hi2c1, I2C_ID, &i2cData[1], 1,10);
	return i2cData[1];
}

//I2C Array Write 8bit address, 8bit data
int wrSensorRegs8_8(const struct sensor_reg reglist[])
{
  int err = 0;
  uint8_t reg_addr = 0;
  uint8_t reg_val = 0;
  uint8_t i2cData[2];

  const struct sensor_reg *next = reglist;

  while ((reg_addr != 0xff) | (reg_val != 0xff))
  {
    reg_addr = next->reg;
    reg_val = next->val;

    i2cData[0]= reg_addr;
    i2cData[1]= reg_val;


   // err = wrSensorReg8_8(reg_addr, reg_val);
    HAL_I2C_Master_Transmit(&hi2c1, I2C_ID, i2cData, 2,1);
 //   delay_us(400);
    next++;
  }

  return err;
}

 

So the question is, how to use the I2C, use the CubeMx generated initialization or the the existing initialization and handler?

 

Thanks,

MMD

by
Hi MMD,

it seems, that you have now a couple of other questions (e.g. concerning CubeMX and I2C) which are not related to the original question about extern bitmap.

Please try to separate the questions and open new threads for new topics. This helps others to find suitable answers...

Thank you!

Best regards,

Manfred.
by
Hi Manfred,

 

I think I have a good handle on the passing a bitmap pointer to my application and populating the buffer. I will try to post my question on the SPI interface in a separate thread.

 

Thanks!

MMD

Embedded Wizard Website | Privacy Policy | Imprint

...