/*                                                   */
   
/*    2007/12/21   小型三位计算器                    */     

/*                                                   */


#include <reg52.H>
#include <math.H>
//#include <stdio.H>

//#define unchar unsigned char
//#define unint  unsigned int

#define in_right 1
#define in_flase 0

#define key_flase 1

sbit LCDE=P2^2;
sbit LCDRW=P2^1;
sbit LCDRS=P2^0;
sbit wink=P1^5;


unsigned char division_i;  
unsigned long frist_number;  //第一位数的值
unsigned long second_number; //第二位的值
unsigned long result; //运算结果
unsigned char digit;//总的数值的显示位数
unsigned char frist_digit;//第一位数字
unsigned char second_digit;//第二位数字
//unsigned char countmark;   //如果有运算键按下置位
//unsigned char display_position;    //显示位
unsigned char result_display;


bit gameover;
bit countend;
bit negative;
bit decimal;
bit over_range;
bit division;          //除号
bit subtraction;       //减号
bit addition;          //加号
bit multiplication;    //乘号
bit error;             //开始时不能显示运算符号
bit number_second;     //第二位运算数值位

unsigned char mark[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2d,0x2a,0x2f,0x3d,0x5f};// 0.1.2.3.4.5.6.7.8.9.+.-.*./.=..
unsigned char logo_error[5]={0x65,0x72,0x72,0x6f,0x72};//display error
unsigned char logo_range[10]={0x6f,0x76,0x65,0x72,0x20,0x72,0x61,0x6d,0x67,0x65};//over range
void  initial();
void  key_check();
void  display_error();
void  frist_display(unsigned char display_sign,mark1);  //第一行显示
void  second_display(unsigned char display_result,mark2);//第二行显示
void  refresh_display();
void  lcd_control();
void  delays();
void  delayl();
void  display_lcd();
void  number_key();
void  count_result( );
void  compare_result();


void main()

  {
    // unsigned char display_sign;
     negative=0;
     decimal=0;
     gameover=1;
     division=0;          //除号
     subtraction=0;       //减号
     addition=0;          //加号
     multiplication=0;    //乘号
     error=1;             //开始时不能显示运算符号
     number_second=1;     //第二位运算数值位
     digit=0;
     //over_range=0;
	 frist_number=0;
	 second_number=0;
	 result=0;
	 countend=1;
	 //all_number=0;
     P0=0xff;
     P3=0xff;
    // input_data=0;
   //  count_sign=0;
     initial();
     //frist_display(0,0);
	 //result_display(0,0);
     for(; ;)
	 { 
	    if(gameover)
         {
		   if(countend==1)
	        {
	         key_check();
	        }
	      else
	        {
			   delays();
			   delays();
			   delays();
			   delays();
			   delays();
	           count_result( );
			   gameover=0;
			 }
		  }
		  else
		    {
			}
     
	  }  
    }
void initial()
    {
      delayl();
      LCDE=0;
	  LCDRW=0;
	  LCDRS=0;
	  delayl();
      P0=0x01;
	  lcd_control();
	  P0=0x06;         // 
      lcd_control();
	  P0=0x38;         //ac 自动增加 画面动 设置输入方式
      lcd_control();
	  P0=0x14;         // 设置显示方式
      lcd_control();
      P0=0x0c;
	  lcd_control();
	  delayl();
      
    }

void frist_display(unsigned char display_sign,mark1)
     {
	   //mark1=0;
	   LCDE=0;
	   LCDRW=0;
	   LCDRS=0;
	   //P0=0x1c;
	   //lcd_control();
	   //P0=0x06;
	   //lcd_control();
	   P0=(0x80+mark1);
	   lcd_control();
	   LCDE=0;
	   LCDRW=0;
	   LCDRS=1;
	   P0=mark[display_sign];
	   lcd_control();
	   digit=digit+1;
	   if( number_second )  //number_second=0 是按运算符号键后
	      {
		         //digit=digit+1;
		         frist_digit=digit-1;
				 if (display_sign<10)
		         {
				   frist_number=((frist_number*10)+display_sign);
				   wink=0;
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				   delays();
				
				 }
				 else
				 {}
          }
	   else 
	     {
		    
		    if (countend)
		       { 
			     second_number=((second_number*10)+display_sign);
			   }
			else
			   {
			     second_digit=(digit-frist_digit-2);
			   }
		 }
	  }

void second_display(unsigned char display_result,mark2)
     {
       delayl();
	   delayl();
	   delayl();
	   LCDE=0;
	   LCDRW=0;
	   LCDRS=0;
	   //P0=0x3d;
	   //lcd_control();
	   P0=(0xc0+mark2);
	   lcd_control();
	   LCDE=0;
	   LCDRW=0;
	   LCDRS=1;
	   P0=mark[display_result];
	   lcd_control();
	   delayl();
	   delayl();
     }

void key_check()    //键盘扫描
    {
      
       unsigned char key,allkey,keysign,scankey;
	      P1=0xff;
          P3=0xff;
          scankey=0;
	 if( ((P1&0x1f)!=0x1f)&(~error) )
	    {
	      delays();
		  delays();
		  delays();
		  keysign=P1&0x1f;
	      switch(keysign)
		   {  
		      case 0x0f:
		        { 
			       
				   addition=1;
				   error=1;
				   frist_display(10,digit);
				   number_second=0;
                  
				   
		        }
			   break;
		       case 0x17:
		        {
			       
				   subtraction=1;
				   error=1;
				   frist_display(11,digit);
				   number_second=0;
				  
				}
			   break;
		      case 0x1b:
                {
			        multiplication=1;
				    error=1;
				    frist_display(12,digit);
					number_second=0;
                   
			    }
			   break;
		       case 0x1d:
		        {
			      division=1;
				  error=1;
				  frist_display(13,digit);
				  number_second=0;
				  
                }
		 	   break;
		       case 0x1e:
			     {
			        countend=0;
					error=1;
				    frist_display(14,digit);
				 }
			      break;
		         default: ;
		     }
		   }
		   
      else if ((P3&0x7c)!=0x7c)
	      { 
              allkey=P3&0x7c;
		      P3=0xfd;
              if ((P3&0x7c)!=0x7c)
                     { 
                        key=1;
                      
                     }
               else 
			         { 
                        key=0;
                     }
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
					 delays();
				 P3=0xff;
			  if ((P3&0x7c)==0x7c)
			     
			     {
			       switch(allkey)
	                {  
				      case 0x3c:
	                  {
		                  
					    scankey=0+key;
                        frist_display(scankey,digit);
						error=0;
                        
		               
		              }
			          break;
		             case 0x5c:
			          {
			            
					    scankey=2+key;
                        frist_display(scankey,digit);
                        error=0;
			            
			          }
			         break;
			         case 0x6c:
			          {
			            
					    scankey=4+key;
                        frist_display(scankey,digit);
                        error=0;
                        
			          }
			          break;
			         case 0x74:
			         {
			             
					     scankey=6+key;
                         frist_display(scankey,digit);
                         error=0;
			           
			          } 
			          break;
			          case 0x78: 
			          {
			             
					     scankey=8+key;
                         frist_display(scankey,digit);
                         error=0;
                       
			          }
			          break;
			          default: ;
				   }
				  }
				else
				{ }
              }

		else {}

	 }

void count_result()
     {
	             unsigned char sum=1;
				 unsigned long compare;  
	             
	              if (addition)
				      {
					   result=(frist_number+second_number);
					   compare_result();
					  }
				    else if (subtraction)
			           {
					     if(second_number>frist_number)
					     {  
					      negative=1;
					      result=(second_number-frist_number);
                          second_display(11,0);
						  compare_result();
					     }
					     else
					     {
					      result=(frist_number-second_number);
						  compare_result();
                          }
						 }
					else if (multiplication)
					     {
					      result=frist_number*second_number;
						  compare_result();
					     }
					else if (division)
					     {
					     if(second_number>frist_number)
						    {
							  division_i=second_digit-frist_digit;
							     while (division_i>0)
							      {
								    sum=sum*10;
								    division_i--;
								  }
								    
								    compare=frist_number*sum;
									if (compare<second_number)
									   {
									     sum=sum*10;
										 division_i=division_i+1;
									   }
									else
									   {
                                       }
                                    result=(compare)/second_number;
                                    compare_result();
								}
							 
						 else
						    {
							  result=frist_number/second_number;
							  compare_result();
							  
						    }
					     }
					else 
					   {
					   } 
					   
	 }
void compare_result()
    {
      unsigned char i;
	   unsigned long x,y,z;
	   y=z=result;
	   if (result>0)
	       {
		    i=15;
	        do
			 {
			      x=(z%10);
				  second_display(x,i);
				  z=z/10;
				  i=i-1;
             }
			 while(z>0);
			 if (division_i)
			  {
			    while(division_i>0)
				{
				  second_display(0,division_i);
				  division_i--;
				}
			  }
			 else
			  {
			  }
		   }
		else if (result==0)
		   {
		     second_display(0,15);
		   }
		else 
		   {
		    // i=2;
		    // do  {
		     //      x=(z%10);
				//   second_display(x,i);
				//   z=z/10;
				 //  i=i+1;
			   //  }
			 // while(i<16);
			 
		   }
       
	  }

void lcd_control()
   {
     LCDE=1;
	 delays();
	 LCDE=0;
	 delays();
   }

void delays()
   {
    unsigned char i;
    for(i=1000;i>0;i--)
	{ }
   }

void delayl()
   {
     unsigned char i;
	 for(i=50;i>0;i--)
	 {
	  delays();
	 }
  }