Shows how to use a display and the onboard SD Card. Requires a display module with an adapter
Dependencies: DmTftLibrary SDFileSystem mbed
Revision 0:ee27d4c12433, committed 2014-05-20
- Comitter:
- displaymodule
- Date:
- Tue May 20 15:42:31 2014 +0000
- Child:
- 1:64173e1ae223
- Commit message:
- First version
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DmDrawBmpBase.cpp Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,252 @@ +/********************************************************************************************** + Copyright (c) 2014 DisplayModule. All rights reserved. + + Redistribution and use of this source code, part of this source code or any compiled binary + based on this source code is permitted as long as the above copyright notice and following + disclaimer is retained. + + DISCLAIMER: + THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES + NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE. + ********************************************************************************************/ + +#include "DmDrawBmpBase.h" + +bool DmDrawBmpBase::drawBitmap(DmTftBase& tft, uint16_t x, uint16_t y, readFunc func, uint32_t userData) { + _readFunc = func; + _userData = userData; + _readPos = 0; + + if (readBmpHeader()) { + if (IsValid565Bitmap()) { + return draw565Bitmap(tft, x, y); + } + if (IsValid888Bitmap()) { + return draw888Bitmap(tft, x, y); + } + } + return false; +} + +bool DmDrawBmpBase::draw888Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) { + const uint8_t bytesPerPixel = 3; + uint32_t filePosition = _bitmapOffset; + uint8_t red, green, blue; + uint16_t row, column; + uint16_t bytesPerRow = (bytesPerPixel*_width + 3) & ~3; + uint8_t buff[20*bytesPerPixel]; + uint8_t buffPos = sizeof(buff); + + tft.select(); + tft.setAddress(x, y, x+_width-1, y+_height-1); + tft.unSelect(); + + for(row=0; row<_height; row++) { + _readPos = filePosition = _bitmapOffset + (_height - 1 -row ) * bytesPerRow; +// if(_imageFile.position() != filePosition) { +// tft.unSelect(); +// _imageFile.seek(filePosition); +// tft.select(); +// buffPos = sizeof(buff); +// } + buffPos = sizeof(buff); + + for(column=0; column<_width; column++) { + if (buffPos >= sizeof(buff)) { + tft.unSelect(); + _readFunc(_userData, buff, _readPos, sizeof(buff)); + _readPos += sizeof(buff); +// _imageFile.read(buff, sizeof(buff)); + tft.select(); + buffPos = 0; + } + + blue = buff[buffPos++]; + green = buff[buffPos++]; + red = buff[buffPos++]; + + tft.sendData(Convert888to565(red, green, blue)); + } + } + tft.unSelect(); + return true; +} + +bool DmDrawBmpBase::draw565Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) { + const uint8_t bytesPerPixel = 2; + uint8_t buff[30*bytesPerPixel]; // Should be dividable by bytesPerPixel + uint8_t buffPos = sizeof(buff); + uint16_t bytesPerRow = (bytesPerPixel * _width + 3) & ~3; // bytes Per Row including padding to 4 bytes boundary + uint16_t paddingSize = bytesPerRow - (bytesPerPixel * _width); // paddingSize for each row + uint16_t height = -_height; // Change if load bottom-top + uint16_t pixel; + uint16_t row, column; + _readPos = _bitmapOffset; + + //_imageFile.seek(_bitmapOffset); + + tft.select(); + tft.setAddress(x, y, x+_width-1, y+height-1); + tft.unSelect(); + + for(row=0; row<height; row++) { + for(column=0; column<_width; column++) { + if (buffPos >= sizeof(buff)) { + tft.unSelect(); + _readFunc(_userData, buff, _readPos, sizeof(buff)); + _readPos += sizeof(buff); + //_imageFile.read(buff, sizeof(buff)); + tft.select(); + buffPos = 0; + } + pixel = buff[buffPos++] & 0xFF; + pixel |= buff[buffPos++] << 8; + tft.sendData(pixel); + } + + if ( paddingSize > 0 ) { // Check if there is padding in the file + if ((sizeof(buff) - buffPos) >= paddingSize) { // Most common case, the padding is in the buffer + buffPos += paddingSize; + } + else { // Padding is not in the buffer, we have to load the buffer from file + tft.unSelect(); + _readFunc(_userData, buff, _readPos, sizeof(buff)); + _readPos += sizeof(buff); +// _imageFile.read(buff, sizeof(buff)); + tft.select(); + buffPos = paddingSize-(sizeof(buff) - buffPos); // paddingSize (0-3) spaceLeftInBuffer (0-3) where spaceLeftInBuffer < paddingSize + } + } + } + tft.unSelect(); + + return true; +} + +void DmDrawBmpBase::printBmpHeaderInfo() { + printf("Image size: %d\n", _fileSize); + printf("Image offset: %d\n", _bitmapOffset); + printf("Image size: %d, %d\n", _width, _height); + printf("BitsPerPixel: %d\n",_bitsPerPixel); + printf("Compression: %d\n",_compression); + printf("Is 24-bit bmp: %d\n", IsValid888Bitmap()); + printf("Is 16-bit 565 bmp: %d\n", IsValid565Bitmap()); + printf("Has 565 color mask: %d\n", Is565ColorMask()); +} + +bool DmDrawBmpBase::readBmpHeader() { + if (read16() !=0x4D42){ // read magic byte + return false; + } + + _fileSize = read32(); + read32(); // Value depends on application which created the image + _bitmapOffset = read32(); + + // read DIB header + _headerSize = read32(); + _width = readInt32(); + _height = readInt32(); + + if (read16() != 1) { // number of color planes must be 1 + return false; + } + + _bitsPerPixel = read16(); + _compression = read32(); + + if (_bitmapOffset == 66 || _bitmapOffset == 70) { // V3 or v2 format + //setPosition(54); + _readPos = 54; + _redMask = read32(); + _greenMask = read32(); + _blueMask = read32(); + } + else { + _redMask = 0x00; + _greenMask = 0x00; + _blueMask = 0x00; + } + + if (!IsValid888Bitmap() && !IsValid565Bitmap()) + { + return false; + } + + return true; +} + +// In this context a valid bitmap +// - Stored bottom to top +// - 24-bit file +// - No compression +bool DmDrawBmpBase::IsValid888Bitmap() { + if (_height > 0 && _bitsPerPixel == 24 && _compression == 0) + { + return true; + } + return false; +} + +// In this context a valid bitmap +// - Stored top to bottom +// - 16-bit file +// - Compression 3 (BI_BITFIELDS) +// - Have a 565 Colormask +bool DmDrawBmpBase::IsValid565Bitmap() { + if (_height < 0 && _bitsPerPixel == 16 && _compression == 3 && Is565ColorMask()) + { + return true; + } + return false; +} + +bool DmDrawBmpBase::Is565ColorMask() { + if (_redMask == 0xF800 && _greenMask == 0x7E0 && _blueMask == 0x1F) + { + return true; + } + return false; +} + +int32_t DmDrawBmpBase::readInt32() { + int32_t d; + uint16_t b; + + b = read16(); + d = read16(); + d <<= 16; + d |= b; + return d; +} + +uint32_t DmDrawBmpBase::read32() { + uint32_t d; + uint16_t b; + + b = read16(); + d = read16(); + d <<= 16; + d |= b; + return d; +} + +uint16_t DmDrawBmpBase::read16() { + //uint16_t d; + //uint8_t b; + uint8_t buff[2]; + //b = _imageFile.read(); + //d = _imageFile.read(); + _readFunc(_userData, buff, _readPos, 2); + _readPos+=2; + //d <<= 8; + //d |= b; + //return d; + return (buff[1] << 8) | buff[0]; +} + +// http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888 +uint16_t DmDrawBmpBase::Convert888to565(uint8_t red, uint8_t green, uint8_t blue){ + return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DmDrawBmpBase.h Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,57 @@ +/********************************************************************************************** + Copyright (c) 2014 DisplayModule. All rights reserved. + + Redistribution and use of this source code, part of this source code or any compiled binary + based on this source code is permitted as long as the above copyright notice and following + disclaimer is retained. + + DISCLAIMER: + THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES + NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE. + ********************************************************************************************/ + +#ifndef DM_DRAW_BMP_BASE_h +#define DM_DRAW_BMP_BASE_h + +#include "dm_platform.h" +#include "DmTftBase.h" + + +typedef bool (*readFunc)(uint32_t userData, uint8_t* data, int offset, int numBytes); + +class DmDrawBmpBase { +public: + bool drawBitmap(DmTftBase& tft, uint16_t x, uint16_t y, readFunc func, uint32_t userData=0); +protected: + bool draw565Bitmap(DmTftBase& tft, uint16_t x, uint16_t y); + bool draw888Bitmap(DmTftBase& tft, uint16_t x, uint16_t y); + //virtual void setPosition(uint32_t newPosition) = 0; + uint16_t read16(); + + void printBmpHeaderInfo(); + bool readBmpHeader(); + bool IsValid888Bitmap(); + bool IsValid565Bitmap(); + bool Is565ColorMask(); + uint16_t Convert888to565(uint8_t red, uint8_t green, uint8_t blue); + + uint32_t read32(); + int32_t readInt32(); + + uint32_t _fileSize; + uint32_t _bitmapOffset; + + uint32_t _headerSize; + int32_t _width, _height; + uint16_t _bitsPerPixel; + uint32_t _compression; + uint32_t _redMask; + uint32_t _greenMask; + uint32_t _blueMask; + + readFunc _readFunc; + uint32_t _userData; + uint32_t _readPos; +}; +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DmTftLibrary.lib Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/displaymodule/code/DmTftLibrary/#59be7fca4581
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/SDFileSystem/#7b35d1709458
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/W25Q16BV.cpp Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,252 @@ +// W25Q16BV.cpp + +#include"W25Q16BV.h" + +// CONSTRUCTOR +W25Q16BV::W25Q16BV(PinName mosi, PinName miso, PinName sclk, PinName cs) : _spi(mosi, miso, sclk), _cs(cs) { + _spi.format(SPI_NBIT, SPI_MODE); + _spi.frequency(SPI_FREQ); + chipDisable(); + + exitDeepPowerDown(); + // The SPI Flash cannot safely be accessed the first 1-10 ms after power ON +// wait_us(WAIT_US_TPUW); +} + + +// READING +int W25Q16BV::readByte(int addr) { + chipEnable(); + _spi.write(R_INST); + _spi.write((addr >> 16) & 0xff); + _spi.write((addr >> 8) & 0xff); + _spi.write((addr ) & 0xff); + int response = _spi.write(DUMMY_ADDR); + chipDisable(); + return response; +} +int W25Q16BV::readByte(int a2, int a1, int a0) { + chipEnable(); + _spi.write(R_INST); + _spi.write(a2); + _spi.write(a1); + _spi.write(a0); + int response = _spi.write(DUMMY_ADDR); + chipDisable(); + return response; +} +void W25Q16BV::readStream(int addr, char* buf, int count) { + if (count < 1) + return; + chipEnable(); + _spi.write(R_INST); + _spi.write((addr >> 16) & 0xff); + _spi.write((addr >> 8) & 0xff); + _spi.write((addr ) & 0xff); + for (int i = 0; i < count; i++) + buf[i] = _spi.write(DUMMY_ADDR); + chipDisable(); +} +void W25Q16BV::readJEDEC(uint8_t* manId, uint8_t* memType, uint8_t* cap) +{ + chipEnable(); + _spi.write(JDEC_INST); + *manId = _spi.write(DUMMY_ADDR); + *memType = _spi.write(DUMMY_ADDR); + *cap = _spi.write(DUMMY_ADDR); + chipDisable(); +} +uint8_t W25Q16BV::readStatus1() +{ + uint8_t status; + chipEnable(); + _spi.write(STATUS1_INST); + status = _spi.write(DUMMY_ADDR); + chipDisable(); + return status; +} +uint8_t W25Q16BV::readStatus2() +{ + uint8_t status; + chipEnable(); + _spi.write(STATUS2_INST); + status = _spi.write(DUMMY_ADDR); + chipDisable(); + return status; +} + +// WRITING +void W25Q16BV::writeByte(int addr, int data) { + writeEnable(); + chipEnable(); + _spi.write(W_INST); + _spi.write((addr >> 16) & 0xff); + _spi.write((addr >> 8) & 0xff); + _spi.write((addr ) & 0xff); + _spi.write(data); + chipDisable(); + writeDisable(); +// wait_us(WAIT_US_TBP); + waitWhileBusy(); +} +void W25Q16BV::writeByte(int a2, int a1, int a0, int data) { + writeEnable(); + chipEnable(); + _spi.write(W_INST); + _spi.write(a2); + _spi.write(a1); + _spi.write(a0); + _spi.write(data); + chipDisable(); + writeDisable(); +// wait_us(WAIT_US_TBP); + waitWhileBusy(); +} +#if 0 +void W25Q16BV::writeStream(int addr, char* buf, int count) { + if (count < 1) + return; + writeEnable(); + chipEnable(); + _spi.write(W_INST); + _spi.write((addr & ADDR_BMASK2) >> ADDR_BSHIFT2); + _spi.write((addr & ADDR_BMASK1) >> ADDR_BSHIFT1); + _spi.write((addr & ADDR_BMASK0) >> ADDR_BSHIFT0); + for (int i = 0; i < count; i++) + _spi.write(buf[i]); + chipDisable(); + writeDisable(); + wait(WAIT_TIME_MS); +} +#else +void W25Q16BV::writeStream(int addr, char* buf, int count) +{ + int left = count; + int offset = 0; + int len = 0; + + if (count < 1) { + return; + } + + // find length of first page write + if ((addr / PAGE_SIZE) != ((addr + count) / PAGE_SIZE)) { + //spans across at least one boundary + len = PAGE_SIZE - (addr % PAGE_SIZE); + } else { + // ends inside same page => use normal length + len = count % PAGE_SIZE; + } + + //break up large write operation into several page write operations + while (left > 0) { + writeEnable(); + chipEnable(); + _spi.write(W_INST); + _spi.write(((addr + offset) >> 16) & 0xff); + _spi.write(((addr + offset) >> 8) & 0xff); + _spi.write(((addr + offset) ) & 0xff); + for (int i = 0; i < len; i++) { + _spi.write(buf[offset + i]); + } + chipDisable(); + //writeDisable(); + + offset += len; + left -= len; + len = (left < PAGE_SIZE) ? left : PAGE_SIZE; + + //wait_us(WAIT_US_TPP); + waitWhileBusy(); + } +} +#endif + +//ERASING +void W25Q16BV::chipErase() { + writeEnable(); + chipEnable(); + _spi.write(C_ERASE_INST); + chipDisable(); +// writeDisable(); +// wait_us(WAIT_US_TCE); + waitWhileBusy(); +} +bool W25Q16BV::blockErase(int startBlock, int num) { + if ((num < 1) || (startBlock < 0) || ((startBlock+num) > NUM_64KB_BLOCKS)) { + return false; + } + for (int i = 0; i < num; i++) { + writeEnable(); + chipEnable(); + _spi.write(B_ERASE_INST); + _spi.write(startBlock + i); + _spi.write(0); + _spi.write(0); + chipDisable(); +// writeDisable(); +// wait_us(WAIT_US_TBE); + waitWhileBusy(); + } + return true; +} +bool W25Q16BV::sectorErase(int startSector, int num) { + if ((num < 1) || (startSector < 0) || ((startSector+num) > NUM_SECTORS)) { + return false; + } + int addr = startSector * SECTOR_SIZE; + for (int i = 0; i < num; i++) { + writeEnable(); + chipEnable(); + _spi.write(S_ERASE_INST); + _spi.write((addr >> 16) & 0xff); + _spi.write((addr >> 8) & 0xff); + _spi.write((addr ) & 0xff); + chipDisable(); +// writeDisable(); +// wait_us(WAIT_US_TSE); + waitWhileBusy(); + + addr += SECTOR_SIZE; + } + return true; +} + +// Wakeup from deep power down (default state) +void W25Q16BV::exitDeepPowerDown() { + chipEnable(); + _spi.write(POWERUP_INST); + chipDisable(); + wait_us(WAIT_US_TRES1); +} + +void W25Q16BV::waitWhileBusy() { + uint8_t status = 0; + int i = 0; + + do { + for (i = 0; i < 0x2000; i++); + + status = readStatus1(); + } + while ((status & STATUS_1_BUSY) != 0); +} + +//ENABLE/DISABLE (private functions) +void W25Q16BV::writeEnable() { + chipEnable(); + _spi.write(WE_INST); + chipDisable(); +} +void W25Q16BV::writeDisable() { + chipEnable(); + _spi.write(WD_INST); + chipDisable(); +} +void W25Q16BV::chipEnable() { + _cs = 0; +} +void W25Q16BV::chipDisable() { + _cs = 1; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/W25Q16BV.h Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,87 @@ +// W25Q16BV.h + +#ifndef W25Q16BV_H +#define W25Q16BV_H + +#include "mbed.h" +//#include "BitBangedSPI.h" + +#define SPI_FREQ 1000000 +#define SPI_MODE 0 +#define SPI_NBIT 8 + +#define POWERUP_INST 0xAB +#define STATUS1_INST 0x05 +#define STATUS2_INST 0x35 +#define JDEC_INST 0x9F +#define UNIQUE_INST 0x4B +#define WE_INST 0x06 +#define WD_INST 0x04 +#define R_INST 0x03 +#define W_INST 0x02 +#define S_ERASE_INST 0x20 /* 4KB sector erase */ +#define B_ERASE_INST 0xD8 /* 64KB block erase */ +#define C_ERASE_INST 0x60 + +#define DUMMY_ADDR 0x00 + +#define WAIT_US_TRES1 5 /* Power Up: 3us */ +//#define WAIT_US_TPUW 10000 /* Power Up Write Time: 1-10ms */ +//#define WAIT_US_TBP 50 /* Byte Program Time: 20-50us */ +//#define WAIT_US_TPP 3000 /* Page Program Time: 0.7-3ms */ +//#define WAIT_US_TSE 400000 /* Sector Erase Time: 30-400ms */ +//#define WAIT_US_TBE 1000000 /* 64KB Block Erase Time: 1000ms */ +//#define WAIT_US_TCE 10000000 /* Chip Erase Time: 3-10s */ + +//#define ADDR_BMASK2 0x00ff0000 +//#define ADDR_BMASK1 0x0000ff00 +//#define ADDR_BMASK0 0x000000ff + +//#define ADDR_BSHIFT2 16 +//#define ADDR_BSHIFT1 8 +//#define ADDR_BSHIFT0 0 + +#define PAGE_SIZE 256 +#define SECTOR_SIZE 4096 +#define NUM_SECTORS 512 +#define NUM_64KB_BLOCKS 32 + +#define STATUS_1_BUSY 0x01 + +class W25Q16BV /*: public BitBangedSPI*/ { +public: + W25Q16BV(PinName mosi, PinName miso, PinName sclk, PinName cs); + + int readByte(int addr); // takes a 24-bit (3 bytes) address and returns the data (1 byte) at that location + int readByte(int a2, int a1, int a0); // takes the address in 3 separate bytes A[23,16], A[15,8], A[7,0] + void readStream(int addr, char* buf, int count); // takes a 24-bit address, reads count bytes, and stores results in buf + + void readJEDEC(uint8_t* manId, uint8_t* memType, uint8_t* cap); + uint8_t readStatus1(); + uint8_t readStatus2(); + + void writeByte(int addr, int data); // takes a 24-bit (3 bytes) address and a byte of data to write at that location + void writeByte(int a2, int a1, int a0, int data); // takes the address in 3 separate bytes A[23,16], A[15,8], A[7,0] + void writeStream(int addr, char* buf, int count); // write count bytes of data from buf to memory, starting at addr + + void chipErase(); // erase all data on chip + bool blockErase(int startBlock, int num=1); // erase all data in the specified number of 64KB blocks, return false if block number is invalid + bool sectorErase(int startSector, int num=1); // erase all data in the specified number of 4KB sectors, return false if sector number is invalid + +private: + + void exitDeepPowerDown(); + void waitWhileBusy(); + + void writeEnable(); // write enable + void writeDisable(); // write disable + void chipEnable(); // chip enable + void chipDisable(); // chip disable + +// BitBangedSPI _spi; + SPI _spi; + DigitalOut _cs; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,107 @@ +/********************************************************************************************** + Copyright (c) 2014 DisplayModule. All rights reserved. + + Redistribution and use of this source code, part of this source code or any compiled binary + based on this source code is permitted as long as the above copyright notice and following + disclaimer is retained. + + DISCLAIMER: + THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES + NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE. + ********************************************************************************************/ + +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" + +#include "DmTftHX8353C.h" +#include "DmTftS6D0164.h" +#include "DmTftIli9325.h" +#include "DmTftSsd2119.h" +#include "DmTouch.h" + +#include "DmDrawBmpBase.h" +#include "SDFileSystem.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + +#define log(...) printf(__VA_ARGS__) +//#define log(...) + +#define DM_PIN_SPI_MOSI A0 +#define DM_PIN_SPI_MISO D9 +#define DM_PIN_SPI_SCLK A1 + +#define DM_PIN_CS_TOUCH D8 +#define DM_PIN_CS_TFT A3 +#define DM_PIN_CS_SDCARD D10 + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +DmTftHX8353C tft; /* DM_TFT18_101 */ +//DmTftS6D0164 tft; /* DM_TFT22_102 */ +//DmTftIli9325 tft; /* DM_TFT28_103 and DM_TFT24_104 */ +//DmTftSsd2119 tft; /* DM_TFT35_107 */ + +//DmTouch touch(DmTouch::DM_TFT28_103, false); /* For LPC4088 QuickStart Board */ +//DmTouch touch(DmTouch::DM_TFT28_103); +//DmTouch touch(DmTouch::DM_TFT24_104); +//DmTouch touch(DmTouch::DM_TFT24_104, false); /* For LPC4088 QuickStart Board */ +//DmTouch touch(DmTouch::DM_TFT35_107); + +SDFileSystem sd(DM_PIN_SPI_MOSI, DM_PIN_SPI_MISO, DM_PIN_SPI_SCLK, DM_PIN_CS_SDCARD, "sd"); // mosi,miso,clk,cs + +DigitalInOut csTouch(DM_PIN_CS_TOUCH, PIN_OUTPUT, PullUp, 1); +DigitalInOut csDisplay(DM_PIN_CS_TFT, PIN_OUTPUT, PullUp, 1); +DigitalInOut csSDCard(DM_PIN_CS_SDCARD, PIN_OUTPUT, PullUp, 1); + + +/****************************************************************************** + * Global variables + *****************************************************************************/ + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +static bool sdcardReader(uint32_t userData, uint8_t* data, int offset, int numBytes) { + FILE* fp = (FILE*)userData; + fseek(fp, offset, SEEK_SET); + fread(data, 1, numBytes, fp); + return true; +} + +/****************************************************************************** + * Main + *****************************************************************************/ + +int main() { + DmDrawBmpBase bmp; + const char* fname = "/sd/logop565.bmp"; + + log("init tft \r\n"); + tft.init(); + + while (true) { + log("Drawing from SD card (%s) ...\n", fname); + FILE *fp = fopen(fname, "r"); + if (fp != NULL) { + bmp.drawBitmap(tft, 0, 0, sdcardReader, (uint32_t)fp); + fclose(fp); + } else { + log("failed to open file\n"); + log("Skipping SDCard reading as it is unsupported\n"); + tft.drawStringCentered(0, 0, tft.width(), tft.height(), "SD Card Unsupported!"); + } + + wait_ms(3000); + tft.clearScreen(RED); + wait_ms(1000); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-src.lib Tue May 20 15:42:31 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/displaymodule/code/mbed-src/#3306e8fd8143