First things first, here's what I'm using:
MPLAB X v5.30
XC32 v2.30
Harmony 3
PIC32MZDA Starter Kit (Non-Crypto, Internal DDR)
MEBII Display Kit
I have a project in which I need to read a USB Mass Storage Device for images, and show these images on a display. I've only been using harmony for a couple weeks, and it's been quite the trip.
I've had some success so far manually reading a 24-bit bitmap, converting it over to 32-bit ARGB, and manually drawing the bitmap using the n2d_blit function (as chronicled here: https://www.microchip.com/forums/m1120120.aspx).
Where I'm running into some issues is making the transition between images clean. I have a weird visual artifact that looks like the image is being drawn wrapped around the display (up to about 1/3 of the image), and then "slides" into the correct place. It almost seems like a timing issue of some kind. This isn't a showstopper (this project is for a display test rig, so clean transitions between images isn't a huge problem, it actually almost looks like a feature!) but I'd like to figure out why it's behaving like this, and find a workaround if possible.
I initially thought that maybe performing the read from USB and displaying the image all in one go might be messing with the timing for drawing the image, so I split up the read and the blit into two separate states (and also checked to make sure no draw was already taking place) so the image is read and displayed on successive calls of APP_Tasks(). This unfortunately didn't do anything to solve the issue.
It was suggested in another thread (https://www.microchip.com/forums/m1120944.aspx#1121189) to maybe try using the harmony Image Widget rather than a direct blit. This seems promising but I can't seem to get it to work correctly, and the tips I'm getting just seem to cycle back to "let harmony configurator pre-process the images to a bin file before putting them on the USB MSD", which is not an option. Requirement is to have the images be loaded as images onto a USB MSD. We can't really tell the customer that they need to preprocess images with harmony configurator. I should definitely be able to at least take a bitmap and put it into the image widget at runtime.
From what I understand, to process an image for use with the image widget, I need to use laUtils_PreprocessImage() to process the image data into a format where it can be written to the widget.
What I want to do is:
- Load image from USB MSD to DDR
- Process this image to a "staging" area elsewhere in DDR memory
- Write the newly processed image to the Image Widget
My code to attempt this:
- Code: Select all
#define IMAGE_DATA_ADDR 0xA827E800 //Processed image is placed here by laUtils_PreprocessImage()
#define IMAGE_TEMP_ADDR 0xA817E000 //Image is read from USB to this address in DDR
uint32_t * ptrImageData = (uint32_t *)IMAGE_DATA_ADDR;
uint32_t * ptrImageTemp = (uint32_t *)IMAGE_TEMP_ADDR;
GFXU_ImageAsset ImageAsset_Pre;
GFXU_ImageAsset ImageAsset_Post;
/*BITMAP_DATA contains the file handle, size of the file, and the index of the beginning of pixel data (currently unused)*/
void SetupBitmapData (BITMAP_DATA * bmp_info){
uint32_t size = SYS_FS_FileSize(bmp_info->fs_handle);
SYS_FS_FileRead(bmp_info->fs_handle, ptrImageTemp, size);
ImageAsset_Pre.header.type = GFXU_ASSET_TYPE_IMAGE;
ImageAsset_Pre.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
ImageAsset_Pre.header.dataAddress = (void *)ptrImageTemp;
ImageAsset_Pre.header.dataSize = size;
ImageAsset_Pre.format = GFXU_IMAGE_FORMAT_RAW; //bitmap - raw pixel data
ImageAsset_Pre.width = IMAGE_WIDTH;
ImageAsset_Pre.height = IMAGE_HEIGHT;
ImageAsset_Pre.bufferWidth = IMAGE_WIDTH;
ImageAsset_Pre.bufferHeight = IMAGE_HEIGHT;
ImageAsset_Pre.colorMode = GFX_COLOR_MODE_RGB_888; //24-bit bitmap
ImageAsset_Pre.compType = GFXU_IMAGE_COMPRESSION_NONE;
ImageAsset_Pre.flags = 0;
ImageAsset_Pre.mask = 0x0;
ImageAsset_Pre.palette = GFX_NULL;
/*Process image to IMG_DATA_ADDR in DDR as ARGB8888*/
laUtils_PreprocessImage(&ImageAsset_Pre, IMAGE_DATA_ADDR, GFX_COLOR_MODE_ARGB_8888, GFX_FALSE, NULL);
/*Setup ImageAsset_Post to describe our new post-processed image data*/
ImageAsset_Post.header.type = GFXU_ASSET_TYPE_IMAGE;
ImageAsset_Post.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
ImageAsset_Post.header.dataAddress = (void *)ptrImageData;
ImageAsset_Post.header.dataSize = size + (IMAGE_HEIGHT * IMAGE_WIDTH); //+1 alpha byte for each pixel of the image
ImageAsset_Post.format = GFXU_IMAGE_FORMAT_RAW; //bitmap - raw pixel data
ImageAsset_Post.width = IMAGE_WIDTH;
ImageAsset_Post.height = IMAGE_HEIGHT;
ImageAsset_Post.bufferWidth = IMAGE_WIDTH;
ImageAsset_Post.bufferHeight = IMAGE_HEIGHT;
ImageAsset_Post.colorMode = GFX_COLOR_MODE_ARGB_8888; //Process should have made image data ARGB8888
ImageAsset_Post.compType = GFXU_IMAGE_COMPRESSION_NONE;
ImageAsset_Post.flags = 0;
ImageAsset_Post.mask = 0x0;
ImageAsset_Post.palette = GFX_NULL;
}
The image is then displayed on the next call of APP_Tasks():
- Code: Select all
laImageWidget_SetImage((laImageWidget*)img_backImage, &ImageAsset_Post);
All this gives me is a white screen for all my images. Would anyone be able to tell me if I'm on the right track here? Am I missing something?