Subversion Repositories group.electronics

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <avr/io.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include "wire.h"
#include "avrutil.h"
#include <util/delay.h>
#include <string.h>

#include "oled.h"

#define OLED_SETCONTRAST                        0x81
#define OLED_DISPLAYALLON_RESUME        0xA4
#define OLED_DISPLAYALLON                       0xA5
#define OLED_NORMALDISPLAY                      0xA6
#define OLED_INVERTDISPLAY                      0xA7
#define OLED_DISPLAYOFF                         0xAE
#define OLED_DISPLAYON                          0xAF

#define OLED_SETDISPLAYOFFSET           0xD3
#define OLED_SETCOMPINS                         0xDA

#define OLED_SETVCOMDETECT                      0xDB

#define OLED_SETDISPLAYCLOCKDIV         0xD5
#define OLED_SETPRECHARGE                       0xD9

#define OLED_SETMULTIPLEX                       0xA8

#define OLED_SETLOWCOLUMN                       0x00
#define OLED_SETHIGHCOLUMN                      0x10
#define OLED_SETSTARTLINE                       0x40

#define OLED_MEMORYMODE                         0x20
#define OLED_COMSCANINC                         0xC0
#define OLED_COMSCANDEC                         0xC8
#define OLED_SEGREMAP                           0xA0
#define OLED_CHARGEPUMP                         0x8D

/**
 * Color is simply true (white) or false (black)
 */
void oled_drawPixel(uint8_t* buffer, uint16_t x, uint16_t y, uint8_t color) {
          if (color)
            buffer[x+ (y/8)*oled.width] |= _BV((y%8));
          else
            buffer[x+ (y/8)*oled.width] &= ~_BV((y%8));
}


void oled_invert(uint8_t i) {
        if (i)
                oled_cmd(OLED_INVERTDISPLAY);
        else
                oled_cmd(OLED_NORMALDISPLAY);
}

uint8_t* oled_getBuffer(void) {
        return oled.buffer;
}

uint8_t* oled_init(uint8_t width, uint8_t height, uint8_t vccstate, uint8_t address) {
  oled.i2c_addr = address;
  oled.width = width;
  oled.height = height;

  oled.buffer = malloc((oled.height * oled.width / 8) * sizeof(uint8_t));

  //Reset high, (1), Low (10), High

  // Init Sequence
  oled_cmd(OLED_DISPLAYOFF);
  oled_cmd(OLED_SETDISPLAYCLOCKDIV);
  oled_cmd(0x80);                                               // ratio
  oled_cmd(OLED_SETMULTIPLEX);
  oled_cmd(0x3F);
  oled_cmd(OLED_SETDISPLAYOFFSET);
  oled_cmd(0x0);
  oled_cmd(OLED_SETSTARTLINE | 0x0);    // line 0
  oled_cmd(OLED_CHARGEPUMP);
  (vccstate) ? oled_cmd(0x14) : oled_cmd(0x10);
  oled_cmd(OLED_MEMORYMODE);
  oled_cmd(0x00);
  oled_cmd(OLED_SEGREMAP | 0x01);
  oled_cmd(OLED_COMSCANDEC);
  oled_cmd(OLED_SETCOMPINS);
  oled_cmd(0x12);
  oled_cmd(OLED_SETCONTRAST);
  (vccstate) ? oled_cmd(0xCF) : oled_cmd(0x9F);
  oled_cmd(OLED_SETPRECHARGE);
  (vccstate) ? oled_cmd(0xF1) : oled_cmd(0x22);
  oled_cmd(OLED_SETVCOMDETECT);
  oled_cmd(0x40);
  oled_cmd(OLED_DISPLAYALLON_RESUME);
  oled_cmd(OLED_NORMALDISPLAY);
  oled_cmd(OLED_DISPLAYON);
  
  return oled.buffer;
}

inline void oled_cmd(uint8_t cmd) {
        const uint8_t CONTROL = 0x00;
        oled_write(CONTROL, cmd);
}

inline void oled_data(uint8_t data) {
        const uint8_t CONTROL = 0x04;
        oled_write(CONTROL, data);
}

void oled_write(uint8_t control, uint8_t data) {
        i2c_beginTransmission(oled.i2c_addr);
        i2c_writeByte(control);
        i2c_writeByte(data);
        i2c_endTransmission(1);
}

void oled_clear(void) {
        memset(oled.buffer, 0, (oled.width*oled.height/8));
}

void oled_power(uint8_t pwr) {
        if (pwr)
                oled_cmd(OLED_DISPLAYON);
        else
                oled_cmd(OLED_DISPLAYOFF);
}

void oled_display(void) {
        oled_cmd(OLED_SETLOWCOLUMN | 0x0);
        oled_cmd(OLED_SETHIGHCOLUMN | 0x0);
        oled_cmd(OLED_SETSTARTLINE | 0x0);

        uint16_t i;
        for (i=0; i<(oled.width * oled.height / 8); i++) {

                // @todo: Get twi to send 17 bytes
                // Need to fix this up
                //  my twi lib can only send 4 bytes at a time...
                //   though can change to 15 if needed
                //   still not enough to send full block
                uint8_t x;
                for (x=0; x<16; x++) {
                        i2c_beginTransmission(oled.i2c_addr);
                        i2c_writeByte(0x40);
                        i2c_writeByte(oled.buffer[i]);
                        i2c_endTransmission(1);
                        i++;
                }
                i--;
        }
}