Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RA8875 by
Diff: SPI_TFT.cpp
- Revision:
- 1:17e12e4e149f
- Parent:
- 0:de9d1462a835
- Child:
- 2:f30ea1eb3681
--- a/SPI_TFT.cpp Mon Sep 10 19:23:26 2012 +0000
+++ b/SPI_TFT.cpp Tue Sep 11 15:51:52 2012 +0000
@@ -18,6 +18,7 @@
// 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.
#include "SPI_TFT.h"
@@ -31,7 +32,7 @@
//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), _reset(reset),GraphicsDisplay(name) {
+ : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name) {
tft_reset();
orientation = 0;
char_x = 0;
@@ -76,9 +77,10 @@
void SPI_TFT::wr_cmd(unsigned char cmd) {
unsigned short spi_d;
spi_d = 0x7000 | cmd ;
+ _cs = 0;
if (spi_port == 0) { // TFT on SSP0
LPC_SSP0->DR = spi_d;
- // we have to wait for SPI IDLE to get SSEL (CS) back to high
+ // we have to wait for SPI IDLE to set CS back to high
do {
} while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
} else {
@@ -86,7 +88,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
}
-
+ _cs = 1;
}
@@ -94,9 +96,10 @@
void SPI_TFT::wr_dat(unsigned char dat) {
unsigned short spi_d;
spi_d = 0x7200 | dat;
+ _cs = 0;
if (spi_port == 0) { // TFT on SSP0
LPC_SSP0->DR = spi_d;
- // we have to wait for SPI IDLE to get SSEL (CS) back to high
+ // we have to wait for SPI IDLE to set CS back to high
do {
} while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
} else {
@@ -104,19 +107,20 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
}
+ _cs = 1;
}
// the HX8347-D controller do not use the MISO (SDO) Signal.
-// The controller use the MOSI signal bidirectional.
-// To read from the controller we have to make some bit banging
+// This is a bug - ?
+// A read will return 0 at the moment
unsigned short SPI_TFT::rd_dat (void) {
unsigned short val = 0;
- //val = _spi.write(0x73ff); /* Dummy read 1 */
- //val = _spi.write(0x0000); /* Read D8..D15 */
+ //val = _spi.write(0x73ff); /* Dummy read 1 */
+ //val = _spi.write(0x0000); /* Read D8..D15 */
return (val);
}
@@ -131,17 +135,19 @@
}
void SPI_TFT::tft_reset() {
- static unsigned short driverCode;
+ //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
+ //
+ // 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);
- }
+ // LPC_PINCON->PINSEL1 |= (1UL << 1);
+ // } else {
+ // // Set up SSEL1
+ // LPC_PINCON->PINSEL0 |= (1UL << 13);
+ // }
wait_us(50);
_reset = 1; // end reset
wait_ms(5);
@@ -240,8 +246,6 @@
}
-
-
void SPI_TFT::pixel(int x, int y, int color) {
unsigned char u,l;
wr_reg(0x03, (x >> 0));
@@ -251,14 +255,14 @@
wr_cmd(0x22);
u = color >> 8;
l = color & 0xff;
-
+ _cs = 0;
if (spi_port == 0) { // TFT on SSP0
LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->DR = u; // high byte
LPC_SSP0->DR = l; // low byte
LPC_SSP0->CR0 |= 0x08UL; // set back to 16 bit
- // we have to wait for SPI IDLE to get SSEL (CS) back to high
+ // we have to wait for SPI IDLE to set CS back to high
do {
} while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
} else {
@@ -267,10 +271,11 @@
LPC_SSP1->DR = u;
LPC_SSP1->DR = l;
LPC_SSP1->CR0 |= 0x08UL; // set back to 16 bit
- // we have to wait for SPI IDLE to get SSEL (CS) back to high
+ // we have to wait for SPI IDLE to set CS back to high
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
}
+ _cs = 1;
}
@@ -303,27 +308,25 @@
// 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;
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->CR0 |= 0x300UL; // clock div / 4 slow down to prevent a fifo emty
LPC_SSP0->DR = 0x72; // start byte
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
} 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
- }
+ }
// start DMA
do {
@@ -355,7 +358,7 @@
/* disable SSP1 for DMA. */
LPC_SSP1->DMACR = 0x0;
}
-
+ _cs = 1;
}
@@ -479,25 +482,21 @@
w = x1 - x0 + 1;
window(x0,y,w,1);
wr_cmd(0x22);
-
+ _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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
} 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
}
LPC_GPDMA->DMACIntTCClear = 0x1;
@@ -515,6 +514,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
}
+ _cs = 1;
WindowMax();
return;
}
@@ -524,25 +524,21 @@
h = y1 - y0 + 1;
window(x,y0,1,h);
wr_cmd(0x22);
-
+ _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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
- } else {
+ } 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
}
LPC_GPDMA->DMACIntTCClear = 0x1;
@@ -561,6 +557,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
}
+ _cs = 1;
WindowMax();
return;
}
@@ -665,25 +662,21 @@
int dma_count;
window(x0,y0,w,h);
wr_cmd(0x22);
-
+ _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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
- } else {
+ } 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
}
do {
@@ -712,7 +705,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
}
-
+ _cs = 1;
WindowMax();
return;
}
@@ -808,24 +801,21 @@
// copy the buffer with DMA SPI to display
dma_off = 0; // offset for DMA transfer
+ _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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
} 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
}
// start DMA
@@ -861,7 +851,7 @@
/* disable SSP1 for DMA. */
LPC_SSP1->DMACR = 0x0;
}
-
+ _cs = 1;
WindowMax();
if ((w + 2) < hor) { // x offset to next char
char_x += w + 2;
@@ -887,25 +877,21 @@
} while (2*(w + padd)%4 != 0);
window(x, y, w, h);
wr_cmd(0x22);
-
+ _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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
} 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
}
bitmap_ptr += ((h - 1)* (w + padd));
for (j = 0; j < h; j++) { //Lines
@@ -929,7 +915,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
}
-
+ _cs = 1;
WindowMax();
}
@@ -960,7 +946,6 @@
fprintf(stderr, "filename : %s \n\r",filename);
-
FILE *Image = fopen((const char *)&filename[0], "r"); // open the bmp file
if (!Image) {
return(0); // error file not found !
@@ -987,7 +972,6 @@
}
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) {
@@ -1002,7 +986,7 @@
window(x, y,PixelWidth+1,PixelHeigh);
wr_cmd(0x22);
-
+ _cs = 0;
for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up
off = j * (PixelWidth * 2 + padd) + start_data; // start of line
fseek(Image, off ,SEEK_SET);
@@ -1012,20 +996,16 @@
/* Enable SSP0 for DMA. */
LPC_SSP0->DMACR = 0x2;
LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
- LPC_SSP0->CR0 |= 0x300UL; // clock div / 4
LPC_SSP0->DR = 0x72; // start Data
LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP0->CR0 &= ~(0x300UL); // reset clock div
- } else {
+ } 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->CR0 |= 0x300UL; // clock div / 4
LPC_SSP1->DR = 0x72; // start Data
LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
- LPC_SSP1->CR0 &= ~(0x300UL); // reset clock div
- }
+ }
LPC_GPDMA->DMACIntTCClear = 0x1;
LPC_GPDMA->DMACIntErrClr = 0x1;
@@ -1045,7 +1025,7 @@
do {
} while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
}
-
+ _cs = 1;
free (line);
fclose(Image);
WindowMax();
