#include "oled.h"
#include "AI8051U_I2C.h"
#include "string.h"
#include "font.h"
#include "stdio.h"

uint8_t xdata showbuff[8][128];                           //OLED全局缓存


static void oled_write_byte(uint8_t _data, uint8_t cmd)
{
    uint8_t write_data;
	
    write_data = _data;
	
    if(cmd == OLED_CMD)
	{
		i2c_write_data(OLED_ADDRESS, OLED_WRITE_CMD_REG, &write_data, 1);
	}
    else if(cmd == OLED_DATA)
	{
		i2c_write_data(OLED_ADDRESS, OLED_WRITE_DATA_REG, &write_data, 1);
	}
}

void oled_init()
{
	i2c_init();
    oled_write_byte(0xAE,OLED_CMD);		/* turn off oled panel */
    oled_write_byte(0x00,OLED_CMD);		/* set low column address */
    oled_write_byte(0x10,OLED_CMD);		/* set high column address */
    oled_write_byte(0x40,OLED_CMD);		/* set start line address  Set Mapping RAM Display Start Line (0x00~0x3F) */
    oled_write_byte(0x81,OLED_CMD);		/* set contrast control register */
    oled_write_byte(0xCF,OLED_CMD);		/* Set SEG Output Current Brightness */
    oled_write_byte(0xA1,OLED_CMD);		/* Set SEG/Column Mapping     0xa0左右反置 0xa1正常 */
    oled_write_byte(0xC8,OLED_CMD);		/* Set COM/Row Scan Direction   0xc0上下反置 0xc8正常 */
    oled_write_byte(0xA6,OLED_CMD);		/* set normal display */
    oled_write_byte(0xA8,OLED_CMD);		/* set multiplex ratio(1 to 64) */
    oled_write_byte(0x1f,OLED_CMD);		/* 1/64 duty  12864:0x3f 12832:0x1f*/
    oled_write_byte(0xD3,OLED_CMD);		/* set display offset	Shift Mapping RAM Counter (0x00~0x3F) */
    oled_write_byte(0x00,OLED_CMD);		/* not offset */
    oled_write_byte(0xd5,OLED_CMD);		/* set display clock divide ratio/oscillator frequency */
    oled_write_byte(0x80,OLED_CMD);		/* set divide ratio, Set Clock as 100 Frames/Sec */
    oled_write_byte(0xD9,OLED_CMD);		/* set pre-charge period */
    oled_write_byte(0xF1,OLED_CMD);		/* Set Pre-Charge as 15 Clocks & Discharge as 1 Clock */
    oled_write_byte(0xDA,OLED_CMD);		/* set com pins hardware configuration */
    oled_write_byte(0x02,OLED_CMD);		/* 12864:0x12  12832:0x02 */
    oled_write_byte(0xDB,OLED_CMD);		/* set vcomh */
    oled_write_byte(0x40,OLED_CMD);		/* Set VCOM Deselect Level */
    oled_write_byte(0x20,OLED_CMD);		/* Set Page Addressing Mode (0x00/0x01/0x02) */
    oled_write_byte(0x02,OLED_CMD);
    oled_write_byte(0x8D,OLED_CMD);		/* set Charge Pump enable/disable */
    oled_write_byte(0x14,OLED_CMD);		/* set(0x10) disable */
    oled_write_byte(0xA4,OLED_CMD);		/* Disable Entire Display On (0xa4/0xa5) */
    oled_write_byte(0xA6,OLED_CMD);		/* Disable Inverse Display On (0xa6/a7)  */
    oled_write_byte(0xAF,OLED_CMD);
}

void oled_set_pos(uint8_t x, uint8_t y) 
{ 
	oled_write_byte((uint8_t)(0xb0 + y), OLED_CMD);
	oled_write_byte(((x & 0xf0)>>4) | 0x10, OLED_CMD);
	oled_write_byte((x & 0x0f), OLED_CMD); 
} 

void oled_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bmp[])
{
    uint8_t xdata j=0;
    uint8_t xdata x,y;

    for(y=y0;y<(y1+y0);y++)
    {
        oled_set_pos(x0,y);
        for(x=0;x<x1;x++)
        {      
            oled_write_byte(bmp[j++],OLED_DATA);	    	
        }
    }
}

void oled_display_on()
{
    oled_write_byte(0x8D,OLED_CMD);//电荷泵使能
    oled_write_byte(0x14,OLED_CMD);//开启电荷泵
    oled_write_byte(0xAF,OLED_CMD);//点亮屏幕   
}

void oled_display_off()
{
    oled_write_byte(0x8D,OLED_CMD);//电荷泵使能
    oled_write_byte(0x10,OLED_CMD);//关闭电荷泵
    oled_write_byte(0xAF,OLED_CMD);//关闭屏幕 
}

void oled_buff_clear()
{
	memset(showbuff,0,128*8);
}

void oled_buff_show(void)
{
    uint8_t xdata i,n;

    for(i = 0; i < 8; i++)
	{
		oled_write_byte(0xb0 + i, OLED_CMD); //设置行起始地址
		oled_write_byte(0x00, OLED_CMD);   //设置低列起始地址
		oled_write_byte(0x10, OLED_CMD);   //设置高列起始地址
		
		for(n = 0; n < 128; n++)
		{
			oled_write_byte(showbuff[i][n],OLED_DATA);
		}
    }
}

void oled_buff_show_char(uint8_t x, uint8_t y, char asc, uint8_t mode)
{
    uint8_t j,k;
    for(j = 0; j < 2; j++ )
    {
        for(k = 0;k < 8; k++ )
        {
            if(mode == 0)            
                showbuff[j + y][x + k] = Ascll_16[(asc-' ') * 2][j * 8 + k];
            else
                showbuff[j + y][x + k] = ~Ascll_16[(asc-' ') * 2][j * 8 + k];
        }
    }    
}

void oled_buff_show_GBK(uint8_t x, uint8_t y, char *gbk, uint8_t mode)
{
    uint8_t i;
    uint8_t j,k;
    for(i = 0; i < 200; i++)
    {
        if((gbk[0] == GBK16[i].gbn_bum[0] ) && ( gbk[1] == GBK16[i].gbn_bum[1]))
        {
            for(j = 0; j < 2; j++)
            {
                for(k = 0; k < 16; k++)
                {
                    if(mode == 0)
                        showbuff[j + y][x + k] = GBK16[i].gbk_font[j * 16 + k];
                    else
                        showbuff[j + y][x + k] = ~GBK16[i].gbk_font[j * 16 + k];
                }
            }
            break;
        }
    }    
}

void oled_buff_show_string(uint8_t x, uint8_t y, char *s, uint8_t mode)
{
    char s_num[2];
	while(*s != '\0')       //字符串不为空，循环
	{
        if ((uint8_t)*s < 0x80)     //根据输入数据的大小判断是字符还是汉字，
        {
            oled_buff_show_char(x, y, *s, mode);
            x += 8;
            s++;
        }
        else
        {
            s_num[0] = *s ;
            s_num[1] = *(s + 1) ;
            oled_buff_show_GBK(x, y, s_num, mode);
            x += 16;
            s += 2;
        }
		if(x > 127)
        {
            x = 0;
            y += 2;
        }
	}   
}

void oled_buff_show_num(uint8_t x, uint8_t y, long num, uint8_t mode)
{
    uint8_t xdata str[10];
    memset(str,0,10);
    sprintf(str,"%ld",num);
    oled_buff_show_string(x, y,(uint8_t*)str, mode);
}

void oled_buff_show_num02F(uint8_t x, uint8_t y, float num, uint8_t mode)
{
    uint8_t xdata str[10];
    memset(str,0,10);
    sprintf(str,"%.2f",num);
    oled_buff_show_string(x, y,(uint8_t*)str, mode);
}


void oled_buff_show_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bmp[])
{
	uint8_t k,j;
    uint16_t xdata num = 0;
    
    for(j = 0; j < y1; j++ )
    {
        for(k = 0; k < x1; k++)
        {
            showbuff[j + y0][x0 + k] = bmp[num++];
        }
    }
}