//Internal Prototypes
void MX_LCD_Enable (void);
void MX_Write_Command(char cmd, char chip);
void GotoXY(char x, char y);
void MX_WriteData(char data);
char MX_ReadData(void);
//Internal Functions
void MX_LCD_Enable (void)
{
set_bit(MX_CONTROL_PORT, MX_ENABLE);
//delay_10us(1); //Min delay 450ns
nop();
nop();
nop();
nop();
nop();
clear_bit(MX_CONTROL_PORT, MX_ENABLE);
//delay_10us(1); //Min delay 1.5us
nop();
nop();
nop();
nop();
nop();
}
void MX_Write_Command(char cmd, char chip)
{
if(chip == MX_CHIP1) //Select Chip 1
{
clear_bit(MX_CONTROL_PORT, MX_CS2);
set_bit(MX_CONTROL_PORT, MX_CS1);
}
else if(chip == MX_CHIP2) //Select Chip 2
{
clear_bit(MX_CONTROL_PORT, MX_CS1);
set_bit(MX_CONTROL_PORT, MX_CS2);
}
clear_bit(MX_CONTROL_PORT, MX_READ_WRITE); //Write Command
clear_bit(MX_CONTROL_PORT, MX_DAT_INST); //Instruction code
MX_DATA_TRIS = 0x00; //Configure data port as output
MX_DATA_PORT = cmd;
MX_LCD_Enable();
MX_DATA_PORT = 0x00;
}
void MX_GotoXY(char x, char y)
{
char chip = MX_CHIP1;
char cmd;
if(x > 127) x = 0; //Ensure that coordinates are legal
if(y > 63) y = 0;
mx_currentx = x;
mx_currenty = y;
mx_page = y / 8;
if(x >= 64) //Select the right chip
{
x = x - 64;
chip = MX_CHIP2;
}
cmd = MX_LCD_SET_PAGE | mx_page; //Set y address on both chips
MX_Write_Command(cmd, MX_CHIP1);
MX_Write_Command(cmd, MX_CHIP2);
cmd = MX_LCD_SET_ADD | x; //Set x address on active chip
MX_Write_Command(cmd, chip);
}
void MX_WriteData(char data)
{
char displayData, yOffset, cmdPort;
if(mx_currentx >= 128)
return;
if(mx_currentx < 64)
{
clear_bit(MX_CONTROL_PORT, MX_CS2); //Select chip 1
set_bit(MX_CONTROL_PORT, MX_CS1);
}
else if(mx_currentx >= 64)
{
clear_bit(MX_CONTROL_PORT, MX_CS1); //Select chip 2
set_bit(MX_CONTROL_PORT, MX_CS2);
}
if(mx_currentx == 64) //Chip 2 X Address = 0
MX_Write_Command(MX_LCD_SET_ADD, MX_CHIP2);
set_bit(MX_CONTROL_PORT, MX_DAT_INST); //Configure to send data
clear_bit(MX_CONTROL_PORT, MX_READ_WRITE); //Configure to write data
MX_DATA_TRIS = 0x00; //Configure data port to Output
yOffset = mx_currenty % 8;
if(yOffset != 0) //First page?
{
cmdPort = MX_CONTROL_PORT; //Save command port
displayData = MX_ReadData();
MX_CONTROL_PORT = cmdPort; //Restore command port
MX_DATA_TRIS = 0x00; //Data port is output
displayData = displayData | (data << yOffset);
MX_DATA_PORT = displayData; //Write data
MX_LCD_Enable(); //Enable
// second page
MX_GotoXY(mx_currentx, (mx_currenty + 8));
displayData = MX_ReadData();
MX_CONTROL_PORT = cmdPort; //Restore command port
MX_DATA_TRIS = 0x00; //Data port is output
displayData = displayData | (data >> (8-yOffset));
MX_DATA_PORT = displayData; //Write data
MX_LCD_Enable(); //Enable
MX_GotoXY(mx_currentx + 1, (mx_currenty - 8));
}
else
{
MX_DATA_PORT = data; //Write data
MX_LCD_Enable(); //Enable
mx_currentx = mx_currentx + 1;
}
MX_DATA_PORT = 0x00;
}
char MX_ReadData(void)
{
char data, i;
MX_DATA_PORT = 0x00;
MX_DATA_TRIS = 0xFF; //Data port is input
set_bit(MX_CONTROL_PORT, MX_READ_WRITE); //Configure to read data
set_bit(MX_CONTROL_PORT, MX_DAT_INST); //Configure to send data
if(mx_currentx < 64)
{
clear_bit(MX_CONTROL_PORT, MX_CS2); //Select chip 1
set_bit(MX_CONTROL_PORT, MX_CS1);
}
else if(mx_currentx >= 64)
{
clear_bit(MX_CONTROL_PORT, MX_CS1); //Select chip 2
set_bit(MX_CONTROL_PORT, MX_CS2);
}
set_bit(MX_CONTROL_PORT, MX_ENABLE); //Set the enable bit
for (i=0; i<3; i++);
clear_bit(MX_CONTROL_PORT, MX_ENABLE); //Clear the enable bit
for (i=0; i<8; i++); //Min 1.5us delay
set_bit(MX_CONTROL_PORT, MX_ENABLE); //Set the enable bit
for (i=0; i<15; i++); //Min 450ns delay
data = MX_DATA_PORT; //Read Data
clear_bit(MX_CONTROL_PORT, MX_ENABLE); //Clear the enable bit
MX_DATA_TRIS = 0x00; //Configure port as output
MX_GotoXY(mx_currentx, mx_currenty);
return data;
}
// Dummy function to close the defines section off
void CUSTOM_Dummy_Function();
void CUSTOM_Dummy_Function()
{
}
void FCD_Custom0_LCD_Init()
{
mx_currentx = 0;
mx_currenty = 0;
mx_page = 0;
MX_DATA_TRIS = 0x00; //Convert data port to output
MX_DATA_PORT = 0x00;
clear_bit(MX_CONTROL_TRIS, MX_ENABLE); //Convert control pins to output
clear_bit(MX_CONTROL_TRIS, MX_DAT_INST);
clear_bit(MX_CONTROL_TRIS, MX_CS1);
clear_bit(MX_CONTROL_TRIS, MX_CS2);
clear_bit(MX_CONTROL_TRIS, MX_READ_WRITE);
set_bit(MX_CONTROL_PORT, MX_ENABLE);
clear_bit(MX_CONTROL_PORT, MX_READ_WRITE); //Write Command
clear_bit(MX_CONTROL_PORT, MX_DAT_INST); //Instruction code
set_bit(MX_CONTROL_PORT, MX_CS1); //Select Chip 1
clear_bit(MX_CONTROL_PORT, MX_CS2);
MX_Write_Command(MX_LCD_ON, MX_CHIP1); //Switch on LCD controller chips
MX_Write_Command(MX_LCD_ON, MX_CHIP2);
MX_Write_Command(MX_LCD_DISP_START, MX_CHIP1); //Configure the display start address
MX_Write_Command(MX_LCD_DISP_START, MX_CHIP2);
FCD_Custom0_LCD_Clear();
MX_GotoXY(0,0);
}
void FCD_Custom0_LCD_Clear()
{
FCD_Custom0_LCD_Draw_Rect(0, 0, 127, 63, MX_WHITE);
}
void FCD_Custom0_LCD_PlotPixel(char x, char y, char colour)
{
char data, mod_y;
mod_y = y%8;
MX_GotoXY(x, y - mod_y);
data = MX_ReadData(); //Read 8 pixels from display
if (colour)
data = data | (0x01 << mod_y); //Set Pixel
else
data = data & (~(0x01 << mod_y)); //Clear Pixel
MX_WriteData(data);
}
void FCD_Custom0_LCD_Draw_Line(char x, char y, char x2, char y2, char colour)
{
int C1, M1;
signed int D1 = 0;
signed int Pixelx = x2 - x; //number of X-pixels;
signed int Pixely = y2 - y; //Number of Y-pixels
signed char Xinc = 1;
signed char Yinc = 1;
if (Pixelx < 0) //If negative X direction
{
Xinc = -1;
Pixelx = Pixelx * -1;
}
if (Pixely < 0) //If negative Y direction
{
Yinc = -1;
Pixely = Pixely * -1;
}
if (Pixely <= Pixelx)
{
C1 = 2 * Pixelx;
M1 = 2 * Pixely;
while (x != x2)
{
FCD_Custom0_LCD_PlotPixel(x, y, colour); //ForePlot line
x = x + Xinc;
D1 = D1 + M1;
if (D1 > Pixelx)
{
y = y + Yinc;
D1 = D1 - C1;
}
}
}
else
{
C1 = 2 * Pixely;
M1 = 2 * Pixelx;
while (y != y2)
{
FCD_Custom0_LCD_PlotPixel(x, y, colour); //ForePlot Line
y = y + Yinc;
D1 = D1 + M1;
if (D1 > Pixely)
{
x = x + Xinc;
D1 = D1 - C1;
}
}
FCD_Custom0_LCD_PlotPixel(x, y, colour);
}
}
void FCD_Custom0_LCD_Draw_Rect(char x, char y, char width, char height, char colour)
{
char mask, pageOffset, h, i, data;
if(colour)
colour = 255;
height = height + 1;
pageOffset = y % 8;
y = y - pageOffset;
mask = 0xFF;
if(height < (8 - pageOffset))
{
mask = mask >> (8-height);
h = height;
}
else
h = (8 - pageOffset);
mask = mask << pageOffset;
MX_GotoXY(x, y);
for(i=0; i<=width; i++)
{
data = MX_ReadData();
if(colour)
data = data | mask;
else
data = data & (~mask);
MX_WriteData(data);
}
while((h + 8) <= height)
{
h = h + 8;
y = y + 8;
MX_GotoXY(x, y);
for(i=0; i<=width; i++)
MX_WriteData(colour);
}
if(h < height)
{
mask = ~(0xFF << (height - h));
MX_GotoXY(x, (y + 8));
for(i=0; i<=width; i++)
{
data = MX_ReadData();
if(colour)
data = data | mask;
else
data = data & (~mask);
MX_WriteData(data);
}
}
}
void FCD_Custom0_LCD_Print_String(char* String, char MSZ_String, char X, char Y, char Font, char Transparent, char Colour)
{
char xpix, ypix, pos_Str, count, xcount, ycount, height, width, i;
char Fontwidth = 1; //First we assume small font
char Fontheight = 1;
char inv_colour = 1;
char temp[6];
temp[5] = 0x00; //Spacing Line
if (Colour)
inv_colour = 0;
if (Font == 1) //Double Height Sizes //Double Width
{
Fontwidth = 2;
}
if (Font == 2) //Double Height and Width Sizes
{
Fontwidth = 2;
Fontheight = 2;
}
if (Font == 3) //Double Height Sizes
{
Fontheight = 2;
}
if (Font == 4) //Double Height and Width Sizes
{
Fontwidth = 3;
Fontheight = 3;
}
if (Font == 5) //Double Height and Width Sizes
{
Fontwidth = 7;
Fontheight = 7;
}
xcount = 0;
for (i=0;i<MSZ_String;i++) //Start at beginning of string and work along
{
if (String[i] == 0)
return;
pos_Str = String[i] - 32; //Calculate place in ASCII memory
for (count = 0; count < 5; count++) //Use correct buffer location
{
if (pos_Str < 12)
{
temp[count]=ASCII1[(pos_Str*5)+count];
}
else if (pos_Str < 24)
{
temp[count]=ASCII2[((pos_Str - 12)*5)+count];
}
else if (pos_Str < 36)
{
temp[count]=ASCII3[((pos_Str - 24)*5)+count];
}
else if (pos_Str < 48)
{
temp[count]=ASCII4[((pos_Str - 36)*5)+count];
}
else if (pos_Str < 60)
{
temp[count]=ASCII5[((pos_Str - 48)*5)+count];
}
else if (pos_Str < 72)
{
temp[count]=ASCII6[((pos_Str - 60)*5)+count];
}
else if (pos_Str < 84)
{
temp[count]=ASCII7[((pos_Str - 72)*5)+count];
}
else if (pos_Str < 95)
{
temp[count]=ASCII8[((pos_Str - 84)*5)+count];
}
}
for (xpix=0;xpix<6;xpix++) //For 6 ASCII bytes 0 - 5
{
for (width=0;width<Fontwidth;width++)
{
ycount = 0;
for (ypix=0;ypix<8;ypix++) //For 8 data bits in bytes 0 - 7
{
for (height=0;height<Fontheight;height++)
{
if (test_bit(temp[xpix],ypix))
{
FCD_Custom0_LCD_PlotPixel(X + xcount, Y + ycount, Colour);
}
else if (Transparent == 0)
{
FCD_Custom0_LCD_PlotPixel(X+xcount, Y+ycount, inv_colour);
}
ycount++;
}
}
xcount++;
}
}
}
}
void FCD_Custom0_LCD_Print_Number(short Number, char X, char Y, char Font, char Transparent, char Colour)
{
char string_length;
if (Number < -10000 )
string_length = 6;
else if(Number > 10000 || Number < -1000)
string_length = 5;
else if(Number > 1000 || Number < -100)
string_length = 4;
else if(Number > 100 || Number < -10)
string_length = 3;
else if(Number > 10 || Number < -1)
string_length = 2;
else
string_length = 1;
char temp_str[6];
FCI_TOSTRING(Number,temp_str,string_length); //Convert number to String
FCD_Custom0_LCD_Print_String(temp_str, string_length, X, Y, Font, Transparent, Colour); //Send string to Print function
}
void FCD_Custom0_LCD_Invert_Rect(char x, char y, char width, char height)
{
char mask, pageOffset, h, i, data, tmpData;
height++;
pageOffset = y % 8;
y = y - pageOffset;
mask = 0xFF;
if(height < (8 - pageOffset))
{
mask = mask >> (8-height);
h = height;
}
else
{
h = 8 - pageOffset;
}
mask = mask << pageOffset;
MX_GotoXY(x, y);
for(i=0; i<=width; i++)
{
data = MX_ReadData();
tmpData = ~data;
data = (tmpData & mask) | (data & ~mask);
MX_WriteData(data);
}
while((h + 8) <= height)
{
h = h + 8;
y = y + 8;
MX_GotoXY(x, y);
for(i=0; i<=width; i++)
{
data = MX_ReadData();
MX_WriteData(~data);
}
}
if(h < height)
{
mask = ~(0xFF << (height-h));
MX_GotoXY(x, y+8);
for(i=0; i<=width; i++)
{
data = MX_ReadData();
tmpData = ~data;
data = (tmpData & mask) | (data & ~mask);
MX_WriteData(data);
}
}
}
//Macro implementations
void FCM_TIMER_SERVICE()
{
//Decision
//Decision: INT < 75?
if (FCV_INT < 75)
{
//Calculation
//Calculation:
// INT = INT + 1
FCV_INT = FCV_INT + 1;
} else {
//Calculation
//Calculation:
// INT = 0
FCV_INT = 0;
//Calculation
//Calculation:
// SECONDS = SECONDS + 1
FCV_SECONDS = FCV_SECONDS + 1;
}
}
//Supplementary implementations
void main()
{
//Initialisation
adcon1 = 0x07;
//Interrupt initialisation code
option_reg = 0xC0;
//Call Component Macro
//Call Component Macro: Custom(0)::LCD_Init
FCD_Custom0_LCD_Init();
//Interrupt
//Interrupt: Enable TMR0 Overflow
option_reg.T0CS=0;
option_reg.T0SE=1;
option_reg = (option_reg & 0xF0) | 0x07;
intcon.GIE=1;
intcon.T0IE=1;
//Output
//Output: 1 -> C2
trisc = trisc & 0xfb;
if (1)
portc = (portc & 0xfb) | 0x04;
else
portc = portc & 0xfb;
//Loop
//Loop: While 1
while (1)
{
//Decision
//Decision: SECONDS = 1?
if (FCV_SECONDS == 1)
{
//Output
//Output: 1 -> D1
trisd = trisd & 0xfd;
if (1)
portd = (portd & 0xfd) | 0x02;
else
portd = portd & 0xfd;
//Delay
//Delay: 100 ms
delay_ms(100);
//Output
//Output: 0 -> D1
trisd = trisd & 0xfd;
if (0)
portd = (portd & 0xfd) | 0x02;
else
portd = portd & 0xfd;
//Calculation
//Calculation:
// SECONDS = 0
FCV_SECONDS = 0;
}
//Delay
//Delay: 50 ms
delay_ms(50);
//
//Call Component Macro: Custom(0)::LCD_Print_Number(SECONDS, 40, 30, 0, 0, 1)
FCD_Custom0_LCD_Print_Number(FCV_SECONDS, 40, 30, 0, 0, 1);
}
mainendloop: goto mainendloop;
}
void interrupt(void)
{
if (intcon & (1 << T0IF))
{
FCM_TIMER_SERVICE();
clear_bit(intcon, T0IF);
}
}