Frank Duignan
/
NRF52832_ili9341
Basic driver working
Revision 81:7087ba9d18bb, committed 2021-02-20
- Comitter:
- f3d
- Date:
- Sat Feb 20 16:34:49 2021 +0000
- Parent:
- 80:ff42f77928ad
- Commit message:
- Display driver working with touch input
Changed in this revision
--- a/display.cpp Wed Feb 03 11:30:30 2021 +0000 +++ b/display.cpp Sat Feb 20 16:34:49 2021 +0000 @@ -1,25 +1,26 @@ #include "mbed.h" #include "display.h" +#include "font5x7.h" +extern Serial g_Serial_pc; //mosi,miso,clk,ss -SPI spi(P0_25,P0_26,P0_27,P0_28); +SPI spi(P0_25,P0_26,P0_27); DigitalOut Rst(P0_7); DigitalOut DC(P0_6); - +DigitalOut D_CS(P0_28); +DigitalOut T_CS(P0_5); +DigitalIn PenIRQ(P0_4); void Display::begin() { - while(0) - { - DC = 1; - Rst = 1; - wait(0.5); - DC = 0; - Rst = 0; - wait(0.5); - } + spi.format(8, 0); spi.frequency(8000000); + T_CS = 1; // de-assert the touch interface for now + D_CS = 1; + resetDisplay(); - + + LCD_Write_Data(0x21); // Set GVDD (varies contrast) + LCD_Write_Cmd(0xC0); // Power control LCD_Write_Data(0x21); // Set GVDD (varies contrast) @@ -46,18 +47,17 @@ LCD_Write_Cmd(0xB6); // Display Function Control LCD_Write_Data(0x00); // Use default values LCD_Write_Data(0x82); - LCD_Write_Data(0x27); - + LCD_Write_Data(0x27); LCD_Write_Cmd(0x11); //Exit Sleep wait(0.120); - + LCD_Write_Cmd(0x29); //Display on LCD_Write_Cmd(0x2c); wait(0.005); - fillRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,RGBToWord(0,0,0)); - - + fillRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,RGBToWord(0x00,0,0)); + D_CS = 1; + } void Display::CommandMode() @@ -70,13 +70,19 @@ } void Display::LCD_Write_Cmd(uint8_t cmd) { + CommandMode(); + D_CS = 0; spi.write(cmd); + D_CS = 1; } void Display::LCD_Write_Data(uint8_t data) { + DataMode(); + D_CS = 0; spi.write(data); + D_CS = 1; } void Display::resetDisplay() { @@ -103,21 +109,26 @@ void Display::putPixel(uint16_t x, uint16_t y, uint16_t Colour) { uint16_t rx; + openAperture(x,y,x+1,y+1); DataMode(); + D_CS = 0; spi.write((const char *) &Colour,2,(char *)&rx,0); + D_CS = 1; } -void Display::putImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *Image) +void Display::putImage(uint16_t xofs, uint16_t yofs, uint16_t width, uint16_t height, const uint16_t *Image) { uint16_t rx; uint16_t Colour; - openAperture(x,y,width,height); - for (y = 0; y < height; y++) + + uint16_t x,y; + for (y = 0; y < height; y++) { for (x=0; x < width; x++) { - Colour = *(Image++); - spi.write((const char *) &Colour,2,(char *)&rx,0); - } + Colour = *(Image++); + putPixel(x+xofs,y+yofs,Colour); + } + } } void Display::fillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t Colour) { @@ -129,9 +140,10 @@ #define BUF_SIZE 32 uint16_t rx; uint16_t txBuffer[BUF_SIZE]; - int count; + int count; openAperture(x,y,width,height); DataMode(); + D_CS = 0; count = (width*height)/BUF_SIZE; if (count) { // big area @@ -160,6 +172,7 @@ } } + D_CS = 1; } void Display::drawLineLowSlope(uint16_t x0, uint16_t y0, uint16_t x1,uint16_t y1, uint16_t Colour) @@ -219,6 +232,7 @@ void Display::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t Colour) { // Reference : https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm + D_CS = 0; if ( iabs(y1 - y0) < iabs(x1 - x0) ) { if (x0 > x1) @@ -242,6 +256,7 @@ } } + D_CS = 1; } @@ -345,4 +360,139 @@ err += dx - (radius << 1); } } +} +void Display::print(const char *Text, uint16_t len, uint16_t x, uint16_t y, uint16_t ForeColour, uint16_t BackColour) +{ + // This function draws each character individually. It uses an array called TextBox as a temporary storage + // location to hold the dots for the character in question. It constructs the image of the character and then + // calls on putImage to place it on the screen + uint8_t Index = 0; + uint8_t Row, Col; + const uint8_t *CharacterCode = 0; + uint16_t TextBox[FONT_WIDTH * FONT_HEIGHT]; + for (Index = 0; Index < len; Index++) + { + CharacterCode = &Font5x7[FONT_WIDTH * (Text[Index] - 32)]; + Col = 0; + while (Col < FONT_WIDTH) + { + Row = 0; + while (Row < FONT_HEIGHT) + { + if (CharacterCode[Col] & (1 << Row)) + { + TextBox[(Row * FONT_WIDTH) + Col] = ForeColour; + } + else + { + TextBox[(Row * FONT_WIDTH) + Col] = BackColour; + } + Row++; + } + Col++; + } + putImage(x, y, FONT_WIDTH, FONT_HEIGHT, (const uint16_t *)TextBox); + x = x + FONT_WIDTH + 2; + } +} +void Display::print(uint16_t Number, uint16_t x, uint16_t y, uint16_t ForeColour, uint16_t BackColour) +{ + // This function converts the supplied number into a character string and then calls on puText to + // write it to the display + char Buffer[5]; // Maximum value = 65535 + Buffer[4] = Number % 10 + '0'; + Number = Number / 10; + Buffer[3] = Number % 10 + '0'; + Number = Number / 10; + Buffer[2] = Number % 10 + '0'; + Number = Number / 10; + Buffer[1] = Number % 10 + '0'; + Number = Number / 10; + Buffer[0] = Number % 10 + '0'; + print(Buffer, 5, x, y, ForeColour, BackColour); +} +void Display::initTouch(void) +{ + // This display module has an XPT2046 touch screen controller connected over the SPI interface + // The XPT2046 + T_CS = 0; + spi.write(0b10011000); // 8 bit conversion, ratiometric measurement, read XP + //wait_us(100); + uint16_t indata,outdata; + outdata = 0xffff; + spi.write((const char *) &outdata,2,(char *)&indata,2); // write a block of colour + T_CS = 1; +} +uint16_t Display::readYTouch(void) +{ + // This display module has an XPT2046 touch screen controller connected over the SPI interface + // The XPT2046 + /* + Format of command word : + b7 : must be 1 + b6,5,4 : A2,A1,A0 + 000 : temperature + + b3 : Mode + b2 : SER,DFR + b1,0 : PD1,PD0 + */ + uint16_t indata,outdata; + spi.frequency(2000000); // Can't run the touch screen controller at high speed + T_CS = 0; + spi.write((uint8_t)0b10011000); // 12 bit conversion, ratiometric measurement, reference off + // read XP which tells us Y (see diagram in datasheet) + wait_us(20); + outdata = 0xffff; + spi.write((const char *) &outdata,2,(char *)&indata,2); + T_CS = 1; + spi.frequency(8000000); + int calibrated_return= (indata>>12)+((indata & 0xff)<<4); + calibrated_return = (calibrated_return - Y_TOUCH_MIN); + if (calibrated_return < 0) + calibrated_return = 0; + calibrated_return = (calibrated_return * SCREEN_HEIGHT) / (Y_TOUCH_MAX - Y_TOUCH_MIN) ; + return calibrated_return; +} +uint16_t Display::readXTouch(void) +{ + // This display module has an XPT2046 touch screen controller connected over the SPI interface + // The XPT2046 + /* + Format of command word : + b7 : must be 1 + b6,5,4 : A2,A1,A0 + 000 : temperature + + b3 : Mode + b2 : SER,DFR + b1,0 : PD1,PD0 + */ + uint16_t indata,outdata; + spi.frequency(2000000);// Can't run the touch screen controller at high speed + T_CS = 0; + spi.write((uint8_t)0b11011000); // 12 bit conversion, ratiometric measurement, reference off + // read YP which tells us X (see diagram in datasheet) + wait_us(20); + outdata = 0xffff; + spi.write((const char *) &outdata,2,(char *)&indata,2); + T_CS = 1; + spi.frequency(8000000); + int calibrated_return= (indata>>12)+((indata & 0xff)<<4); + calibrated_return = (calibrated_return - X_TOUCH_MIN); + if (calibrated_return < 0) + calibrated_return = 0; + calibrated_return = (calibrated_return * SCREEN_WIDTH) / (X_TOUCH_MAX - X_TOUCH_MIN); + // The X reading is backwards so need to subtract it from the screen width + calibrated_return = SCREEN_WIDTH - calibrated_return; + if (calibrated_return < 0) + calibrated_return = 0; + return calibrated_return; +} +int Display::penDown(void) +{ + if (PenIRQ.read()==0) + return 1; + else + return 0; } \ No newline at end of file
--- a/display.h Wed Feb 03 11:30:30 2021 +0000 +++ b/display.h Sat Feb 20 16:34:49 2021 +0000 @@ -4,6 +4,10 @@ #define SCREEN_WIDTH 240 #define SCREEN_HEIGHT 320 +#define Y_TOUCH_MAX 1952 +#define Y_TOUCH_MIN 88 +#define X_TOUCH_MAX 1920 +#define X_TOUCH_MIN 112 class Display { public: Display() {}; @@ -16,6 +20,12 @@ void drawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t Colour); void drawCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t Colour); void fillCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t Colour); + // Graphics text functions + void print(const char *Text, uint16_t len, uint16_t x, uint16_t y, uint16_t ForeColour, uint16_t BackColour); + void print(uint16_t Number, uint16_t x, uint16_t y, uint16_t ForeColour, uint16_t BackColour); + int penDown(void); + uint16_t readYTouch(void); + uint16_t readXTouch(void); private: void CommandMode(); @@ -33,5 +43,7 @@ else return x; } + void initTouch(void); + }; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/font5x7.h Sat Feb 20 16:34:49 2021 +0000 @@ -0,0 +1,123 @@ +/*! \file font5x7.h \brief Graphic LCD Font (Ascii Characters). */ +//***************************************************************************** +// +// File Name : 'font5x7.h' +// Title : Graphic LCD Font (Ascii Charaters) +// Author : Pascal Stang +// Date : 10/19/2001 +// Revised : 10/19/2001 +// Version : 0.1 +// Target MCU : Atmel AVR +// Editor Tabs : 4 +// +//***************************************************************************** + +#ifndef FONT5X7_H +#define FONT5X7_H +#define FONT_WIDTH 5 +#define FONT_HEIGHT 7 +#include <stdint.h> +// standard ascii 5x7 font +// defines ascii characters 0x20-0x7F (32-127) +#pragma pack(1) +const uint8_t Font5x7[] = { + 0x00, 0x00, 0x00, 0x00, 0x00,// (space) + 0x00, 0x00, 0x5F, 0x00, 0x00,// ! + 0x00, 0x07, 0x00, 0x07, 0x00,// " + 0x14, 0x7F, 0x14, 0x7F, 0x14,// # + 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $ + 0x23, 0x13, 0x08, 0x64, 0x62,// % + 0x36, 0x49, 0x55, 0x22, 0x50,// & + 0x00, 0x05, 0x03, 0x00, 0x00,// ' + 0x00, 0x1C, 0x22, 0x41, 0x00,// ( + 0x00, 0x41, 0x22, 0x1C, 0x00,// ) + 0x08, 0x2A, 0x1C, 0x2A, 0x08,// * + 0x08, 0x08, 0x3E, 0x08, 0x08,// + + 0x00, 0x50, 0x30, 0x00, 0x00,// , + 0x08, 0x08, 0x08, 0x08, 0x08,// - + 0x00, 0x60, 0x60, 0x00, 0x00,// . + 0x20, 0x10, 0x08, 0x04, 0x02,// / + 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 + 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 + 0x42, 0x61, 0x51, 0x49, 0x46,// 2 + 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 + 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 + 0x27, 0x45, 0x45, 0x45, 0x39,// 5 + 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 + 0x01, 0x71, 0x09, 0x05, 0x03,// 7 + 0x36, 0x49, 0x49, 0x49, 0x36,// 8 + 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 + 0x00, 0x36, 0x36, 0x00, 0x00,// : + 0x00, 0x56, 0x36, 0x00, 0x00,// ; + 0x00, 0x08, 0x14, 0x22, 0x41,// < + 0x14, 0x14, 0x14, 0x14, 0x14,// = + 0x41, 0x22, 0x14, 0x08, 0x00,// > + 0x02, 0x01, 0x51, 0x09, 0x06,// ? + 0x32, 0x49, 0x79, 0x41, 0x3E,// @ + 0x7E, 0x11, 0x11, 0x11, 0x7E,// A + 0x7F, 0x49, 0x49, 0x49, 0x36,// B + 0x3E, 0x41, 0x41, 0x41, 0x22,// C + 0x7F, 0x41, 0x41, 0x22, 0x1C,// D + 0x7F, 0x49, 0x49, 0x49, 0x41,// E + 0x7F, 0x09, 0x09, 0x01, 0x01,// F + 0x3E, 0x41, 0x41, 0x51, 0x32,// G + 0x7F, 0x08, 0x08, 0x08, 0x7F,// H + 0x00, 0x41, 0x7F, 0x41, 0x00,// I + 0x20, 0x40, 0x41, 0x3F, 0x01,// J + 0x7F, 0x08, 0x14, 0x22, 0x41,// K + 0x7F, 0x40, 0x40, 0x40, 0x40,// L + 0x7F, 0x02, 0x04, 0x02, 0x7F,// M + 0x7F, 0x04, 0x08, 0x10, 0x7F,// N + 0x3E, 0x41, 0x41, 0x41, 0x3E,// O + 0x7F, 0x09, 0x09, 0x09, 0x06,// P + 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q + 0x7F, 0x09, 0x19, 0x29, 0x46,// R + 0x46, 0x49, 0x49, 0x49, 0x31,// S + 0x01, 0x01, 0x7F, 0x01, 0x01,// T + 0x3F, 0x40, 0x40, 0x40, 0x3F,// U + 0x1F, 0x20, 0x40, 0x20, 0x1F,// V + 0x7F, 0x20, 0x18, 0x20, 0x7F,// W + 0x63, 0x14, 0x08, 0x14, 0x63,// X + 0x03, 0x04, 0x78, 0x04, 0x03,// Y + 0x61, 0x51, 0x49, 0x45, 0x43,// Z + 0x00, 0x00, 0x7F, 0x41, 0x41,// [ + 0x02, 0x04, 0x08, 0x10, 0x20,// "\" + 0x41, 0x41, 0x7F, 0x00, 0x00,// ] + 0x04, 0x02, 0x01, 0x02, 0x04,// ^ + 0x40, 0x40, 0x40, 0x40, 0x40,// _ + 0x00, 0x01, 0x02, 0x04, 0x00,// ` + 0x20, 0x54, 0x54, 0x54, 0x78,// a + 0x7F, 0x48, 0x44, 0x44, 0x38,// b + 0x38, 0x44, 0x44, 0x44, 0x20,// c + 0x38, 0x44, 0x44, 0x48, 0x7F,// d + 0x38, 0x54, 0x54, 0x54, 0x18,// e + 0x08, 0x7E, 0x09, 0x01, 0x02,// f + 0x08, 0x14, 0x54, 0x54, 0x3C,// g + 0x7F, 0x08, 0x04, 0x04, 0x78,// h + 0x00, 0x44, 0x7D, 0x40, 0x00,// i + 0x20, 0x40, 0x44, 0x3D, 0x00,// j + 0x00, 0x7F, 0x10, 0x28, 0x44,// k + 0x00, 0x41, 0x7F, 0x40, 0x00,// l + 0x7C, 0x04, 0x18, 0x04, 0x78,// m + 0x7C, 0x08, 0x04, 0x04, 0x78,// n + 0x38, 0x44, 0x44, 0x44, 0x38,// o + 0x7C, 0x14, 0x14, 0x14, 0x08,// p + 0x08, 0x14, 0x14, 0x18, 0x7C,// q + 0x7C, 0x08, 0x04, 0x04, 0x08,// r + 0x48, 0x54, 0x54, 0x54, 0x20,// s + 0x04, 0x3F, 0x44, 0x40, 0x20,// t + 0x3C, 0x40, 0x40, 0x20, 0x7C,// u + 0x1C, 0x20, 0x40, 0x20, 0x1C,// v + 0x3C, 0x40, 0x30, 0x40, 0x3C,// w + 0x44, 0x28, 0x10, 0x28, 0x44,// x + 0x0C, 0x50, 0x50, 0x50, 0x3C,// y + 0x44, 0x64, 0x54, 0x4C, 0x44,// z + 0x00, 0x08, 0x36, 0x41, 0x00,// { + 0x00, 0x00, 0x7F, 0x00, 0x00,// | + 0x00, 0x41, 0x36, 0x08, 0x00,// } + 0x08, 0x08, 0x2A, 0x1C, 0x08,// -> + 0x08, 0x1C, 0x2A, 0x08, 0x08 // <- +}; + +#endif +
--- a/main.cpp Wed Feb 03 11:30:30 2021 +0000 +++ b/main.cpp Sat Feb 20 16:34:49 2021 +0000 @@ -11,7 +11,8 @@ #define LED_ON 0 #define LED_OFF 1 -DigitalOut g_DO_LedBlue(A5, LED_OFF); +DigitalOut DataLED(A5, LED_OFF); + Display display; uint32_t prbs() @@ -39,37 +40,28 @@ } int main(void) { - int Count; + int count; + + display.begin(); - - while(true) { - g_Serial_pc.printf("LED Toggle\r\n"); - g_DO_LedBlue = !g_DO_LedBlue; - - for (Count = 0; Count < 200; Count++) - { - display.drawRectangle(random(0,240),random(0,320),random(0,240),random(0,320),random(0,0xffff)); - } - display.fillRectangle(0,0,240,320,0); - for (Count = 0; Count < 200; Count++) + while(1) + { + DataLED = !DataLED; + if (display.penDown()) { - - display.fillRectangle(random(0,240),random(0,320),random(0,240),random(0,320),random(0,0xffff)); - - } - display.fillRectangle(0,0,240,320,0); - for (Count = 0; Count < 200; Count++) + display.print(display.readXTouch(),10,10,display.RGBToWord(0xff,0xff,0),display.RGBToWord(0,0,0)); + display.print(display.readYTouch(),80,10,display.RGBToWord(0xff,0xff,0),display.RGBToWord(0,0,0)); + } + display.drawRectangle(random(0,240),random(0,320),random(0,240),random(0,320),random(0,0xffff)); + //display.fillRectangle(random(0,240),random(0,320),random(0,240),random(0,320),random(0,0xffff)); + display.drawCircle(random(0,240),random(0,240),random(0,320),random(0,0xffff)); + //display.fillCircle(random(0,240),random(0,320),random(0,120),random(0,0xffff)); + count++; + if (count >= 10) { - display.drawCircle(random(0,240),random(0,240),random(0,320),random(0,0xffff)); - + display.fillRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0); + count = 0; } - display.fillRectangle(0,0,240,320,0); - for (Count = 0; Count < 50; Count++) - { - display.fillCircle(random(0,240),random(0,320),random(0,120),random(0,0xffff)); - - } - display.fillRectangle(0,0,240,320,0); }