//***************************(C) COPYRIGHT 2015 CZQ******************************
//*******************************************************************************
// File Name   	: print.h
// Version		  : V0.1
// Compiler		  : GCCARM
// Target		    : E3RCU (STM32F103VET6)
// Author		    : CZQ
// Date			    : 2015/10/28
// Description  : 打印相关函数,支持中文
//*******************************************************************************
// V0.0 print函数支持的打印输出数据格式为:
//      %c 字符(ASCII)
//      %s 字符串,支持中文
//      %f 浮点型double
//      %d,%i 有符号十进制数
//      %u 无符号十进制数
//      %o 无符号八进制数
//      %B 二进制数
//      %x %X 十六进制数
// V0.1 %#B,%#o,%#x,%#X,二/八/十六进制数分别前面显示0b/o/0x
//*******************************************************************************
#ifndef _JMDPRINT_H_
#define _JMDPRINT_H_

#ifndef NULL
#define NULL ((void *)0)
#endif

#include"JMDKernel.h"
//#include <stdio.h>
#include <stdarg.h>
#include"LCD_COLOR.h"
//#include <jmkernel32.h>
//#include"LCD320240.h"
#define __PRINT_FONT_CN_EN		0//1:打印支持中文,0打印不支持中文
#define __PRINT_FLOAT_EN			0//1:支持浮点型数据,0不支持浮点型数据
//定义打印相关变量
static unsigned int LcdBackColor=BLACK,//显示背景色
                    LcdFontColor=WHITE,//显示字体颜色
                    DispCursor_x=0,//X光标
                    DispCursor_y=0;//Y光标

//***用到与字库或者液晶相关的函数***************************************************
void SetFlashFontSize(u16 type);
u16 GetFontLibWidth(void);
u16 GetFontLibHeight(void);
void SetNumFontType(void);//读取数字字库
u32 GetLCDFontLib(void);
u16 GetLCDFontType(void);
//***用到与字库或者液晶相关的变量或定义***********************************************
#define RINT_FONT_EN_TYPE		0//GetAsciiFontType()//ASII字符类型

#define PRINT_FONT_WIDTH		8//GetFontLibWidth()//字符宽
#define PRINT_FONT_HEIGHT	16//GetFontLibHeight()//字符高
#define RINT_FONT_TYPE			0//GetLCDFontType()//当前字符类型

#define ClearPrintScreen()	 LCD_Pant(LcdBackColor)
#define DisplayPrintChar(c) LCD_en(DispCursor_x,DispCursor_y,c,LcdFontColor,LcdBackColor,0)//ASCII

#if __PRINT_FONT_CN_EN>0//中文
#define RINT_FONT_CN_TYPE 	 GetChineseFontType()//中文字库类型
#define DisplayPrintCn(c)   LCD_DisplayFont(DispCursor_x,DispCursor_y,c,LcdFontColor,LcdBackColor,0,RINT_FONT_CN_TYPE)
#endif//__PRINT_FONT_CN_EN

//设置背景色
void SetPrintfFontColor(unsigned int fontcolor,unsigned int backcolor){	LcdBackColor=backcolor,LcdFontColor=fontcolor;}
//设置显示光标
void SetPrintfCursor(unsigned int x,unsigned int y){DispCursor_x=x;DispCursor_y=y;}
void GetPrintfCurrentCursor(unsigned int *x,unsigned int *y){*x=DispCursor_x;*y=DispCursor_y;}
//清屏，并且光标回到原始位置
void PrintCleanScreen(void){SetPrintfCursor(0,0);ClearPrintScreen();}
void SetPrintfNextCursorY(void)//设置光标Y轴
{
	DispCursor_y+=PRINT_FONT_HEIGHT;
	if(DispCursor_y>(LCD_Heigh-PRINT_FONT_HEIGHT))
	{
		DispCursor_y=0;//从头显示
		PrintCleanScreen();//清屏
	}
	//DispCursor_x=0;
}
void SetPrintfNextCursorX(void)//光标移动到下一位
{
	DispCursor_x+=PRINT_FONT_WIDTH;
	if(DispCursor_x>(LCD_Width-(PRINT_FONT_WIDTH)))
	{
		SetPrintfNextCursorY();
		DispCursor_x=0;
	}
}
#define SetPrintfNextCursor() SetPrintfNextCursorX()//设置下一个坐标
#if __PRINT_FONT_CN_EN>0//支持中文
signed int fputcn(char *pStr)//显示中文
{
	int state=0;
	if(RINT_FONT_TYPE!=RINT_FONT_CN_TYPE)//在英->中文在边界的特殊处理
	{
		if(DispCursor_x>(LCD_Width-(PRINT_FONT_WIDTH<<1)))
		{
			DispCursor_x=0;
			SetPrintfNextCursorY();
		}
	}
	//SetPrintFontSizeChinese();
	state= DisplayPrintCn(pStr);
	if(state!=0)//显示成功
	{
		SetPrintfNextCursor();//光标移到下一位
		return 1;
	}
	if(*(pStr+1)<0x80)
	{
		return 2;
	}
	return 0;//要显示的中文字不在中文字库
}
#endif//#if __PRINT_FONT_CN_EN>0//支持中文

char printchar(unsigned char c)//显示字符
{
	//SetPrintFontSizeAscii();
	switch(c)
	{
		case '\r':SetPrintfNextCursorY();break;//光标移动到下一行
		case '\n':DispCursor_x=0;        break;
		default:break;
	}
	//if(c<0x20||c>0x7e)return 2;//其他ASCII不显示
	if(c<0x20||(c>0x7e&&c<0x80))return 2;//其他ASCII不显示

	DisplayPrintChar(c);
	SetPrintfNextCursor();//光标移到下一位
	return 0;
}
void print(char* fmt, ...);
void printch(char ch);
void printdec(int dec,int numfirst);
void printunsigneddec(unsigned int dec,int numfirst);
#if __PRINT_FLOAT_EN>0
void printflt(double flt,int numfirst);
#endif
void printbin(unsigned int bin,int numfirst);
void printhex(unsigned int hex,char c,int numfirst);
void printoctal(unsigned int octal,int numfirst);
void printstr(char* str);

#define console_print(ch)    printchar(ch)//putchar(ch)

void print(char* fmt, ...)
{
#if __PRINT_FLOAT_EN>0
    double vargflt = 0;
#else
		int vargflt = 0;
#endif//#if __PRINT_FLOAT_EN>0
    int  vargint = 0,sta=0;
    char* vargpch = NULL;
    char vargch = 0;
    char* pfmt = NULL;
    va_list vp;
    unsigned char c;
    int numfirst=0;//用于标志显示的数字是不是第一次显示
    //int numflag=0;//符号标志位

    va_start(vp, fmt);
    pfmt = fmt;
    while(*pfmt)
    {
        if(*pfmt == '%')
        {
      NextStep:
            switch(*(++pfmt))
            {

                case 'c'://ascii
                    vargch = va_arg(vp, int);
                    /*  va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    printch(vargch);
                    break;
                case 'd'://十进制整数
                case 'i'://十进制整数
                	  vargint = va_arg(vp, int);
                    printdec(vargint,numfirst);

                    break;
                case 'u'://%u 不带正负号的十进制值
                	  vargint = va_arg(vp, unsigned int);
                    printunsigneddec(vargint,numfirst);
                    break;
								#if __PRINT_FLOAT_EN>0
                case 'f'://浮点格式
                    vargflt = va_arg(vp, double);
                    /*  va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    printflt(vargflt,numfirst);
                    break;
								#endif//__PRINT_FLOAT_EN
                case 's'://字符串
                    vargpch = va_arg(vp, char*);
                    printstr(vargpch);
                    break;
                //case 'b'://二进制
                case 'B':
                    vargint = va_arg(vp, unsigned int);
                    printbin(vargint,numfirst);
                    break;
                case 'o'://不带正负号的八进制
                    vargint = va_arg(vp, unsigned int);
                    printoctal(vargint,numfirst);
                    break;
                case 'x':// 不带正负号的十六进制
                case 'X':
                    vargint = va_arg(vp, unsigned int);
                    printhex(vargint,*pfmt,numfirst);
                    break;
                case '%'://%
                    printch('%');
                    break;
                case '#'://# 二/八/十六进制数前缀0b/o/0x：对c,s,d,u类无影响；对o类，在输出时加前缀o；对x类，在输出时加前缀0x；
                    if(*(pfmt+1)=='x'||*(pfmt+1)=='X')
                    {
                    	//numflag=1;
                    	printstr("0x");
                    	goto NextStep;
                    }
                    else if(*(pfmt+1)=='B')
                    {
                    	//numflag=1;
                    	printstr("0b");
                    	goto NextStep;
                    }
                    else if(*(pfmt+1)=='o')
                    {
                    	//numflag=1;
                    	printstr("o");
                    	goto NextStep;
                    }
                    break;
                default:
                    break;
            }//switch(*(++pfmt))
            pfmt++;
        }//if(*pfmt == '%')
        else
        {
        	c=*pfmt;
#if __PRINT_FONT_CN_EN>0//支持中文
        	if(c<0x80)
#endif//#if __PRINT_FONT_CN_EN>0//支持中文
        	{
        		printch(*pfmt++);
        	}
#if __PRINT_FONT_CN_EN>0//支持中文
        	else//汉字
        	{
          	sta=fputcn((unsigned char *)pfmt);//显示汉字
          	if(sta!=1)//显示汉字失败
      			{//在字库列表中找不到相应字库,则显示为空格
          		printch('?');
          		if(sta==0)
          		{
          			printch('?');
          			pfmt++;
          		}
          		pfmt++;
      			}
          	else//显示成功
          	{
      				pfmt+=2;
          	}
        	}
#endif//#if __PRINT_FONT_CN_EN>0//支持中文
        }
    }//while(*pfmt)
    va_end(vp);
}

void printch(char ch)
{
    console_print(ch);
}
//static char decnew=0;
void printdec(int dec,int numfirst)
{
		if(dec<0)//负数处理
		{
			dec=-dec;
			printch('-');
		}
    if(dec==0&&numfirst)
    {
    	numfirst=0;
      return;
    }
    if(numfirst==0) numfirst=1;
    printdec(dec/10,numfirst);
    printch((char)(dec%10 + '0'));
}
//static char udecnew=0;
void printunsigneddec(unsigned int dec,int numfirst)
{
    if(dec==0&&numfirst)
    {
    	numfirst=0;
      return;
    }
    if(numfirst==0) numfirst=1;
    printunsigneddec(dec/10,numfirst);
    printch((char)(dec%10 + '0'));
}
#if __PRINT_FLOAT_EN >0
void printflt(double flt,int numfirst)
{
    int icnt = 0;
    int tmpint = 0;
    int n;

    tmpint = (int)flt;
    printdec(tmpint,numfirst);
    printch('.');
    flt = flt - tmpint+0.0000005;// 四舍五入
    tmpint = (int)(flt * 1000000);

    for(n=0;n<5;n++)//去掉后面的0
    {
    	if(tmpint%10)break;
    	else tmpint/=10;
    }

    printdec(tmpint,numfirst);
}
#endif//__PRINT_FLOAT_EN
void printstr(char* str)
{
	int sta;
    while(*str)
    {
#if __PRINT_FONT_CN_EN>0//支持中文
    	if((unsigned char)*str<0x80)//
#endif//#if __PRINT_FONT_CN_EN>0//支持中文
    	{//
        printch(*str++);
    	}//
#if __PRINT_FONT_CN_EN>0//支持中文
    	else//显示中文
    	{//
    		sta=fputcn(str);//
    		if(sta!=1)//判断要显示的字符是否在中文字库里面
				{//在字库列表中找不到相应字库,则显示为空格
    			printch('?');//PrintChar('?');//
    			if(sta==0)//
    			{//
    				printch('?');//PrintChar('?');//
    				str++;//
    			}//if(sta==0)
    			str++;//
				}//if(sta!=1)
    		else//显示成功
    		{
    			str+=2;//
    		}//else if(sta==1)
    	}//else if(ch>=0x80)
#endif//#if __PRINT_FONT_CN_EN>0//支持中文
    }
}
//static char ubinnew=0;
void printbin(unsigned int bin,int numfirst)
{
    if(bin == 0&&numfirst)
    {
       // printstr("0b");
    	numfirst=0;
      return;
    }
    if(numfirst==0)
    {
    	//if(numflag)printstr("0b");
    	numfirst=1;
    }
    printbin(bin/2,numfirst);
    printch((char)(bin%2 + '0'));
}
//static char hexnew=0;
void printhex(unsigned int hex,char c,int numfirst)
{
  if(hex==0&&numfirst)
  {
  	numfirst=0;
    return;
  }
  if(numfirst==0)
  {
  	//if(numflag)printstr("0x");
  	numfirst=1;
  }
  printhex((hex>>4),c,numfirst);//
	//printhex(hex/16,c);
  if((hex&0XF) < 10)
  {
    printch((char)((hex&0X0F) + '0'));
		//printch((char)((hex%16) + '0'));
  }
  else
  {
    if(c=='X')	printch((char)(((hex&0X0F) - 10) + 'A' ));
		//printch((char)((hex%16) - 10 + 'A' ));
    else 	printch((char)(((hex&0X0F) - 10) + 'a' ));
		//printch((char)((hex%16) - 10 + 'a' ));
  }
}
//static char octalnew=0;
void printoctal(unsigned int octal,int numfirst)//八进制数
{
  if(octal==0&&numfirst)
  {
  	numfirst=0;
    return;
  }
  if(numfirst==0)
  {
  	//if(numflag)printstr("o");
  	numfirst=1;
  }
  printoctal(octal/8,numfirst);
  printch((char)(octal%8 + '0'));
}

#endif//_PRINTF_H_
