1.2k 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 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

...