• AVR Freaks

Helpful ReplyHot!Harmony v3: How to write a 24-bit bitmap to a MEBII display

Author
KTrenholm
Super Member
  • Total Posts : 783
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
2019/11/25 09:40:22 (permalink)
0

Harmony v3: How to write a 24-bit bitmap to a MEBII display

Hi there,
 
I've got a question about writing a 24-bit bitmap to the MEBII display.  I seem to be unable to get my bitmap image data to display, and I'm having trouble figuring out why.
 
I am using
MPLAB X 5.30
XC32 v2.30
Harmony v3
aria graphics library
 
The project itself is basically the aria quickstart project provided in the harmony examples modified for my needs.  I can provide a link to the project if necessary (it's too big to attach, I'd need to externally host it).
 
The way I am set up currently, I am reading a 50% gray (alternating black and white pixels) bitmap from a USB MSD, and transferring it to DDR RAM.  It appears to be reading in correctly (I am seeing 0x00 0x00 0x00 0xFF 0xFF 0xFF alternating on my read-in). but I'm having problems getting it out to the MEBII.  Here is my current code to do this:
 

/*Definitions*/
#define IMAGE_WIDTH 480
#define IMAGE_HEIGHT 272
#define MAX_IMAGE_SIZE ((IMAGE_WIDTH * IMAGE_HEIGHT) * 4)
 
/*Address of LAYER0 in DDR*/
#define GFX_GLCD_LAYER0_BASEADDR    0xA8000000
 
/*Pointer to our image data placed in DDR when USB MSD attached*/
#define IMAGE_DATA_ADDR 0xA817E800
uint8_t * ptrImageData = (uint8_t *)IMAGE_DATA_ADDR;
 
typedef struct
{
    /*File System handle of bitmap file*/
    SYS_FS_HANDLE fs_handle;
    
    /*Size of bitmap file in bytes*/
    uint32_t size;
    
    /*Starting index of pixel data*/
    uint32_t px_index;
} BITMAP_DATA;
 
void APP_Initialize(void){
/*Initialization of the GLCD Layer0 and the displaybuffer*/
    scr_rect.height = IMAGE_HEIGHT;
    scr_rect.width = IMAGE_WIDTH;
 
    PLIB_GLCD_LayerBaseAddressSet( 0, (uint32_t)GFX_GLCD_LAYER0_BASEADDR);

    displaybuffer.format = N2D_RGBA8888;
    displaybuffer.gpu = KVA_TO_PA(GFX_GLCD_LAYER0_BASEADDR);
    displaybuffer.memory = (void*)GFX_GLCD_LAYER0_BASEADDR;
    displaybuffer.width = scr_rect.width;
    displaybuffer.height = scr_rect.height;
    displaybuffer.orientation = N2D_0;
    displaybuffer.stride = displaybuffer.width * 32 / 8;
}

 
 

static void WriteBitmapToDisplay (BITMAP_DATA * bmp_info){
    uint32_t line;
    uint32_t px;
    uint32_t fileindex = bmp_info->px_index;
    uint8_t linedata[IMAGE_WIDTH * BMP_BYTES_PER_PX];
    
    SYS_FS_FileSeek(bmp_info->fs_handle, fileindex, SYS_FS_SEEK_SET); /*Set file pointer to first pixel of image data after header*/
    
    /*Image is 24bpp, outgoing display format is 32bpp (RGBA)*/
    /*Read in each horizontal line and insert an Alpha byte for each pixel*/
    for (line = 0; line < IMAGE_HEIGHT; line++){
        
        SYS_FS_FileRead(bmp_info->fs_handle, &linedata, IMAGE_WIDTH * 3);
        
        for (px = 0; px < IMAGE_WIDTH; px++){
            ptrImageData[px * 4]         = linedata[px * 3];
            ptrImageData[(px * 4) + 1]   = linedata[(px * 3) + 1];
            ptrImageData[(px * 4) + 2]   = linedata[(px * 3) + 2];
            ptrImageData[(px * 4) + 3]   = 0xFF;
        }
        
    }

    /*Set up image buffer for our bitmap*/
    imgbuffer.format = N2D_RGBA8888;
    imgbuffer.gpu = KVA_TO_PA(&ptrImageData);
    imgbuffer.memory = (void*)ptrImageData;
    imgbuffer.height = IMAGE_HEIGHT;
    imgbuffer.width = IMAGE_WIDTH;
    imgbuffer.orientation = N2D_0;
    imgbuffer.stride = imgbuffer.width * 32 / 8;
    
    /*Change over to our "Image" screen and blit the image data to display*/
    laContext_SetActiveScreen(imagescreen_ID);  
    n2d_blit(&displaybuffer, NULL, &imgbuffer, NULL, N2D_BLEND_NONE);
}

 
The screen I am attempting to blit to is an empty white screen with a single text widget (that I assume would be overwritten by my image).
Since it appears my image data is being written to DDR, and since even if it wasn't I'd presumably just see garbage or a white/black screen if the blit was working, something must be going on with how I'm using n2d_blit().  I'm just not really sure what I'm missing?
 
Any tips for what I might be doing wrong?
 
Thanks!
 
#1
KTrenholm
Super Member
  • Total Posts : 783
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Harmony v3: How to write a 24-bit bitmap to a MEBII display 2019/11/26 09:29:28 (permalink)
0
So I found a couple things, but still no success with the n2d_blit().
 
I found that the n2d_fill() function is working:

n2d_color_t redColor = 0x00FF0000;
n2d_fill(&displaybuffer, N2D_NULL, redColor, N2D_BLEND_NONE);

 
This results in a red screen, so the n2d IS working.
I also noticed that calling laContext_SetActiveScreen() immediately before n2d_fill() results in the fill executing before the screen change, which gave the appearance of n2d_fill() not working (you could maybe spot a flash of a red screen before the screen changes).  Since I was calling SetActiveScreen() before my n2d_blit(), I thought this may have been the problem, but unfortunately that does not appear to be the issue.
 
Also, does anyone know where the latest documentation for the nano 2d libraries are?  I'm using the Harmony v2.06 graphics library doc, which I found an error in on page 401:

n2d_color_t redColor = 0x00ff000000;
n2d_color_t greenColor = 0x0000ff0000;

These two definitions have and extra byte at the end, the n2d_color_t is just an unsigned 32-bit int, so it just cuts off the 2 MSB.  This is a problem when the extra 0x00 bytes are at the LSB (I was very confused when I was getting a black screen instead of a red one).  They should be:

n2d_color_t redColor = 0x00ff0000;
n2d_color_t greenColor = 0x0000ff00;

#2
KTrenholm
Super Member
  • Total Posts : 783
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Harmony v3: How to write a 24-bit bitmap to a MEBII display 2019/11/26 13:12:30 (permalink) ☄ Helpfulby MHGC 2019/11/26 14:44:41
5 (4)
Problem solved!
 
There were a couple things going on, both of them just things I missed.
Firstly, I was setting up the n2d buffer incorrectly.  I was assigning the pointer to the gpu and memory members rather than just a constant value of the address.  It should be set as follows:

 
 
 
#define IMAGE_DATA_ADDR 0xA817E800
imgbuffer.gpu = KVA_TO_PA(IMAGE_DATA_ADDR);
imgbuffer.memory = (void*)IMAGE_DATA_ADDR;
 
 
 

 
This finally gave me an image on the display, but it was mostly garbage.
The reason for this was that I was writing the DDR incorrectly.  My brain told me I was writing bytes, so I assigned to DDR like I was writing an array of bytes, but that's not how the memory is being read by the GPU. It's not reading a byte in each 32-bit word, it's reading each 32-bit word as an ARGB value.
 
Essentially I was writing this:
0x000000RR 0x000000GG 0x000000BB 0x000000AA
 
Where I wanted this:
0xRRGGBBAA
 
So I needed to change my line reading loop to:

 
 
 
for (line = 0; line < IMAGE_HEIGHT; line++){
        
        SYS_FS_FileRead(bmp_info->fs_handle, &linedata, IMAGE_WIDTH * 3);
        
        for (px = 0; px < IMAGE_WIDTH; px++){
            ptrImageData[(IMAGE_WIDTH * line) + px] = JOIN_UINT32(linedata[px * 3], linedata[(px * 3) + 1], linedata[(px * 3) + 2], 0x00);
        }
    }
 
 
 

 
This seems to have cleared it up for me, I'm now getting my bitmap on the display.  Hopefully down the road someone will find this and it will save them some time.
post edited by KTrenholm - 2019/11/26 13:52:00
#3
Jump to:
© 2020 APG vNext Commercial Version 4.5