summaryrefslogtreecommitdiff
path: root/boards/dk-tm4c129x/fontview/fatwrapper.c
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-06-29 12:34:32 +0300
committerYuval Adam <yuv.adm@gmail.com>2014-06-29 12:34:32 +0300
commitc3e4c9a25c2910d2d66d52215b3406b13d5b23d5 (patch)
treeadded370d1e356901f8579f076e3263fb0464db7 /boards/dk-tm4c129x/fontview/fatwrapper.c
parent990090a4cc9070837d31e66b58d40f0c3d038741 (diff)
Add more board models
Diffstat (limited to 'boards/dk-tm4c129x/fontview/fatwrapper.c')
-rw-r--r--boards/dk-tm4c129x/fontview/fatwrapper.c858
1 files changed, 858 insertions, 0 deletions
diff --git a/boards/dk-tm4c129x/fontview/fatwrapper.c b/boards/dk-tm4c129x/fontview/fatwrapper.c
new file mode 100644
index 0000000..2d7607c
--- /dev/null
+++ b/boards/dk-tm4c129x/fontview/fatwrapper.c
@@ -0,0 +1,858 @@
+//*****************************************************************************
+//
+// fatwrapper.c - A simple wrapper allowing access to binary fonts stored in
+// the FAT file system.
+//
+// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "inc/hw_memmap.h"
+#include "inc/hw_types.h"
+#include "driverlib/debug.h"
+#include "driverlib/gpio.h"
+#include "driverlib/interrupt.h"
+#include "driverlib/rom.h"
+#include "driverlib/sysctl.h"
+#include "grlib/grlib.h"
+#include "utils/uartstdio.h"
+#include "utils/ustdlib.h"
+#include "third_party/fatfs/src/ff.h"
+#include "third_party/fatfs/src/diskio.h"
+
+//*****************************************************************************
+//
+// The number of font block headers that we cache when a font is opened.
+//
+//*****************************************************************************
+#define MAX_FONT_BLOCKS 16
+
+//*****************************************************************************
+//
+// The amount of memory set aside to hold compressed data for a single glyph.
+// Fonts for use with the graphics library limit compressed glyphs to 256 bytes.
+// If you are sure your fonts contain small glyphs, you could reduce this to
+// save space.
+//
+//*****************************************************************************
+#define MAX_GLYPH_SIZE 256
+
+//*****************************************************************************
+//
+// Instance data for a single loaded font.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ // The FATfs file object associated with the font.
+ //
+ FIL sFile;
+
+ //
+ // The font header as read from the file.
+ //
+ tFontWide sFontHeader;
+
+ //
+ // Storage for the font block table.
+ //
+ tFontBlock psBlocks[MAX_FONT_BLOCKS];
+
+ //
+ // A marker indicating whether or not the structure is in use.
+ //
+ bool bInUse;
+
+ //
+ // The codepoint of the character whose glyph data is currently stored in
+ // pui8GlyphStore.
+ //
+ uint32_t ui32CurrentGlyph;
+
+ //
+ // Storage for the compressed data of the latest glyph. In a more complex
+ // implementation, you would likely want to cache this data to reduce
+ // slow disk interaction.
+ //
+ uint8_t pui8GlyphStore[MAX_GLYPH_SIZE];
+}
+tFontFile;
+
+//*****************************************************************************
+//
+// Workspace for FATfs.
+//
+//*****************************************************************************
+FATFS g_sFatFs;
+
+//*****************************************************************************
+//
+// Instance data for a single loaded font. This implementation only supports
+// a single font open at any one time. If you wanted to implement something
+// more general, a memory manager could be used to allocate these structures
+// dynamically in FATWrapperFontLoad().
+//
+//*****************************************************************************
+tFontFile g_sFontFile;
+
+//*****************************************************************************
+//
+// A structure that holds a mapping between an FRESULT numerical code,
+// and a string represenation. FRESULT codes are returned from the FatFs
+// FAT file system driver.
+//
+//*****************************************************************************
+typedef struct
+{
+ FRESULT iFResult;
+ char *pcResultStr;
+}
+tFresultString;
+
+//*****************************************************************************
+//
+// A macro to make it easy to add result codes to the table.
+//
+//*****************************************************************************
+#define FRESULT_ENTRY(f) { (f), (#f) }
+
+//*****************************************************************************
+//
+// A table that holds a mapping between the numerical FRESULT code and
+// it's name as a string. This is used for looking up error codes for
+// printing to the console.
+//
+//*****************************************************************************
+tFresultString g_psFresultStrings[] =
+{
+ FRESULT_ENTRY(FR_OK),
+ FRESULT_ENTRY(FR_DISK_ERR),
+ FRESULT_ENTRY(FR_INT_ERR),
+ FRESULT_ENTRY(FR_NOT_READY),
+ FRESULT_ENTRY(FR_NO_FILE),
+ FRESULT_ENTRY(FR_NO_PATH),
+ FRESULT_ENTRY(FR_INVALID_NAME),
+ FRESULT_ENTRY(FR_DENIED),
+ FRESULT_ENTRY(FR_EXIST),
+ FRESULT_ENTRY(FR_INVALID_OBJECT),
+ FRESULT_ENTRY(FR_WRITE_PROTECTED),
+ FRESULT_ENTRY(FR_INVALID_DRIVE),
+ FRESULT_ENTRY(FR_NOT_ENABLED),
+ FRESULT_ENTRY(FR_NO_FILESYSTEM),
+ FRESULT_ENTRY(FR_MKFS_ABORTED),
+ FRESULT_ENTRY(FR_TIMEOUT),
+ FRESULT_ENTRY(FR_LOCKED),
+ FRESULT_ENTRY(FR_NOT_ENOUGH_CORE),
+ FRESULT_ENTRY(FR_TOO_MANY_OPEN_FILES),
+ FRESULT_ENTRY(FR_INVALID_PARAMETER),
+};
+
+//*****************************************************************************
+//
+// Error reasons returned by ChangeDirectory().
+//
+//*****************************************************************************
+#define NAME_TOO_LONG_ERROR 1
+#define OPENDIR_ERROR 2
+
+//*****************************************************************************
+//
+// A macro that holds the number of result codes.
+//
+//*****************************************************************************
+#define NUM_FRESULT_CODES (sizeof(g_psFresultStrings) / sizeof(tFresultString))
+
+//*****************************************************************************
+//
+// Internal function prototypes.
+//
+//*****************************************************************************
+static const char *StringFromFresult(FRESULT iFResult);
+static void FATWrapperFontInfoGet(uint8_t *pui8FontID,
+ uint8_t *pui8Format,
+ uint8_t *pui8Width,
+ uint8_t *pui8Height,
+ uint8_t *pui8Baseline);
+static const uint8_t *FATWrapperFontGlyphDataGet(
+ uint8_t *pui8FontID,
+ uint32_t ui32CodePoint,
+ uint8_t *pui8Width);
+static uint16_t FATWrapperFontCodepageGet(uint8_t *pui8FontID);
+static uint16_t FATWrapperFontNumBlocksGet(uint8_t *pui8FontID);
+static uint32_t FATWrapperFontBlockCodepointsGet(
+ uint8_t *pui8FontID,
+ uint16_t ui16BlockIndex,
+ uint32_t *pui32Start);
+
+//*****************************************************************************
+//
+// Access function pointers required to complete the tFontWrapper structure
+// for this font.
+//
+//*****************************************************************************
+const tFontAccessFuncs g_sFATFontAccessFuncs =
+{
+ FATWrapperFontInfoGet,
+ FATWrapperFontGlyphDataGet,
+ FATWrapperFontCodepageGet,
+ FATWrapperFontNumBlocksGet,
+ FATWrapperFontBlockCodepointsGet
+};
+
+//*****************************************************************************
+//
+// This function returns a string representation of an error code
+// that was returned from a function call to FatFs. It can be used
+// for printing human readable error messages.
+//
+//*****************************************************************************
+static const char *
+StringFromFresult(FRESULT iFResult)
+{
+ uint32_t ui32Idx;
+
+ //
+ // Enter a loop to search the error code table for a matching
+ // error code.
+ //
+ for(ui32Idx = 0; ui32Idx < NUM_FRESULT_CODES; ui32Idx++)
+ {
+ //
+ // If a match is found, then return the string name of the
+ // error code.
+ //
+ if(g_psFresultStrings[ui32Idx].iFResult == iFResult)
+ {
+ return(g_psFresultStrings[ui32Idx].pcResultStr);
+ }
+ }
+
+ //
+ // At this point no matching code was found, so return a
+ // string indicating unknown error.
+ //
+ return("UNKNOWN ERROR CODE");
+}
+
+//*****************************************************************************
+//
+// Returns information about a font previously loaded using FATFontWrapperLoad.
+//
+//*****************************************************************************
+static void
+FATWrapperFontInfoGet(uint8_t *pui8FontID, uint8_t *pui8Format,
+ uint8_t *pui8Width, uint8_t *pui8Height,
+ uint8_t *pui8Baseline)
+{
+ tFontFile *psFont;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+ ASSERT(pui8Format);
+ ASSERT(pui8Width);
+ ASSERT(pui8Height);
+ ASSERT(pui8Baseline);
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ ASSERT(psFont->bInUse);
+
+ //
+ // Return the requested information.
+ //
+ *pui8Format = psFont->sFontHeader.ui8Format;
+ *pui8Width = psFont->sFontHeader.ui8MaxWidth;
+ *pui8Height = psFont->sFontHeader.ui8Height;
+ *pui8Baseline = psFont->sFontHeader.ui8Baseline;
+}
+
+//*****************************************************************************
+//
+// Returns the codepage used by the font whose handle is passed.
+//
+//*****************************************************************************
+static uint16_t
+FATWrapperFontCodepageGet(uint8_t *pui8FontID)
+{
+ tFontFile *psFont;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ ASSERT(psFont->bInUse);
+
+ //
+ // Return the codepage identifier from the font.
+ //
+ return(psFont->sFontHeader.ui16Codepage);
+}
+
+//*****************************************************************************
+//
+// Returns the number of glyph blocks supported by a particular font.
+//
+//*****************************************************************************
+static uint16_t
+FATWrapperFontNumBlocksGet(uint8_t *pui8FontID)
+{
+ tFontFile *psFont;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ ASSERT(psFont->bInUse);
+
+ //
+ // Return the number of glyph blocks contained in the font.
+ //
+ return(psFont->sFontHeader.ui16NumBlocks);
+}
+
+//*****************************************************************************
+//
+// Read a given font block header from the provided file.
+//
+//*****************************************************************************
+static bool
+FATWrapperFontBlockHeaderGet(FIL *psFile, tFontBlock *psBlock,
+ uint32_t ui32Index)
+{
+ FRESULT iFResult;
+ UINT uiRead;
+
+ //
+ // Set the file pointer to the position of the block header we want.
+ //
+ iFResult = f_lseek(psFile, sizeof(tFontWide) +
+ (sizeof(tFontBlock) * ui32Index));
+ if(iFResult == FR_OK)
+ {
+ //
+ // Now read the block header.
+ //
+ iFResult = f_read(psFile, psBlock, sizeof(tFontBlock), &uiRead);
+ if((iFResult == FR_OK) && (uiRead == sizeof(tFontBlock)))
+ {
+ return(true);
+ }
+ }
+
+ //
+ // If we get here, we experienced an error so return a bad return code.
+ //
+ return(false);
+}
+
+//*****************************************************************************
+//
+// Returns information on the glyphs contained within a given font block.
+//
+//*****************************************************************************
+static uint32_t
+FATWrapperFontBlockCodepointsGet(uint8_t *pui8FontID,
+ uint16_t ui16BlockIndex,
+ uint32_t *pui32Start)
+{
+ tFontBlock sBlock;
+ tFontFile *psFont;
+ bool bRetcode;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ ASSERT(psFont->bInUse);
+
+ //
+ // Have we been passed a valid block index?
+ //
+ if(ui16BlockIndex >= psFont->sFontHeader.ui16NumBlocks)
+ {
+ //
+ // No - return an error.
+ //
+ return(0);
+ }
+
+ //
+ // Is this block header cached?
+ //
+ if(ui16BlockIndex < MAX_FONT_BLOCKS)
+ {
+ //
+ // Yes - return the information from our cached copy.
+ //
+ *pui32Start = psFont->psBlocks[ui16BlockIndex].ui32StartCodepoint;
+ return(psFont->psBlocks[ui16BlockIndex].ui32NumCodepoints);
+ }
+ else
+ {
+ //
+ // We don't have the block header cached so read it from the
+ // SDCard. First move the file pointer to the expected position.
+ //
+ bRetcode = FATWrapperFontBlockHeaderGet(&psFont->sFile, &sBlock,
+ ui16BlockIndex);
+ if(bRetcode)
+ {
+ *pui32Start = sBlock.ui32StartCodepoint;
+ return(sBlock.ui32NumCodepoints);
+ }
+ else
+ {
+ UARTprintf("Error reading block header!\n");
+ }
+ }
+
+ //
+ // If we get here, something horrible happened so return a failure.
+ //
+ *pui32Start = 0;
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Retrieves the data for a particular font glyph. This function returns
+// a pointer to the glyph data in linear, random access memory if the glyph
+// exists or NULL if not.
+//
+//*****************************************************************************
+static const uint8_t *
+FATWrapperFontGlyphDataGet(uint8_t *pui8FontID,
+ uint32_t ui32Codepoint,
+ uint8_t *pui8Width)
+{
+ tFontFile *psFont;
+ uint32_t ui32Loop, ui32GlyphOffset, ui32TableOffset;
+ UINT uiRead;
+ tFontBlock sBlock;
+ tFontBlock *psBlock;
+ bool bRetcode;
+ FRESULT iFResult;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+ ASSERT(pui8Width);
+
+ //
+ // If passed a NULL codepoint, return immediately.
+ //
+ if(!ui32Codepoint)
+ {
+ return(0);
+ }
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ ASSERT(psFont->bInUse);
+
+ //
+ // Look for the trivial case - do we have this glyph in our glyph store
+ // already?
+ //
+ if(psFont->ui32CurrentGlyph == ui32Codepoint)
+ {
+ //
+ // We struck gold - we already have this glyph in our buffer. Return
+ // the width (from the second byte of the data) and a pointer to the
+ // glyph data.
+ //
+ *pui8Width = psFont->pui8GlyphStore[1];
+ return(psFont->pui8GlyphStore);
+ }
+
+ //
+ // First find the block that contains the glyph we've been asked for.
+ //
+ for(ui32Loop = 0; ui32Loop < psFont->sFontHeader.ui16NumBlocks; ui32Loop++)
+ {
+ if(ui32Loop < MAX_FONT_BLOCKS)
+ {
+ psBlock = &psFont->psBlocks[ui32Loop];
+ }
+ else
+ {
+ bRetcode = FATWrapperFontBlockHeaderGet(&psFont->sFile, &sBlock,
+ ui32Loop);
+ psBlock = &sBlock;
+ if(!bRetcode)
+ {
+ //
+ // We failed to read the block header so return an error.
+ //
+ return(0);
+ }
+ }
+
+ //
+ // Does the requested character exist in this block?
+ //
+ if((ui32Codepoint >= (psBlock->ui32StartCodepoint)) &&
+ ((ui32Codepoint < (psBlock->ui32StartCodepoint +
+ psBlock->ui32NumCodepoints))))
+ {
+ //
+ // The glyph is in this block. Calculate the offset of it's
+ // glyph table entry in the file.
+ //
+ ui32TableOffset = psBlock->ui32GlyphTableOffset +
+ ((ui32Codepoint - psBlock->ui32StartCodepoint) *
+ sizeof(uint32_t));
+
+ //
+ // Move the file pointer to the offset position.
+ //
+ iFResult = f_lseek(&psFont->sFile, ui32TableOffset);
+
+ if(iFResult != FR_OK)
+ {
+ return(0);
+ }
+
+ //
+ // Read the glyph data offset.
+ //
+ iFResult = f_read(&psFont->sFile, &ui32GlyphOffset,
+ sizeof(uint32_t), &uiRead);
+
+ //
+ // Return if there was an error or if the offset is 0 (which
+ // indicates that the character is not included in the font.
+ //
+ if((iFResult != FR_OK) || (uiRead != sizeof(uint32_t)) ||
+ !ui32GlyphOffset)
+ {
+ return(0);
+ }
+
+ //
+ // Move the file pointer to the start of the glyph data remembering
+ // that the glyph table offset is relative to the start of the
+ // block not the start of the file (so we add the table offset
+ // here).
+ //
+ iFResult = f_lseek(&psFont->sFile, (psBlock->ui32GlyphTableOffset +
+ ui32GlyphOffset));
+
+ if(iFResult != FR_OK)
+ {
+ return(0);
+ }
+
+ //
+ // Read the first byte of the glyph data to find out how long it
+ // is.
+ //
+ iFResult = f_read(&psFont->sFile, psFont->pui8GlyphStore, 1,
+ &uiRead);
+
+ if((iFResult != FR_OK) || !uiRead)
+ {
+ return(0);
+ }
+
+ //
+ // Now read the glyph data.
+ //
+ iFResult = f_read(&psFont->sFile, psFont->pui8GlyphStore + 1,
+ psFont->pui8GlyphStore[0] - 1, &uiRead);
+
+ if((iFResult != FR_OK) ||
+ (uiRead != (psFont->pui8GlyphStore[0] - 1)))
+ {
+ return(0);
+ }
+
+ //
+ // If we get here, things are good. Return a pointer to the glyph
+ // store data.
+ //
+ psFont->ui32CurrentGlyph = ui32Codepoint;
+ *pui8Width = psFont->pui8GlyphStore[1];
+ return(psFont->pui8GlyphStore);
+ }
+ }
+
+ //
+ // If we get here, the codepoint doesn't exist in the font so return an
+ // error.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Prepares the FAT file system font wrapper for use.
+//
+// This function must be called before any attempt to use a font stored on the
+// FAT file system. It initializes FATfs for use.
+//
+// \return Returns \b true on success or \b false on failure.
+//
+//*****************************************************************************
+bool
+FATFontWrapperInit(void)
+{
+ FRESULT iFResult;
+
+ //
+ // Mount the file system, using logical disk 0.
+ //
+ iFResult = f_mount(0, &g_sFatFs);
+ if(iFResult != FR_OK)
+ {
+ //
+ // We failed to mount the volume. Tell the user and return an error.
+ //
+ UARTprintf("f_mount error: %s (%d)\n", StringFromFresult(iFResult),
+ iFResult);
+ return(false);
+ }
+
+ //
+ // All is well so tell the caller.
+ //
+ return(true);
+}
+
+//*****************************************************************************
+//
+// Provides the FATfs timer tick.
+//
+// This function must be called every 10mS or so by the application. It
+// provides the time reference required by the FAT file system.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+FATWrapperSysTickHandler(void)
+{
+ //
+ // Call the FatFs tick timer.
+ //
+ disk_timerproc();
+}
+
+//*****************************************************************************
+//
+// Prepares a font in the FATfs file system for use by the graphics library.
+//
+// This function must be called to prepare a font for use by the graphics
+// library. It opens the font file whose name is passed and reads the
+// header information. The value returned should be written into the
+// pui8FontID field of the tFontWrapper structure that will be passed to
+// graphics library.
+//
+// This is a very simple (and slow) implementation. More complex wrappers
+// may also initialize a glyph cache here.
+//
+// \return On success, returns a non-zero pointer identifying the font. On
+// error, zero is returned.
+//
+//*****************************************************************************
+uint8_t *
+FATFontWrapperLoad(char *pcFilename)
+{
+ FRESULT iFResult;
+ UINT uiRead, uiToRead;
+
+ UARTprintf("Attempting to load font %s from FAT file system.\n",
+ pcFilename);
+
+ //
+ // Make sure a font is not already open.
+ //
+ if(g_sFontFile.bInUse)
+ {
+ //
+ // Oops - someone tried to load a new font without unloading the
+ // previous one.
+ //
+ UARTprintf("Another font is already loaded!\n");
+ return(0);
+ }
+
+ //
+ // Try to open the file whose name we've been given.
+ //
+ iFResult = f_open(&g_sFontFile.sFile, pcFilename, FA_READ);
+ if(iFResult != FR_OK)
+ {
+ //
+ // We can't open the file. Either the file doesn't exist or there is
+ // no SDCard installed. Regardless, return an error.
+ //
+ UARTprintf("Error %s (%d) from f_open.\n", StringFromFresult(iFResult),
+ iFResult);
+ return(0);
+ }
+
+ //
+ // We opened the file successfully. Does it seem to contain a valid
+ // font? Read the header and see.
+ //
+ iFResult = f_read(&g_sFontFile.sFile, &g_sFontFile.sFontHeader,
+ sizeof(tFontWide), &uiRead);
+ if((iFResult == FR_OK) && (uiRead == sizeof(tFontWide)))
+ {
+ //
+ // We read the font header. Is the format correct? We only support
+ // wide fonts via wrappers.
+ //
+ if((g_sFontFile.sFontHeader.ui8Format != FONT_FMT_WIDE_UNCOMPRESSED) &&
+ (g_sFontFile.sFontHeader.ui8Format != FONT_FMT_WIDE_PIXEL_RLE))
+ {
+ //
+ // This is not a supported font format.
+ //
+ UARTprintf("Unrecognized font format. Failing "
+ "FATFontWrapperLoad.\n");
+ f_close(&g_sFontFile.sFile);
+ return(0);
+ }
+
+ //
+ // The format seems to be correct so read as many block headers as we
+ // have storage for.
+ //
+ uiToRead = ((g_sFontFile.sFontHeader.ui16NumBlocks > MAX_FONT_BLOCKS) ?
+ MAX_FONT_BLOCKS * sizeof(tFontBlock) :
+ (g_sFontFile.sFontHeader.ui16NumBlocks *
+ sizeof(tFontBlock)));
+
+ iFResult = f_read(&g_sFontFile.sFile, &g_sFontFile.psBlocks, uiToRead,
+ &uiRead);
+ if((iFResult == FR_OK) && (uiRead == uiToRead))
+ {
+ //
+ // All is well. Tell the caller the font was opened successfully.
+ //
+ UARTprintf("Font %s opened successfully.\n", pcFilename);
+ g_sFontFile.bInUse = true;
+ return((uint8_t *)&g_sFontFile);
+ }
+ else
+ {
+ UARTprintf("Error %s (%d) reading block headers. Read %d, exp %d "
+ "bytes.\n", StringFromFresult(iFResult), iFResult,
+ uiRead, uiToRead);
+ f_close(&g_sFontFile.sFile);
+ return(0);
+ }
+ }
+ else
+ {
+ //
+ // We received an error while reading the file header so fail the call.
+ //
+ UARTprintf("Error %s (%d) reading font header.\n",
+ StringFromFresult(iFResult), iFResult);
+ f_close(&g_sFontFile.sFile);
+ return(0);
+ }
+}
+
+//*****************************************************************************
+//
+// Frees a font and cleans up once an application has finished using it.
+//
+// This function releases all resources allocated during a previous call to
+// FATFontWrapperLoad(). The caller must not make any further use of the
+// font following this call unless another call to FATFontWrapperLoad() is
+// made.
+//
+// \return None.
+//
+//*****************************************************************************
+void FATFontWrapperUnload(uint8_t *pui8FontID)
+{
+ tFontFile *psFont;
+ FRESULT iFResult;
+
+ //
+ // Parameter sanity check.
+ //
+ ASSERT(pui8FontID);
+
+ //
+ // Get a pointer to our instance data.
+ //
+ psFont = (tFontFile *)pui8FontID;
+
+ //
+ // Make sure a font is already open. If not, just return.
+ //
+ if(!psFont->bInUse)
+ {
+ return;
+ }
+
+ //
+ // Close the font file.
+ //
+ UARTprintf("Unloading font... \n");
+ iFResult = f_close(&psFont->sFile);
+ if(iFResult != FR_OK)
+ {
+ UARTprintf("Error %s (%d) from f_close.\n", StringFromFresult(iFResult),
+ iFResult);
+ }
+
+ //
+ // Clean up our instance data.
+ //
+ psFont->bInUse = false;
+ psFont->ui32CurrentGlyph = 0;
+}