Frank Duignan
/
NRF52832_ili9341
Basic driver working
display.cpp
- Committer:
- f3d
- Date:
- 2021-02-03
- Revision:
- 80:ff42f77928ad
- Child:
- 81:7087ba9d18bb
File content as of revision 80:ff42f77928ad:
#include "mbed.h" #include "display.h" //mosi,miso,clk,ss SPI spi(P0_25,P0_26,P0_27,P0_28); DigitalOut Rst(P0_7); DigitalOut DC(P0_6); 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); resetDisplay(); LCD_Write_Cmd(0xC0); // Power control LCD_Write_Data(0x21); // Set GVDD (varies contrast) LCD_Write_Cmd(0xC1); // Power control LCD_Write_Data(0x10); // default value LCD_Write_Cmd(0xC5); //VCM control LCD_Write_Data(0x31); // default values LCD_Write_Data(0x3c); // LCD_Write_Cmd(0xC7); //VCM control2 LCD_Write_Data(0xc0); // default value LCD_Write_Cmd(0x36); // Memory Access Control LCD_Write_Data(0x48); // Set display orientation and RGB colour order LCD_Write_Cmd(0x3A); // Set Pixel format LCD_Write_Data(0x55); // To 16 bits per pixel LCD_Write_Cmd(0xB1); // Frame rate control LCD_Write_Data(0x00); // Use Fosc without divisor LCD_Write_Data(0x1B); // set 70Hz refresh rate LCD_Write_Cmd(0xB6); // Display Function Control LCD_Write_Data(0x00); // Use default values LCD_Write_Data(0x82); 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)); } void Display::CommandMode() { DC = 0; } void Display::DataMode() { DC = 1; } void Display::LCD_Write_Cmd(uint8_t cmd) { CommandMode(); spi.write(cmd); } void Display::LCD_Write_Data(uint8_t data) { DataMode(); spi.write(data); } void Display::resetDisplay() { Rst = 0; wait(0.01); Rst = 1; wait(0.12); } void Display::openAperture(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { LCD_Write_Cmd(0x2a); LCD_Write_Data(x1>>8); LCD_Write_Data(x1); LCD_Write_Data(x2>>8); LCD_Write_Data(x2); LCD_Write_Cmd(0x2b); LCD_Write_Data(y1>>8); LCD_Write_Data(y1); LCD_Write_Data(y2>>8); LCD_Write_Data(y2); LCD_Write_Cmd(0x2c); } // Simple Pixel drawing routines void Display::putPixel(uint16_t x, uint16_t y, uint16_t Colour) { uint16_t rx; openAperture(x,y,x+1,y+1); DataMode(); spi.write((const char *) &Colour,2,(char *)&rx,0); } void Display::putImage(uint16_t x, uint16_t y, 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++) for (x=0; x < width; x++) { Colour = *(Image++); spi.write((const char *) &Colour,2,(char *)&rx,0); } } void Display::fillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t Colour) { /* in an effort to reduce overhead here a large word buffer is created. If the number of words to to write is greater than or equal to the size of this buffer then it is filled with the relevant colour and used as the source of data in the spi.write function. This greatly speeds up the writing of large arease of the screen. The choice of buffer size is interesting. */ #define BUF_SIZE 32 uint16_t rx; uint16_t txBuffer[BUF_SIZE]; int count; openAperture(x,y,width,height); DataMode(); count = (width*height)/BUF_SIZE; if (count) { // big area for (int i=0;i<BUF_SIZE;i++) { txBuffer[i]=Colour; } while(count--) { spi.write((const char *)txBuffer,2*BUF_SIZE,(char *)&rx,0); } count = (width*height)%BUF_SIZE; // write remainder of block while (count--) { spi.write((const char *) &Colour,2,(char *)&rx,0); // write a block of colour } } else { // small area so write 1 word at a time. count = (width*height); while(count--) { spi.write((const char *) &Colour,2,(char *)&rx,0); } } } void Display::drawLineLowSlope(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 int dx = x1 - x0; int dy = y1 - y0; int yi = 1; if (dy < 0) { yi = -1; dy = -dy; } int D = 2*dy - dx; int y = y0; for (int x=x0; x <= x1;x++) { putPixel(x,y,Colour); if (D > 0) { y = y + yi; D = D - 2*dx; } D = D + 2*dy; } } void Display::drawLineHighSlope(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 int dx = x1 - x0; int dy = y1 - y0; int xi = 1; if (dx < 0) { xi = -1; dx = -dx; } int D = 2*dx - dy; int x = x0; for (int y=y0; y <= y1; y++) { putPixel(x,y,Colour); if (D > 0) { x = x + xi; D = D - 2*dy; } D = D + 2*dx; } } 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 if ( iabs(y1 - y0) < iabs(x1 - x0) ) { if (x0 > x1) { drawLineLowSlope(x1, y1, x0, y0, Colour); } else { drawLineLowSlope(x0, y0, x1, y1, Colour); } } else { if (y0 > y1) { drawLineHighSlope(x1, y1, x0, y0, Colour); } else { drawLineHighSlope(x0, y0, x1, y1, Colour); } } } uint16_t Display::RGBToWord(uint16_t R, uint16_t G, uint16_t B) { uint16_t rvalue = 0; rvalue += G >> 5; rvalue += (G & (0b111)) << 13; rvalue += (B >> 3) << 8; rvalue += (R >> 3) << 3; return rvalue; } void Display::drawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t Colour) { drawLine(x,y,x+w,y,Colour); drawLine(x,y,x,y+h,Colour); drawLine(x+w,y,x+w,y+h,Colour); drawLine(x,y+h,x+w,y+h,Colour); } void Display::drawCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t Colour) { // Reference : https://en.wikipedia.org/wiki/Midpoint_circle_algorithm int x = radius-1; int y = 0; int dx = 1; int dy = 1; int err = dx - (radius << 1); if (radius > x0) return; // don't draw even parially off-screen circles if (radius > y0) return; // don't draw even parially off-screen circles if ((x0+radius) > SCREEN_WIDTH) return; // don't draw even parially off-screen circles if ((y0+radius) > SCREEN_HEIGHT) return; // don't draw even parially off-screen circles while (x >= y) { putPixel(x0 + x, y0 + y, Colour); putPixel(x0 + y, y0 + x, Colour); putPixel(x0 - y, y0 + x, Colour); putPixel(x0 - x, y0 + y, Colour); putPixel(x0 - x, y0 - y, Colour); putPixel(x0 - y, y0 - x, Colour); putPixel(x0 + y, y0 - x, Colour); putPixel(x0 + x, y0 - y, Colour); if (err <= 0) { y++; err += dy; dy += 2; } if (err > 0) { x--; dx += 2; err += dx - (radius << 1); } } } void Display::fillCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t Colour) { // Reference : https://en.wikipedia.org/wiki/Midpoint_circle_algorithm // Similar to drawCircle but fills the circle with lines instead int x = radius-1; int y = 0; int dx = 1; int dy = 1; int err = dx - (radius << 1); if (radius > x0) return; // don't draw even parially off-screen circles if (radius > y0) return; // don't draw even parially off-screen circles if ((x0+radius) > SCREEN_WIDTH) return; // don't draw even parially off-screen circles if ((y0+radius) > SCREEN_HEIGHT) return; // don't draw even parially off-screen circles while (x >= y) { drawLine(x0 - x, y0 + y,x0 + x, y0 + y, Colour); drawLine(x0 - y, y0 + x,x0 + y, y0 + x, Colour); drawLine(x0 - x, y0 - y,x0 + x, y0 - y, Colour); drawLine(x0 - y, y0 - x,x0 + y, y0 - x, Colour); if (err <= 0) { y++; err += dy; dy += 2; } if (err > 0) { x--; dx += 2; err += dx - (radius << 1); } } }