a partial porting OLED_I2C library

Dependents:   ou_mbed_oled ou_mbed_tmp102

oled_i2c.cpp

Committer:
poushen
Date:
2018-06-29
Revision:
3:909dd63644b4
Parent:
0:b5cb0f340c1a

File content as of revision 3:909dd63644b4:

#include "oled_i2c.h"

oled_i2c::oled_i2c(I2C &i2c_obj, char address)
    : i2c(i2c_obj), adr(address), epm_p(new eeprom(i2c, address)), epm(*epm_p)
{
    init();
}

oled_i2c::~oled_i2c()
{
    if(NULL!=epm_p)
        delete epm_p;
}

void oled_i2c::init(void)
{
}

void oled_i2c::comm_out(uint8_t a)
{
    epm.byte_write(SSD1306_COMMAND, ONE_BYTE_ADDRESS, a);
}

void oled_i2c::comm_page_out(uint8_t* pPage, uint8_t size)
{
    epm.page_write(SSD1306_COMMAND, ONE_BYTE_ADDRESS, pPage, size);
}

void oled_i2c::data_out(uint8_t a)
{
    epm.byte_write(SSD1306_DATA_CONTINUE, ONE_BYTE_ADDRESS, a);
}

void oled_i2c::data_page_out(uint8_t* pPage, uint8_t size)
{
    epm.page_write(SSD1306_DATA_CONTINUE, ONE_BYTE_ADDRESS, pPage, size);
}

void oled_i2c::init_oled(void)
{   
    uint8_t comm[33] = {0, 0, 0, SSD1306_DISPLAY_OFF,
                        SSD1306_SET_DISPLAY_CLOCK_DIV_RATIO,
                        0x80,
                        SSD1306_SET_MULTIPLEX_RATIO,
                        0x3F,
                        SSD1306_SET_DISPLAY_OFFSET,
                        0x00,
                        SSD1306_SET_START_LINE,
                        SSD1306_CHARGE_PUMP,
                        0x14,
                        SSD1306_MEMORY_ADDR_MODE,
                        0x00,               // Horizontal Addressing Mode
                        // --------
                        0x21,               // Set Column Address
                        0x00,       //28
                        127,
                        0x22,               // Set Page Address
                        0,
                        7,
                        // --------
                        SSD1306_SET_SEGMENT_REMAP | 0x1,
                        SSD1306_COM_SCAN_DIR_DEC,
                        SSD1306_SET_COM_PINS,
                        0x12,
//                      0xAD,
//                      0x30,
                        SSD1306_SET_CONTRAST_CONTROL,
                        0xCF,
                        SSD1306_SET_PRECHARGE_PERIOD,
                        0xF1,
                        SSD1306_SET_VCOM_DESELECT,
                        0x40,
                        SSD1306_DISPLAY_ALL_ON_RESUME,
                        SSD1306_NORMAL_DISPLAY,};
    comm_page_out(comm, 30);

    for(int i=0; i<8; i++) {
        uint8_t data[6] = {0, 0, 0, 0xb0+i, 0x00, 0x00};
        comm_page_out(data, 3);
            
        for(int j=0; j<128; j++)
            data_out(0x00);
    }

    comm_out(SSD1306_DISPLAY_ON);               //Set Display On
}

void oled_i2c::pixel_on(void)
{
    for(int i=0; i<5; i++)
    {
        uint8_t data[6] = {0, 0, 0, 0xb2+i, 0x0c, 0x11};
        comm_page_out(data, 3);
                
        //data_page_out(&scrbuf[i*SSD1306_WIDTH], 30);
        //data_page_out(&scrbuf[i*SSD1306_WIDTH + 30], 30);
        //data_page_out(&scrbuf[i*SSD1306_WIDTH + 60], 12);
        for (int j=0; j<72; j++) {
            data_out(scrbuf[i*SSD1306_WIDTH + j]);   
        }
    }
}

void oled_i2c::update(void)
{
    pixel_on();
}

void oled_i2c::clrScr()
{
    memset(scrbuf, 0, SSD1306_MEM_SIZE);
}

void oled_i2c::fillScr()
{
    memset(scrbuf, 0xFF, SSD1306_MEM_SIZE);
}

void oled_i2c::setPixel(uint16_t x, uint16_t y)
{
    int by, bi;
    
    if ((x<SSD1306_WIDTH) && (y<SSD1306_LENGTH))
    {
        by = ((y/8)*SSD1306_WIDTH) + x;
        bi = y % 8;
            
        scrbuf[by] = scrbuf[by] | (1<<bi);
    }
}

void oled_i2c::clrPixel(uint16_t x, uint16_t y)
{
    int by, bi;
    
    if ((x<SSD1306_WIDTH) && (y<SSD1306_LENGTH))
    {
        by = ((y/8)*SSD1306_WIDTH) + x;
        bi = y % 8;
            
        scrbuf[by] = scrbuf[by] & ~(1<<bi);
    }
}

void oled_i2c::setFont(const uint8_t* font)
{
    cfont.font = font;
    cfont.x_size = font[0];
    cfont.y_size = font[1];
    cfont.offset = font[2];
    cfont.numchars = font[3];
}

void oled_i2c::print_char(unsigned char c, int x, int y)
{
    if ((cfont.y_size % 8) == 0)
    {
        int font_idx = ((c - cfont.offset)*(cfont.x_size * (cfont.y_size/8)))+4;
        for (int rowcnt=0; rowcnt<(cfont.y_size/8); rowcnt++)
        {
            for(int cnt=0; cnt<cfont.x_size; cnt++)
            {
                for (int b=0; b<8; b++)
                    if ((cfont.font[font_idx+cnt+(rowcnt*cfont.x_size)] & (1<<b))!=0)
                        //if (cfont.inverted==0)
                            setPixel(x+cnt, y+(rowcnt*8)+b);
                        //else
                        //  oled_clrPixel(x+cnt, y+(rowcnt*8)+b);
                    else
                        //if (cfont.inverted==0)
                            clrPixel(x+cnt, y+(rowcnt*8)+b);
                        //else
                        //  oled_setPixel(x+cnt, y+(rowcnt*8)+b);
            }
        }
    }
    else
    {
        int font_idx = ((c - cfont.offset)*((cfont.x_size*cfont.y_size/8)))+4;
        int cbyte=cfont.font[font_idx];
        int cbit=7;
        for (int cx=0; cx<cfont.x_size; cx++)
        {
            for (int cy=0; cy<cfont.y_size; cy++)
            {
                if ((cbyte & (1<<cbit)) != 0)
                    //if (cfont.inverted==0)
                        setPixel(x+cx, y+cy);
                    //else
                    //  oled_clrPixel(x+cx, y+cy);
                else
                    //if (cfont.inverted==0)
                        clrPixel(x+cx, y+cy);
                    //else
                    //  oled_setPixel(x+cx, y+cy);
                    cbit--;
                    if (cbit<0)
                    {
                        cbit=7;
                        font_idx++;
                        cbyte=cfont.font[font_idx];
                    }
            }
        }
    }
}

void oled_i2c::print(char *st, int x, int y)
{
    //unsigned char ch;
    int stl;
    
    stl = strlen(st);
    if (x == RIGHT)
        x = SSD1306_WIDTH - (stl * cfont.x_size);
    if (x == CENTER)
        x = (SSD1306_WIDTH - (stl * cfont.x_size))/2;
        
    for (int cnt=0; cnt<stl; cnt++)
        print_char(*st++, x + (cnt*(cfont.x_size)), y);
}

void oled_i2c::printNumI(long num, int x, int y, int length, char filler)
{
    char buf[25];
    char st[27];
    bool neg=false;
    int c=0, f=0;
  
    if (num==0)
    {
        if (length!=0)
        {
            for (c=0; c<(length-1); c++)
                st[c]=filler;
            st[c]=48;
            st[c+1]=0;
        }
        else
        {
            st[0]=48;
            st[1]=0;
        }
    }
    else
    {
        if (num<0)
        {
            neg=true;
            num=-num;
        }
      
        while (num>0)
        {
            buf[c]=48+(num % 10);
            c++;
            num=(num-(num % 10))/10;
        }
        buf[c]=0;
      
        if (neg)
        {
            st[0]=45;
        }
      
        if (length>(c+neg))
        {
            for (int i=0; i<(length-c-neg); i++)
            {
                st[i+neg]=filler;
                f++;
            }
        }

        for (int i=0; i<c; i++)
        {
            st[i+neg+f]=buf[c-i-1];
        }
        st[c+neg+f]=0;
    }

    print(st,x,y);
}

void oled_i2c::printNumF(double num, uint8_t dec, int x, int y, char divider, int length, char filler)
{
    char st[27];
    bool neg=false;

    if (num<0)
        neg = true;

    //_convert_float(st, num, length, dec);
    //ftoa(num, st, dec);
    sprintf(st, "%.*f", dec, num);
    if (divider != '.')
    {
        for (int i=0; i<sizeof(st); i++)
            if (st[i]=='.')
                st[i]=divider;
    }

    if (filler != ' ')
    {
        if (neg)
        {
            st[0]='-';
            for (int i=1; i<sizeof(st); i++)
                if ((st[i]==' ') || (st[i]=='-'))
                    st[i]=filler;
        }
        else
        {
            for (int i=0; i<sizeof(st); i++)
                if (st[i]==' ')
                    st[i]=filler;
        }
    }

    print(st,x,y);
}