Subversion Repositories Code-Repo

Rev

Blame | Last modification | View Log | RSS feed

#include "maindefs.h"
#include "oled_ssd1331.h"
#include "spi.h"
#include "string.h"
#include "Adafruit_GFX.h"
#include <delays.h>

void SSD1331_Init() {
    GFX_Init(SSD1331_LCDWIDTH, SSD1331_LCDHEIGHT);
}

void SSD1331_Begin() {
    unsigned char buffer[37];

    // Toggle reset pin
    LATBbits.LATB6 = 0;
    Delay10KTCYx(1);
    LATBbits.LATB6 = 1;

    // Initialization Sequence
    buffer[0] = SSD1331_CMD_DISPLAYOFF; // 0xAE
    buffer[1] = SSD1331_CMD_SETREMAP; // 0xA0
#if defined SSD1331_COLORORDER_RGB
    buffer[2] = 0x72; // RGB Color
#else
    buffer[2] = 0x76; // BGR Color
#endif
    buffer[3] = SSD1331_CMD_STARTLINE; // 0xA1
    buffer[4] = 0x0;
    buffer[5] = SSD1331_CMD_DISPLAYOFFSET; // 0xA2
    buffer[6] = 0x0;
    buffer[7] = SSD1331_CMD_NORMALDISPLAY; // 0xA4
    buffer[8] = SSD1331_CMD_SETMULTIPLEX; // 0xA8
    buffer[9] = 0x3F; // 0x3F 1/64 duty
    buffer[10] = SSD1331_CMD_SETMASTER; // 0xAD
    buffer[11] = 0x8E;
    buffer[12] = SSD1331_CMD_POWERMODE; // 0xB0
    buffer[13] = 0x0B;
    buffer[14] = SSD1331_CMD_PRECHARGE; // 0xB1
    buffer[15] = 0x31;
    buffer[16] = SSD1331_CMD_CLOCKDIV; // 0xB3
    buffer[17] = 0xF0; // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
    buffer[18] = SSD1331_CMD_PRECHARGEA; // 0x8A
    buffer[19] = 0x64;
    buffer[20] = SSD1331_CMD_PRECHARGEB; // 0x8B
    buffer[21] = 0x78;
    buffer[22] = SSD1331_CMD_PRECHARGEA; // 0x8C
    buffer[23] = 0x64;
    buffer[24] = SSD1331_CMD_PRECHARGELEVEL; // 0xBB
    buffer[25] = 0x3A;
    buffer[26] = SSD1331_CMD_VCOMH; // 0xBE
    buffer[27] = 0x3E;
    buffer[28] = SSD1331_CMD_MASTERCURRENT; // 0x87
    buffer[29] = 0x06;
    buffer[30] = SSD1331_CMD_CONTRASTA; // 0x81
    buffer[31] = 0x91;
    buffer[32] = SSD1331_CMD_CONTRASTB; // 0x82
    buffer[33] = 0x50;
    buffer[34] = SSD1331_CMD_CONTRASTC; // 0x83
    buffer[35] = 0x7D;
    buffer[36] = SSD1331_CMD_DISPLAYON; //--turn on oled panel

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 37);
}

void SSD1331_GoTo(int x, int y) {
    unsigned char buffer[6];
    if ((x >= SSD1331_LCDWIDTH) || (y >= SSD1331_LCDHEIGHT)) return;

    // set x and y coordinate
    buffer[0] = (SSD1331_CMD_SETCOLUMN);
    buffer[1] = (x);
    buffer[2] = (SSD1331_LCDWIDTH - 1);

    buffer[3] = (SSD1331_CMD_SETROW);
    buffer[4] = (y);
    buffer[5] = (SSD1331_LCDHEIGHT - 1);

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 6);
}

void SSD1331_Reset() {

}

void SSD1331_Command(unsigned char cmd) {
    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(&cmd, 1);
}

void SSD1331_Data(unsigned char data) {
    LATBbits.LATB5 = 1; // D/C high (data)
    SPI2_Write(&data, 1);
}

void SSD1331_Draw_Pixel(int x, int y, unsigned int color) {
    unsigned char buffer[2];
    buffer[0] = color >> 8;
    buffer[1] = color;
    if ((x < 0) || (x >= GFX_width()) || (y < 0) || (y >= GFX_height())) return;

    // check rotation, move pixel around if necessary
    switch (GFX_getRotation()) {
        case 1:
            GFX_Swap(&x, &y);
            x = SSD1331_LCDWIDTH - x - 1;
            break;
        case 2:
            x = SSD1331_LCDWIDTH - x - 1;
            y = SSD1331_LCDHEIGHT - y - 1;
            break;
        case 3:
            GFX_Swap(&x, &y);
            y = SSD1331_LCDHEIGHT - y - 1;
            break;
    }

    SSD1331_GoTo(x, y);

    // setup for data
    LATBbits.LATB5 = 1; // D/C high (data)

    SPI2_Write(buffer, 2);
}

void SSD1331_Draw_Line(int x0, int y0, int x1, int y1, unsigned int color) {
    unsigned char buffer[8];

    // check rotation, move pixel around if necessary
    switch (GFX_getRotation()) {
        case 1:
            GFX_Swap(&x0, &y0);
            GFX_Swap(&x1, &y1);
            x0 = SSD1331_LCDWIDTH - x0 - 1;
            x1 = SSD1331_LCDWIDTH - x1 - 1;
            break;
        case 2:
            x0 = SSD1331_LCDWIDTH - x0 - 1;
            y0 = SSD1331_LCDHEIGHT - y0 - 1;
            x1 = SSD1331_LCDWIDTH - x1 - 1;
            y1 = SSD1331_LCDHEIGHT - y1 - 1;
            break;
        case 3:
            GFX_Swap(&x0, &y0);
            GFX_Swap(&x1, &y1);
            y0 = SSD1331_LCDHEIGHT - y0 - 1;
            y1 = SSD1331_LCDHEIGHT - y1 - 1;
            break;
    }

    // Boundary check
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
        return;
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
        return;
    if (x0 >= SSD1331_LCDWIDTH)
        x0 = SSD1331_LCDWIDTH - 1;
    if (y0 >= SSD1331_LCDHEIGHT)
        y0 = SSD1331_LCDHEIGHT - 1;
    if (x1 >= SSD1331_LCDWIDTH)
        x1 = SSD1331_LCDWIDTH - 1;
    if (y1 >= SSD1331_LCDHEIGHT)
        y1 = SSD1331_LCDHEIGHT - 1;
    if (x0 < 0)
        x0 = 0;
    if (y0 < 0)
        y0 = 0;
    if (x1 < 0)
        x1 = 0;
    if (y1 < 0)
        y1 = 0;

    buffer[0] = SSD1331_CMD_DRAWLINE;
    buffer[1] = x0;
    buffer[2] = y0;
    buffer[3] = x1;
    buffer[4] = y1;
    buffer[5] = (color >> 11) << 1;
    buffer[6] = (color >> 5) & 0x3F;
    buffer[7] = (color << 1) & 0x3F;

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 8);
}

void SSD1331_Draw_Rect(int tx0, int ty0, int tx1, int ty1, unsigned int color) {
    unsigned char buffer[13];
    int x0,y0,x1,y1;
    
    // check rotation, move pixel around if necessary
    switch (GFX_getRotation()) {
        case 0:
            x0 = tx0;
            y0 = ty0;
            x1 = tx1;
            y1 = ty1;
            break;
        case 1:
            x0 = SSD1331_LCDWIDTH - ty1 - 1;
            y0 = tx0;
            x1 = SSD1331_LCDWIDTH - ty0 - 1;
            y1 = tx1;
            break;
        case 2:
            x0 = SSD1331_LCDWIDTH - tx1 - 1;
            y0 = SSD1331_LCDHEIGHT - ty1 - 1;
            x1 = SSD1331_LCDWIDTH - tx0 - 1;
            y1 = SSD1331_LCDHEIGHT - ty0 - 1;
            break;
        case 3:
            x0 = ty0;
            y0 = SSD1331_LCDHEIGHT - tx1 - 1;
            x1 = ty1;
            y1 = SSD1331_LCDHEIGHT - tx0 - 1;
            break;
    }

    // Boundary check
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
        return;
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
        return;
    if (x0 >= SSD1331_LCDWIDTH)
        x0 = SSD1331_LCDWIDTH - 1;
    if (y0 >= SSD1331_LCDHEIGHT)
        y0 = SSD1331_LCDHEIGHT - 1;
    if (x1 >= SSD1331_LCDWIDTH)
        x1 = SSD1331_LCDWIDTH - 1;
    if (y1 >= SSD1331_LCDHEIGHT)
        y1 = SSD1331_LCDHEIGHT - 1;
    if (x0 < 0)
        x0 = 0;
    if (y0 < 0)
        y0 = 0;
    if (x1 < 0)
        x1 = 0;
    if (y1 < 0)
        y1 = 0;

    buffer[0] = SSD1331_CMD_FILL;
    buffer[1] = 0;
    buffer[2] = SSD1331_CMD_DRAWRECT;
    buffer[3] = x0;
    buffer[4] = y0;
    buffer[5] = x1;
    buffer[6] = y1;
    buffer[7] = (color >> 11) << 1;
    buffer[8] = (color >> 5) & 0x3F;
    buffer[9] = (color << 1) & 0x3F;
    buffer[10] = 0;
    buffer[11] = 0;
    buffer[12] = 0;

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 13);
}

void SSD1331_Fill_Rect(int tx0, int ty0, int tx1, int ty1, unsigned int color) {
    unsigned char buffer[13];
    int x0,y0,x1,y1;
    
    // check rotation, move pixel around if necessary
    switch (GFX_getRotation()) {
        case 0:
            x0 = tx0;
            y0 = ty0;
            x1 = tx1;
            y1 = ty1;
            break;
        case 1:
            x0 = SSD1331_LCDWIDTH - ty1 - 1;
            y0 = tx0;
            x1 = SSD1331_LCDWIDTH - ty0 - 1;
            y1 = tx1;
            break;
        case 2:
            x0 = SSD1331_LCDWIDTH - tx1 - 1;
            y0 = SSD1331_LCDHEIGHT - ty1 - 1;
            x1 = SSD1331_LCDWIDTH - tx0 - 1;
            y1 = SSD1331_LCDHEIGHT - ty0 - 1;
            break;
        case 3:
            x0 = ty0;
            y0 = SSD1331_LCDHEIGHT - tx1 - 1;
            x1 = ty1;
            y1 = SSD1331_LCDHEIGHT - tx0 - 1;
            break;
    }

    // Boundary check
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
        return;
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
        return;
    if (x0 >= SSD1331_LCDWIDTH)
        x0 = SSD1331_LCDWIDTH - 1;
    if (y0 >= SSD1331_LCDHEIGHT)
        y0 = SSD1331_LCDHEIGHT - 1;
    if (x1 >= SSD1331_LCDWIDTH)
        x1 = SSD1331_LCDWIDTH - 1;
    if (y1 >= SSD1331_LCDHEIGHT)
        y1 = SSD1331_LCDHEIGHT - 1;
    if (x0 < 0)
        x0 = 0;
    if (y0 < 0)
        y0 = 0;
    if (x1 < 0)
        x1 = 0;
    if (y1 < 0)
        y1 = 0;

    buffer[0] = SSD1331_CMD_FILL;
    buffer[1] = 1;
    buffer[2] = SSD1331_CMD_DRAWRECT;
    buffer[3] = x0;
    buffer[4] = y0;
    buffer[5] = x1;
    buffer[6] = y1;
    buffer[7] = (color >> 11) << 1;
    buffer[8] = (color >> 5) & 0x3F;
    buffer[9] = (color << 1) & 0x3F;
    buffer[10] = (color >> 11) << 1;
    buffer[11] = (color >> 5) & 0x3F;
    buffer[12] = (color << 1) & 0x3F;

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 13);

    Delay1KTCYx(4);
}

void SSD1331_Clear_Display() {
    unsigned char buffer[5];

    buffer[0] = SSD1331_CMD_CLEARWINDOW;
    buffer[1] = 0;
    buffer[2] = 0;
    buffer[3] = SSD1331_LCDWIDTH-1;
    buffer[4] = SSD1331_LCDHEIGHT-1;

    LATBbits.LATB5 = 0; // D/C low (cmd)
    SPI2_Write(buffer, 5);

    Delay1KTCYx(4);
}

unsigned int SSD1331_Color565(unsigned char r, unsigned char g, unsigned char b) {
    unsigned int c;
    c = r >> 3;
    c <<= 6;
    c |= g >> 2;
    c <<= 5;
    c |= b >> 3;

    return c;
}

void SSD1331_Test_DrawLines(unsigned int color) {
    int x, y;
    GFX_clearScreen();
    for (x = 0; x < GFX_width() - 1; x += 6) {
        GFX_drawLine(0, 0, x, GFX_height() - 1, color);
    }
    for (y = 0; y < GFX_height() - 1; y += 6) {
        GFX_drawLine(0, 0, GFX_width() - 1, y, color);
    }

    GFX_clearScreen();
    for (x = 0; x < GFX_width() - 1; x += 6) {
        GFX_drawLine(GFX_width() - 1, 0, x, GFX_height() - 1, color);
    }
    for (y = 0; y < GFX_height() - 1; y += 6) {
        GFX_drawLine(GFX_width() - 1, 0, 0, y, color);
    }

    GFX_clearScreen();
    for (x = 0; x < GFX_width() - 1; x += 6) {
        GFX_drawLine(0, GFX_height() - 1, x, 0, color);
    }
    for (y = 0; y < GFX_height() - 1; y += 6) {
        GFX_drawLine(0, GFX_height() - 1, GFX_width() - 1, y, color);
    }

    GFX_clearScreen();
    for (x = 0; x < GFX_width() - 1; x += 6) {
        GFX_drawLine(GFX_width() - 1, GFX_height() - 1, x, 0, color);
    }
    for (y = 0; y < GFX_height() - 1; y += 6) {
        GFX_drawLine(GFX_width() - 1, GFX_height() - 1, 0, y, color);
    }
}

void SSD1331_Test_DrawRect(unsigned int color) {
    int x;
    GFX_clearScreen();
    if (GFX_height() < GFX_width()) {
        for (x = 0; x < GFX_height() - 1; x += 6) {
            GFX_drawRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color);
        }
    } else {
        for (x = 0; x < GFX_width() - 1; x += 6) {
            GFX_drawRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color);
        }
    }
}

void SSD1331_Test_FillRect(unsigned int color1, unsigned int color2) {
    int x;
    GFX_clearScreen();
    if (GFX_height() < GFX_width()) {
        for (x = GFX_height() - 1; x > 6; x -= 6) {
            GFX_fillRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color1);
            GFX_drawRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color2);
        }
    } else {
        for (x = GFX_width() - 1; x > 6; x -= 6) {
            GFX_fillRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color1);
            GFX_drawRect((GFX_width() - 1) / 2 - x / 2, (GFX_height() - 1) / 2 - x / 2, x, x, color2);
        }
    }
}

void SSD1331_Test_DrawCircle(unsigned int radius, unsigned int color) {
    int x, y;
    for (x = 0; x < GFX_width() - 1 + radius; x += radius * 2) {
        for (y = 0; y < GFX_height() - 1 + radius; y += radius * 2) {
            GFX_drawCircle(x, y, radius, color);
        }
    }
}

void SSD1331_Test_FillCircle(unsigned int radius, unsigned int color) {
    unsigned char x, y;
    for (x = radius; x < GFX_width() - 1; x += radius * 2) {
        for (y = radius; y < GFX_height() - 1; y += radius * 2) {
            GFX_fillCircle(x, y, radius, color);
        }
    }
}

void SSD1331_Test_DrawTria(void) {
    int color = 0xF800;
    int t;
    int w = GFX_width() / 2;
    int x = GFX_height();
    int y = 0;
    int z = GFX_width();
    GFX_clearScreen();
    for (t = 0; t <= 15; t += 1) {
        GFX_drawTriangle(w, y, y, x, z, x, color);
        x -= 4;
        y += 4;
        z -= 4;
        color += 100;
    }
}

void SSD1331_Test_DrawRoundRect(void) {
    int color = 100;
    int i, t, x, y, w, h;
    GFX_clearScreen();
    for (t = 0; t <= 4; t += 1) {
        x = 0;
        y = 0;
        w = GFX_width();
        h = GFX_height();
        for (i = 0; i <= 24; i += 1) {
            GFX_drawRoundRect(x, y, w, h, 5, color);
            x += 2;
            y += 3;
            w -= 4;
            h -= 6;
            color += 1100;
        }
        color += 100;
    }
}

void SSD1331_Test_MediaButtons(void) {
    // play
    GFX_clearScreen();
    GFX_fillRoundRect(25, 10, 78, 60, 8, SSD1331_WHITE);
    GFX_fillTriangle(42, 20, 42, 60, 90, 40, SSD1331_RED);
    Delay10KTCYx(100);
    // pause
    GFX_fillRoundRect(25, 90, 78, 60, 8, SSD1331_WHITE);
    GFX_fillRoundRect(39, 98, 20, 45, 5, SSD1331_GREEN);
    GFX_fillRoundRect(69, 98, 20, 45, 5, SSD1331_GREEN);
    Delay10KTCYx(100);
    // play color
    GFX_fillTriangle(42, 20, 42, 60, 90, 40, SSD1331_BLUE);
    Delay10KTCYx(100);
    // pause color
    GFX_fillRoundRect(39, 98, 20, 45, 5, SSD1331_RED);
    GFX_fillRoundRect(69, 98, 20, 45, 5, SSD1331_RED);
    // play color
    GFX_fillTriangle(42, 20, 42, 60, 90, 40, SSD1331_GREEN);
}

void SSD1331_Test_Pattern(void) {
    unsigned char buffer[2];
    unsigned int i, j;
    SSD1331_GoTo(0, 0);

    for (i = 0; i < 64; i++) {
        for (j = 0; j < 96; j++) {
            if (i > 55) {
                buffer[0] = (SSD1331_WHITE >> 8);
                buffer[1] = (SSD1331_WHITE);
            } else if (i > 47) {
                buffer[0] = (SSD1331_BLUE >> 8);
                buffer[1] = (SSD1331_BLUE);
            } else if (i > 39) {
                buffer[0] = (SSD1331_GREEN >> 8);
                buffer[1] = (SSD1331_GREEN);
            } else if (i > 31) {
                buffer[0] = (SSD1331_CYAN >> 8);
                buffer[1] = (SSD1331_CYAN);
            } else if (i > 23) {
                buffer[0] = (SSD1331_RED >> 8);
                buffer[1] = (SSD1331_RED);
            } else if (i > 15) {
                buffer[0] = (SSD1331_MAGENTA >> 8);
                buffer[1] = (SSD1331_MAGENTA);
            } else if (i > 7) {
                buffer[0] = (SSD1331_YELLOW >> 8);
                buffer[1] = (SSD1331_YELLOW);
            } else {
                buffer[0] = (SSD1331_BLACK >> 8);
                buffer[1] = (SSD1331_BLACK);
            }
            LATBbits.LATB5 = 1; // D/C high (data)
            SPI2_Write(buffer, 2);
        }
    }
}