Section 73: Algorithm program for mirroring fonts on the LCD screen

Publisher:CreativeDreamerLatest update time:2016-03-16 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
Opening remarks:

Some projects require mirroring of fonts or images. This section will teach you the algorithm.

The essence of this algorithm is:

A 16x16 dot matrix image or font has 16 lines, each line has 2 bytes. If these 2 bytes are regarded as a 16-bit int data, then the data needs to be reversed from the original order of high bits on the left and low bits on the right. This program does not merge the 2 bytes into an int data, but directly reverses the order of high and low bits in a byte data, and then swaps the first byte data with the second byte data.

An 8x16 dot matrix image or font has 16 lines, each line has 1 byte, and the data is reversed from the original order of high bits on the left and low bits on the right.

For details, please see the source code.

(1) Hardware platform:

Based on Zhu Zhaoqi 51 single-chip microcomputer learning board.

(2) Function: After the machine is powered on, the four characters "Mantou V5" and the four characters "Mantou V5" on the right side after being mirrored are displayed from top to bottom.

(3) The source code is explained as follows:

#include "REG52.H"

sbit LCDCS_dr = P1^6; //chip select line

sbit LCDSID_dr = P1^7; //Serial data line

sbit LCDCLK_dr = P3^2; //Serial clock line

sbit LCDRST_dr = P3^4; //reset line

void SendByteToLcd(unsigned char ucData); //Send a byte of data to the LCD module

void SPIWrite(unsigned char ucWData, unsigned char ucWRS); //Simulate SPI to send a byte of command or data to the underlying driver of the LCD module

void WriteCommand(unsigned char ucCommand); //Send a byte command to the LCD module

void LCDWriteData(unsigned char ucData); //Send one byte of data to the LCD module

void LCDInit(void); //Initialization function including LCD module reset

void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount); //Display any lattice function

void display_clear(void); // Clear the screen

void hz1616_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult); //Mirror the 16x16 dot matrix font

void hz816_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult); //Mirror the 8x16 dot matrix font

void delay_short(unsigned int uiDelayshort); //Delay

code unsigned char Hz1616_man[]= /* horizontal modulus 16X16 dot matrix*/

{

0x21,0xF8,0x21,0x08,0x21,0xF8,0x3D,0x08,0x45,0xF8,0x48,0x00,0x83,0xFC,0x22,0x94,

0x23,0xFC,0x20,0x00,0x21,0xF8,0x20,0x90,0x28,0x60,0x30,0x90,0x23,0x0E,0x00,0x00,

};

code unsigned char Hz1616_tou[]= /*Head horizontal modulus 16X16 dot matrix*/

{

0x00,0x80,0x10,0x80,0x0C,0x80,0x04,0x80,0x10,0x80,0x0C,0x80,0x08,0x80,0x00,0x80,

0xFF,0xFE,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x30,0x08,0x18,0x10,0x0C,0x20,0x08,

};

code unsigned char Zf816_V[]= /*V horizontal modulus 8x16 dot matrix*/

{

0x00,0x00,0x00,0xE7,0x42,0x42,0x44,0x24,0x24,0x28,0x28,0x18,0x10,0x10,0x00,0x00,

};

code unsigned char Zf816_5[]= /*5 horizontal modulus 8x16 dot matrix*/

{

0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,

};

unsigned char ucBufferResult[32]; //Used to temporarily store the character array after the conversion is completed

void main()

{

LCDInit(); // Initialize 12864 including the reset of the LCD module

display_clear(); // Clear the screen

display_lattice(0,0,Hz1616_man,0,2,16); //Display the word <馒> before mirroring

hz1616_mirror(Hz1616_man,ucBufferResult); //Mirror the character <馒> and put it into the temporary variable ucBufferResult.

display_lattice(1,0,ucBufferResult,0,2,16); //Display the mirrored word <馒>

display_lattice(0,16,Hz1616_tou,0,2,16); //Display the word before the mirror

hz1616_mirror(Hz1616_tou,ucBufferResult); //Mirror the character and put it into the ucBufferResult temporary variable.

display_lattice(1,16,ucBufferResult,0,2,16); //Display the mirrored

character

display_lattice(8,0,Zf816_V,0,1,16); //Display the characters before mirroring

hz816_mirror(Zf816_V,ucBufferResult); //Mirror the characters and put them into the temporary variable ucBufferResult.

display_lattice(9,0,ucBufferResult,0,1,16); //Display the mirrored characters

display_lattice(8,16,Zf816_5,0,1,16); //Display the character <5> before the mirror

hz816_mirror(Zf816_5,ucBufferResult); //Mirror the <5> character and put it into the ucBufferResult temporary variable.

display_lattice(9,16,ucBufferResult,0,1,16); //Display the mirrored character <5>

while(1)

{

;

}

}

void display_clear(void) // Clear the screen

{

unsigned char x,y;

WriteCommand(0x34); //Display buffer command

WriteCommand(0x34); //Display buffer off command is intentionally written twice, for fear that it will not work once. This is because I refer to a driver from a certain manufacturer that is also written in this way.

y=0;

while(y<32) //y axis ranges from 0 to 31

{

WriteCommand(y+0x80); //vertical address

WriteCommand(0x80); //Horizontal address

for(x=0;x<32;x++) //256 horizontal points, 32 bytes

{

LCDWriteData(0x00);

}

y++;

}

WriteCommand(0x36); //Open display buffer command

}

/* Note 1:

* The essence of 16x16 dot matrix mirror:

* A 16x16 dot matrix has 16 rows, each row has 2 bytes. If these 2 bytes are regarded as a 16-bit int data,

* Then the data is reversed from the original order of high bits on the left and low bits on the right. This program does not convert the 2 bytes

* Instead of merging them into an int data, the high and low bit order is directly reversed within a byte of data, and then the first byte of data is swapped with the second byte of data.

*/

void hz1616_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult) //Function to mirror the 16x16 dot matrix font library

{

unsigned char a;

unsigned char b;

unsigned char c;

unsigned char d;

for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 2 bytes. Consider each byte as a column. Here, we first reverse the order of the bytes in the first column from the original high bits on the left to the low bits on the right, which is equivalent to a mirror image.

{

b=p_ucHz[a*2+0]; //The 2 here means that there are 2 columns of bytes in each row of the 16x16 dot matrix, and 0 means starting from the 1st column.

c=0;

for(d=0;d<8;d++) //switch the order of a byte

{

c=c>>1;

if((b&0x80)==0x80)

{

c=c|0x80;

}

b=b<<1;

}

p_ucResult[a*2+1]=c; //Note that because it is a mirror image, the bytes in reverse order should be swapped from the first column to the second column

}

for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 2 bytes. Consider each byte as a column. Here, we first reverse the order of the bytes in the second column from the original high bits on the left to the low bits on the right, which is equivalent to a mirror image.

{

b=p_ucHz[a*2+1]; //The 2 here means that there are 2 columns of bytes in each row of the 16x16 dot matrix, and 1 means starting from the 2nd column.

c=0;

for(d=0;d<8;d++) //switch the order of a byte

{

c=c>>1;

if((b&0x80)==0x80)

{

c=c|0x80;

}

b=b<<1;

}

p_ucResult[a*2+0]=c; //Note that because it is a mirror image, the bytes in reverse order should be swapped from the second column to the first column

}

}

/* Note 2:

* The essence of 8x16 dot matrix mirror:

* 8x16 dot matrix has 16 rows, each row has 1 byte, the data is reversed from the original order of high bits on the left and low bits on the right.

*/

void hz816_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult) //Function to mirror the 8x16 dot matrix font library

{

unsigned char a;

unsigned char b;

unsigned char c;

unsigned char d;

for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 1 byte. Here, we first reverse the order of the bytes in each row from the original left side being high bits and the right side being low bits, which is equivalent to mirroring.

{

b=p_ucHz[a*1+0]; //Here 1 means that there is 1 column of bytes in each row of the 8x16 dot matrix, and 0 means starting from the 1st column.

c=0;

for(d=0;d<8;d++) //switch the order of a byte

{

c=c>>1;

if((b&0x80)==0x80)

{

c=c|0x80;

}

b=b<<1;

}

p_ucResult[a*1+0]=c; //Note that since each row has only one column, there is no need to swap the first column with the second column like in a 16x16 matrix.

}

}

/* Note 3: The core function of this section. Readers should especially understand the display relationship between x_amount and y_amount.

* The first and second parameters x and y are coordinate systems. The range of x is 0 to 15, and the range of y is 0 to 31.

* The third parameter *ucArray is the array of fonts.

* The fourth parameter ucFbFlag is the reverse display flag. 0 represents normal display, 1 represents reverse display.

* The 5th and 6th parameters x_amount and y_amount represent the number of bytes in the horizontal direction and the number of bytes in the vertical direction of the font array respectively.

*/

void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount)

{

unsigned int j=0;

unsigned int i=0;

unsigned char ucTemp;

WriteCommand(0x34); //Display buffer command

WriteCommand(0x34); //Display buffer off command is intentionally written twice, for fear that it will not work once. This is because I refer to a driver from a certain manufacturer that is also written in this way.

for(j=0;j

{

WriteCommand(y+j+0x80); //vertical address

WriteCommand(x+0x80); //Horizontal address

for(i=0;i

{

ucTemp=ucArray[j*x_amount+i];

if(ucFbFlag==1) //Highlight

{

ucTemp=~ucTemp;

}

LCDWriteData(ucTemp);

// delay_short(30000); //Remove the delay function in the previous section to speed up the screen refresh

}

}

WriteCommand(0x36); //Open display buffer command

}

void SendByteToLcd(unsigned char ucData) //Send a byte of data to the LCD module

{

unsigned char i;

for ( i = 0; i < 8; i++ )

{

if ( (ucData << i) & 0x80 )

{

LCDSID_dr = 1;

}

else

{

LCDSID_dr = 0;

}

LCDCLK_dr = 0;

LCDCLK_dr = 1;

}

}

void SPIWrite(unsigned char ucWData, unsigned char ucWRS) //Simulate SPI to send a byte of command or data to the underlying driver of the LCD module

{

SendByteToLcd( 0xf8 + (ucWRS << 1) );

SendByteToLcd(ucWData & 0xf0);

SendByteToLcd( (ucWData << 4) & 0xf0);

}

void WriteCommand(unsigned char ucCommand) //Send a byte command to the LCD module

{

LCDCS_dr = 0;

LCDCS_dr = 1;

SPIWrite(ucCommand, 0);

delay_short(90);

}

void LCDWriteData(unsigned char ucData) //Send one byte of data to the LCD module

{

LCDCS_dr = 0;

LCDCS_dr = 1;

SPIWrite(ucData, 1);

}

void LCDInit(void) //Initialization function including LCD module reset

{

LCDRST_dr = 1; // reset

LCDRST_dr = 0;

LCDRST_dr = 1;

}

void delay_short(unsigned int uiDelayShort) //delay function

{

unsigned int i;

for(i=0;i

{

;

}

}

Closing remarks:

Careful netizens will definitely find that this 12864 LCD screen generally has a problem. It cannot fully display as desired in the x and y directions of the coordinate axis with one dot matrix. For example, the horizontal direction is at least one byte of 8 dots, and the 1st and 2nd rows and the 3rd and 4th rows cannot be seamlessly displayed. If I want to display half of the Chinese characters in the 2nd row and half in the 3rd row, is it possible? Of course. But we need to write an additional algorithm program. How is this algorithm program written? For details, please listen to the next analysis - the algorithm program that allows fonts to be seamlessly displayed across regions in the LCD screen.

Reference address:Section 73: Algorithm program for mirroring fonts on the LCD screen

Previous article:Section 72: Algorithm program for rotating the font 90 degrees clockwise on the LCD screen
Next article:Section 74: Algorithm program for seamlessly displaying fonts across regions on LCD screens

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号