emWin GetData Function
With emWin, it is possible to display files such as bitmaps or other common image formats stored in memory that is not directly addressable. To access this external data, GetData functions are required. Depending on the type of data, a specific type of "get-data function" is needed.
Objective of this tutorial
This tutorial demonstrates how to use two different types of GetData functions (GUI_GET_DATA_FUNC_I and GUI_GET_DATA_FUNC_II) to access a BMP file and a DTA file, and display the images with emWin.
For simplicity, we will use the Windows API to access the files in this tutorial. You should be able to run this tutorial in emWin simulation.
Get a free Window trial from our download section.
Requirements
To access files on external memory, you will need a fully initialized external memory device (e.g., an MMC device) and a filesystem to access the data stored on it.
We will start this tutorial with a very basic emWin application, so please ensure that emWin is already functioning properly.
Differences of the GetData functions
GUI_GET_DATA_FUNC_I
The first type of GetData function requires its own small buffer to read data from a file. The address of the buffer will be returned to the calling function via an out-pointer. The buffer needs to remain valid, so ensure it is not located on the stack.
GUI_GET_DATA_FUNC_II
The second type does not require a buffer. This function simply reads the requested data into the address passed to it.
Start application
Below is the application we will use to start this tutorial. You can call it from your main() or run it as a dedicated task.
#include "GUI.h"
void MainTask(void) {
GUI_Init();
while (1) {
GUI_Delay(100);
}
}
Drawing a BMP file
At first we will implement the code to draw BMP file located on your hard disk drive.
We start by adding a new function which will create a file handle with the given file name, draw the BMP file with the function GUI_BMP_DrawEx() and close the handle again.
The new will look like below. Make sure the path to the BMP file is valid.
#include "GUI.h"
#include "Windows.h"
static void _DrawBMP(const char * pFileName, int x, int y) {
HANDLE hFile;
hFile = CreateFile(pFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
GUI_BMP_DrawEx(_GetData_I, &hFile, x, y);
CloseHandle(hFile);
}
}
void MainTask(void) {
GUI_Init();
_DrawBMP("myBMP.bmp", 10, 10);
while (1) {
GUI_Delay(100);
}
}
Now we will only need the GetData function. Simply add the code below to the application.
This GetData function will receive a pointer to the previously created file handle and reads the requested number of bytes into the buffer. The pointer-pointer is used to return the address of the read buffer to emWin. Makes sure that the buffer stays valid.
static int _GetData_I(void * p, const U8 ** ppData, unsigned NumBytes, U32 Off) {
static U8 acBuffer[0x200];
HANDLE * phFile;
DWORD NumBytesRead;
phFile = (HANDLE *)p;
if (NumBytes > sizeof(acBuffer)) {
NumBytes = sizeof(acBuffer);
}
SetFilePointer(*phFile, Off, 0, FILE_BEGIN);
ReadFile(*phFile, acBuffer, NumBytes, &NumBytesRead, NULL);
*ppData = (const U8 *)acBuffer;
return NumBytesRead;
}
Drawing a DTA file
Drawing a DTA files works quite similar to drawing a BMP file but uses a slightly different GetData function.
As a first step we will write again a simple function which creates a file handle calls the drawing function GUI_DrawStreamedBitmapExAuto().
static void _DrawDTA(const char * pFileName, int x, int y) {
HANDLE hFile;
hFile = CreateFile(pFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
GUI_DrawStreamedBitmapExAuto(_GetData_II, &hFile, x, y);
CloseHandle(hFile);
}
}
The next step is adding the GetData function. This function does not have its own buffer; instead, it will simply read the requested amount of bytes into the buffer passed to it.
Below is a GetData function which can be used to draw a DTA file.
static int _GetData_II(void * p, const U8 ** ppData, unsigned NumBytes, U32 Off) {
HANDLE * phFile;
DWORD NumBytesRead;
U8 * pData;
pData = (U8 *)*ppData;
phFile = (HANDLE *)p;
SetFilePointer(*phFile, Off, 0, FILE_BEGIN);
ReadFile(*phFile, pData, NumBytes, &NumBytesRead, NULL);
return NumBytesRead;
}
Additional information
For more information on the different types of GetData functions, please refer to the emWin user manual.
Example
The complete code looks like this:
#include "GUI.h"
#include "Windows.h"
static int _GetData_I(void * p, const U8 ** ppData, unsigned NumBytes, U32 Off) {
static U8 acBuffer[0x200];
HANDLE * phFile;
DWORD NumBytesRead;
phFile = (HANDLE *)p;
if (NumBytes > sizeof(acBuffer)) {
NumBytes = sizeof(acBuffer);
}
SetFilePointer(*phFile, Off, 0, FILE_BEGIN);
ReadFile(*phFile, acBuffer, NumBytes, &NumBytesRead, NULL);
*ppData = (const U8 *)acBuffer;
return NumBytesRead;
}
static int _GetData_II(void * p, const U8 ** ppData, unsigned NumBytes, U32 Off) {
HANDLE * phFile;
DWORD NumBytesRead;
U8 * pData;
pData = (U8 *)*ppData;
phFile = (HANDLE *)p;
SetFilePointer(*phFile, Off, 0, FILE_BEGIN);
ReadFile(*phFile, pData, NumBytes, &NumBytesRead, NULL);
return NumBytesRead;
}
static void _DrawBMP(const char * pFileName, int x, int y) {
HANDLE hFile;
hFile = CreateFile(pFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
GUI_BMP_DrawEx(_GetData_I, &hFile, x, y);
CloseHandle(hFile);
}
}
static void _DrawDTA(const char * pFileName, int x, int y) {
HANDLE hFile;
hFile = CreateFile(pFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
GUI_DrawStreamedBitmapExAuto(_GetData_II, &hFile, x, y);
CloseHandle(hFile);
}
}
void MainTask(void) {
GUI_Init();
_DrawBMP("c:\\Work\\Temp\\Backup\\myBMP.bmp", 10, 10);
_DrawDTA("c:\\Work\\Temp\\Backup\\myDTA.dta", 70, 10);
while (1) {
GUI_Delay(100);
}
}