From 14925480325d952577ccd72d7f4674b6ab067d73 Mon Sep 17 00:00:00 2001 From: sumotoy Date: Mon, 2 Mar 2015 23:59:42 +0100 Subject: [PATCH] fixes, added SD subroutines --- TFT_ILI9163C.cpp | 76 +++++++++----- TFT_ILI9163C.h | 8 +- examples/SD_example/SD_example.ino | 158 +++++++++++++++++++++++++++++ examples/bigPicture/bigPicture.ino | 26 ++++- keywords.txt | 7 +- 5 files changed, 241 insertions(+), 34 deletions(-) create mode 100644 examples/SD_example/SD_example.ino diff --git a/TFT_ILI9163C.cpp b/TFT_ILI9163C.cpp index e832508..587e193 100644 --- a/TFT_ILI9163C.cpp +++ b/TFT_ILI9163C.cpp @@ -287,7 +287,7 @@ void TFT_ILI9163C::chipInit() { writedata16_cont(0x00); writedata16_last(_GRAMHEIGH); - SPI.endTransaction(); + endProc(); colorSpace(_colorspaceData); setRotation(0); SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); @@ -361,7 +361,7 @@ void TFT_ILI9163C::chipInit() { //writedata(0X00); //writedata(_GRAMHEIGH); writedata16(0X00); - writedata16(_GRAMHEIGH) + writedata16(_GRAMHEIGH); colorSpace(_colorspaceData); setRotation(0); @@ -468,10 +468,15 @@ void TFT_ILI9163C::defineScrollArea(uint16_t a,uint16_t c){ */ void TFT_ILI9163C::scroll(uint16_t adrs) { - SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); - writecommand_cont(CMD_VSSTADRS); - writedata16_last(adrs); - endProc(); + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); + writecommand_cont(CMD_VSSTADRS); + writedata16_last(adrs); + endProc(); + #else + writecommand(CMD_VSSTADRS); + writedata16(adrs); + #endif } @@ -496,24 +501,55 @@ void TFT_ILI9163C::clearScreen(uint16_t color) { #endif } -void TFT_ILI9163C::writeScreen(const uint32_t *bitmap) { +void TFT_ILI9163C::startPushData(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + setAddr(x0,y0,x1,y1); +} + +void TFT_ILI9163C::pushData(uint16_t color) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writedata16_cont(color); + #else + writedata16(color); + #endif +} + + +void TFT_ILI9163C::endPushData() { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writecommand_last(CMD_NOP); + endProc(); + #endif +} + + +void TFT_ILI9163C::pushColor(uint16_t color) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); + writedata16_last(color); + endProc(); + #else + writedata16(color); + #endif +} + +void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) { uint16_t color; int px; #if defined(__MK20DX128__) || defined(__MK20DX256__) writecommand_cont(CMD_RAMWR); - for (px = 0;px < 16384; px++){ + for (px = 0;px < size; px++){//16384 color = Color24To565(bitmap[px]); writedata16_cont(color); } - _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); + _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//home endProc(); #else writecommand(CMD_RAMWR); - for (px = 0;px < 16384; px++){ + for (px = 0;px < size; px++){ color = Color24To565(bitmap[px]); writedata16(color); } - setAddr(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); + homeAddress(); #endif } @@ -533,15 +569,7 @@ void TFT_ILI9163C::setCursor(int16_t x, int16_t y) { -void TFT_ILI9163C::pushColor(uint16_t color) { - #if defined(__MK20DX128__) || defined(__MK20DX256__) - SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); - writedata16_last(color); - SPI.endTransaction(); - #else - writedata16(color); - #endif -} + void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) { if (boundaryCheck(x,y)) return; @@ -740,11 +768,6 @@ void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t #endif -// Pass 8-bit (each) R,G,B, get back 16-bit packed color - -uint16_t TFT_ILI9163C::Color565(uint8_t r, uint8_t g, uint8_t b) { - return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); -} void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { @@ -784,7 +807,6 @@ void TFT_ILI9163C::_setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_ writedata16_cont(x0 + __OFFSET); writedata16_cont(x1 + __OFFSET); } - writecommand_cont(CMD_PGEADRS); // Page if (rotation == 0){ writedata16_cont(y0 + __OFFSET); @@ -826,7 +848,7 @@ void TFT_ILI9163C::setRotation(uint8_t m) { SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); writecommand_cont(CMD_MADCTL); writedata8_last(_Mactrl_Data); - SPI.endTransaction(); + endProc(); #else writecommand(CMD_MADCTL); writedata(_Mactrl_Data); diff --git a/TFT_ILI9163C.h b/TFT_ILI9163C.h index dab2f0e..e91d6db 100644 --- a/TFT_ILI9163C.h +++ b/TFT_ILI9163C.h @@ -74,6 +74,7 @@ 0.4: some improvement, new ballistic gauge example! 0.5: Added scroll and more commands, optimizations Fixed a nasty bug in fill screen! + 0.6: Small fix, added SD example and subroutines +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BugList of the current version: @@ -266,8 +267,11 @@ class TFT_ILI9163C : public Adafruit_GFX { void sleepMode(boolean mode); //void defineScrollArea(uint16_t a,uint16_t c); void scroll(uint16_t adrs); - void writeScreen(const uint32_t *bitmap); - uint16_t Color565(uint8_t r, uint8_t g, uint8_t b); + void startPushData(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); + void pushData(uint16_t color); + void endPushData(); + void writeScreen24(const uint32_t *bitmap,uint16_t size=_TFTWIDTH*_TFTHEIGHT); + inline uint16_t Color565(uint8_t r, uint8_t g, uint8_t b) {return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);}; //convert 24bit color into packet 16 bit one (credits for this are all mine) inline uint16_t Color24To565(int32_t color_) { return ((((color_ >> 16) & 0xFF) / 8) << 11) | ((((color_ >> 8) & 0xFF) / 4) << 5) | (((color_) & 0xFF) / 8);} void setBitrate(uint32_t n); diff --git a/examples/SD_example/SD_example.ino b/examples/SD_example/SD_example.ino new file mode 100644 index 0000000..c75689b --- /dev/null +++ b/examples/SD_example/SD_example.ino @@ -0,0 +1,158 @@ +/* +An SD bmp image load example. (extracted and modded by Adafruit old library http://www.adafruit.com ) + This use NOT the adafruit SD library (or the standard arduino SD!) + but SdFat created by bill greiman https://github.com/greiman/SdFat much better to me!!! + Note about SPI Transactions <------------------------------------------- + To enable compatibility for SPI Transactions please open + SfFatCinfig.h in SdFat libary and set + #define ENABLE_SPI_TRANSACTION 0 + to + #define ENABLE_SPI_TRANSACTION 1 + */ + +#include +#include +#include +#include + +#define __CS 10 +#define __DC 9 +#define __SDCS 2 + +TFT_ILI9163C tft = TFT_ILI9163C(__CS, __DC); +SdFat SD; +SdFile myFile; + +void setup(void) { + Serial.begin(9600); + + tft.begin(); + //tft.setRotation(2); + + //I have a crappy chinese SD card holder that it's not compatible + //with hi speeds SPI (SPI_FULL_SPEED). If you have better luck set it to + //SPI_FULL_SPEED + if (!SD.begin(__SDCS,SPI_HALF_SPEED)) { + tft.setCursor(0,0); + tft.print("sd failed!"); + } + Serial.println("OK!"); + //your image here! + bmpDraw("star.bmp", 0, 0); +} + +void loop() { +} + +// This function opens a Windows Bitmap (BMP) file and +// displays it at the given coordinates. It's sped up +// by reading many pixels worth of data at a time +// (rather than pixel by pixel). Increasing the buffer +// size takes more of the Arduino's precious RAM but +// makes loading a little faster. 20 pixels seems a +// good balance. + +#define BUFFPIXEL 20 + +void bmpDraw(char *filename, uint8_t x, uint16_t y) { + + File bmpFile; + uint16_t bmpWidth, bmpHeight; // W+H in pixels + uint8_t bmpDepth; // Bit depth (currently must be 24) + uint32_t bmpImageoffset; // Start of image data in file + uint32_t rowSize; // Not always = bmpWidth; may have padding + uint8_t sdbufferLen = BUFFPIXEL * 3; + uint8_t sdbuffer[sdbufferLen]; // pixel buffer (R+G+B per pixel) + uint8_t buffidx = sdbufferLen; // Current position in sdbuffer + boolean goodBmp = false; // Set to true on valid header parse + boolean flip = true; // BMP is stored bottom-to-top + uint16_t w, h, row, col; + uint8_t r, g, b; + uint32_t pos = 0; + + if((x >= tft.width()) || (y >= tft.height())) return; + + // Open requested file on SD card + if ((bmpFile = SD.open(filename)) == NULL) { + tft.setCursor(0,0); + tft.print("file not found!"); + return; + } + + // Parse BMP header + if(read16(bmpFile) == 0x4D42) { // BMP signature + read32(bmpFile); + (void)read32(bmpFile); // Read & ignore creator bytes + bmpImageoffset = read32(bmpFile); // Start of image data + // Read DIB header + read32(bmpFile); + bmpWidth = read32(bmpFile); + bmpHeight = read32(bmpFile); + if(read16(bmpFile) == 1) { // # planes -- must be '1' + bmpDepth = read16(bmpFile); // bits per pixel + if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed + goodBmp = true; // Supported BMP format -- proceed! + rowSize = (bmpWidth * 3 + 3) & ~3;// BMP rows are padded (if needed) to 4-byte boundary + if (bmpHeight < 0) { + bmpHeight = -bmpHeight; + flip = false; + } + // Crop area to be loaded + w = bmpWidth; + h = bmpHeight; + if((x+w-1) >= tft.width()) w = tft.width() - x; + if((y+h-1) >= tft.height()) h = tft.height() - y; + tft.startPushData(x, y, x+w-1, y+h-1); + for (row=0; row= sdbufferLen) { // Indeed + bmpFile.read(sdbuffer, sdbufferLen); + buffidx = 0; // Set index to beginning + } + // Convert pixel from BMP to TFT format, push to display + b = sdbuffer[buffidx++]; + g = sdbuffer[buffidx++]; + r = sdbuffer[buffidx++]; + tft.pushData(tft.Color565(r,g,b)); + } // end pixel + } // end scanline + tft.endPushData(); + } // end goodBmp + } + } + + bmpFile.close(); + if(!goodBmp) { + tft.setCursor(0,0); + tft.print("file unrecognized!"); + } +} + + +uint16_t read16(File &f) { + uint16_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); // MSB + return result; +} + +uint32_t read32(File &f) { + uint32_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); + ((uint8_t *)&result)[2] = f.read(); + ((uint8_t *)&result)[3] = f.read(); // MSB + return result; +} + diff --git a/examples/bigPicture/bigPicture.ino b/examples/bigPicture/bigPicture.ino index d63ee3e..aeb9d22 100644 --- a/examples/bigPicture/bigPicture.ino +++ b/examples/bigPicture/bigPicture.ino @@ -2,9 +2,29 @@ #include #include -//be careful, big image! Only Teensy or DUE probably work - +/* +Want to load 24 bit iamges directly? This demo it's cool to understand how it works. +The 24bit data can also be stored in a flash if you like! +be careful, big ram requirements!! Only Teensy or DUE probably work +You need the utility lcd-image-converter in the utility folder. +Open an image with lcd-image-converter, go to menu->Options->Conversion... +'Prepare' sub-menu tag should be set as follow: +Type: color +Main Scan Direction: Top to Bottom +Line Scan Direction: Forwaed +All the rest should be unchecked. +Go to sub-menu tag 'Image' +Prefix:0x +Block size: 24bit +Delimeter:, +Byte Order: Little-Endian +Done. Now save preset if you like! +Now go to menu File->Convert and save .c file +Open with any text editor, you need to copy in your sketch only the data so the array +that start with static const uint24_t yourimage[16384] = { ....}; +Change uint24_t to uint32_t. +*/ /* Teensy3.x and Arduino's You are using 4 wire SPI here, so: @@ -32,7 +52,7 @@ static const uint32_t image_data_batman_ume[16384] = { void setup() { tft.begin(); - tft.writeScreen(image_data_batman_ume); + tft.writeScreen24bit(image_data_batman_ume); } diff --git a/keywords.txt b/keywords.txt index 6b7b4f9..103b1d8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,5 +1,6 @@ TFT_ILI9163C KEYWORD1 begin KEYWORD2 +setAddrWindow KEYWORD2 pushColor KEYWORD2 setBrightness KEYWORD2 writeData KEYWORD2 @@ -7,10 +8,12 @@ setBitrate KEYWORD2 Color565 KEYWORD2 setBitrate KEYWORD2 clearScreen KEYWORD2 -writeScreen KEYWORD2 Color24To565 KEYWORD2 sleepMode KEYWORD2 display KEYWORD2 -writeScreen KEYWORD2 +startPushData KEYWORD2 +pushData KEYWORD2 +endPushData KEYWORD2 +writeScreen24 KEYWORD2