##// END OF EJS Templates
Removed error on fat32 library, seems now to be able navigate among sectors in...
Removed error on fat32 library, seems now to be able navigate among sectors in both directions. Improved SDLCD drawing performances by almost 1000x.

File last commit:

r67:604c231d911c dev_alexis
r68:104125d87b89 dev_alexis
Show More
ili9328.c
535 lines | 18.8 KiB | text/x-c | CLexer
/*------------------------------------------------------------------------------
-- This file is a part of the libuc, microcontroler library
-- Copyright (C) 2012, Alexis Jeandet
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-------------------------------------------------------------------------------
-- Author : Alexis Jeandet
-- Mail : alexis.jeandet@member.fsf.org
-------------------------------------------------------------------------------*/
#define _PRVATE_ILI9328_
#include <ili9328.h>
#include <stdio.h>
#include <stddef.h>
#include <core.h>
#include <math.h>
#include <stdint.h>
#include <malloc.h>
#ifdef __OPTIMIZED_MATH
#include <optimised_math.h>
#endif
#define ilipaintLine(LCD,X,Y,W,buffer,buffsize) \
for(int l=0;l<1;l++)\
{\
ili9328setFrame(LCD,X,Y,W,1);\
int rem=(W)%buffsize;\
if(rem)LCD->interface->writeGRAM(buffer,rem);\
for(int i=rem;i<(W);i+=buffsize)\
{\
LCD->interface->writeGRAM(buffer,buffsize);\
}\
}
#define ilipaintHLineWithCont(LCD,X,Y,W,ContSz,bufferInt,buffIntsize,bufferCont,buffContsize) \
for(int l=0;l<1;l++)\
{\
ili9328setFrame(LCD,X,Y,W,1);\
int rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
if((2*ContSz)<W) \
{\
rem=(W-(2*ContSz))%buffIntsize;\
if(rem)LCD->interface->writeGRAM(bufferInt,rem);\
for(int i=rem;i<(W-(2*ContSz));i+=buffIntsize)\
{\
LCD->interface->writeGRAM(bufferInt,buffIntsize);\
}\
}\
rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
}\
#define ilipaintVLineWithCont(LCD,X,Y,H,ContSz,bufferInt,buffIntsize,bufferCont,buffContsize) \
for(int l=0;l<1;l++)\
{\
ili9328setFrame(LCD,X,Y,1,H);\
int rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
if((2*ContSz)<H) \
{\
rem=(H-(2*ContSz))%buffIntsize;\
if(rem)LCD->interface->writeGRAM(bufferInt,rem);\
for(int i=rem;i<(H-(2*ContSz));i+=buffIntsize)\
{\
LCD->interface->writeGRAM(bufferInt,buffIntsize);\
}\
}\
rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
}\
#define ilipaintHalfTopVLineWithCont(LCD,X,Y,H,ContSz,bufferInt,buffIntsize,bufferCont,buffContsize) \
for(int l=0;l<1;l++)\
{\
ili9328setFrame(LCD,X,Y,1,H);\
int rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
if(ContSz<H) \
{\
rem=(H-ContSz)%buffIntsize;\
if(rem)LCD->interface->writeGRAM(bufferInt,rem);\
for(int i=rem;i<(H-ContSz);i+=buffIntsize)\
{\
LCD->interface->writeGRAM(bufferInt,buffIntsize);\
}\
}\
}\
#define ilipaintHalfBottomVLineWithCont(LCD,X,Y,H,ContSz,bufferInt,buffIntsize,bufferCont,buffContsize) \
for(int l=0;l<1;l++)\
{\
ili9328setFrame(LCD,X,Y,1,H);\
int rem;\
if(ContSz<H) \
{\
rem=(H-ContSz)%buffIntsize;\
if(rem)LCD->interface->writeGRAM(bufferInt,rem);\
for(int i=rem;i<(H-ContSz);i+=buffIntsize)\
{\
LCD->interface->writeGRAM(bufferInt,buffIntsize);\
}\
}\
rem=(ContSz)%buffContsize;\
if(rem)LCD->interface->writeGRAM(bufferCont,rem);\
for(int i=rem;i<(ContSz);i+=buffContsize)\
{\
LCD->interface->writeGRAM(bufferCont,buffContsize);\
}\
}\
void ili9328setGRAMaddress(LCD_t* LCD,uint16_t Haddress,uint16_t Vaddress)
{
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALGRAMADDRESSSET,Haddress);
LCD->interface->writereg(ILI9328_REGISTER_VERTICALGRAMADDRESSSET,Vaddress);
}
void ili9328refreshenable(struct LCD_t* LCD,int enable)
{
if(enable)
{
//LCD->interface->writereg(ILI9328_REGISTER_ENTRYMODE,0x1018);
}
else
{
//LCD->interface->writereg(ILI9328_REGISTER_ENTRYMODE,0x1008);
}
}
void ili9328setFrame(LCD_t* LCD,uint16_t X,uint16_t Y,uint16_t W,uint16_t H)
{
if((X>239) || (Y>319) || ((X+W)>240) || ((Y+H)>320))
{
while (1);
}
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALADDRESSSTARTPOSITION,(uint32_t)X);
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALADDRESSENDPOSITION,(uint32_t)(W+X-1));
LCD->interface->writereg(ILI9328_REGISTER_VERTICALADDRESSSTARTPOSITION,(uint32_t)Y);
LCD->interface->writereg(ILI9328_REGISTER_VERTICALADDRESSENDPOSITION,(uint32_t)(Y+H-1));
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALGRAMADDRESSSET,(uint32_t)X);
LCD->interface->writereg(ILI9328_REGISTER_VERTICALGRAMADDRESSSET,(uint32_t)Y);
}
void ili9328paint(LCD_t* LCD,void* buffer,uint16_t Xpos,uint16_t Ypos,uint16_t Width,uint16_t Height)
{
if((LCD!=NULL) && (LCD->interface!=NULL) && (LCD->interface->writeGRAM!=NULL) && (LCD->width>=(Xpos+Width)) && (LCD->height>=(Ypos+Height)))
{
ili9328setFrame(LCD,Xpos,Ypos,Width,Height);
LCD->interface->writeGRAM(buffer,Width*Height);
}
}
void ili9328paintFilCirc(LCD_t* LCD,uint16_t Xpos,uint16_t Ypos,uint16_t r,uint32_t contColor,uint16_t contSz,uint32_t fillColor)
{
//Based on the mid point circle algorithm from Wikipedia
//http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
uint16_t innerbuffer[16];
uint16_t outterbuffer[16];
for(int i=0;i<16;i++)innerbuffer[i]=fillColor;
for(int i=0;i<16;i++)outterbuffer[i]=contColor;
if(contSz<r)
{
int error = -r,error_int = -r+contSz;
int x = r,x_int=r-contSz;
int y = 0,y_int=0;
while (x >= y)
{
ilipaintHLineWithCont(LCD,(Xpos-x),(Ypos+y),(2*x),(x-x_int),innerbuffer,16,outterbuffer,16);
ilipaintHLineWithCont(LCD,(Xpos-x),(Ypos-y),(2*x),(x-x_int),innerbuffer,16,outterbuffer,16);
ilipaintHalfTopVLineWithCont(LCD,(Xpos+y),(Ypos-x),(x),(x-x_int),innerbuffer,16,outterbuffer,16);
ilipaintHalfTopVLineWithCont(LCD,(Xpos-y),(Ypos-x),(x),(x-x_int),innerbuffer,16,outterbuffer,16);
ilipaintHalfBottomVLineWithCont(LCD,(Xpos-y),(Ypos),(x),(x-x_int),innerbuffer,16,outterbuffer,16);
ilipaintHalfBottomVLineWithCont(LCD,(Xpos+y),(Ypos),(x),(x-x_int),innerbuffer,16,outterbuffer,16);
error += y;
++y;
error += y;
error_int += y_int;
++y_int;
error_int += y_int;
if(error >= 0)
{
error -= x;
--x;
error -= x;
}
if(error_int >= 0)
{
error_int -= x_int;
--x_int;
error_int -= x_int;
}
}
}
}
void ili9328paintFilCirc_old(LCD_t* LCD,uint16_t Xpos,uint16_t Ypos,uint16_t r,uint32_t contColor,uint16_t contSz,uint32_t fillColor)
{
if(contSz<r)
{
uint16_t innerbuffer[16];
uint16_t outterbuffer[16];
int32_t rr=(r*r),rr2=((r-contSz)*(r-contSz)),contSz2,Val1,Val2,X1,W,rem;
for(int i=0;i<16;i++)innerbuffer[i]=fillColor;
for(int i=0;i<16;i++)outterbuffer[i]=contColor;
/* Y = b +/- sqrt[r^2 - (x - a)^2] */
for(int32_t line=-r;line<r;line++)
{
#ifdef __OPTIMIZED_MATH
Val1 = (uint32_t)optimised_sqrt((float32_t)(rr - (line*line)) );
Val2 = (uint32_t)optimised_sqrt((float32_t)(rr2 - (line*line)) );
#else
Val1 = sqrt( (double)(rr - ((line)*(line))) );
Val2 = sqrt( (double)(rr2 - ((line)*(line))) );
#endif
X1=Xpos - Val1;
contSz2= Val1-Val2;
ili9328setFrame(LCD,X1,line+Ypos,2*Val1,1);
rem=(contSz2)%16;
if(rem)LCD->interface->writeGRAM(outterbuffer,rem);
for(int i=rem;i<(contSz2);i+=16)
{
LCD->interface->writeGRAM(outterbuffer,16);
}
W=2*Val1;
if(W>(2*contSz2))
{
W-=2*contSz2;
rem=(W)%16;
if(rem)LCD->interface->writeGRAM(innerbuffer,rem);
for(int i=rem;i<(W);i+=16)
{
LCD->interface->writeGRAM(innerbuffer,16);
}
}
rem=(contSz2)%16;
if(rem)LCD->interface->writeGRAM(outterbuffer,rem);
for(int i=rem;i<(contSz2);i+=16)
{
LCD->interface->writeGRAM(outterbuffer,16);
}
}
}
}
void ili9328paintFilRect(LCD_t* LCD,uint16_t Xpos,uint16_t Ypos,uint16_t w,uint16_t h,uint32_t contColor,uint16_t contSz,uint32_t fillColor)
{
ili9328setFrame(LCD,Xpos,Ypos,w,h);
uint16_t tmp[32];
for(int i=0;i<32;i++)tmp[i]=fillColor;
for(int i=0;i<(h*w);i+=32)
{
LCD->interface->writeGRAM(tmp,32);
}
int rem=(w*h)%32;
if(rem)LCD->interface->writeGRAM(tmp,rem);
if(contSz)
{
ili9328setFrame(LCD,Xpos,Ypos,w,contSz);
for(int i=0;i<32;i++)tmp[i]=contColor;
rem=(w*contSz)%32;
if(rem)LCD->interface->writeGRAM(tmp,rem);
for(int i=rem;i<(w*contSz);i+=32)
{
LCD->interface->writeGRAM(tmp,32);
}
ili9328setFrame(LCD,Xpos,Ypos+h-contSz,w,contSz);
rem=(w*contSz)%32;
if(rem)LCD->interface->writeGRAM(tmp,rem);
for(int i=rem;i<(w*contSz);i+=32)
{
LCD->interface->writeGRAM(tmp,32);
}
ili9328setFrame(LCD,Xpos,Ypos,contSz,h);
rem=(h*contSz)%32;
if(rem)LCD->interface->writeGRAM(tmp,rem);
for(int i=rem;i<(h*contSz);i+=32)
{
LCD->interface->writeGRAM(tmp,32);
}
ili9328setFrame(LCD,Xpos+w-contSz,Ypos,contSz,h);
rem=(h*contSz)%32;
if(rem)LCD->interface->writeGRAM(tmp,rem);
for(int i=rem;i<(h*contSz);i+=32)
{
LCD->interface->writeGRAM(tmp,32);
}
}
}
void ili9328paintText(LCD_t* LCD,char* buffer,uint16_t Xpos,uint16_t Ypos,sFONT* font,uint32_t color)
{
int w=font->Width,h=font->Height,bpl=font->bytesPerLine,pix=0,tableoffset=0;
uint16_t tmp[w];
uint16_t linenum=0,charnum=0;
uint8_t line=0;
while(*buffer!='\0')
{
if(*buffer<32)*buffer=32;
if(*buffer>127)*buffer=32;
ili9328setFrame(LCD,Xpos+(charnum*w),Ypos-h,w,1);
// LCD->interface->readGRAM(tmp,w);
ili9328getPix(LCD,tmp,Xpos+(charnum*w),Ypos-h,w,1);
for(int i=0;i<(h*w);i++)
{
if( ((i%w)==0) ) //read current line to apply text pixmap
{
if(linenum++>0)
{
ili9328setFrame(LCD,Xpos+(charnum*w),Ypos + linenum -h,w,1);
LCD->interface->writeGRAM(tmp,w);
//ili9328setFrame(LCD,Xpos+(charnum*w),Ypos + linenum + 1-h,w,1);
// LCD->interface->readGRAM(tmp,w);
ili9328getPix(LCD,tmp,Xpos+(charnum*w),Ypos + linenum + 1-h,w,1);
pix=0;
}
}
if((pix%8) == 0)
{
line=font->table[(((*buffer)-32)*h*bpl)+tableoffset++];
}
//tmp[pix]=0;
if((line & (uint8_t)0x01)==(uint8_t)1)tmp[pix]=(uint16_t)color;
pix++;
line>>=1;
}
linenum=0;
tableoffset=0;
charnum++;
buffer++;
}
}
void ili9328paintChar(LCD_t* LCD,char buffer,uint16_t Xpos,uint16_t Ypos,sFONT* font,uint32_t color)
{
int w=font->Width,h=font->Height,bpl=font->bytesPerLine,pix=0,tableoffset=0;
uint16_t tmp[w];
uint16_t tmp2[w];
uint16_t linenum=0,charnum=0;
uint8_t line=0;
if(buffer<32)buffer=32;
if(buffer>127)buffer=32;
ili9328setFrame(LCD,Xpos,Ypos-h,w,1);
// LCD->interface->readGRAM(tmp,w);
ili9328getPix(LCD,tmp2,Xpos,Ypos-h,w,1);
for(int i=0;i<w;i++)
{
tmp[i]=0;
}
for(int i=0;i<(h*w);i++)
{
if( ((i%w)==0) ) //read current line to apply text pixmap
{
if(linenum++>0)
{
ili9328setFrame(LCD,Xpos,Ypos + linenum -h,w,1);
LCD->interface->writeGRAM(tmp,w);
//ili9328setFrame(LCD,Xpos+(charnum*w),Ypos + linenum + 1-h,w,1);
// LCD->interface->readGRAM(tmp,w);
ili9328getPix(LCD,tmp2,Xpos,Ypos + linenum + 1-h,w,1);
for(int i=0;i<w;i++)
{
tmp[i]=0;
}
pix=0;
}
}
if((pix%8) == 0)
{
line=font->table[(((buffer)-32)*h*bpl)+tableoffset++];
}
//tmp[pix]=0;
if((line & (uint8_t)0x01)==(uint8_t)1)tmp[pix]=(uint16_t)color;
pix++;
line>>=1;
}
}
int ili9328init(struct LCD_t* LCD)
{
if((LCD!=NULL) && (LCD->interface!=NULL) && (LCD->interface->writereg!=NULL))
{
LCD->interface->writereg(ILI9328_REGISTER_DRIVEROUTPUTCONTROL1, 0x0100); // Driver Output Control Register (R01h)
LCD->interface->writereg(ILI9328_REGISTER_LCDDRIVINGCONTROL, 0x0700); // LCD Driving Waveform Control (R02h)
LCD->interface->writereg(ILI9328_REGISTER_ENTRYMODE, 0x0230); // Entry Mode (R03h)
LCD->interface->writereg(ILI9328_REGISTER_DISPLAYCONTROL1, 0xC000);
LCD->interface->writereg(ILI9328_REGISTER_DISPLAYCONTROL2, 0x0302);
LCD->interface->writereg(ILI9328_REGISTER_DISPLAYCONTROL3, 0x0000);
LCD->interface->writereg(ILI9328_REGISTER_DISPLAYCONTROL4, 0x0000); // Fmark On
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL1, 0x0000); // Power Control 1 (R10h)
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL2, 0x0007); // Power Control 2 (R11h)
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL3, 0x0000); // Power Control 3 (R12h)
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL4, 0x0000); // Power Control 4 (R13h)
delay_100us(1000);
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL1, 0x14B0); // Power Control 1 (R10h)
delay_100us(500);
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL2, 0x0007); // Power Control 2 (R11h)
delay_100us(500);
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL3, 0x008E); // Power Control 3 (R12h)
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL4, 0x0C00); // Power Control 4 (R13h)
LCD->interface->writereg(ILI9328_REGISTER_POWERCONTROL7, 0x0015); // NVM read data 2 (R29h)
delay_100us(500);
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL1, 0x0000); // Gamma Control 1
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL2, 0x0107); // Gamma Control 2
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL3, 0x0000); // Gamma Control 3
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL4, 0x0203); // Gamma Control 4
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL5, 0x0402); // Gamma Control 5
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL6, 0x0000); // Gamma Control 6
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL7, 0x0207); // Gamma Control 7
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL8, 0x0000); // Gamma Control 8
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL9, 0x0203); // Gamma Control 9
LCD->interface->writereg(ILI9328_REGISTER_GAMMACONTROL10, 0x0403); // Gamma Control 10
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALADDRESSSTARTPOSITION, 0x0000); // Window Horizontal RAM Address Start (R50h)
LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALADDRESSENDPOSITION, LCD->width - 1); // Window Horizontal RAM Address End (R51h)
LCD->interface->writereg(ILI9328_REGISTER_VERTICALADDRESSSTARTPOSITION, 0X0000); // Window Vertical RAM Address Start (R52h)
LCD->interface->writereg(ILI9328_REGISTER_VERTICALADDRESSENDPOSITION, LCD->height - 1); // Window Vertical RAM Address End (R53h)
LCD->interface->writereg(ILI9328_REGISTER_DRIVEROUTPUTCONTROL2, 0xa700); // Driver Output Control (R60h)
LCD->interface->writereg(ILI9328_REGISTER_BASEIMAGEDISPLAYCONTROL, 0x0003); // Driver Output Control (R61h) - enable VLE
LCD->interface->writereg(ILI9328_REGISTER_PANELINTERFACECONTROL1, 0X0010); // Panel Interface Control 1 (R90h)
// Display On
LCD->interface->writereg(ILI9328_REGISTER_DISPLAYCONTROL1, 0x0133); // Display Control (R07h)
delay_100us(500);
LCD->paintFilRect(LCD,0,0,LCD->width,LCD->height,0,0,0xFFFF);
}
return 0;
}
void ili9328cpFrame(LCD_t* LCD,void* buffer,int x,int y,int w, int h)
{
#define __set__Address__(_x_,_y_) LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALGRAMADDRESSSET,_x_); \
LCD->interface->writereg(ILI9328_REGISTER_VERTICALGRAMADDRESSSET,_y_)
uint16_t* castedBuff = (uint16_t*)buffer;
int cx=x,cy=y;
for(int i=0;i<(w*h);i++)
{
__set__Address__(cx,cy);
LCD->interface->readGRAM((void*)(&castedBuff[i]),1);
cx+=1;
if(cx>=(w+x))
{
cx=x;
cy+=1;
}
}
}
void ili9328getPix(struct LCD_t* LCD,uint16_t* buffer,uint16_t Xpos,uint16_t Ypos,uint16_t w,uint16_t h)
{
#define __set__Address__(_x_,_y_) LCD->interface->writereg(ILI9328_REGISTER_HORIZONTALGRAMADDRESSSET,_x_); \
LCD->interface->writereg(ILI9328_REGISTER_VERTICALGRAMADDRESSSET,_y_)
int cx=Xpos,cy=Ypos;
ili9328setFrame(LCD,Xpos,Ypos,w,h);
for(int i=0;i<(w*h);i++)
{
__set__Address__(cx,cy);
LCD->interface->readGRAM((void*)(&buffer[i]),1);
cx+=1;
if(cx>=(w+Xpos))
{
cx=Xpos;
cy+=1;
}
}
}