SD + Bitmap
Dependencies: TS_DISCO_F746NG LCD_DISCO_F746NG BSP_DISCO_F746NG
Revision 0:14e97aa401f3, committed 2019-05-21
- Comitter:
- iut_cachan01
- Date:
- Tue May 21 10:24:03 2019 +0000
- Commit message:
- SD + Bitmap
Changed in this revision
diff -r 000000000000 -r 14e97aa401f3 BSP_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BSP_DISCO_F746NG.lib Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/iut_cachan01/code/BSP_DISCO_F746NG/#3da5a7fdce6c
diff -r 000000000000 -r 14e97aa401f3 LCD_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD_DISCO_F746NG.lib Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ST/code/LCD_DISCO_F746NG/#d44525b1de98
diff -r 000000000000 -r 14e97aa401f3 SD_BD_DISCO/sd_bd_disco.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SD_BD_DISCO/sd_bd_disco.cpp Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,261 @@ +/* SD/MMC Block device Library for MBED-OS + * Copyright 2017 Roy Krikke + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "sd_bd_disco.h" +#include "mbed_debug.h" + +/* Required version: 5.5.0 and above */ +#if defined(MBED_MAJOR_VERSION) && MBED_MAJOR_VERSION >= 5 +#if (MBED_VERSION < MBED_ENCODE_VERSION(5,5,0)) +#error "Incompatible mbed-os version detected! Required 5.5.0 and above" +#endif +#else +#warning "mbed-os version 5.5.0 or above required" +#endif + +/* Required version: 5.5.0 and above */ +#warning "Block device class BD_SD_DISCO_F746NG is depending on BSP_DISCO_F746NG libary (Revision 9:df2ea349c37a with date 06 Jul 2017)" + +#define SD_DBG 0 /*!< 1 - Enable debugging */ + +/** Enum of standard error codes + * + * @enum bd_sd_error + */ +enum bd_sd_error { + SD_BLOCK_DEVICE_OK = 0, /*!< no error */ + SD_BLOCK_DEVICE_ERROR = -5000, /*!< device specific error */ + //SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK = -5001, /*!< operation would block */ + //SD_BLOCK_DEVICE_ERROR_UNSUPPORTED = -5002, /*!< unsupported operation */ + SD_BLOCK_DEVICE_ERROR_PARAMETER = -5003, /*!< invalid parameter */ + SD_BLOCK_DEVICE_ERROR_NO_INIT = -5004, /*!< uninitialized */ + SD_BLOCK_DEVICE_ERROR_NO_DEVICE = -5005, /*!< device is missing or not connected */ + //SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED = -5006, /*!< write protected */ + //SD_BLOCK_DEVICE_ERROR_UNUSABLE = -5007, /*!< unusable card */ + //SD_BLOCK_DEVICE_ERROR_NO_RESPONSE = -5008, /*!< No response from device */ + //SD_BLOCK_DEVICE_ERROR_CRC = -5009, /*!< CRC error */ + SD_BLOCK_DEVICE_ERROR_ERASE = -5010, /*!< Erase error */ + SD_BLOCK_DEVICE_ERROR_READ = -5011, /*!< Read error */ + SD_BLOCK_DEVICE_ERROR_PROGRAM = -5012, /*!< Program error */ +}; + +#define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */ + +SDBlockDeviceDISCOF746NG::SDBlockDeviceDISCOF746NG() : + _read_size (BLOCK_SIZE_HC), _program_size (BLOCK_SIZE_HC), + _erase_size(BLOCK_SIZE_HC), _block_size (BLOCK_SIZE_HC), + _capacity_in_blocks (0) +{ + _timeout = 1000; +} + +SDBlockDeviceDISCOF746NG::~SDBlockDeviceDISCOF746NG() +{ + if(_is_initialized) { + deinit (); + } +} + +int SDBlockDeviceDISCOF746NG::init() +{ + lock(); + _sd_state = BSP_SD_Init(); + + if(_sd_state != MSD_OK) { + if(_sd_state == MSD_ERROR_SD_NOT_PRESENT) { + debug_if(SD_DBG, "SD card is missing or not connected\n"); + unlock (); + return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + } else { + debug_if(SD_DBG, "SD card initialization failed\n"); + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + } + BSP_SD_GetCardInfo(&_current_card_info); + + _card_type = _current_card_info.CardType; + _read_size = _current_card_info.BlockSize; + _program_size = _current_card_info.BlockSize; + _erase_size = _current_card_info.BlockSize; + _block_size = _current_card_info.BlockSize; + _capacity_in_blocks = _current_card_info.BlockNbr; + + debug_if(SD_DBG, "Card Type: %i\n", _current_card_info.CardType); + debug_if(SD_DBG, "Card Version: %i\n", _current_card_info.CardVersion); + debug_if(SD_DBG, "Class: %i\n", _current_card_info.Class); + debug_if(SD_DBG, "Relative Card Address: %x\n", _current_card_info.RelCardAdd); + debug_if(SD_DBG, "Card Capacity in blocks: %i\n", _current_card_info.BlockNbr); + debug_if(SD_DBG, "One block size in bytes: %i\n", _current_card_info.BlockSize); + debug_if(SD_DBG, "Card logical Capacity in blocks: %i\n", _current_card_info.LogBlockNbr); + debug_if(SD_DBG, "Logical block size in bytes: %i\n", _current_card_info.LogBlockSize); + debug_if(SD_DBG, "Timeout: %i\n", _timeout); + + _is_initialized = true; + unlock(); + return SD_BLOCK_DEVICE_OK; +} + +int SDBlockDeviceDISCOF746NG::deinit() +{ + lock(); + _sd_state = BSP_SD_DeInit (); + if(_sd_state != MSD_OK) { + debug_if (SD_DBG, "SD card deinitialization failed\n"); + return SD_BLOCK_DEVICE_ERROR; + } + _is_initialized = false; + unlock(); + return BD_ERROR_OK; +} + +int SDBlockDeviceDISCOF746NG::read(void *b, bd_addr_t addr, bd_size_t size) +{ + if(!is_valid_read (addr, size)) { + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + lock(); + if(!_is_initialized) { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + uint32_t *buffer = static_cast<uint32_t *> (b); + int status = SD_BLOCK_DEVICE_OK; + + // Get block address + uint32_t block_addr = addr / _block_size; + // Get block count + uint32_t block_cnt = size / _block_size; + + debug_if( + SD_DBG, + "BD_SD_DISCO_F746NG::read addr: 0x%x, block_addr: %i size: %lu block count: %i\n", + addr, block_addr, size, block_cnt); + + if(BSP_SD_ReadBlocks (buffer, block_addr, block_cnt, _timeout) != MSD_OK) { + status = SD_BLOCK_DEVICE_ERROR_READ; + } + + // Wait until SD card is ready to use for new operation + while(BSP_SD_GetCardState() != SD_TRANSFER_OK) { + } + + unlock (); + return status; +} + +int SDBlockDeviceDISCOF746NG::program(const void *b, bd_addr_t addr, bd_size_t size) +{ + if(!is_valid_program (addr, size)) { + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + lock(); + if(!_is_initialized) { + unlock (); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + uint32_t* buffer = + const_cast<uint32_t*> (reinterpret_cast<const uint32_t*> (b)); + int status = SD_BLOCK_DEVICE_OK; + + // Get block address + uint32_t block_addr = addr / _block_size; + // Get block count + uint32_t block_cnt = size / _block_size; + + debug_if ( + SD_DBG, + "BD_SD_DISCO_F746NG::program addr: 0x%x, block_addr: %i size: %lu block count: %i\n", + addr, block_addr, size, block_cnt); + + if(BSP_SD_WriteBlocks (buffer, block_addr, block_cnt, _timeout) != MSD_OK) { + status = SD_BLOCK_DEVICE_ERROR_PROGRAM; + } + + // Wait until SD card is ready to use for new operation + while(BSP_SD_GetCardState() != SD_TRANSFER_OK) { + } + + unlock(); + return status; +} + +int SDBlockDeviceDISCOF746NG::erase(bd_addr_t addr, bd_size_t size) +{ + if (!is_valid_erase(addr, size)) { + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + lock(); + if(!_is_initialized) { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + size -= _block_size; + + int status = SD_BLOCK_DEVICE_OK; + uint32_t start_addr = addr; + uint32_t end_addr = start_addr + size; + + // Get block count + uint32_t block_start_addr = start_addr / _block_size; + // Get block address + uint32_t block_end_addr = end_addr / _block_size; + + debug_if( + SD_DBG, + "BD_SD_DISCO_F746NG::erase start_addr: 0x%x, block_start_addr: %i | end_addr: 0x%x, block_end_addr: %i size: %lu\n", + start_addr, block_start_addr, end_addr, block_end_addr, size); + + if(BSP_SD_Erase (block_start_addr, block_end_addr) != MSD_OK) { + status = SD_BLOCK_DEVICE_ERROR_ERASE; + } + + /* Wait until SD card is ready to use for new operation */ + while(BSP_SD_GetCardState() != SD_TRANSFER_OK) { + } + + unlock(); + return status; +} + +bd_size_t SDBlockDeviceDISCOF746NG::get_read_size() const +{ + return _read_size; +} + +bd_size_t SDBlockDeviceDISCOF746NG::get_program_size() const +{ + return _program_size; +} + +bd_size_t SDBlockDeviceDISCOF746NG::get_erase_size() const +{ + return _erase_size; +} + +bd_size_t SDBlockDeviceDISCOF746NG::size() const +{ + return (_block_size * _capacity_in_blocks); +} + + \ No newline at end of file
diff -r 000000000000 -r 14e97aa401f3 SD_BD_DISCO/sd_bd_disco.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SD_BD_DISCO/sd_bd_disco.h Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,198 @@ +/* SD/MMC Block device Library for MBED-OS + * Copyright 2017 Roy Krikke + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __SD_BD_DISCO_H +#define __SD_BD_DISCO_H + +#include "mbed.h" +#include "BlockDevice.h" +#include "platform/PlatformMutex.h" +#include "stm32746g_discovery_sd.h" + +#define BD_SD_DISCO_F746NG_MAJOR_VERSION 1 +#define BD_SD_DISCO_F746NG_MINOR_VERSION 0 +#define BD_SD_DISCO_F746NG_PATCH_VERSION 0 + +/** + * BD_SD_DISCO_F746NG class. + * Block device class for creating a block device to access a SD/MMC card via SD/MMC interface on DISCO_F746NG + * + * Example: + * @code + * #include "mbed.h" + * #include "SDBlockDeviceDISCOF746NG.h" + * + * DigitalOut led (LED1); + * + * // Instantiate the Block Device for sd card on DISCO-F746NG + * SDBlockDeviceDISCOF746NG bd; + * uint8_t block[512] = "Hello World!\n"; + * + * int + * main () { + * Serial pc(SERIAL_TX, SERIAL_RX); + * pc.baud (115200); + * printf("Start\n"); + * + * // Call the SDBlockDevice-DISCO-F746NG instance initialisation method. + * printf("sd card init...\n"); + * if (0 != bd.init ()) { + * printf("Init failed \n"); + * return -1; + * } + * + * printf("sd size: %llu\n", bd.size ()); + * printf("sd read size: %llu\n", bd.get_read_size ()); + * printf("sd program size: %llu\n", bd.get_program_size ()); + * printf("sd erase size: %llu\n\n", bd.get_erase_size ()); + * + * printf("sd erase...\n"); + * if (0 != bd.erase (0, bd.get_erase_size ())) { + * printf ("Error Erasing block \n"); + * } + * + * // Write some the data block to the device + * printf("sd write: %s\n", block); + * if (0 == bd.program (block, 0, 512)) { + * // read the data block from the device + * printf ("sd read: "); + * if (0 == bd.read (block, 0, 512)) { + * // print the contents of the block + * printf ("%s", block); + * } + * } + * + * // Call the BD_SD_DISCO_F746NG instance de-initialisation method. + * printf("sd card deinit...\n"); + * if(0 != bd.deinit ()) { + * printf ("Deinit failed \n"); + * return -1; + * } + * + * // Blink led with 2 Hz + * while(true) { + * led = !led; + * wait (0.5); + * } + * } + * @endcode + * + */ +class SDBlockDeviceDISCOF746NG : public BlockDevice +{ +public: + + /** Lifetime of the memory block device + * + * Only a block size of 512 bytes is supported + * + */ + SDBlockDeviceDISCOF746NG(); + virtual ~SDBlockDeviceDISCOF746NG(); + + /** Initialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int init(); + + /** Deinitialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int deinit(); + + /** Read blocks from a block device + * + * @param buffer Buffer to read blocks into + * @param addr Address of block to begin reading from + * @param size Size to read in bytes, must be a multiple of read block size + * @return 0 on success, negative error code on failure + */ + virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); + + /** Program blocks to a block device + * + * The blocks must have been erased prior to being programmed + * + * @param buffer Buffer of data to write to blocks + * @param addr Address of block to begin writing to + * @param size Size to write in bytes, must be a multiple of program block size + * @return 0 on success, negative error code on failure + */ + virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); + + /** Erase blocks on a block device + * + * The state of an erased block is undefined until it has been programmed + * + * @param addr Address of block to begin erasing + * @param size Size to erase in bytes, must be a multiple of erase block size + * @return 0 on success, negative error code on failure + */ + virtual int erase(bd_addr_t addr, bd_size_t size); + + /** Get the size of a readable block + * + * @return Size of a readable block in bytes + */ + virtual bd_size_t get_read_size() const; + + /** Get the size of a programable block + * + * @return Size of a programable block in bytes + */ + virtual bd_size_t get_program_size() const; + + /** Get the size of a eraseable block + * + * @return Size of a eraseable block in bytes + */ + virtual bd_size_t get_erase_size() const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + virtual bd_size_t size() const; + +private: + uint8_t _card_type; + bd_size_t _read_size; + bd_size_t _program_size; + bd_size_t _erase_size; + bd_size_t _block_size; + bd_size_t _capacity_in_blocks; + BSP_SD_CardInfo _current_card_info; + uint8_t _sd_state; + uint32_t _timeout; + PlatformMutex _mutex; + bool _is_initialized; + + virtual void + lock () { + _mutex.lock(); + } + + virtual void + unlock() { + _mutex.unlock (); + } + +}; + +#endif /* __SD_BD_DISCO_H */
diff -r 000000000000 -r 14e97aa401f3 TS_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TS_DISCO_F746NG.lib Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ST/code/TS_DISCO_F746NG/#fe0cf5e2960f
diff -r 000000000000 -r 14e97aa401f3 bitmap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bitmap.h Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,774 @@ +/* + * Windows Bitmap File Loader + * Version 1.2.5 (20120929) + * + * Supported Formats: 1, 4, 8, 16, 24, 32 Bit Images + * Alpha Bitmaps are also supported. + * Supported compression types: RLE 8, BITFIELDS + * + * Created by: Benjamin Kalytta, 2006 - 2012 + * Thanks for bug fixes goes to: Chris Campbell + * + * Licence: Free to use, URL to my source and my name is required in your source code. + * + * Source can be found at http://www.kalytta.com/bitmap.h + * + * Warning: This code should not be used in unmodified form in a production environment. + * It should only serve as a basis for your own development. + * There is only a minimal error handling in this code. (Notice added 20111211) + */ + +#ifndef BITMAP_H +#define BITMAP_H + +#include <iostream> +#include <fstream> +#include <string> + +#ifndef __LITTLE_ENDIAN__ + #ifndef __BIG_ENDIAN__ + #define __LITTLE_ENDIAN__ + #endif +#endif + +#ifdef __LITTLE_ENDIAN__ + #define BITMAP_SIGNATURE 0x4d42 +#else + #define BITMAP_SIGNATURE 0x424d +#endif + +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) + typedef unsigned __int32 uint32_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int8 uint8_t; + typedef __int32 int32_t; +#elif defined(__GNUC__) || defined(__CYGWIN__) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__PGI) || defined(__LCC__) + #include <stdint.h> +#else + typedef unsigned int uint32_t; + typedef unsigned short int uint16_t; + typedef unsigned char uint8_t; + typedef int int32_t; +#endif + +#pragma pack(push, 1) + +typedef struct _BITMAP_FILEHEADER { + uint16_t Signature; + uint32_t Size; + uint32_t Reserved; + uint32_t BitsOffset; +} BITMAP_FILEHEADER; + +#define BITMAP_FILEHEADER_SIZE 14 + +typedef struct _BITMAP_HEADER { + uint32_t HeaderSize; + int32_t Width; + int32_t Height; + uint16_t Planes; + uint16_t BitCount; + uint32_t Compression; + uint32_t SizeImage; + int32_t PelsPerMeterX; + int32_t PelsPerMeterY; + uint32_t ClrUsed; + uint32_t ClrImportant; + uint32_t RedMask; + uint32_t GreenMask; + uint32_t BlueMask; + uint32_t AlphaMask; + uint32_t CsType; + uint32_t Endpoints[9]; // see http://msdn2.microsoft.com/en-us/library/ms536569.aspx + uint32_t GammaRed; + uint32_t GammaGreen; + uint32_t GammaBlue; +} BITMAP_HEADER; + +typedef struct _RGBA { + uint8_t Red; + uint8_t Green; + uint8_t Blue; + uint8_t Alpha; +} RGBA; + +typedef struct _BGRA { + uint8_t Blue; + uint8_t Green; + uint8_t Red; + uint8_t Alpha; +} BGRA; + +#pragma pack(pop) + +class CBitmap { +private: + BITMAP_FILEHEADER m_BitmapFileHeader; + BITMAP_HEADER m_BitmapHeader; + BGRA *m_BitmapData; + unsigned int m_BitmapSize; + + // Masks and bit counts shouldn't exceed 32 Bits +public: + class CColor { +public: + static inline unsigned int BitCountByMask(unsigned int Mask) { + unsigned int BitCount = 0; + while (Mask) { + Mask &= Mask - 1; + BitCount++; + } + return BitCount; + } + + static inline unsigned int BitPositionByMask(unsigned int Mask) { + return BitCountByMask((Mask & (~Mask + 1)) - 1); + } + + static inline unsigned int ComponentByMask(unsigned int Color, unsigned int Mask) { + unsigned int Component = Color & Mask; + return Component >> BitPositionByMask(Mask); + } + + static inline unsigned int BitCountToMask(unsigned int BitCount) { + return (BitCount == 32) ? 0xFFFFFFFF : (1 << BitCount) - 1; + } + + static unsigned int Convert(unsigned int Color, unsigned int FromBitCount, unsigned int ToBitCount) { + if (ToBitCount < FromBitCount) { + Color >>= (FromBitCount - ToBitCount); + } else { + Color <<= (ToBitCount - FromBitCount); + if (Color > 0) { + Color |= BitCountToMask(ToBitCount - FromBitCount); + } + } + return Color; + } + }; + +public: + + CBitmap() : m_BitmapData(0), m_BitmapSize(0) { + Dispose(); + } + + CBitmap(const char* Filename) : m_BitmapData(0), m_BitmapSize(0) { + Load(Filename); + } + + ~CBitmap() { + Dispose(); + } + + void Dispose() { + if (m_BitmapData) { + delete[] m_BitmapData; + m_BitmapData = 0; + } + memset(&m_BitmapFileHeader, 0, sizeof(m_BitmapFileHeader)); + memset(&m_BitmapHeader, 0, sizeof(m_BitmapHeader)); + } + + /* Load specified Bitmap and stores it as RGBA in an internal buffer */ + + bool Load(const char *Filename) { + std::ifstream file(Filename, std::ios::binary | std::ios::in); + + if (file.bad()) { + return false; + } + + if (file.is_open() == false) { + return false; + } + + Dispose(); + + file.read((char*) &m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE); + if (m_BitmapFileHeader.Signature != BITMAP_SIGNATURE) { + return false; + } + + file.read((char*) &m_BitmapHeader, sizeof(BITMAP_HEADER)); + + /* Load Color Table */ + + file.seekg(BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, std::ios::beg); + + unsigned int ColorTableSize = 0; + + if (m_BitmapHeader.BitCount == 1) { + ColorTableSize = 2; + } else if (m_BitmapHeader.BitCount == 4) { + ColorTableSize = 16; + } else if (m_BitmapHeader.BitCount == 8) { + ColorTableSize = 256; + } + + // Always allocate full sized color table + + BGRA* ColorTable = new BGRA[ColorTableSize]; // std::bad_alloc exception should be thrown if memory is not available + + file.read((char*) ColorTable, sizeof(BGRA) * m_BitmapHeader.ClrUsed); + + /* ... Color Table for 16 bits images are not supported yet */ + + m_BitmapSize = GetWidth() * GetHeight(); + m_BitmapData = new BGRA[m_BitmapSize]; + + unsigned int LineWidth = ((GetWidth() * GetBitCount() / 8) + 3) & ~3; + uint8_t *Line = new uint8_t[LineWidth]; + + file.seekg(m_BitmapFileHeader.BitsOffset, std::ios::beg); + + int Index = 0; + bool Result = true; + + if (m_BitmapHeader.Compression == 0) { + for (unsigned int i = 0; i < GetHeight(); i++) { + file.read((char*) Line, LineWidth); + + uint8_t *LinePtr = Line; + + for (unsigned int j = 0; j < GetWidth(); j++) { + if (m_BitmapHeader.BitCount == 1) { + uint32_t Color = *((uint8_t*) LinePtr); + for (int k = 0; k < 8; k++) { + m_BitmapData[Index].Red = ColorTable[Color & 0x80 ? 1 : 0].Red; + m_BitmapData[Index].Green = ColorTable[Color & 0x80 ? 1 : 0].Green; + m_BitmapData[Index].Blue = ColorTable[Color & 0x80 ? 1 : 0].Blue; + m_BitmapData[Index].Alpha = ColorTable[Color & 0x80 ? 1 : 0].Alpha; + Index++; + Color <<= 1; + } + LinePtr++; + j += 7; + } else if (m_BitmapHeader.BitCount == 4) { + uint32_t Color = *((uint8_t*) LinePtr); + m_BitmapData[Index].Red = ColorTable[(Color >> 4) & 0x0f].Red; + m_BitmapData[Index].Green = ColorTable[(Color >> 4) & 0x0f].Green; + m_BitmapData[Index].Blue = ColorTable[(Color >> 4) & 0x0f].Blue; + m_BitmapData[Index].Alpha = ColorTable[(Color >> 4) & 0x0f].Alpha; + Index++; + m_BitmapData[Index].Red = ColorTable[Color & 0x0f].Red; + m_BitmapData[Index].Green = ColorTable[Color & 0x0f].Green; + m_BitmapData[Index].Blue = ColorTable[Color & 0x0f].Blue; + m_BitmapData[Index].Alpha = ColorTable[Color & 0x0f].Alpha; + Index++; + LinePtr++; + j++; + } else if (m_BitmapHeader.BitCount == 8) { + uint32_t Color = *((uint8_t*) LinePtr); + m_BitmapData[Index].Red = ColorTable[Color].Red; + m_BitmapData[Index].Green = ColorTable[Color].Green; + m_BitmapData[Index].Blue = ColorTable[Color].Blue; + m_BitmapData[Index].Alpha = ColorTable[Color].Alpha; + Index++; + LinePtr++; + } else if (m_BitmapHeader.BitCount == 16) { + uint32_t Color = *((uint16_t*) LinePtr); + m_BitmapData[Index].Red = ((Color >> 10) & 0x1f) << 3; + m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3; + m_BitmapData[Index].Blue = (Color & 0x1f) << 3; + m_BitmapData[Index].Alpha = 255; + Index++; + LinePtr += 2; + } else if (m_BitmapHeader.BitCount == 24) { + uint32_t Color = *((uint32_t*) LinePtr); + m_BitmapData[Index].Blue = Color & 0xff; + m_BitmapData[Index].Green = (Color >> 8) & 0xff; + m_BitmapData[Index].Red = (Color >> 16) & 0xff; + m_BitmapData[Index].Alpha = 255; + Index++; + LinePtr += 3; + } else if (m_BitmapHeader.BitCount == 32) { + uint32_t Color = *((uint32_t*) LinePtr); + m_BitmapData[Index].Blue = Color & 0xff; + m_BitmapData[Index].Green = (Color >> 8) & 0xff; + m_BitmapData[Index].Red = (Color >> 16) & 0xff; + m_BitmapData[Index].Alpha = Color >> 24; + Index++; + LinePtr += 4; + } + } + } + } else if (m_BitmapHeader.Compression == 1) { // RLE 8 + uint8_t Count = 0; + uint8_t ColorIndex = 0; + int x = 0, y = 0; + + while (file.eof() == false) { + file.read((char*) &Count, sizeof(uint8_t)); + file.read((char*) &ColorIndex, sizeof(uint8_t)); + + if (Count > 0) { + Index = x + y * GetWidth(); + for (int k = 0; k < Count; k++) { + m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red; + m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green; + m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue; + m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha; + } + x += Count; + } else if (Count == 0) { + int Flag = ColorIndex; + if (Flag == 0) { + x = 0; + y++; + } else if (Flag == 1) { + break; + } else if (Flag == 2) { + char rx = 0; + char ry = 0; + file.read((char*) &rx, sizeof(char)); + file.read((char*) &ry, sizeof(char)); + x += rx; + y += ry; + } else { + Count = Flag; + Index = x + y * GetWidth(); + for (int k = 0; k < Count; k++) { + file.read((char*) &ColorIndex, sizeof(uint8_t)); + m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red; + m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green; + m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue; + m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha; + } + x += Count; + // Attention: Current Microsoft STL implementation seems to be buggy, tellg() always returns 0. + if (file.tellg() & 1) { + file.seekg(1, std::ios::cur); + } + } + } + } + } else if (m_BitmapHeader.Compression == 2) { // RLE 4 + /* RLE 4 is not supported */ + Result = false; + } else if (m_BitmapHeader.Compression == 3) { // BITFIELDS + + /* We assumes that mask of each color component can be in any order */ + + uint32_t BitCountRed = CColor::BitCountByMask(m_BitmapHeader.RedMask); + uint32_t BitCountGreen = CColor::BitCountByMask(m_BitmapHeader.GreenMask); + uint32_t BitCountBlue = CColor::BitCountByMask(m_BitmapHeader.BlueMask); + uint32_t BitCountAlpha = CColor::BitCountByMask(m_BitmapHeader.AlphaMask); + + for (unsigned int i = 0; i < GetHeight(); i++) { + file.read((char*) Line, LineWidth); + + uint8_t *LinePtr = Line; + + for (unsigned int j = 0; j < GetWidth(); j++) { + + uint32_t Color = 0; + + if (m_BitmapHeader.BitCount == 16) { + Color = *((uint16_t*) LinePtr); + LinePtr += 2; + } else if (m_BitmapHeader.BitCount == 32) { + Color = *((uint32_t*) LinePtr); + LinePtr += 4; + } else { + // Other formats are not valid + } + m_BitmapData[Index].Red = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.RedMask), BitCountRed, 8); + m_BitmapData[Index].Green = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.GreenMask), BitCountGreen, 8); + m_BitmapData[Index].Blue = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.BlueMask), BitCountBlue, 8); + m_BitmapData[Index].Alpha = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.AlphaMask), BitCountAlpha, 8); + + Index++; + } + } + } + + delete [] ColorTable; + delete [] Line; + + file.close(); + return Result; + } + + bool Save(const char* Filename, unsigned int BitCount = 32) { + bool Result = true; + + std::ofstream file(Filename, std::ios::out | std::ios::binary); + + if (file.is_open() == false) { + return false; + } + + BITMAP_FILEHEADER bfh; + BITMAP_HEADER bh; + memset(&bfh, 0, sizeof(bfh)); + memset(&bh, 0, sizeof(bh)); + + bfh.Signature = BITMAP_SIGNATURE; + bfh.BitsOffset = BITMAP_FILEHEADER_SIZE + sizeof(BITMAP_HEADER); + bfh.Size = (GetWidth() * GetHeight() * BitCount) / 8 + bfh.BitsOffset; + + bh.HeaderSize = sizeof(BITMAP_HEADER); + bh.BitCount = BitCount; + + if (BitCount == 32) { + bh.Compression = 3; // BITFIELD + bh.AlphaMask = 0xff000000; + bh.BlueMask = 0x00ff0000; + bh.GreenMask = 0x0000ff00; + bh.RedMask = 0x000000ff; + } else if (BitCount == 16) { + bh.Compression = 3; // BITFIELD + bh.AlphaMask = 0x00000000; + bh.BlueMask = 0x0000001f; + bh.GreenMask = 0x000007E0; + bh.RedMask = 0x0000F800; + } else { + bh.Compression = 0; // RGB + } + + unsigned int LineWidth = (GetWidth() + 3) & ~3; + + bh.Planes = 1; + bh.Height = GetHeight(); + bh.Width = GetWidth(); + bh.SizeImage = (LineWidth * BitCount * GetHeight()) / 8; + bh.PelsPerMeterX = 3780; + bh.PelsPerMeterY = 3780; + + if (BitCount == 32) { + file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER)); + file.write((char*) &bh, sizeof(BITMAP_HEADER)); + file.write((char*) m_BitmapData, bh.SizeImage); + } else if (BitCount < 16) { + uint8_t* Bitmap = new uint8_t[bh.SizeImage]; + + BGRA *Palette = 0; + unsigned int PaletteSize = 0; + + if (GetBitsWithPalette(Bitmap, bh.SizeImage, BitCount, Palette, PaletteSize)) { + bfh.BitsOffset += PaletteSize * sizeof(BGRA); + + file.write((char*) &bfh, BITMAP_FILEHEADER_SIZE); + file.write((char*) &bh, sizeof(BITMAP_HEADER)); + file.write((char*) Palette, PaletteSize * sizeof(BGRA)); + file.write((char*) Bitmap, bh.SizeImage); + } + delete [] Bitmap; + delete [] Palette; + } else { + uint32_t RedMask = 0; + uint32_t GreenMask = 0; + uint32_t BlueMask = 0; + uint32_t AlphaMask = 0; + + if (BitCount == 16) { + RedMask = 0x0000F800; + GreenMask = 0x000007E0; + BlueMask = 0x0000001F; + AlphaMask = 0x00000000; + } else if (BitCount == 24) { + RedMask = 0x00FF0000; + GreenMask = 0x0000FF00; + BlueMask = 0x000000FF; + } else { + // Other color formats are not valid + Result = false; + } + + if (Result) { + if (GetBits(NULL, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) { + uint8_t* Bitmap = new uint8_t[bh.SizeImage]; + if (GetBits(Bitmap, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) { + file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER)); + file.write((char*) &bh, sizeof(BITMAP_HEADER)); + file.write((char*) Bitmap, bh.SizeImage); + } + delete [] Bitmap; + } + } + } + + file.close(); + return Result; + } + + unsigned int GetWidth() { + /* Add plausibility test */ + // if (abs(m_BitmapHeader.Width) > 8192) { + // m_BitmapHeader.Width = 8192; + // } + return m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width; + } + + unsigned int GetHeight() { + /* Add plausibility test */ + // if (abs(m_BitmapHeader.Height) > 8192) { + // m_BitmapHeader.Height = 8192; + // } + return m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height; + } + + unsigned int GetBitCount() { + /* Add plausibility test */ + // if (m_BitmapHeader.BitCount > 32) { + // m_BitmapHeader.BitCount = 32; + // } + return m_BitmapHeader.BitCount; + } + + /* Copies internal RGBA buffer to user specified buffer */ + + bool GetBits(void* Buffer, unsigned int &Size) { + bool Result = false; + if (Size == 0 || Buffer == 0) { + Size = m_BitmapSize * sizeof(RGBA); + Result = m_BitmapSize != 0; + } else { + memcpy(Buffer, m_BitmapData, Size); + Result = true; + } + return Result; + } + + /* Returns internal RGBA buffer */ + + void* GetBits() { + return m_BitmapData; + } + + /* Copies internal RGBA buffer to user specified buffer and converts it into destination + * bit format specified by component masks. + * + * Typical Bitmap color formats (BGR/BGRA): + * + * Masks for 16 bit (5-5-5): ALPHA = 0x00000000, RED = 0x00007C00, GREEN = 0x000003E0, BLUE = 0x0000001F + * Masks for 16 bit (5-6-5): ALPHA = 0x00000000, RED = 0x0000F800, GREEN = 0x000007E0, BLUE = 0x0000001F + * Masks for 24 bit: ALPHA = 0x00000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF + * Masks for 32 bit: ALPHA = 0xFF000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF + * + * Other color formats (RGB/RGBA): + * + * Masks for 32 bit (RGBA): ALPHA = 0xFF000000, RED = 0x000000FF, GREEN = 0x0000FF00, BLUE = 0x00FF0000 + * + * Bit count will be rounded to next 8 bit boundary. If IncludePadding is true, it will be ensured + * that line width is a multiple of 4. padding bytes are included if necessary. + * + * NOTE: systems with big endian byte order may require masks in inversion order. + */ + + bool GetBits(void* Buffer, unsigned int &Size, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask, bool IncludePadding = true) { + bool Result = false; + + uint32_t BitCountRed = CColor::BitCountByMask(RedMask); + uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask); + uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask); + uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask); + + unsigned int BitCount = (BitCountRed + BitCountGreen + BitCountBlue + BitCountAlpha + 7) & ~7; + + if (BitCount > 32) { + return false; + } + + unsigned int w = GetWidth(); + //unsigned int LineWidth = (w + 3) & ~3; + unsigned int dataBytesPerLine = (w * BitCount + 7) / 8; + unsigned int LineWidth = (dataBytesPerLine + 3) & ~3; + + if (Size == 0 || Buffer == 0) { + //Size = (LineWidth * GetHeight() * BitCount) / 8 + sizeof(unsigned int); + Size = (GetWidth() * GetHeight() * BitCount) / 8 + sizeof(unsigned int); + return true; + } + + uint8_t* BufferPtr = (uint8_t*) Buffer; + + Result = true; + + uint32_t BitPosRed = CColor::BitPositionByMask(RedMask); + uint32_t BitPosGreen = CColor::BitPositionByMask(GreenMask); + uint32_t BitPosBlue = CColor::BitPositionByMask(BlueMask); + uint32_t BitPosAlpha = CColor::BitPositionByMask(AlphaMask); + + unsigned int j = 0; + + for (unsigned int i = 0; i < m_BitmapSize; i++) { + *(uint32_t*) BufferPtr = + (CColor::Convert(m_BitmapData[i].Blue, 8, BitCountBlue) << BitPosBlue) | + (CColor::Convert(m_BitmapData[i].Green, 8, BitCountGreen) << BitPosGreen) | + (CColor::Convert(m_BitmapData[i].Red, 8, BitCountRed) << BitPosRed) | + (CColor::Convert(m_BitmapData[i].Alpha, 8, BitCountAlpha) << BitPosAlpha); + + if (IncludePadding) { + j++; + if (j >= w) { + for (unsigned int k = 0; k < LineWidth - dataBytesPerLine; k++) { + BufferPtr += (BitCount >> 3); + } + j = 0; + } + } + + BufferPtr += (BitCount >> 3); + } + + Size -= sizeof(unsigned int); + + return Result; + } + + /* See GetBits(). + * It creates a corresponding color table (palette) which have to be destroyed by the user after usage. + * + * Supported Bit depths are: 4, 8 + * + * Todo: Optimize, use optimized palette, do ditehring (see my dithering class), support padding for 4 bit bitmaps + */ + + bool GetBitsWithPalette(void* Buffer, unsigned int &Size, unsigned int BitCount, BGRA* &Palette, unsigned int &PaletteSize, bool OptimalPalette = false, bool IncludePadding = true) { + bool Result = false; + + if (BitCount > 16) { + return false; + } + + unsigned int w = GetWidth(); + unsigned int dataBytesPerLine = (w * BitCount + 7) / 8; + unsigned int LineWidth = (dataBytesPerLine + 3) & ~3; + + if (Size == 0 || Buffer == 0) { + Size = (LineWidth * GetHeight() * BitCount) / 8; + return true; + } + + + if (OptimalPalette) { + PaletteSize = 0; + // Not implemented + } else { + if (BitCount == 1) { + PaletteSize = 2; + // Not implemented: Who need that? + } else if (BitCount == 4) { // 2:2:1 + PaletteSize = 16; + Palette = new BGRA[PaletteSize]; + for (int r = 0; r < 4; r++) { + for (int g = 0; g < 2; g++) { + for (int b = 0; b < 2; b++) { + Palette[r | g << 2 | b << 3].Red = r ? (r << 6) | 0x3f : 0; + Palette[r | g << 2 | b << 3].Green = g ? (g << 7) | 0x7f : 0; + Palette[r | g << 2 | b << 3].Blue = b ? (b << 7) | 0x7f : 0; + Palette[r | g << 2 | b << 3].Alpha = 0xff; + } + } + } + } else if (BitCount == 8) { // 3:3:2 + PaletteSize = 256; + Palette = new BGRA[PaletteSize]; + for (int r = 0; r < 8; r++) { + for (int g = 0; g < 8; g++) { + for (int b = 0; b < 4; b++) { + Palette[r | g << 3 | b << 6].Red = r ? (r << 5) | 0x1f : 0; + Palette[r | g << 3 | b << 6].Green = g ? (g << 5) | 0x1f : 0; + Palette[r | g << 3 | b << 6].Blue = b ? (b << 6) | 0x3f : 0; + Palette[r | g << 3 | b << 6].Alpha = 0xff; + } + } + } + } else if (BitCount == 16) { // 5:5:5 + // Not implemented + } + } + + unsigned int j = 0; + uint8_t* BufferPtr = (uint8_t*) Buffer; + + for (unsigned int i = 0; i < m_BitmapSize; i++) { + if (BitCount == 1) { + // Not implemented: Who needs that? + } else if (BitCount == 4) { + *BufferPtr = ((m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3) << 4; + i++; + *BufferPtr |= (m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3; + } else if (BitCount == 8) { + *BufferPtr = (m_BitmapData[i].Red >> 5) | (m_BitmapData[i].Green >> 5) << 3 | (m_BitmapData[i].Blue >> 5) << 6; + } else if (BitCount == 16) { + // Not implemented + } + + if (IncludePadding) { + j++; + if (j >= w) { + for (unsigned int k = 0; k < (LineWidth - dataBytesPerLine); k++) { + BufferPtr += BitCount / 8; + } + j = 0; + } + } + + BufferPtr++; + } + + Result = true; + + return Result; + } + + /* Set Bitmap Bits. Will be converted to RGBA internally */ + + bool SetBits(void* Buffer, unsigned int Width, unsigned int Height, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask = 0) { + if (Buffer == 0) { + return false; + } + + uint8_t *BufferPtr = (uint8_t*) Buffer; + + Dispose(); + + m_BitmapHeader.Width = Width; + m_BitmapHeader.Height = Height; + m_BitmapHeader.BitCount = 32; + m_BitmapHeader.Compression = 3; + + m_BitmapSize = GetWidth() * GetHeight(); + m_BitmapData = new BGRA[m_BitmapSize]; + + /* Find bit count by masks (rounded to next 8 bit boundary) */ + + unsigned int BitCount = (CColor::BitCountByMask(RedMask | GreenMask | BlueMask | AlphaMask) + 7) & ~7; + + uint32_t BitCountRed = CColor::BitCountByMask(RedMask); + uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask); + uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask); + uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask); + + for (unsigned int i = 0; i < m_BitmapSize; i++) { + unsigned int Color = 0; + if (BitCount <= 8) { + Color = *((uint8_t*) BufferPtr); + BufferPtr += 1; + } else if (BitCount <= 16) { + Color = *((uint16_t*) BufferPtr); + BufferPtr += 2; + } else if (BitCount <= 24) { + Color = *((uint32_t*) BufferPtr); + BufferPtr += 3; + } else if (BitCount <= 32) { + Color = *((uint32_t*) BufferPtr); + BufferPtr += 4; + } else { + /* unsupported */ + BufferPtr += 1; + } + m_BitmapData[i].Alpha = CColor::Convert(CColor::ComponentByMask(Color, AlphaMask), BitCountAlpha, 8); + m_BitmapData[i].Red = CColor::Convert(CColor::ComponentByMask(Color, RedMask), BitCountRed, 8); + m_BitmapData[i].Green = CColor::Convert(CColor::ComponentByMask(Color, GreenMask), BitCountGreen, 8); + m_BitmapData[i].Blue = CColor::Convert(CColor::ComponentByMask(Color, BlueMask), BitCountBlue, 8); + } + + return true; + } +}; + +#endif
diff -r 000000000000 -r 14e97aa401f3 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,169 @@ +/* Example file of using SD/MMC Block device Library for MBED-OS + * Copyright 2017 Roy Krikke + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "mbed.h" +#include "FATFileSystem.h" +#include "sd_bd_disco.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "TS_DISCO_F746NG.h" +#include "LCD_DISCO_F746NG.h" +#include "stm32746g_discovery_lcd.h" +#include "bitmap.h" + +LCD_DISCO_F746NG lcd; +TS_DISCO_F746NG ts; + +DigitalOut led (LED1); + +// Instantiate the Block Device for sd card on DISCO-F746NG +SDBlockDeviceDISCOF746NG bd; +FATFileSystem fs ("fs"); + +void return_error (int ret_val) +{ + char buf[30]; + if (ret_val) { + sprintf(buf, "Fail %d", ret_val); + lcd.DisplayStringAt(0, LINE(8), (uint8_t *)buf, CENTER_MODE); + } else { + lcd.DisplayStringAt(0, LINE(8), (uint8_t *)"Done", CENTER_MODE); + } +} + +void errno_error(void* ret_val) +{ + char buf[30]; + if (ret_val == NULL) { + sprintf(buf, "Fail %d", errno); + lcd.DisplayStringAt(0, LINE(9), (uint8_t *)buf, CENTER_MODE); + } else { + lcd.DisplayStringAt(0, LINE(9), (uint8_t *)"Done", CENTER_MODE); + } +} + +int main () +{ + char buf[100]; + + lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"TOUCHSCREEN SD DEMO", CENTER_MODE); + lcd.SetFont(&Font12); + lcd.DisplayStringAt(0, LINE(2), (uint8_t *)"Start", CENTER_MODE); + wait(1); + + int error = 0; + /* + error = FATFileSystem::format(&bd); + return_error(error); + */ + lcd.DisplayStringAt(0, LINE(3), (uint8_t *)"Mounting the filesystem on \"/fs\". ", CENTER_MODE); + error = fs.mount(&bd); + return_error(error); + + CBitmap bmp("/fs/minion.bmp"); + + sprintf(buf, "Bitmap width: %3d - height: %3d", bmp.GetWidth(), bmp.GetHeight()); + lcd.DisplayStringAt(0, LINE(5), (uint8_t *)buf, CENTER_MODE); + +// BSP_LCD_DrawBitmapRAM(150,100,bmp.GetWidth(), bmp.GetHeight(),(uint8_t *)bmp.GetBits()); + while (1) { + int layer = 0; + for (int k=0; k<50; k++) { + uint32_t *p = (uint32_t *)bmp.GetBits(); + lcd.SelectLayer(layer); + lcd.Clear(0); + for (int i=bmp.GetHeight()-1; i>=0; i--) { + if (i+2*k >= lcd.GetYSize()) { + p += bmp.GetWidth(); + continue; + } + for (int j=0; j<bmp.GetWidth(); j++) { + /* uint32_t c0 = *p++; + uint8_t a = c0>>24; + uint8_t r = c0>>16; + uint8_t g = c0>>8; + uint8_t b = c0; + uint32_t c = (a<<24)+(b<<16)+(g<<8)+r;*/ + uint32_t x = j + 3*k; + if (x >= lcd.GetXSize()) break; + lcd.DrawPixel(x, i+2*k, *p++); + } + } + /* lcd.SetLayerVisible(layer, ENABLE); + layer = !layer; + lcd.SetLayerVisible(layer, DISABLE);*/ + BSP_LCD_SetLayerVisible_NoReload(layer, ENABLE); + layer = !layer; + BSP_LCD_SetLayerVisible_NoReload(layer, DISABLE); + BSP_LCD_Reload(LCD_RELOAD_VERTICAL_BLANKING); + wait(0.02); + } + wait(1); + } +// lcd.DrawBitmap(0,0,(uint8_t *)bmp.GetBits()); + /* + lcd.DisplayStringAt(0, LINE(4), (uint8_t *)"Opening a new file, numbers.txt.", CENTER_MODE); + FILE* fd = fopen("/fs/numbers.txt", "w"); + errno_error(fd); + + for (int i = 0; i < 20; i++) { + sprintf(buf, "Writing decimal numbers to a file (%2d/20)", i+1); + lcd.DisplayStringAt(0, LINE(5), (uint8_t *)buf, CENTER_MODE); + fprintf(fd, "%d\r\n", i); + } + + fclose(fd); + printf(" done.\r\n"); + lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"File closed", CENTER_MODE); + */ + /* fd = fopen("/fs/numbers.txt", "r"); + errno_error(fd); + + printf("Dumping file to screen.\r\n"); + char buff[16] = { 0 }; + while(!feof (fd)) { + int size = fread(&buff[0], 1, 15, fd); + fwrite(&buff[0], 1, size, stdout); + } + printf("EOF.\r\n"); + + printf("Closing file."); + fclose(fd); + printf(" done.\r\n"); + + printf("Opening root directory."); + DIR* dir = opendir("/fs/"); + errno_error(fd); + + struct dirent* de; + printf("Printing all filenames:\r\n"); + while((de = readdir (dir)) != NULL) { + printf(" %s\r\n", &(de->d_name)[0]); + } + + printf("Closeing root directory. "); + error = closedir(dir); + return_error(error); + printf("Filesystem Demo complete.\r\n"); + */ + // Blink led with 2 Hz + while(true) { + led = !led; + wait (0.5); + } +}
diff -r 000000000000 -r 14e97aa401f3 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Tue May 21 10:24:03 2019 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#ae6c7c60f91c89cbf755a2f3c8ec9c66635849fd