Library to control a QVGA TFT connected to SPI. You can use printf to print text The lib can handle different fonts, draw lines, circles, rect and bmp
Dependents: TFT_Test1 SourceCodePro31-SB Mandelbrot Mindwave-screen ... more
See http://mbed.org/cookbook/SPI-driven-QVGA-TFT for details.
Diff: SPI_TFT.cpp
- Revision:
- 3:7f1d793b90df
- Parent:
- 2:f30ea1eb3681
- Child:
- 4:824715115046
--- a/SPI_TFT.cpp Tue Sep 11 20:37:13 2012 +0000 +++ b/SPI_TFT.cpp Thu Sep 20 23:24:43 2012 +0000 @@ -18,8 +18,8 @@ // 15.03.12 use SSEL for TFT CS to enable DMA Register writes // 06.04.12 fix SSEL CS problem // 06.04.12 use direct access to the spi register to speed up the library. -// 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS. - +// 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS. + #include "SPI_TFT.h" #include "mbed.h" @@ -28,11 +28,12 @@ #define BPP 16 // Bits per pixel -//extern Serial pc; +extern Serial pc; //extern DigitalOut xx; // debug !! SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name) - : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name) { + : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name) +{ tft_reset(); orientation = 0; char_x = 0; @@ -40,19 +41,22 @@ else spi_port = 1; } -int SPI_TFT::width() { +int SPI_TFT::width() +{ if (orientation == 0 || orientation == 2) return 240; else return 320; } -int SPI_TFT::height() { +int SPI_TFT::height() +{ if (orientation == 0 || orientation == 2) return 320; else return 240; } -void SPI_TFT::set_orientation(unsigned int o) { +void SPI_TFT::set_orientation(unsigned int o) +{ orientation = o; switch (orientation) { case 0: @@ -74,7 +78,8 @@ // write command to tft register -void SPI_TFT::wr_cmd(unsigned char cmd) { +void SPI_TFT::wr_cmd(unsigned char cmd) +{ unsigned short spi_d; spi_d = 0x7000 | cmd ; _cs = 0; @@ -93,7 +98,8 @@ -void SPI_TFT::wr_dat(unsigned char dat) { +void SPI_TFT::wr_dat(unsigned char dat) +{ unsigned short spi_d; spi_d = 0x7200 | dat; _cs = 0; @@ -116,7 +122,8 @@ // This is a bug - ? // A read will return 0 at the moment -unsigned short SPI_TFT::rd_dat (void) { +unsigned short SPI_TFT::rd_dat (void) +{ unsigned short val = 0; //val = _spi.write(0x73ff); /* Dummy read 1 */ @@ -124,30 +131,26 @@ return (val); } -void SPI_TFT::wr_reg (unsigned char reg, unsigned char val) { +void SPI_TFT::wr_reg (unsigned char reg, unsigned char val) +{ wr_cmd(reg); wr_dat(val); } -unsigned short SPI_TFT::rd_reg (unsigned char reg) { +unsigned short SPI_TFT::rd_reg (unsigned char reg) +{ wr_cmd(reg); return(rd_dat()); } -void SPI_TFT::tft_reset() { +void SPI_TFT::tft_reset() +{ //static unsigned short driverCode; _spi.format(16,3); // 16 bit spi mode 3 _spi.frequency(48000000); // 48 Mhz SPI clock _cs = 1; // cs high _reset = 0; // display reset - // - // if (spi_port == 0) { // TFT on SSP0 - // Set up SSEL0 for CS - // LPC_PINCON->PINSEL1 |= (1UL << 1); - // } else { - // // Set up SSEL1 - // LPC_PINCON->PINSEL0 |= (1UL << 13); - // } + wait_us(50); _reset = 1; // end reset wait_ms(5); @@ -246,7 +249,8 @@ } -void SPI_TFT::pixel(int x, int y, int color) { +void SPI_TFT::pixel(int x, int y, int color) +{ unsigned char u,l; wr_reg(0x03, (x >> 0)); wr_reg(0x02, (x >> 8)); @@ -255,7 +259,7 @@ wr_cmd(0x22); u = color >> 8; l = color & 0xff; - _cs = 0; + _cs = 0; if (spi_port == 0) { // TFT on SSP0 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit LPC_SSP0->DR = 0x72; // start Data @@ -279,7 +283,8 @@ } -void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) { +void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) +{ wr_reg(0x03, x ); wr_reg(0x02, (x >> 8)); wr_reg(0x05, x+w-1 ); @@ -291,12 +296,14 @@ } -void SPI_TFT::WindowMax (void) { +void SPI_TFT::WindowMax (void) +{ window (0, 0, width(), height()); } -void SPI_TFT::cls (void) { +void SPI_TFT::cls (void) +{ //unsigned int i int pixel = ( width() * height()); @@ -308,7 +315,7 @@ // The SSEL signal is held low until the spi FIFO is emty. // We have to lower the SPI clock for the 8 bit start to get the spi running // until the next data word - + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; _cs = 0; @@ -326,7 +333,7 @@ LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit LPC_SSP1->DR = 0x72; // start Data LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit - } + } // start DMA do { @@ -362,7 +369,8 @@ } -void SPI_TFT::circle(int x0, int y0, int r, int color) { +void SPI_TFT::circle(int x0, int y0, int r, int color) +{ int draw_x0, draw_y0; int draw_x1, draw_y1; @@ -469,7 +477,8 @@ return; } -void SPI_TFT::fillcircle(int x, int y, int r, int color) { +void SPI_TFT::fillcircle(int x, int y, int r, int color) +{ int i; for (i = 0; i <= r; i++) circle(x,y,i,color); @@ -477,7 +486,8 @@ -void SPI_TFT::hline(int x0, int x1, int y, int color) { +void SPI_TFT::hline(int x0, int x1, int y, int color) +{ int w; w = x1 - x0 + 1; window(x0,y,w,1); @@ -519,7 +529,8 @@ return; } -void SPI_TFT::vline(int x, int y0, int y1, int color) { +void SPI_TFT::vline(int x, int y0, int y1, int color) +{ int h; h = y1 - y0 + 1; window(x,y0,1,h); @@ -532,7 +543,7 @@ LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit LPC_SSP0->DR = 0x72; // start Data LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit - } else { + } else { LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 /* Enable SSP1 for DMA. */ LPC_SSP1->DMACR = 0x2; @@ -564,7 +575,8 @@ -void SPI_TFT::line(int x0, int y0, int x1, int y1, int color) { +void SPI_TFT::line(int x0, int y0, int x1, int y1, int color) +{ //WindowMax(); int dx = 0, dy = 0; int dx_sym = 0, dy_sym = 0; @@ -635,7 +647,8 @@ } -void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color) { +void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color) +{ if (x1 > x0) hline(x0,x1,y0,color); else hline(x1,x0,y0,color); @@ -654,7 +667,8 @@ -void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color) { +void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color) +{ int h = y1 - y0 + 1; int w = x1 - x0 + 1; @@ -670,7 +684,7 @@ LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit LPC_SSP0->DR = 0x72; // start Data LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit - } else { + } else { LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 /* Enable SSP1 for DMA. */ LPC_SSP1->DMACR = 0x2; @@ -711,26 +725,30 @@ } -void SPI_TFT::locate(int x, int y) { +void SPI_TFT::locate(int x, int y) +{ char_x = x; char_y = y; } -int SPI_TFT::columns() { +int SPI_TFT::columns() +{ return width() / font[1]; } -int SPI_TFT::rows() { +int SPI_TFT::rows() +{ return height() / font[2]; } -int SPI_TFT::_putc(int value) { +int SPI_TFT::_putc(int value) +{ if (value == '\n') { // new line char_x = 0; char_y = char_y + font[2]; @@ -746,7 +764,8 @@ -void SPI_TFT::character(int x, int y, int c) { +void SPI_TFT::character(int x, int y, int c) +{ unsigned int hor,vert,offset,bpl,j,i,b,p; unsigned char* zeichen; unsigned char z,w; @@ -860,13 +879,15 @@ } -void SPI_TFT::set_font(unsigned char* f) { +void SPI_TFT::set_font(unsigned char* f) +{ font = f; } -void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) { +void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) +{ unsigned int j; int padd; unsigned short *bitmap_ptr = (unsigned short *)bitmap; @@ -880,19 +901,22 @@ _cs = 0; if (spi_port == 0) { // TFT on SSP0 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 - /* Enable SSP0 for DMA. */ - LPC_SSP0->DMACR = 0x2; LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit LPC_SSP0->DR = 0x72; // start Data LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit + /* Enable SSP0 for DMA. */ + LPC_SSP0->DMACR = 0x2; + } else { LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 + LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit + LPC_SSP1->DR = 0x72; // start Data command + LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit /* Enable SSP1 for DMA. */ LPC_SSP1->DMACR = 0x2; - LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit - LPC_SSP1->DR = 0x72; // start Data - LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit + } + bitmap_ptr += ((h - 1)* (w + padd)); for (j = 0; j < h; j++) { //Lines LPC_GPDMA->DMACIntTCClear = 0x1; @@ -920,7 +944,8 @@ } -int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) { +int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) +{ #define OffsetPixelWidth 18 #define OffsetPixelHeigh 22 @@ -946,7 +971,7 @@ fprintf(stderr, "filename : %s \n\r",filename); - FILE *Image = fopen((const char *)&filename[0], "r"); // open the bmp file + FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file if (!Image) { return(0); // error file not found ! } @@ -972,7 +997,7 @@ } start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); - + line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line if (line == NULL) { return(-4); // error no memory @@ -984,28 +1009,37 @@ padd ++; } while ((PixelWidth * 2 + padd)%4 != 0); - window(x, y,PixelWidth+1,PixelHeigh); + + pc.printf("width = %d \n\r",PixelWidth); + pc.printf("heigh = %d \n\r",PixelHeigh); + pc.printf("padd = %d \n\r",padd); + pc.printf("start = 0x%x \n\r",start_data); + +//fseek(Image, 70 ,SEEK_SET); + window(x, y,PixelWidth ,PixelHeigh); wr_cmd(0x22); _cs = 0; + + if (spi_port == 0) { // TFT on SSP0 + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 + LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit + LPC_SSP0->DR = 0x72; // start Data + LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit + /* Enable SSP0 for DMA. */ + LPC_SSP0->DMACR = 0x2; + + } else { + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 + LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit + LPC_SSP1->DR = 0x72; // start Data + LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit + /* Enable SSP1 for DMA. */ + LPC_SSP1->DMACR = 0x2; + } for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up - off = j * (PixelWidth * 2 + padd) + start_data; // start of line + off = j * (PixelWidth * 2 + padd) + start_data; // start of line fseek(Image, off ,SEEK_SET); fread(line,1,PixelWidth * 2,Image); // read a line - slow ! - if (spi_port == 0) { // TFT on SSP0 - LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 - /* Enable SSP0 for DMA. */ - LPC_SSP0->DMACR = 0x2; - LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit - LPC_SSP0->DR = 0x72; // start Data - LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit - } else { - LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 - /* Enable SSP1 for DMA. */ - LPC_SSP1->DMACR = 0x2; - LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit - LPC_SSP1->DR = 0x72; // start Data - LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit - } LPC_GPDMA->DMACIntTCClear = 0x1; LPC_GPDMA->DMACIntErrClr = 0x1;