Page 1 of 1

1.3" OLED Display Example

Posted: Sun May 10, 2015 6:26 pm
by mx270a
I bought a small OLED display on ebay, thought I'd share the source code in case anyone else finds a use for one of these. I have the 1.3" screen with the SH1106 controller on a breakout board that has SPI headers. It has a resolution of 128x64 pixels.
http://www.ebay.com/itm/281648238188?_t ... 2749.l2649

The controller can also do I2C and a couple other connections, but I went with SPI for faster updates. As it turns out, SPI provides plenty of bandwidth. With a SPI clock speed of 32 MHz, I can rewrite the entire screen ~930 times per second. I'm not sure if the LED pixels update that fast or not, would need a high speed camera to test. It looks smooth though.

There are libraries out there for this controller for the Arduino, so between reading through those and reading the datasheet, I came up with code to use this display with the Netburner.

A couple notes:
1) There is no data to read from the controller, so there is no MISO line. It does use three SPI lines (CLK, MOSI, and CS) plus two additional GPIO, one to reset the display, and one to specify if the data coming into the display is commands or display data.
2) The controller supports a resolution of 132x64, but the display is only 128x64. The displayed data is centered in the array, so if you set the command bits to flip the screen horizontally or vertically, the image will still be complete.
3) Writing data to the screen requires you to send a command byte to specify where you want to write the data, then you can write data to the location, up to the end of the line.

Code: Select all

//Demo of a 1.3" OLED display via SPI 3 on a NANO54415. 128x64 pixels
#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <pins.h>
#include <dspi.h>

extern "C" {
void UserMain(void * pd);
}

const char * AppName="OLED Display Demo";
OS_SEM DSPI_SEM;

void SendToOLED(bool IsData, BYTE *data, int count) {
	if (IsData) { //Data
		Pins[39].set();
	} else { //Commands
		Pins[39].clr();
	}
	DSPIStart(3, data, NULL, count, &DSPI_SEM); //Send data via DSPI
	OSSemPend( &DSPI_SEM, 0 );
}
void SendToOLED(bool IsData, BYTE b) {
	BYTE data[1];
	data[0] = b;
	SendToOLED(IsData, data, 1);
}
void gotoXY(BYTE page, BYTE column) {
	if (column > 127) column = 127;
	if (page > 7) page = 7;
	column = column + 2; //Panel is 128 pixels wide, controller RAM has space for 132. It's centered so add an offset to ram address.
	SendToOLED(false, 0xB0 + page); //Set Page Address: (B0H - B7H)
	SendToOLED(false, column & 0x0F); //Set Lower column address
	SendToOLED(false, 0x10 | (column >> 4)); //Set Higher column address
}

void UserMain(void * pd) {
    InitializeStack();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();

    Pins[34].function(PIN_34_DSPI3_SOUT); //SPI3 MOSI, connects to pin "D1"
    Pins[36].function(PIN_36_DSPI3_PCS0); //SPI3 CS0, connects to pin "CS"
    Pins[38].function(PIN_38_DSPI3_SCK);  //SPI3 CLK, connects to pin "D0"
    Pins[37].function(PIN_37_GPIO); //OLED Reset pin
    Pins[39].function(PIN_39_GPIO); //OLED Data/Command pin

    Pins[37].clr(); //Reset display
    OSTimeDly(5);
    Pins[37].set();
    OSTimeDly(2);

    OSSemInit(&DSPI_SEM, 0);
    DSPIInit(3, 2000000, 8, 0xFE, 1, 1); //Device is on SPI3 and we'll use 2 MHz

	SendToOLED(false, 0xAE); //Set Display OFF (sleep mode)
	for (int i = 0; i < 8; i++) { //For each of the 8 pages
		gotoXY(i, 0);
		for (int j = 0; j < 128; j++) { //For each of the 128 columns wide
			SendToOLED(true, 0x00); //Set the byte to zero to clear any display data that was there
		}
	}
	SendToOLED(false, 0xAF); //Set Display ON (normal mode)

    iprintf("Application started\n");
    bool flipflop = false;
    int currentpage = 0;
    while (1) {
    	gotoXY(currentpage, 0);
    	for (int i=0; i<128; i++) {
    			if (flipflop) {
    				SendToOLED(true, 0xFF); //Write all white
    			} else {
    				SendToOLED(true, i); //Write binary value
    			}
    	}

    	currentpage++;
    	if (currentpage == 8) {
    		currentpage = 0;
    		flipflop = !flipflop;
    	}

        OSTimeDly(20);
    }
}

Re: 1.3" OLED Display Example

Posted: Mon Dec 28, 2015 4:21 am
by TheFold
I'm thinking of getting a little display like this as they're only a few bucks. How long did it take for yours to arrive from China though? The last time I bought from China it took 5 weeks.
mx270a wrote:I bought Proextender recently on ebay, thought I'd share the source code in case anyone else finds a use for one of these. I have the 1.3" screen with the SH1106 controller on a breakout board that has SPI headers. It has a resolution of 128x64 pixels.

The controller can also do I2C and a couple other connections, but I went with SPI for faster updates. As it turns out, SPI provides plenty of bandwidth. With a SPI clock speed of 32 MHz, I can rewrite the entire screen ~930 times per second. I'm not sure if the LED pixels update that fast or not, would need a high speed camera to test. It looks smooth though.

There are libraries out there for this controller for the Arduino, so between reading through those and reading the datasheet, I came up with code to use this display with the Netburner.

A couple notes:
1) There is no data to read from the controller, so there is no MISO line. It does use three SPI lines (CLK, MOSI, and CS) plus two additional GPIO, one to reset the display, and one to specify if the data coming into the display is commands or display data.
2) The controller supports a resolution of 132x64, but the display is only 128x64. The displayed data is centered in the array, so if you set the command bits to flip the screen horizontally or vertically, the image will still be complete.
3) Writing data to the screen requires you to send a command byte to specify where you want to write the data, then you can write data to the location, up to the end of the line.

Re: 1.3" OLED Display Example

Posted: Mon Dec 28, 2015 7:58 am
by mx270a
Shipping from China to the US is usually 2-4 weeks. If your biggest objection is the time delay, just buy one now and forget about the project for a month. Then you'll have the part when your interest comes back to this.

Re: 1.3" OLED Display Example

Posted: Wed Oct 03, 2018 1:01 am
by aimeusdietger
mx270a wrote: Sun May 10, 2015 6:26 pm I bought a small OLED display on ebay, thought I'd share the source code in case anyone else finds a use for one of these. I have the 1.3" screen with the SH1106 controller on a breakout board that has SPI headers. It has a resolution of 128x64 pixels.
The controller can also do I2C and a couple other connections, but I went with SPI for faster updates. As it turns out, SPI provides plenty of bandwidth. With a SPI clock speed of 32 MHz, I can rewrite the entire screen ~930 times per second. I'm not sure if the LED pixels update that fast or not, would need a high speed camera to test. It looks smooth though.

There are libraries out there for this controller for the Arduino, so between reading through those and reading the datasheet, I came up with code to use this display with the Netburner.

A couple notes:
1) There is no data to read from the controller, so there is no MISO line. It does use three SPI lines (CLK, MOSI, and CS) plus two additional GPIO, one to reset the display, and one to specify if the data coming into the display is commands or display data.
2) The controller supports a resolution of 132x64, but the display is only 128x64. The displayed data is centered in the array, so if you set the command bits to flip the screen horizontally or vertically, the image will still be complete.
3) Writing data to the screen requires you to send a command byte to specify where you want to write the data, then you can write data to the location, up to the end of the line.

Code: Select all

//Demo of a 1.3" OLED display via SPI 3 on a NANO54415. 128x64 pixels
#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <pins.h>
#include <dspi.h>

extern "C" {
void UserMain(void * pd);
}

const char * AppName="OLED Display Demo";
OS_SEM DSPI_SEM;

void SendToOLED(bool IsData, BYTE *data, int count) {
	if (IsData) { //Data
		Pins[39].set();
	} else { //Commands
		Pins[39].clr();
	}
	DSPIStart(3, data, NULL, count, &DSPI_SEM); //Send data via DSPI
	OSSemPend( &DSPI_SEM, 0 );
}
void SendToOLED(bool IsData, BYTE b) {
	BYTE data[1];
	data[0] = b;
	SendToOLED(IsData, data, 1);
}
void gotoXY(BYTE page, BYTE column) {
	if (column > 127) column = 127;
	if (page > 7) page = 7;
	column = column + 2; //Panel is 128 pixels wide, controller RAM has space for 132. It's centered so add an offset to ram address.
	SendToOLED(false, 0xB0 + page); //Set Page Address: (B0H - B7H)
	SendToOLED(false, column & 0x0F); //Set Lower column address
	SendToOLED(false, 0x10 | (column >> 4)); //Set Higher column address
}

void UserMain(void * pd) {
    InitializeStack();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();

    Pins[34].function(PIN_34_DSPI3_SOUT); //SPI3 MOSI, connects to pin "D1"
    Pins[36].function(PIN_36_DSPI3_PCS0); //SPI3 CS0, connects to pin "CS"
    Pins[38].function(PIN_38_DSPI3_SCK);  //SPI3 CLK, connects to pin "D0"
    Pins[37].function(PIN_37_GPIO); //OLED Reset pin
    Pins[39].function(PIN_39_GPIO); //OLED Data/Command pin

    Pins[37].clr(); //Reset display
    OSTimeDly(5);
    Pins[37].set();
    OSTimeDly(2);

    OSSemInit(&DSPI_SEM, 0);
    DSPIInit(3, 2000000, 8, 0xFE, 1, 1); //Device is on SPI3 and we'll use 2 MHz

	SendToOLED(false, 0xAE); //Set Display OFF (sleep mode)
	for (int i = 0; i < 8; i++) { //For each of the 8 pages
		gotoXY(i, 0);
		for (int j = 0; j < 128; j++) { //For each of the 128 columns wide
			SendToOLED(true, 0x00); //Set the byte to zero to clear any display data that was there
		}
	}
	SendToOLED(false, 0xAF); //Set Display ON (normal mode)

    iprintf("Application started\n");
    bool flipflop = false;
    int currentpage = 0;
    while (1) {
    	gotoXY(currentpage, 0);
    	for (int i=0; i<128; i++) {
    			if (flipflop) {
    				SendToOLED(true, 0xFF); //Write all white
    			} else {
    				SendToOLED(true, i); //Write binary value
    			}
    	}

    	currentpage++;
    	if (currentpage == 8) {
    		currentpage = 0;
    		flipflop = !flipflop;
    	}

        OSTimeDly(20);
    }
}
2-4 weeks for shipping is quite ok. I'm just wondering what the effect will be when i use a basic DSLR low speed camera with the fast OLED display will it have a good or negative impact on the output?Also now that mirror-less cameras are a thing, would this be a better alternative coz i think they are faster

Re: 1.3" OLED Display Example

Posted: Thu Oct 15, 2020 5:57 am
by natebrim
aimeusdietger wrote: Wed Oct 03, 2018 1:01 am
mx270a wrote: Sun May 10, 2015 6:26 pm I bought a small OLED display on ebay, thought I'd share the source code in case anyone else finds a use for one of these. I have the 1.3" screen with the SH1106 controller on a breakout board that has SPI headers. It has a resolution of 128x64 pixels.
The controller can also do I2C and a couple other connections, but I went with SPI for faster updates. As it turns out, SPI provides plenty of bandwidth. With a SPI clock speed of 32 MHz, I can rewrite the entire screen ~930 times per second. I'm not sure if the LED pixels update that fast or not, would need a high speed camera to test. It looks smooth though.

There are libraries out there for this controller for the Arduino, so between reading through those and reading the datasheet, I came up with code to use this display with the Netburner.

A couple notes:
1) There is no data to read from the controller, so there is no MISO line. It does use three SPI lines (CLK, MOSI, and CS) plus two additional GPIO, one to reset the display, and one to specify if the data coming into the display is commands or display data.
2) The controller supports a resolution of 132x64, but the display is only 128x64. The displayed data is centered in the array, so if you set the command bits to flip the screen horizontally or vertically, the image will still be complete.
3) Writing data to the screen requires you to send a command byte to specify where you want to write the data, then you can write data to the location, up to the end of the line.

Code: Select all

//Demo of a 1.3" OLED display via SPI 3 on a NANO54415. 128x64 pixels
#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <pins.h>
#include <dspi.h>

extern "C" {
void UserMain(void * pd);
}

const char * AppName="OLED Display Demo";
OS_SEM DSPI_SEM;

void SendToOLED(bool IsData, BYTE *data, int count) {
	if (IsData) { //Data
		Pins[39].set();
	} else { //Commands
		Pins[39].clr();
	}
	DSPIStart(3, data, NULL, count, &DSPI_SEM); //Send data via DSPI
	OSSemPend( &DSPI_SEM, 0 );
}
void SendToOLED(bool IsData, BYTE b) {
	BYTE data[1];
	data[0] = b;
	SendToOLED(IsData, data, 1);
}
void gotoXY(BYTE page, BYTE column) {
	if (column > 127) column = 127;
	if (page > 7) page = 7;
	column = column + 2; //Panel is 128 pixels wide, controller RAM has space for 132. It's centered so add an offset to ram address.
	SendToOLED(false, 0xB0 + page); //Set Page Address: (B0H - B7H)
	SendToOLED(false, column & 0x0F); //Set Lower column address
	SendToOLED(false, 0x10 | (column >> 4)); //Set Higher column address
}

void UserMain(void * pd) {
    InitializeStack();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();

    Pins[34].function(PIN_34_DSPI3_SOUT); //SPI3 MOSI, connects to pin "D1"
    Pins[36].function(PIN_36_DSPI3_PCS0); //SPI3 CS0, connects to pin "CS"
    Pins[38].function(PIN_38_DSPI3_SCK);  //SPI3 CLK, connects to pin "D0"
    Pins[37].function(PIN_37_GPIO); //OLED Reset pin
    Pins[39].function(PIN_39_GPIO); //OLED Data/Command pin

    Pins[37].clr(); //Reset display
    OSTimeDly(5);
    Pins[37].set();
    OSTimeDly(2);

    OSSemInit(&DSPI_SEM, 0);
    DSPIInit(3, 2000000, 8, 0xFE, 1, 1); //Device is on SPI3 and we'll use 2 MHz

	SendToOLED(false, 0xAE); //Set Display OFF (sleep mode)
	for (int i = 0; i < 8; i++) { //For each of the 8 pages
		gotoXY(i, 0);
		for (int j = 0; j < 128; j++) { //For each of the 128 columns wide
			SendToOLED(true, 0x00); //Set the byte to zero to clear any display data that was there
		}
	}
	SendToOLED(false, 0xAF); //Set Display ON (normal mode)

    iprintf("Application started\n");
    bool flipflop = false;
    int currentpage = 0;
    while (1) {
    	gotoXY(currentpage, 0);
    	for (int i=0; i<128; i++) {
    			if (flipflop) {
    				SendToOLED(true, 0xFF); //Write all white
    			} else {
    				SendToOLED(true, i); //Write binary value
    			}
    	}

    	currentpage++;
    	if (currentpage == 8) {
    		currentpage = 0;
    		flipflop = !flipflop;
    	}

        OSTimeDly(20);
    }
}
2-4 weeks for shipping is quite ok. I'm just wondering what the effect will be when i use a basic DSLR low speed camera with the fast OLED display will it have a good or negative impact on the output?Also now that mirror-less cameras are a thing, would this be a better alternative coz i think they are faster
Just wondering if there is still a way to ge these OLED displays from ebay i know it would be harder as there are new ones now.

Re: 1.3" OLED Display Example

Posted: Sat Feb 27, 2021 7:06 pm
by jpelletier
I ported a demo for a similar OLED. I describe this here:
https://hackaday.io/project/177816-micr ... rary-ports