/**
 * \file    drv_oled.c
 * \brief
 *
 * \par     Copyright (c) 2017 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2017-11-15
 * \version
 *
 * \history
 *  Date        Note
 *  2017-11-15  Original Creation
 *
 */

#include "drv_i2c.h"
#include "drv_oled.h"
#include "drv_oledfont.h"
#include "drv_rtc.h"

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

// Init SSD1306
void OLED_init(void)
{
    OLED_WR_CMD(0xAE);  //DISPLAY OFF

    OLED_WR_CMD(0x40);  //---set low column address
    OLED_WR_CMD(0xB0);  //---set high column address

    OLED_WR_CMD(0x81);  //contrast ratio
    OLED_WR_CMD(0xFF);

#ifdef OLED_DISPLAY_INVERT
    OLED_WR_CMD(0xA0);  //段重定向设置, 0xa0左右反置 0xa1正常
	OLED_WR_CMD(0xC0);  //Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
#else
	OLED_WR_CMD(0xA1);  //段重定向设置, 0xa0左右反置 0xa1正常
	OLED_WR_CMD(0xC8);  //Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
#endif

    OLED_WR_CMD(0xA6);  //

    OLED_WR_CMD(0xA8);  //设置驱动路数
    OLED_WR_CMD(0x1F);

    OLED_WR_CMD(0xD3);
    OLED_WR_CMD(0x00);

    OLED_WR_CMD(0xD5);
    OLED_WR_CMD(0xF0);

    OLED_WR_CMD(0xD9);
    OLED_WR_CMD(0x22);

    OLED_WR_CMD(0xDA);
    OLED_WR_CMD(0x02);

    OLED_WR_CMD(0xDB);
    OLED_WR_CMD(0x49);

    OLED_WR_CMD(0x8D);
    OLED_WR_CMD(0x14);

    OLED_WR_CMD(0xAF); //DISPLAY ON
    //OLED_clear();
}

//开启OLED显示
void OLED_display_on(void)
{
    OLED_WR_CMD(0x8D);  //SET DCDC命令
    OLED_WR_CMD(0x14);  //DCDC ON
    OLED_WR_CMD(0xAF);  //DISPLAY ON
}

//关闭OLED显示
void OLED_display_off(void)
{
    OLED_WR_CMD(0x8D);  //SET DCDC命令
    OLED_WR_CMD(0x10);  //DCDC OFF
    OLED_WR_CMD(0xAE);  //DISPLAY OFF
}

//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_clear(void)
{
    u8_t i, n;
    for (i = 0; i < OLED_MAX_ROW; i++)
    {
        OLED_WR_CMD(0xB0+i);    //设置页地址（0~7）
        OLED_WR_CMD(0x00);      //设置显示位置—列低地址
        OLED_WR_CMD(0x10);      //设置显示位置—列高地址
        for (n = 0; n < OLED_MAX_COL; n++)
        {
            OLED_WR_DATA(0);
        }
    } //更新显示
}

void OLED_on(void)
{
    u8_t i, n;
    for (i = 0; i < OLED_MAX_ROW; i++)
    {
        OLED_WR_CMD(0xB0+i);    //设置页地址（0~7）
        OLED_WR_CMD(0x00);      //设置显示位置—列低地址
        OLED_WR_CMD(0x10);      //设置显示位置—列高地址
        for (n = 0; n < OLED_MAX_COL; n++)
        {
            OLED_WR_DATA(0xFF);
        }
    } //更新显示
}

void OLED_set_pos(u8_t x, u8_t y)
{
    OLED_WR_CMD(0xB0+y);
    OLED_WR_CMD(((x&0xF0)>>4)|0x10);
    OLED_WR_CMD((x&0x0F));
}

void OLED_draw_char(u8_t x, u8_t y, u8_t chr, u8_t font_size)
{
    u8_t c = 0, i = 0;

    c = chr-' ';//得到偏移后的值

    if (x > (OLED_MAX_COL-1))
    {
        x = 0;
        if (FONT_SIZE_8 == font_size)
        {
            y++;
        }
        else {
            y += 2;
        }
    }

    if (FONT_SIZE_16 == font_size)
    {
        OLED_set_pos(x, y);
        for (i = 0; i < FONT_SIZE_16_WIDTH; i++)
        {
            OLED_WR_DATA(F8X16[c*FONT_SIZE_16+i]);
        }
        OLED_set_pos(x,y+1);
        for (i = 0; i < FONT_SIZE_16_WIDTH; i++)
        {
            OLED_WR_DATA(F8X16[c*FONT_SIZE_16+i+FONT_SIZE_16_WIDTH]);
        }
    }
    else {
        OLED_set_pos(x, y);
        for (i = 0; i < FONT_SIZE_8_WIDTH; i++)
        {
            OLED_WR_DATA(F6x8[c][i]);
        }
    }
}

u32_t OLED_pow(u8_t m, u8_t n)
{
    u32_t result = 1;
    while(n--)result*=m;
    return result;
}

void OLED_draw_digits(u8_t x, u8_t y, u32_t digits, u8_t len, u8_t font_size)
{
    u8_t t, temp;
    u8_t enshow = 0;
    u8_t width = (FONT_SIZE_8 == font_size) ? FONT_SIZE_8_WIDTH : FONT_SIZE_16_WIDTH;
    for (t = 0; t < len; t++)
    {
        temp = (digits/OLED_pow(10,len-t-1))%10;
        if ((enshow == 0) && (t < (len-1)))
        {
            if (temp == 0)
            {
                OLED_draw_char(x+width*t, y, ' ', font_size);
                continue;
            }
            else {
                enshow = 1;
            }
        }
        OLED_draw_char(x+width*t, y, temp+'0', font_size);
    }
}

void OLED_draw_digits_zero_prefix(u8_t x, u8_t y, u32_t digits, u8_t len, u8_t font_size)
{
    u8_t t, temp;
    u8_t enshow = 0;
    u8_t width = (FONT_SIZE_8 == font_size) ? FONT_SIZE_8_WIDTH : FONT_SIZE_16_WIDTH;
    for (t = 0; t < len; t++)
    {
        temp = (digits/OLED_pow(10,len-t-1))%10;
        if ((enshow == 0) && (t < (len-1)))
        {
            if (temp == 0)
            {
                OLED_draw_char(x+width*t, y, '0', font_size);
                continue;
            }
            else {
                enshow = 1;
            }
        }
        OLED_draw_char(x+width*t, y, temp+'0', font_size);
    }
}


void OLED_draw_string(u8_t x, u8_t y, const u8_t *chr, u8_t font_size)
{
    u8_t j = 0;
    u8_t width = (FONT_SIZE_8 == font_size) ? FONT_SIZE_8_WIDTH : FONT_SIZE_16_WIDTH;
    while (chr[j]!='\0')
    {
        OLED_draw_char(x, y, chr[j], font_size);
        x += width;

        if (x > (OLED_MAX_COL-width-1))
        {
            x = 0;
            if (FONT_SIZE_8 == font_size)
            {
                y++;
            }
            else {
                y += 2;
            }
        }
        j++;
    }
}

void OLED_draw_chinese(u8_t x, u8_t y, u8_t idx, u8_t hzk[][16])
{
    u8_t t;
    OLED_set_pos(x, y);
    for (t = 0; t < FONT_SIZE_16; t++)
    {
        OLED_WR_DATA(hzk[2*idx][t]);
    }
    OLED_set_pos(x, y+1);
    for (t = 0; t < FONT_SIZE_16; t++)
    {
        OLED_WR_DATA(hzk[2*idx+1][t]);
    }
}

void OLED_draw_bmp(u8_t x0, u8_t y0, u8_t x1, u8_t y1, const u8_t bmp[])
{
#if 0  /* modified by James Gan - 2017-11-18 */
    u16_t j = 0;
    u8_t x, y;

    for (y = y0; y < y1; y++)
    {
        OLED_set_pos(x0,y);
        for (x = x0; x < x1; x++)
        {
            OLED_WR_DATA(bmp[j++]);
        }
    }
#else
    u16_t j = 0;
    u8_t x, y;
    for (y = y0; y < y1; y++)
    {
        OLED_WR_CMD(0xB0+y);    //设置页地址（0~7）
        OLED_WR_CMD(0x00);      //设置显示位置—列低地址
        OLED_WR_CMD(0x10);      //设置显示位置—列高地址
        for (x = x0; x < x1; x++)
        {
            OLED_WR_DATA(bmp[j++]);
        }
    } //更新显示
#endif /* #if 0 */
}

