EA OLED (Orig. by SFord, retouched by Lerche)

Dependencies:   mbed

EAOLED.cpp

Committer:
Lerche
Date:
2010-10-03
Revision:
0:69334bd84891

File content as of revision 0:69334bd84891:

// test library for Embedded Artists OLED used on Xpresso Baseboard

#include "EAOLED.h"
#include "mbed.h"

EAOLED::EAOLED(PinName mosi, PinName dnc, PinName sclk, PinName cs, PinName power) 
    : _spi(mosi, NC, sclk), _data(dnc), _cs(cs), _power(power) {
    reset();    
}
      
void EAOLED::command(int value) {
    _data = 0;
    _cs = 0;
    _spi.write(value);
    _cs = 1;
}

void EAOLED::data(int value) {
    _data = 1;
    _cs = 0;
    _spi.write(value);
    _cs = 1;
}

void EAOLED::reset() {
    _power = 0;
    _cs = 1;

    // Startup sequence recommended by embedded artists baseboard reference code
    command(0x02); // set low column address
    command(0x12); // set high column address
    command(0x40); // display start set
    command(0x2e); // stop horzontal scroll
    command(0x81); // set contrast control register
    command(0x32); //
    command(0x82); // brightness for color banks
    command(0x80); // display on
    command(0xa1); // set segment re-map
    command(0xa6); // set normal/inverse display
    command(0xa8); // set multiplex ratio
    command(0x3F); //
    command(0xd3); // set display offset
    command(0x40); //
    command(0xad); // set dc-dc on/off
    command(0x8E); //
    command(0xc8); // set com output scan direction
    command(0xd5); // set display clock divide ratio/oscillator/frequency
    command(0xf0); //
    command(0xd8); // set area color mode on/off & low power display mode 
    command(0x05); //
    command(0xd9); // set pre-charge period
    command(0xF1); //
    command(0xda); // set com pins hardware configuration
    command(0x12); //
    command(0xdb); // set vcom deselect level
    command(0x34); //
    command(0x91); // set look up table for area color 
    command(0x3f); //
    command(0x3f); //
    command(0x3f); //
    command(0x3f); //
    command(0xaf); // display on
    command(0xa4); // display on

    wait_us(10);

    _power = 1;
}

#define OLED_DISPLAY_WIDTH  96
#define OLED_DISPLAY_HEIGHT 64

void EAOLED::pixel(int x, int y, int colour) {
    int page = y >> 3;
    int address = 18 + x;
    
    int lo = (address >> 0) & 0x0F;
    int hi =  (address >> 4) | 0x10;
    int mask = 1 << (y & 0x7);
    int byte = page * OLED_DISPLAY_WIDTH + x;
    
    if(colour) {
        framebuffer[byte] |= mask;
    } else {
        framebuffer[byte] &= ~mask;
    }

    command(0xB0 + page);
    command(lo);
    command(hi);
    data(framebuffer[byte]);
}

void EAOLED::circle(int x0, int y0, int r, int colour) {

#define OLED_DISPLAY_WIDTH  96
#define OLED_DISPLAY_HEIGHT 64

    int draw_x0, draw_y0;
    int draw_x1, draw_y1;
    int draw_x2, draw_y2;
    int draw_x3, draw_y3;
    int draw_x4, draw_y4;
    int draw_x5, draw_y5;
    int draw_x6, draw_y6;
    int draw_x7, draw_y7;
    int xx, yy;
    int di;    

    if(r == 0)          /* no radius */
    {
        return;
    }

    draw_x0 = draw_x1 = x0;
    draw_y0 = draw_y1 = y0 + r;
    if(draw_y0 < OLED_DISPLAY_HEIGHT)
    {
        pixel(draw_x0, draw_y0, colour);     /* 90 degree */
    }

    draw_x2 = draw_x3 = x0;
    draw_y2 = draw_y3 = y0 - r;
    if(draw_y2 >= 0)
    {
        pixel(draw_x2, draw_y2, colour);    /* 270 degree */
    }
    
    draw_x4 = draw_x6 = x0 + r;
    draw_y4 = draw_y6 = y0;
    if(draw_x4 < OLED_DISPLAY_WIDTH)
    {
        pixel(draw_x4, draw_y4, colour);     /* 0 degree */
    }    
    
    draw_x5 = draw_x7 = x0 - r;
    draw_y5 = draw_y7 = y0;
    if(draw_x5>=0)
    {
        pixel(draw_x5, draw_y5, colour);     /* 180 degree */
    }
        
    if(r == 1)
    {
        return;
    }    
    
    di = 3 - 2*r;
    xx = 0;
    yy = r;
    while(xx < yy)
    {

        if(di < 0)
        {
            di += 4*xx + 6;
        }
        else
        {
            di += 4*(xx - yy) + 10;
            yy--;
            draw_y0--;
            draw_y1--;
            draw_y2++;
            draw_y3++;
            draw_x4--;
            draw_x5++;
            draw_x6--;
            draw_x7++;
        }
        xx++;
        draw_x0++;
        draw_x1--;
        draw_x2++;
        draw_x3--;
        draw_y4++;
        draw_y5++;
        draw_y6--;
        draw_y7--;

        if( (draw_x0 <= OLED_DISPLAY_WIDTH) && (draw_y0>=0) )
        {
            pixel(draw_x0, draw_y0, colour);
        }

        if( (draw_x1 >= 0) && (draw_y1 >= 0) )
        {
            pixel(draw_x1, draw_y1, colour);
        }

        if( (draw_x2 <= OLED_DISPLAY_WIDTH) && (draw_y2 <= OLED_DISPLAY_HEIGHT) )
        {
            pixel(draw_x2, draw_y2, colour);
        }

        if( (draw_x3 >=0 ) && (draw_y3 <= OLED_DISPLAY_HEIGHT) )
        {
            pixel(draw_x3, draw_y3, colour);
        }

        if( (draw_x4 <= /*OLED_DISPLAY_HEIGHT*/OLED_DISPLAY_WIDTH) && (draw_y4 >= 0) )
        {
            pixel(draw_x4, draw_y4, colour);
        }

        if( (draw_x5 >= 0) && (draw_y5 >= 0) )
        {
            pixel(draw_x5, draw_y5, colour);
        }
        if( (draw_x6 <= OLED_DISPLAY_WIDTH) && (draw_y6 <= OLED_DISPLAY_HEIGHT) )
        {
            pixel(draw_x6, draw_y6, colour);
        }
        if( (draw_x7 >= 0) && (draw_y7 <= OLED_DISPLAY_HEIGHT) )
        {
            pixel(draw_x7, draw_y7, colour);
        }
    }
    return;
}

void EAOLED::hline(int x0, int x1, int y, int colour) {
    for(int x=x0; x<x1; x++){
        pixel(x, y, colour);
    }
    return;
}

void EAOLED::vline(int y0, int y1, int x, int colour) {
    for(int y=y0; y<y1; y++){
        pixel(x, y, colour);
    }
    return;
}

void EAOLED::line(int x0, int y0, int x1, int y1, int colour) {
    int   dx = 0, dy = 0;
    int   dx_sym = 0, dy_sym = 0;
    int   dx_x2 = 0, dy_x2 = 0;
    int   di = 0;

    dx = x1-x0;
    dy = y1-y0;


    if(dx == 0)           /* vertical line */
    {
        for(int y=y0; y<y1; y++){
            pixel(x0, y, colour);
        }
        return;
    }

    if(dx > 0)
    {
        dx_sym = 1;
    }
    else
    {
        dx_sym = -1;
    }


    if(dy == 0)           /* horizontal line */
    {
        for(int x=x0; x<x1; x++){
            pixel(x, y0, colour);
        }
        return;
    }


    if(dy > 0)
    {
        dy_sym = 1;
    }
    else
    {
        dy_sym = -1;
    }

    dx = dx_sym*dx;
    dy = dy_sym*dy;

    dx_x2 = dx*2;
    dy_x2 = dy*2;

    if(dx >= dy)
    {
        di = dy_x2 - dx;
        while(x0 != x1)
        {

            pixel(x0, y0, colour);
            x0 += dx_sym;
            if(di<0)
            {
                di += dy_x2;
            }
            else
            {
                di += dy_x2 - dx_x2;
                y0 += dy_sym;
            }
        }
        pixel(x0, y0, colour);
    }
    else
    {
        di = dx_x2 - dy;
        while(y0 != y1)
        {
            pixel(x0, y0, colour);
            y0 += dy_sym;
            if(di < 0)
            {
                di += dx_x2;
            }
            else
            {
                di += dx_x2 - dy_x2;
                x0 += dx_sym;
            }
        }
        pixel(x0, y0, colour);
    }
    return;
}

void EAOLED::rect(int x0, int y0, int x1, int y1, int colour) {

    for(int x=x0; x<x1; x++){
        pixel(x, y0, colour);
    }
    for(int x=x0; x<x1; x++){
        pixel(x, y1, colour);
    }
    for(int y=y0; y<y1; y++){
        pixel(x0, y, colour);
    }
    for(int y=y0; y<y1; y++){
        pixel(x1, y, colour);
    }
    return;
}

void EAOLED::fillrect(int x0, int y0, int x1, int y1, int colour) {

    int i = 0;

    if(x0 > x1)
    {
        i  = x0;
        x0 = x1;
        x1 = i;
    }

    if(y0 > y1)
    {
        i  = y0;
        y0 = y1;
        y1 = i;
    }

    if(y0 == y1)
    {
        for(int x=x0; x<x1; x++){
            pixel(x, y0, colour);
        }
        return;
    }

    if(x0 == x1)
    {
        for(int y=y0; y<y1; y++){
            pixel(x0, y, colour);
        }
        return;
    }

    while(y0 <= y1)
    {
        for(int x=x0; x<x1; x++){
            pixel(x, y0, colour);
        }
        y0++;
    }
    return;

}