📄 ltps_lcd_pmp.c
字号:
/*************************************************************************************
Programmer : Stanley Huang, The FAE of Hsinchu office.
Date : 2007.01.31
Processor : PIC24FJ128GA006
Compiler : C30 V3.0
Board : (1)Microchip Taiwan PIC24 64-pin demo board
(2)TPO 1.77" 128x160xRGB LTPS panel, TD018THEM2,
*************************************************************************************/
/* Setup:
- If you plan on interfacing to a CompactFlash card, add cf.c and CF.h to
your project. If you're using SD or MMC cards, add sdmmc.c, sdmmc.h,
and sdmmc_lld.h. Set the appropriate preprocessor directive in _fat.def.
"#if 0" for CF, "#if 1" for SD/MMC.
- Define your system clock in _fat.def
- If you're going to use static memory for your file objects, specify the
maximum number of files that you are going to open at any time in _fat.def
- Uncomment the appropriate SPI line in _fat.def. FAT_MEDIA_IF_SPI if your part
only has one SPI module, FAT_MEDIA_IF_SPI1 if your part has two modules and you
are using the first one, FAT_MEDIA_IF_SPI2 if your part has two modules and you
are using the second one. Only necessary for SD/MMC
- If you are using PIC18, modify your linker file to include a
512-byte section of RAM that will act as a buffer for file reads/writes.
This buffer is defined at the top of the sdmmc.c or
cf.c files. You should also create a section in the linker mapped
to this RAM called "myBuff." An example of how to do this is given
in the 18F4550 linker file included with this library
- If you plan to use dynamic memory to allocate file objects, set the
corresponding preprocessor directive in the _fat.def file to "#if 1"
Also, if you are using PIC18, you must create a section in the linker
file called "_SRAM_ALLOC_HEAP" that contains enough memory to contain all
of the file objects you want to open. Each file object is 46 bytes. Due to
variation in the memory allocation algorithm, the amount you are required to
allocate will be larger than this. This is also true for PIC24. Testing
will be necessary to determine if enough memory was allocated. Include the
salloc.c and salloc.h files in your project if you are using PIC18.
If you plan on using dynamic memory allocation with the PIC24, you will need
to create a heap in the MPLINK30 tab of the Build Options menu.
-Set the library path and include path (and linker path, if PIC18) in the General
tab of the Build Options menu
-Set the required input and output pins in CF.h or sdmmc.h. These include:
CF.h: Address and Data busses and Tri-state registers, Chip select, output enable,
write enable, reset, ready, and card detect
sdmmc.h: Chip select, write enabled, card detect
These pins have separate definitions for PIC18 and PIC24 in the files.
-Make sure that all pins you use are configured as digital I/Os, including PORTB pins set
in the configuration registers, and any pins that could be analog channels for the A/D
converter
-Select the appropriate device and language toolset. The code that will be compiled will
be appropriate to the processor type (PIC18 or PIC24F)
-Add Compiler.h to your project files if you're using PIC18
*/
#include "FAT16.h"
#include "system.h"
#include "Bitmap.h"
// Setup configuration bits
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & IESO_OFF)
//
void InitialIOPort(void);
void PMPInitial(void);
void PowerOnLCD(void);
void WriteLCD_Data(unsigned char DataByte);
void WriteLCD_Command(unsigned char RegAddress, unsigned char CommandByte);
void MovePenXY(unsigned char X, unsigned char Y);
void ADC10_Initial(void);
unsigned int ReadAD(void);
void CheckTask(void);
void PerformTask(void);
void Timer32Init(void);
void WaitNSec(void);
void Delay(int value);
/**************************************************************************************
-This Panel uses these pins below:
PortD<0> = LTPS$CS_N
PortD<1> = LTPS$RESET_N
PortE<7:0> (PMP Data) = LTPS$D7~D0
PortD<4> (PMP PMWR) = LTPS$WR_N
PortB<15> (PMP PMA0) = LTPS$RS // Writing address 0x0000 to set RS=Low
// Writing address 0x0001 to set RS=High
-The POT use these pins below:
PortB<0> => AN0
-The following definition is defined in _fat.def file:
#define SD_CS PORTBbits.RB1
#define SD_CS_TRIS TRISBbits.TRISB1
#define SD_CD 0 //PORTFbits.RF0, Stanley remark, Card alwayse in.
#define SD_CD_TRIS TRISFbits.TRISF0
#define SD_WE 0 //PORTFbits.RF1, Stanley remark, alwayse no protect
#define SD_WE_TRIS TRISFbits.TRISF1
-Note:
(1)LTPS$VDDIO goes to VDD 3.3V directly.
(2)PortB<14> (PMP PMA1) also can't be used duo to PMP setting.
**************************************************************************************/
#define LTPS$CS_N LATDbits.LATD0
#define LTPS$RESET_N LATDbits.LATD1
#define LTPS$XStart 0
#define LTPS$YStart 0
#define LTPS$XEnd 160
#define LTPS$YEnd 128
#define HIGH 1
#define LOW 0
#define MaxTask 12 // 0~12
//The destination for the information read from SD card
unsigned char RdBuffer[3840];
unsigned char NewTask, CurrentTask ;
/**************************************************************************************
|| D7, D6, D5, D4, D3, D2, D1, D0 || D7, D6, D5, D4, D3, D2, D1, D0 ||
=> R5, R4, R3, R2, R1, G5, G4, G3 G2, G1, G0, B5, B4, B3, B2, B1
2 byte per pixel
**************************************************************************************/
unsigned char TPattern[]={
0xF8,0x00, //Red
0xFC,0x00,
0xFF,0xE0, //Yellow
0x04,0x10,
0x00,0x1F,
0x00,0x10,
0x80,0x1F,
0xFF,0xFF
};
int main(void)
{
//Nop()
InitialIOPort();
PowerOnLCD();
PMPInitial(); // Initial PMP Module
LTPS$CS_N = LOW ;
WriteLCD_Command(0x06,0xc7); // Set LCD bias
WriteLCD_Command(0x17,0x01); // Set SRAM writed direction
LTPS$CS_N = HIGH ;
Timer32Init();
ADC10_Initial();
// Obtain information about the file system on the card
// This function will also send initialization codes to the card,
// which means it must be called every time the card is
// removed and reinserted
while (!FAT16Init());
CurrentTask = NewTask = 0 ;
while(1)
{
PerformTask();
}
}
/**************************************************************************************
I/O functions:
**************************************************************************************/
void InitialIOPort(void)
{
TRISD &= 0xfffc ; // Low 2 pins are Control Pins
}
void PMPInitial(void)
{
PMCON = 0x02E1 ; // Setup the PMP
PMMODE = 0x0200 ; // 8 bit mode; No delay cycle;
PMAEN = 0x0001 ; // Use PMPEN, when you use C30 2.05
PMADDR = 0x0001 ;
PMCON |= 0x8000 ;
}
/**************************************************************************************
Subroutines for the panel:
**************************************************************************************/
void PowerOnLCD(void)
{
LTPS$CS_N = LOW ;
LTPS$RESET_N = LOW ;
//-- Reset wavform --
Delay(1000) ;
LTPS$RESET_N = HIGH ;
Delay(1000) ;
LTPS$CS_N = HIGH ;
/****************************************************
Panel registers:
Register(0x01h), MODE_SEL1
register(0x02h), MODE_SEL2
register(0x03h), MODE_SEL3 //for CPU I/F
register(0x04h), MODE_SEL4 //for SPI I/F
register(0x05h), VCO_Mode
register(0x07h), VCOMH_CTRL
register(0x08h), VCOML_CTRL
register(0x09h), PWS_X
register(0x10h), PWS_Y
register(0x11h), PWE_X
register(0x12h), PWE_Y
register(0x18h), SRAM_POSITION_X
register(0x19h), SRAM_POSITION_Y
register(0x17h), SRAM_Control
/***************************************************/
}
void WriteLCD_Data(unsigned char DataByte)
{
//PMADDR = 0x0001 ;
PMDIN1 = DataByte ;
}
void WriteLCD_Command(unsigned char RegAddress, unsigned char CommandByte)
{
PMADDR = 0x0000 ;
PMDIN1 = RegAddress ;
PMADDR = 0x0001 ;
PMDIN1 = CommandByte ;
}
void MovePenXY(unsigned char X, unsigned char Y)
{
WriteLCD_Command(0x18, X);
WriteLCD_Command(0x19, Y);
}
/**************************************************************************************
Peripheral functions:
**************************************************************************************/
void ADC10_Initial(void)
{
AD1PCFG = 0xFFFE; // AN0/RB0 is Analog , others are Digital;
AD1CON2 = 0x0000; // 0000_0000 0000_0000
// Don't Scan, SMPI 00, 16W Buf, MUX A only,
AD1CON3 = 0x1C70; // 0001_1100 0111_0000
AD1CON1 = 0x20E4; // 0b0010 0000 1110 0100
// Integer, Auto-convert, Sample immed.
AD1CSSL = 0x0000; // no scan input selected .......
AD1CHS = 0x0000; // 0000_0000 0000_0000
// MUX A Ch0 Pos, VR- Neg
IEC0bits.AD1IE = 0 ; // Disable AD interrupt
IPC3bits.AD1IP = 0 ; // Set Priority to 0
AD1CON1bits.ADON = 1; // Turn ADC ON
}
unsigned int ReadAD(void)
{
AD1CON1bits.DONE = 0;
while(!AD1CON1bits.DONE);
return(ADC1BUF0) ;
}
void CheckTask(void)
{
unsigned int ADRes;
ADRes = ReadAD();
if(ADRes>=0 && ADRes<0x40)
NewTask = 0;
else if(ADRes>=0x50 && ADRes<0x90)
NewTask = 1;
else if(ADRes>=0xA0 && ADRes<0xE0)
NewTask = 2;
else if(ADRes>=0xF0 && ADRes<0x130)
NewTask = 3;
else if(ADRes>=0x140 && ADRes<0x180)
NewTask = 4;
else if(ADRes>=0x190 && ADRes<0x1D0)
NewTask = 5;
else if(ADRes>=0x1E0 && ADRes<0x220)
NewTask = 6;
else if(ADRes>=0x230 && ADRes<0x270)
NewTask = 7;
else if(ADRes>=0x280 && ADRes<0x2C0)
NewTask = 8;
else if(ADRes>=0x2D0 && ADRes<0x310)
NewTask = 9;
else if(ADRes>=0x320 && ADRes<0x360)
NewTask = 10;
else if(ADRes>=0x370 && ADRes<0x3E0)
NewTask = 11;
else if(ADRes>=0x3F0 && ADRes<=0x3FF)
NewTask = MaxTask;
}
void PerformTask(void)
{
unsigned char x, y, Loop, Rdata, Gdata, Bdata;
unsigned int ImagePt;
FILE *file_ptr; // The file_ptr to the file object
BITMAPFILEHEADER Bitmapfileheader;
// Name of the file to create
const char *fileName[] = {
"dummy", "dummy",
"im1.bmp", "im2.bmp", "im3.bmp", "im4.bmp", "im5.bmp",
"im6.bmp", "im7.bmp", "im8.bmp", "im9.bmp", "im10.bmp"
};
switch( CurrentTask )
{
// ---------------- R ----------------
case 0:
LTPS$CS_N = LOW ;
MovePenXY(0x00, 0x00);
for(x=LTPS$XStart; x<LTPS$XEnd; x++)
{
for(y=LTPS$YStart; y<LTPS$YEnd; y++)
{
WriteLCD_Data(0xF8) ; // R
WriteLCD_Data(0x00) ;
//WriteLCD_Data(0x07) ; // G
//WriteLCD_Data(0xE0) ;
//WriteLCD_Data(0x00) ; // B
//WriteLCD_Data(0x1F) ;
}
}
LTPS$CS_N = HIGH ;
break;
// ---------------- Pattern (Rainbow) ----------------
case 1:
LTPS$CS_N = LOW ;
MovePenXY(0x00, 0x00);
for(Loop=0; Loop<16; Loop+=2)
{
for(x=0; x<20; x++)
{
for(y=LTPS$YStart; y<LTPS$YEnd; y++)
{
WriteLCD_Data(TPattern[Loop]) ;
WriteLCD_Data(TPattern[Loop+1]) ;
}
}
}
LTPS$CS_N = HIGH ;
break;
// ---------------- Read images from SD card ----------------
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
if ((file_ptr = fopenpgm(fileName[CurrentTask], "r")) != NULL)
{
// Check the files if BMP format
fread(Bitmapfileheader.Headerbuffer, 1, 54, file_ptr);
if (Bitmapfileheader.bfType == 0x4D42) // Check if BMP.
{
LTPS$CS_N = LOW ;
MovePenXY(0x00, 0x00);
for(x=0; x<16; x++)
{
// For efficient consideration:
// Read 8 row one time.
// 160(Pixel) * 3(Byte) * 8(Row) = 3840(Byte)
// So read 128/8=16 time.
fread(RdBuffer, 1, 3840, file_ptr);
for(ImagePt=0; ImagePt<3840; ImagePt+=3)
{
Bdata = RdBuffer[ImagePt];
Gdata = RdBuffer[ImagePt+1];
Rdata = RdBuffer[ImagePt+2];
// 3 bytes data are packed into 2 bytes.
// Wrong :
/*
Rdata = ((Rdata<<2) & 0xF8) |
((Gdata>>3) & 0x07) ;
Bdata = ((Gdata<<5) & 0xE0) |
((Bdata>>1) & 0x1F) ;
*/
// Trunk lower bits directly
//asm("nop"); // debug point
WriteLCD_Data( (Rdata & 0xF8) | (Gdata >> 5) ) ;
WriteLCD_Data( ((Gdata << 3) & 0xE0) | ( Bdata >> 3) ) ;
}
}
LTPS$CS_N = HIGH ;
} // End of if (Bitmapfileheader.bfType == 0x4D42)
}
fclose (file_ptr);
break;
default :
break;
} // End of switch( CurrentTask )
if( NewTask == MaxTask )
{
// Auto Run
if( CurrentTask< MaxTask ) // Check boundary
CurrentTask ++;
else
CurrentTask = 0;
WaitNSec();
CheckTask(); // In order to change NewTask.
}
else
{
while( CurrentTask == NewTask )
{
CheckTask();
}
CurrentTask = NewTask ;
}
}
void Timer32Init(void)
{
//IFS0bits.T2IF = 0; // clear IF bit //
//IPC1bits.T2IP = 0; // assigning Interrupt Priority //
IEC0bits.T2IE = 0; // Interrupt Enable /Disable //
PR2 = 0x0000; // Assigning Period to Timer2 & 3
PR3 = 0x0200;
T2CON = 0x2008; // TimerOff, 1:1, T32, IntClk.
// 0b 0010_0000 0011_1000
}
void WaitNSec(void)
{
TMR2 = 0; // Reset Timer2 & 3 to 0x0000 //
TMR3HLD = 0;
IFS0bits.T3IF = 0;
T2CON |=0x8000; // Timer2 On
while(!IFS0bits.T3IF);
T2CON &=0x7FFF; // Timer2 Off
}
/**************************************************************************************
ISR:
**************************************************************************************/
/*
void _ISR _ADCInterrupt(void)
{
Flags.ADC_DONE = 1 ;
IFS0bits.ADIF = 0 ;
MyADC = ADCBUF0 ;
}
*/
/**************************************************************************************
Misc:
**************************************************************************************/
void Delay(int value)
{
for(;value>0;value--);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -