4D Systems uOLED 96 SGC

First, I need to throw out some massive compliments:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1291304406
Kevin Kibbe and Prawnhead put this together, even though every other resource points to this library, which I can't seem to make work:
http://jennylc.com/4d/

I changed some of Kevin and Prawn's code to work with the uOLED-96-SGC (or uOLED-96-G1-SGC or uOLED-96-G1(SGC)).
PDE Code

#include "Oled.h"
#include <string.h>

#define DIGI_A        2    // Values changed in line with
#define DIGI_B        3    // data from shieldlist.org
#define DIGI_C        4    //
#define OLED_WIDTH    96
#define OLED_HEIGHT   64

OLED myOLED(7,8,2500,57600);

int color= 0;
int tick = 0;

int ax = random(1,50);
int ay = random(1,10);
int ag = 1;
int af = 3;

int bx = random(50,160);
int by = random(30,128);
int bg = 3;
int bf = 2;

int latch=0;
int colour = 0;
int delta = 5;
int change = delta;

void setup()
{
  Serial.begin(57600);
  pinMode(10, OUTPUT);
  digitalWrite(10,HIGH);
  myOLED.Init();
  myOLED.Clear();

  int color1 = myOLED.get16bitRGB(255,0,0);
  int color2 = myOLED.get16bitRGB(0,0,255);

  int ax = random(92)+2;
  int ay = random(60)+2;
  int bwidth = random(92-ax);
  int bheight = random(60-ay);

  myOLED.PenSize(1);
  myOLED.DrawRectangle(0, 0, OLED_WIDTH - 1, OLED_HEIGHT - 1, myOLED.get16bitRGB(255,0,0));
}

void loop()
{
  colour += change;
  if (colour > (255-delta)) change = -delta;
  if (colour < delta) change = delta;
  myOLED.DrawString(20, 45, 2, myOLED.get16bitRGB(0,0,colour), 1, 1, "12:58");
  myOLED.DrawString(45, 10, 0, myOLED.get16bitRGB(255-colour,0,0), 1, 1, "Test");
}

OLED.h Code:

/*
	Oled.h - Oled Display library for Arduino & 4d Systems Serial OLEDs
	Copyright(c) 2010 Paul Karlik
	Original Source Copyright(c)2007 Oscar Gonzalez

	Licensed under the MIT license:
	http://www.opensource.org/licenses/mit-license.php

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

	16bitColor from RGB by YAPAN.org's small utilities for Arduino
	http://www.opensource.org/licenses/bsd-license.php
*/

#ifndef Oled_h
#define Oled_h

#include <inttypes.h>

#define OLED_BAUDRATE			57600
#define OLED_RESETPIN			8  
#define OLED_INITDELAYMS		1000

#define	OLED_DETECT_BAUDRATE	        0x55

#define	OLED_CLEAR			0x45
#define	OLED_BKGCOLOR			0x42
#define	OLED_COPYPASTE			0x63

#define OLED_SAVE_CHAR			0x41
#define OLED_DISPLAY_CHAR		0x44

#define	OLED_LINE			0x4C
#define	OLED_CIRCLE			0x43
#define	OLED_CIRCLEFILL			0x69
#define	OLED_PUTPIXEL			0x50
#define	OLED_READPIXEL			0x52
#define	OLED_RECTANGLE			0x72
#define OLED_SETPEN			0x70
#define	OLED_SETFONTSIZE		0x46
#define	OLED_FONT5X7			0x01
#define	OLED_FONT8X8			0x02
#define	OLED_FONT8X12			0x03
#define OLED_TEXT                       0x53
#define	OLED_TEXTFORMATED		0x54

#define	OLED_COMMAND_CONTROL	        0x59
#define	OLED_COMMAND_DISPLAY	        0x01
#define	OLED_COMMAND_CONTRAST	        0x02
#define	OLED_COMMAND_POWER		0x03

#define OLED_ACK			0x06
#define OLED_NAK 			0x15

class OLED
{

  public:
    OLED(uint8_t pinPower, uint8_t pinReset, uint8_t baudRate, uint8_t startUpTimer);

    uint8_t Init();  
    unsigned int get16bitRGB(uint8_t red, uint8_t green, uint8_t blue);
  
    
    uint8_t ResetDisplay();
	uint8_t Clear();
	uint8_t PutPixel(uint8_t x, uint8_t y, unsigned int color);
	uint8_t PenSize(uint8_t size);
	uint8_t DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, unsigned int color);
	uint8_t DrawRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, unsigned int color);
	uint8_t DrawCircle(uint8_t x, uint8_t y, uint8_t radius, unsigned int color);
	uint8_t SetFontSize(uint8_t FontType);
	uint8_t DrawText(uint8_t column, uint8_t row, uint8_t font_size, char *mytext, unsigned int color);
        uint8_t DrawString(uint8_t column, uint8_t row, uint8_t font_size, unsigned int color, uint8_t width, uint8_t height, char* text);
	uint8_t DrawSingleChar(uint8_t column, uint8_t row, uint8_t font_size, uint8_t MyChar, unsigned int color);
	uint8_t CopyPast(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t width, uint8_t height);
	uint8_t SaveBitChar(uint8_t slot, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4, uint8_t data5, uint8_t data6, uint8_t data7, uint8_t data8);
	uint8_t DisplayBitChar(uint8_t slot, uint8_t x, uint8_t y, unsigned int color);

  private:
	uint8_t _pinReset;
	uint8_t _pinPower;
	uint8_t _baudRate;
	uint8_t _startUpTimer;

    void write(uint8_t value);
	  
};

#endif

I changed the code in the PDE and the .h file so that all the baud rates are at 57600.
I also changed the PDE code to the correct width and height for the 96.
Then I changed the text size in the DrawString commands at the bottom of the loop.
The CPP code is unchanged.

I'm using pin 8 as the reset, I have a micro-SD card in the display, and the two pins un-jumpered.

Here is the CPP code for completeness's sake:

#include "Oled.h"

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "WProgram.h"


OLED::OLED(uint8_t pinPower, uint8_t pinReset, uint8_t baudRate, uint8_t startUpTimer){

  _pinReset = pinReset;
  _pinPower = pinPower;
  _baudRate = baudRate;
  _startUpTimer = startUpTimer;
  
  pinMode(_pinPower, OUTPUT);
  pinMode(_pinReset, OUTPUT);
  digitalWrite(_pinPower, HIGH);
  //pinMode(_pinReset, OUTPUT);

}

void OLED::write(uint8_t value) {
  Serial.print(value, BYTE);
}

char GetResponse()
{
	byte incomingByte = OLED_ACK;
	while (!Serial.available()) { delayMicroseconds(150); }
	incomingByte = Serial.read();
	return incomingByte;
}

uint8_t OLED::Init()
{
	ResetDisplay();  
	delay(OLED_INITDELAYMS);
	Serial.write(OLED_DETECT_BAUDRATE);
	GetResponse();
}

// YAPAN.org's small utilities for Arduino //
unsigned int OLED::get16bitRGB(uint8_t red, uint8_t green, uint8_t blue)
{
  uint8_t r = red >> 3;  						// red: 0-31
  uint8_t g = green >> 2;  						// green: 0-63
  uint8_t b = blue >> 3; 						// blue: 0-31

  unsigned int bitRGB = (r << 11) + (g << 5) + b;
  return bitRGB;
}

uint8_t OLED::Clear()
{
	Serial.write(OLED_CLEAR);
    GetResponse();
}

uint8_t OLED::ResetDisplay()
{
	digitalWrite(OLED_RESETPIN, LOW);
	delay(10);                  
	digitalWrite(OLED_RESETPIN, HIGH);
	delay(10);            
}

uint8_t OLED::PutPixel(uint8_t x, uint8_t y, unsigned int color)
{
	Serial.write(OLED_PUTPIXEL);
	Serial.write(x);						// X
	Serial.write(y);						// Y

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

    GetResponse();
}

uint8_t OLED::PenSize(uint8_t size) {
  Serial.write(OLED_SETPEN);
  Serial.write(size);
  
  GetResponse();
}

uint8_t OLED::DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, unsigned int color)
{

	Serial.write(OLED_LINE);

	Serial.write(x1);						// X1
	Serial.write(y1);						// Y1
	Serial.write(x2);						// X2
	Serial.write(y2);						// Y2

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);			// LSB

    GetResponse();

}

uint8_t OLED::DrawRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, unsigned int color)
{

	Serial.write(OLED_RECTANGLE);

	Serial.write(x);						// X1
	Serial.write(y);						// Y1
	Serial.write(x+width);					// X2
	Serial.write(y+height);					// Y1

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

	GetResponse();
}

uint8_t OLED::DrawCircle(uint8_t x, uint8_t y, uint8_t radius, unsigned int color)
{
    
    Serial.write(OLED_CIRCLE);

	Serial.write(x);						// X
	Serial.write(y);						// Y
	Serial.write(radius);					// Radius

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

    GetResponse();

}

uint8_t OLED::SetFontSize(uint8_t FontType)
{
    
    Serial.write(OLED_SETFONTSIZE);
    Serial.write(FontType);
    
    GetResponse();
}

uint8_t OLED::DrawText(uint8_t column, uint8_t row, uint8_t font_size, char *mytext, unsigned int color)
{

	Serial.write(0x73);						// Formated Text
        
    // Adjust to center of the screen (26 Columns at font size 0)
        int newCol = 13 - (strlen(mytext)/2);
  
        Serial.write(column); 					// Column    
	Serial.write(row); 					// Row

	Serial.write(font_size); 				// Font Size

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

	for (int i=0 ; i<strlen(mytext) ; i++)
	{
		Serial.print(mytext[i]); 			// character to write
	}

	Serial.print(0x00, BYTE); 				// string terminator (always 0x00)

    GetResponse();

}

// Added CMurphy 2010-12-12
uint8_t OLED::DrawString(uint8_t column, uint8_t row, uint8_t font_size,
  unsigned int color, uint8_t width, uint8_t height, char* text)
{

  Serial.write(OLED_TEXT);
  Serial.write(column);
  Serial.write(row);
  Serial.write(font_size);
  // Color
  Serial.write(color >> 8);				// MSB
  Serial.write(color & 0xFF);				// LSB
  Serial.write(width);
  Serial.write(height);
  while(*text != '\0') Serial.write((char) *text++);
  Serial.write((uint8_t) 0);

  GetResponse();

}

uint8_t OLED::DrawSingleChar(uint8_t column, uint8_t row, uint8_t font_size, uint8_t MyChar, unsigned int color)
{

	Serial.write(OLED_TEXTFORMATED);

    Serial.write(MyChar);
    Serial.write(column);
    Serial.write(row);
        
	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

    GetResponse();

}

uint8_t OLED::CopyPast(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t width, uint8_t height)
{

	Serial.write(OLED_COPYPASTE);

	Serial.write(x1);						// X1
	Serial.write(y1);						// Y1
	Serial.write(x2);						// X2
	Serial.write(y2);						// Y2

	Serial.write(width);					// Box Width
	Serial.write(height);					// Box Height

    GetResponse();

}

uint8_t OLED::SaveBitChar(uint8_t slot, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4, uint8_t data5, uint8_t data6, uint8_t data7, uint8_t data8  )
{

	Serial.write(OLED_SAVE_CHAR);

	Serial.write(slot);						// Char Slot
	Serial.write(data1);					// Data 1
	Serial.write(data2);					// Data 2
	Serial.write(data3);					// Data 3
	Serial.write(data4);					// Data 4
	Serial.write(data5);					// Data 5
	Serial.write(data6);					// Data 6
	Serial.write(data7);					// Data 7
	Serial.write(data8);					// Data 8

    GetResponse();

}


uint8_t OLED::DisplayBitChar(uint8_t slot, uint8_t x, uint8_t y, unsigned int color)
{

	Serial.print(OLED_DISPLAY_CHAR, BYTE);

	Serial.write(slot);						// Char Slot
	Serial.write(x);						// X
	Serial.write(y);						// Y

	// Color
	Serial.write(color >> 8);				// MSB
	Serial.write(color & 0xFF);				// LSB

    GetResponse();

}

And I'm a bit of a moron, because I forgot the whole reason that I started this thread.

I need to mirror this display (I'm going to be looking at it after I reflect it in a mirror).

I need to implement this:
[http://4d.websitetoolbox.com/post?id=2392828&pid=1267872258#post12678722585]http://4d.websitetoolbox.com/post?id=2392828&pid=1267872258#post1267872258[/url]

I can't seem to figure out how to send multiple commands to the system. I've tried a couple of different ideas, but either they don't work, or I hang the display.

If I get any information from them, I'll post up here, and vice versa.

Hi Static,

For example the CopyPast(..) method sends multiple commands. You would need to structure you method about the same as that for writing to one of the registers. (the display_SetReg thing). The exact command to do that is in the commands pdf.

The actual registers in the controller inside the oled screen (Not the goldelox controller) are in a pdf for your oled screen (again, not the goldelox). I looked for a short time but i couldn't find the datasheet for the .96" screen. For the 1.7" i have it's the SEPS525 Datasheet. (from http://www.4dsystems.com.au/prod.php?id=20 )

Hope this gives some leads.

Jeroen.

ps. There are pre-invented wheels (library). search for uoled library or displayshield4d . I made one myself as well with the switch inputs, sd-card access, sound output and the possibility to use different hardware serial ports in case of an arduino mega. Drop me a message if you want a copy.

Wow!
I was reading your stuff yesterday. I love the internet, you run into the neatest people. It's always thrilling to me when I meet folks who have already "blazed a trail".

I tried your work yesterday, and couldn't get it to work with the 96. I got a reply on the 4D forums, and it seems that the 96 isn't capable of doing this without pre-programming it. I'm surprised by this, as the display just screams to be embedded in something, and used indirectly (Across a mirror).

When I find a solution, I'll post it.

Thanks again.

Not sure which lib. you are using atm but i haven't posted it somewhere yet. I was asked for a copy a few times so that may be one of the libs you saw.

Maybe the disp config file gives some clues as to what registers there are in the screen controller (not the goldelox controller on the board).

Jeroen.

ps. I was a noob only a year ago. Probably still am. :slight_smile:

I've been a noob all my life. Just when you think you've seen it all, something new and different comes along.

That's the problem with not keeping notes. I thought you posted your successful code, and I tried it, and it didn't work. I was literally trying everything that I could find, for awhile. As it stands, the code I'm using is going to need to be expanded, so that more functions can be implemented. I think I'm going to have to learn C, or whatever the libraries are programmed with.

Post your code up! Share the discoveries.

I won't post it yet. Needs some thing before i do that. If you really want you can have a copy. A work in progress version that is.

Jeroen.

I'd love to look at it, if for no other reason that it will help me learn more (and faster).