From c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Sun, 29 Jun 2014 12:34:32 +0300 Subject: Add more board models --- boards/dk-tm4c129x/fontview/fatwrapper.c | 858 +++++++++++++++++++++++++++++++ 1 file changed, 858 insertions(+) create mode 100644 boards/dk-tm4c129x/fontview/fatwrapper.c (limited to 'boards/dk-tm4c129x/fontview/fatwrapper.c') 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 +#include +#include +#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; +} -- cgit v1.3.1