Main Site Documentation

Does FEZ Cerberus have enough RAM to control the N18 display?


#1

I noticed FEZ Cerberus has 112kb of RAM
The N18 display has 128x160 pixels.

With 16BPP an image would take 128x160x2=40960 bytes per image which is already 35% of total RAM
This makes me think FEZ Cerberus will hardly be able to control the N18 display since we are likely to run into System.OutOfMemoryException exceptions.

Am i right?


#2

You might have to use partial Bitmaps to save memory. There are discussions here (search for SkewWorks - he also has a project called picomax that will show you how to handle that).


#3

This should help http://wiki.tinyclr.com/index.php?title=OLED_Display_Module#Using_the_display_in_a_low_memory_situation


#4

Ok, I understand how this works and am certainly willing to give it a try.

However, the function FlushRawBitmap(leftPos, topPos, rightPos, bottomPos, vram) doesn’t seem to be available for the N18 display.
Is there some way to get around this and make my own function performing the same task?


#5

Try using

public void DrawBitmapRawData(byte[] bitmapData, uint x, uint y, uint width, uint height)

#6

Allright, I took the DrawBitmapRawData() function as a start.
Since I FEZ Cerberus doesn’t support NativebitmapConverter() I skipped that part and made my own routine.
I’m posting it here, it might help others people running into this issue.


		public void DrawMyBitmap(byte R, byte G, byte B)
		{
			//Clamp RGB values
			if (R > 0x1F)
				R = 0x1F;	//5 bits red
			if (G > 0x3F)
				G = 0x3F;	//6 bits green
			if (B > 0x1F)
				B = 0x1F;	//5 bits blue

			const uint MyHeight = 40;
			byte[] data = new byte[Width * MyHeight * 2];
			for (int row = 0; row < MyHeight; row++)
			{
				for (int col = 0; col < Width; col++)
				{
					//Fill partial bitmap
					uint index = (uint) (row * Width * 2 + col * 2);
					if (index < Width * MyHeight * 2)
					{
						data[index + 0] = (byte)((R*8) + (G/8));
						data[index + 1] = (byte)((G%8) + (B/1));
					}
					else
					{
						Debug.Print("Array index overflow at data[" + index.ToString() + "]");
					}
				}
			}

			for (uint area = 0; area < 4; area++)
			{
				SetClippingArea(0, area * 40, 128, 40);
				WriteCommand(0x2C);

				DataWrite(data);
				SetClippingArea(0, 0, Width, Height);
			}
		}


Any suggestions on how to write “my own” NativeBitmapConverter for the time being?


#7

Your opening code tag is missing a bracket


#8

Hi everyone,

I hate to revive a resolved thread, but I’ve been having trouble getting the N18 to work with my Cerberus. I have downloaded the latest SDKs, flashed my Cerberus, and tried everything, including drawing a tiny bitmap, and I keep getting Out of Memory errors. I ripped out all unused references and resources; tried a retail build, and still no go. I saw a note on the codeshare indicating that the latest driver didn’t support Cerb-family boards. So… any suggestions/tips would be appreciated. Some here appear to have had success. I’d like to do the same.

Thanks


#9

PicoMax in codeshare is a good way to go. You’ll just need to write a small driver to tell it how to initialize and write to the screen. There’s an example driver in there.

It’s also going to be updated w RLP code in the next few weeks


#10

You build the display by dividing it in e.g. 8 area’s of 64 * 40 pixels.
Then write to that sub-bitmap and put that on the display.

I’ll give you an example below


	//Allocate working bitmap
	MyBitmap = new Bitmap((int)MyWidth, (int)MyHeight);
	
	void InitDisplay()
	{
		mN18Display.Reset();
		mN18Display.Initialize(nSpiClockRateKHz);
		mN18Display.EnableBacklight(true);
	}

	void DrawText()
	{
		MyBitmap.Clear();
		MyBitmap.DrawText("ABC", Font, Color, 0, 0);
		DrawArea(AreaDateValue);
		N18Display.DrawBitmapRawData(
			MyBitmap.GetBitmap(),
			0, 0,
			MyWidth, MyHeight);
	}


Good luck!


#11

Eureka! Thanks Jdv! That was the magic I was missing. It never occurred to me to use an in-memory bitmap as a means to prepare my output. You rock!


#12

@ Skewworks: I took a look at PicoMax and am excited to try and get it working with my Cerb and N18. Any tips?


#13

@ jeffvan - Take a look at the SSD1351Controller project. This is what you’ll need to copy & modify for the N18. The only thing you really need to implement is .Flush which tell it how to place the existing graphics onto this screen. I haven’t checked what controller the N18 uses but I’m sure it’s a fairly simple commandset.


#14

Hi… Finally I’m able to fill N18 display with RGB color 64x40 boxes (not 2 byte as mentioned before) and without “Out of memory”… :slight_smile: Maybe following code will be helpful to someone. BTW: Anyone knows what is the 4th byte for? I’ve expected 3 bytes… :slight_smile:


namespace GadgeteerApp1
{
    public partial class Program
    {
        byte[] data;
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            display_N18.Initialize(4000);
            display_N18.EnableBacklight(true);

            DrawMyBitmap(000, 000, 255, 64, 40);
            display_N18.DrawBitmapRawData(data, 00, 00, 64, 40);
            DrawMyBitmap(000, 255, 000, 64, 40);
            display_N18.DrawBitmapRawData(data, 64, 00, 64, 40);
            DrawMyBitmap(000, 255, 255, 64, 40);
            display_N18.DrawBitmapRawData(data, 00, 40, 64, 40);
            DrawMyBitmap(255, 000, 000, 64, 40);
            display_N18.DrawBitmapRawData(data, 64, 40, 64, 40);
            DrawMyBitmap(255, 000, 255, 64, 40);
            display_N18.DrawBitmapRawData(data, 00, 80, 64, 40);
            DrawMyBitmap(255, 255, 000, 64, 40);
            display_N18.DrawBitmapRawData(data, 64, 80, 64, 40);
            DrawMyBitmap(255, 255, 255, 64, 40);
            display_N18.DrawBitmapRawData(data, 00, 120, 64, 40);
            DrawMyBitmap(128, 128, 128, 64, 40);
            display_N18.DrawBitmapRawData(data, 64, 120, 64, 40);
        }

        public void DrawMyBitmap(byte R, byte G, byte B, int Width, int Height)
        {
            if (data==null) {
                data = new byte[Width * Height * 4];
            }

            uint index;
            int row;
            int col;

            for (row = 0; row < Height; row++)
            {
                for (col = 0; col < Width; col++)
                {
                    //Fill partial bitmap
                    index = (uint)(row * Width * 4 + col * 4);
                    if (index < Width * Height * 4)
                    {
                        data[index + 0] = R;
                        data[index + 1] = G;
                        data[index + 2] = B;
                        data[index + 3] = 0xFF;
                    }
                    else
                    {
                        Debug.Print("Array index overflow at data[" + index.ToString() + "]");
                    }
                }
            }
        }
    }
}