OLED Performance

Hello there people, i need an advice here.

I’m looking to make a Raycaster in Arduino similar to the one of this video

http://www.youtube.com/watch?feature=pl … xd6c#t=35s

he made it using an OLED with SPI interface. the code for it is free so i downloaded, he stated there the exact model (which is Samsung) and controller, but i’m unable to find to buy that specific OLED Model.

i found two alternatives to sell over the web and i’d like to know if they have the same power to achieve that Raycasting with the performance that is in the video. i’m no expert in the hardware area so i’m not sure if the performance is more to do with the ATMEGA Controller than the OLED itself. the videos author also stated that even though SPI is regarded as slow for displays, the OLED thus being 128x128 is able to draw at >30fps.

These are those i found:

http://www.adafruit.com/products/684

http://www.ebay.com/itm/SPI-1-5-Color-O … 1e7212fbc8

ANY help is appreciated, thanks in advance.

-Lucas

You Youtube and Ebay links are messed up.

Oops, sprry for that, fixed already :wink:

Please anyone help me on this :confused:

There is no set speed for SPI transfers. IIRC the default is something like 4 MHz. If you have the source code that was used, you can see what was used for the display(s) he had. There’s no info on the E-Bay display so I can’t tell what speed it would or wouldn’t support. The Adafruit display has a link to the controller datasheet and on pg 57 of that it says the min serial cycle time it will support is 150 nS. I interpret that to mean it’ll work up to a 6.6 MHz SPI rate, perhaps higher though not guaranteed. I’ve not tried to compare the number of pixels btw the displays. Obviously if one has 2x the pixels used in the video, it’ll take 2x longer to transfer the data and that may affect the frame rate.

http://www.adafruit.com/datasheets/SSD1331_1.2.pdf

Thanks for the reply, well in other words, the adafruit display is theoretically capable?

The ebays controller is the SSD1351u3

I found the ebays controller DS:

http://www.embeddedartists.com/sites/de … SD1351.pdf

So, i’m gonna do some math here, correct me if i’m wrong (I really don’t know much about electronics).

You said it to run at 6.6 MHz, that gives us 6,600,000 Bits per second transfer rate?

So considering the screen is 96 x 64 Pixels = 6144 total Pixels

i don’t remember how much data is needed for each pixel, i think its 2 bytes, so we need 6,144 x 16 = 98,304 bits needed to refill the whole screen;

6,600,000 / 98,304 = 67.13, so that gives us 67 Frames per second?

Sorry i’m mistaken a lot, as i don’t understand much of the logic underlying those technologies.

Thanks

Your math is about right. At a glance it looked as the controller did transfer 1 byte at a time so there will be a little wasted time btw each byte’s transfer, and so the overall transfer rate a tad slower … but the above is good enough for now. There’s also time needed to tell the controller what type of data it’s getting and what address the data is going to. I’d expect that you’d only need to specify the stating address and perhaps the number of bytes and then stream the data across (vs send addr, data, addr, data). If it’s the latter then the time needed just to transfer data could be 2x as long.

I think your 2 bytes per pixel is correct. Perhaps in grayscale mode there’s a way to reduce the data needed as there’s only 64 different grayscale levels (6 bits). Again you’d have to read the datasheet or infer the transfer size from the source code. A lot of what can be done can be told by looking at the code as used.

The next question is how the controller handles the data to refresh the display. How long does it take to update the pixels and can it be reading in the data for the next frame while it’s updating the screen ? That is, doing 2 things simultaneously. I’d have to spend some time going through the datasheet but at 1’st blush I’d guess that 30 fps looks do-able.

I note the Adafruit display has the option of using an 8 bit parallel interface and so the above questions become moot if you have the pins to spare.

You might post on an Adafruit forum asking about achieved frame rates with that display. Or perhaps Google the controller PN and see what people claim.

The other controller looks much the same but has more pixels and thus more bits to transfer. And it’s seems to use 18 bits/pixel, I’m not sure if it uses an odd 9 bit / transfer or you have to waste time transfering another byte ? It does list a 50 nS clock period though, perhaps 3x faster than the other controller … if the Arduino could support that ?!?

Its very hard to find someone commenting anything about those displays.

the guy from the video used an arduino too so i assume he is capable of supporting too,

i found out that the eBay display can be configured to use 16 or 18 bits for 64k and 262k color depths.

so, using the same math from above, and assuming it is 3x faster:

Raw Data Transfer: 19,800,000

128 pxls x 128 pxls = 16384 pxls

Number of data needed for 262k = 294912

Number of data needed for 65k = 262144

19,800,000 / 294912 = 67.13

19,800,000 / 262144 = 75.53

so, can we assume they are almost equivalent? as i can see if i lower the color depth i can gain even more “frames”.

I think im going to buy the 128x128 as for i didnt found another one to compare and these two look almost the same on performance, based on our math.

I would only say that I think the fastest SPI clock that the ATMega328 supports is 8 MHz. A faster, more capable controller may not translate into any faster transfer speed. But if the guy in the video did what he did with an ATMega328 and the same pixel count and color depth … seems like a fair bet you can replicate it.

Ok thanks for the advices, shall buy it tomorrow, i was just in doubt if the difference of oled would turn it impossible.

Thanks Mee_n_Mac!

Now i started thinking, you’re right Me_n_mac, Arduino on SPI interface has the maximum Clock of 8Mhz (16mhz/2) so even if the 128x128 OLED can run at more than 8Mhz, it doesnt matter.

I made the final math

[

another interesting discovery is that i found on the Video Authors Code the following:

//	Fill a 16 bit color
//	Blit 16 bit pixels
//	Blit 8 bit indexed pixels from palette
//	400,000 pixels/sec on a 16Mhz AVR for Solid fills and 16bpp blits
//	380,000 pixels/sec for indexed blits
//	The code looks crazy 'cause it is using shadow of the spi data clocks
//	do work for the next round. It is within 10% of a hardware 9 bit spi

So he’s using 65k Color Depth, he manages to get 400,000 pixels/sec on an arduino,which results more or less 24,4 FPS.

The Interesting fact is that on the math theoretically it should perform at 500,000 pixels/sec. So that time loss you said its true, so its not Raw Math, its something around 80% of the math.

Now im afraid again of the choice, but it seems to be OK to use the 128x128 at 65k Colors.](Imgur: The magic of the Internet)

About the only thing I gathered from glancing at the datasheet was that the 3-wire SPI transfers are an odd 9 bit transfer (so you might have to work some special coding to make that happen). Now you might think that’s because of the color depth but nope, it’s 8 bits of data and 1 bit of command-vs-data identifier. The 4-wire SPI breaks that 9’th bit out and puts it on the 4’th “wire” (so SPI transfers are 8 bits).

At the 65k depth it seems that 2 transfers are all that’s needed, the RGB components are packed into 16 bits (see table 8-8 in the file you linked to). Using grayscale doesn’t help as it works on the RGB data after it’s been transferred to the LCD controller. There are perhaps half a dozen or so command registers to be setup prior to every updating of the 128x128 pixels but it looks that you can just transfer pixel1 data, pixel2 data, etc, etc until done and the controller knows to bump the addressing of GDDRAM for each pixel.

As you’ve figured out there’s some overhead that decreases the true overall transfer rate. One thing I think can be done with the 128x128 display is trade off pixels for frame rate. I don’t think you have to display all the pixels. And I believe you can, with some added overhead, transfer only those that will get displayed. So if frame rate is uber important to you, you may give that a thought.

What I don’t know is how, or even if, you can sync the LCD updating with the transferring of new data so as to prevent screens that have part old data, part new data. But perhaps that’s like complaining about how poorly pigs fly.

Good luck with all this.

I’ve seen in another thread (the only one about the 128x128 i could found) in they were complaining that they couldnt “write to pixel”, but write to the ram, and the controller would draw them, thus agreeing in what you said and i dont know if thats good or bad though. It is stated on the DS that it has “programable framerate”, though i cant find on the datasheet how to achieve that.

I found out too that it supports 256 color mode, that would mean that only one byte would be used on the transfer?

As for the adafruit one ive seen that it has an “hardware accelerated drawing” that help drawing lines, squares, etc… That feature would help?

As i will try to port the existing raycast code, the author, after casting the rays he calls this function:

OLED_Slice(ray,SCREEN_HEIGHT,buffer,(u8*)palette);

Which is a wrapper to another function

void OLED_Slice(u8 x, u8 height, u8* buffer, u8 *palette)
{
	FillBlit(0,height,buffer,palette);
}

And fillBlit

void FillBlit(u32 color, u32 count, const u8* data = 0, const u8* palette = 0)
{
	SPSR |= 1;	// 2x clock

	u8 a,b;
	
	//	Handle 16 bit blits and index mode
	signed char x = 0;
	u8 y;
	const u8* p = 0;
	if (data)
	{
		a = *data++;
		x = 1;
		if (palette)
		{
			p = palette + (a << 1);
			a = pgm_read_byte(&p[0]);
			b = pgm_read_byte(&p[1]);
			x = -1;
			y = 0;
		}
	}
	else
	{
		a = color >> 8;
		b = color;
	}

	count <<= 1;
	int loop = count >> 8;
	u8 c = count;
	if (c)
		loop++;

	SPCR = _BV(MSTR) | _BV(SPE);	// SPI Master ... get it?
	while (loop)
	{
		// up to 256 per loop
		for (;;)
		{
			SPDR = a;						// Now we have 16 clocks to kill

			//	16 clocks to do fill, blit or indexed blit

			//	Indexed blit - 380k
			if (x < 0)
			{
				if ((y^=1))
				{
					a = b;
					p = palette + ((*data++) << 1);
					if (--c)
						continue;	// Early out
				} else {
#ifdef OLED96	// shameful hack TODO
					a = p[0];
					b = p[1];
					nop();
					nop();
#else
					a = pgm_read_byte(&p[0]);
					b = pgm_read_byte(&p[1]);
#endif
					if (--c)
						continue;	// Early out
				}
				break;
			}


			if (x)
			{
			//	Blit
				a = *data++;
				nop();
				nop();		// 400k
			}
			else
			{
				// Solid Fill
				u8 t = a;	// swap pixel halves
				a = b;
				b = t;
				nop();
				nop();		// 400k
			}
			if (!--c)
				break;	// 5 
		};				// loop takes 3 clocks
		c = 0;
		loop--;
		while (!(SPSR & _BV(SPIF)));	// wait for last pixel
	}
	SPCR = 0;
}

This last function im not certain of what it does, i think it fills a buffer of a single slice of raycast, maybe im wrong, so i think i would have to make it write to the controllers RAM.

The last function is doing the SPI transfers. But I looked and am unable to figure out all it’s inner workings. I can see where some colors are being packed into the 16 bits. I don’t see what the “palette” sections are intended to do.