Where is the Util code for GHI.OSHW.Hardware?

I have the SDK source code downloaded, but I cannot find the code for Util.

Specifically, I am trying to look at the code for Util.SetSpecialDisplayConfig(

to see how it works and why I cannot get it to work.

I have the Cerb with the N18. I can Rotate the display but it cuts off a section of the display and wraps around even though it has more screen. It work if I just want to invert the display. If I send the raw commands to the display I can get it to write the image upsidedown or normally but if I try to rotate the display 90deg the screen remains black.

Also, why is is so hard just to rotate the display?

No, I am actually looking for the source code for the library as I am troubleshooting a problem I am having.

Look at the photo I posted. Anyhow, OSHW part of the library name stands for Open Source HardWare… I think. If they won’t share the source how can it be called open source?

As for “OSHW!=OSSW” That’s the dumbest thing I’ve heard in a while. What’s open about it if the source is closed? Who hears “open source” and thinks proprietary source code?

Anyways that image shows the issue the display is cropped. There are 3 draw commands on that picture using the n18 simplegraphics. Draw gray rect. Text over. Blue text. The gray react should span the display. Instead it is wrapped at the width…

Ha… You mean i should start writing you before I reply!

Also if you want you can call me Temper or Jason. Jason’s my real name…

Just in case, here is the source https://ghiopensource.codeplex.com/SourceControl/latest
Device > GHI > Libraries > GHI.OSWH.Hardware

1 Like

HAHA, I guess I am still falling down the rabbit hole.

This is all I found:

//This function is defined in each device’s display driver. If it does not support special display configurations, return false.

INT8 LCD_SetSpecialConfig(INT32 key, INT32 value);

INT8 Util::SetSpecialDisplayConfig(INT32 key, INT32 value, HRESULT &hr)
return LCD_SetSpecialConfig(key, value);

So where is it sourcing the LCD_SetSpecial Config?

Also, why is the code dispersed into all these modules? Why isn’t all this stuff just contained in the one driver for the LCD?

@ Tempered Enterprises

The code for LCD_SetSpecialConfig is device specific, so the actual implementation of the function is in the board specific code. Using Find In Files, I found two occurrences of LCD_SetSpecialConfig one in the STM32F4 port and the other in the AT91 port.


When navigating the Porting kit and the specific ports, Find In Files is your friend.


was clearly what I was looking for. I don’t see any reason, however, the device would draw the correct orient, draw 3/4 way down the screen, then stop, go to the start of the lcd and draw the remainder of the screen. Also, I am guessing to play with this code you would have to compile the firmware and then download that. It seems all beyond what I am capable of doing…

Can anyone at GHI just plug in a Cerb+N18 and rotate the display 90 deg clockwise for a horizontal display?

Because I cannot get this to work.

Here’s the perfect opportunity to show a code snippet and picture of what occurs (and a description of what you expect to occur) so anyone can test the same for you…

HA. I posted an image first post. And the WHOLE project source is on code share!

I would say that what I am trying to do is really really REALLY simple.

Think LCD.
Think LCD rotated to the right/left. (landscape mode as it were…)
Think text in that orientation so you can read it.


The example there explicitly shows a way to handle a bitmap. I think the approach you’re going to need to take is to render your text onto a bitmap and then display it, I don’t think the other methods will work explicitly with text onto a rotated bitmap. Someone from GHI might be able to show some demo code for that?

It doesn’t show how to rotate the bitmap. In fact, it doesn’t show you how to rotate the screen. There is just some vague mention of Util.SetSpecialDisplayConfig. Which you do not have access to the first parameter unless you get the n18 code. Then it doesn’t work. Or at least I cannot get it to.

Besides, I am using a display_N18.SimpleGraphics.Draw* functions. All these functions do are wrap the bitmap library draw functions to a class instance of “bitmap” and then automatically draw the bitmap to the screen. AKA the same thing you just recommended that I do.


If you are not going to talk about how to do that - please do not litter my thread.

Think N18 display in LANDSCAPE mode. That means that the display is wider than it is tall. It would also help if you bothered following the already littered thread and LOOKED at the image I posted of where I am. It is drawing in landscape mode but AGAIN for some unknown reason while it is rendering the image 3/4 of the way rendering the screen is stops and starts at the beginning and renders over the top of another area.

So if I printf(“A Big Message!!!”); The display would show:

“age!!!g Mess”[left over space here!]

Look here is a video. It is hard to see that it is actually overwriting it except the “f” in “asdf” is over wrote.

Every second, the device should add one to x and then print out "Test: {x}"
in front/on top of a gray box that spans the entire top of the screen.

[Test: {x} ]


You love my ascii art huh?

What is also disconcerting is the approach they took drawing the display.

The display is actually this one:

which has all it’s source here:

which include examples on how to rotate the display using hardware…
#define MADCTL_MY 0x80
#define MADCTL_MX 0x40
#define MADCTL_MV 0x20
#define MADCTL_ML 0x10
#define MADCTL_RGB 0x00
#define MADCTL_BGR 0x08
#define MADCTL_MH 0x04

void Adafruit_ST7735::setRotation(uint8_t m) {

rotation = m % 4; // can’t be higher than 3
switch (rotation) {
case 0:
if (tabcolor == INITR_BLACKTAB) {
} else {
_width = ST7735_TFTWIDTH;
_height = ST7735_TFTHEIGHT;
case 1:
if (tabcolor == INITR_BLACKTAB) {
} else {
_width = ST7735_TFTHEIGHT;
_height = ST7735_TFTWIDTH;
case 2:
if (tabcolor == INITR_BLACKTAB) {
} else {
_width = ST7735_TFTWIDTH;
_height = ST7735_TFTHEIGHT;
case 3:
if (tabcolor == INITR_BLACKTAB) {
} else {
_width = ST7735_TFTHEIGHT;
_height = ST7735_TFTWIDTH;

void Adafruit_ST7735::invertDisplay(boolean i) {
writecommand(i ? ST7735_INVON : ST7735_INVOFF);

So why is the code muxing bytes to draw the screen when it could just send SPI commands and then block move the data?

void LCD_BitBltEx(int srcX, int srcY, int width, int height, UINT32 data[])

UINT8* u8 = (UINT8*)data;
UINT16* u16 = (UINT16*)data;

int orientation = g_SpecialDisplayConfigOrientation;
int countI, startI, stepI, countJ, startJ, stepJ;
UINT16 windowX, windowY, windowWidth, windowHeight;
int a, b, i, j, *x, *y;

//To align the GameO's orientation with the N18 so they can share the same parameter setup.
if (g_SpecialDisplayConfigType == GAMEO)
	orientation = (orientation + 3) % 4;

if (orientation == ORIENTATION_ROT_0)
	windowX = srcX; windowY = srcY; windowWidth = width; windowHeight = height;
	countI = height; startI = srcY; stepI = 1;
	countJ = width; startJ = srcX; stepJ = 1;
	x = &j; y = &i;
else if (orientation == ORIENTATION_ROT_90)
	windowX = srcY; windowY = LCD_GetWidth() - srcX - width; windowWidth = height; windowHeight = width;
	countI = width; startI = srcX + width - 1; stepI = -1;
	countJ = height; startJ = srcY; stepJ = 1;
	x = &i; y = &j;
else if (orientation == ORIENTATION_ROT_180)
	windowX = LCD_GetWidth() - srcX - width; windowY = LCD_GetHeight() - srcY - height; windowWidth = width; windowHeight = height;
	countI = height; startI = srcY + height - 1; stepI = -1;
	countJ = width; startJ = srcX + width - 1; stepJ = -1;
	x = &j; y = &i;
else if (orientation == ORIENTATION_ROT_270)
	windowX = LCD_GetHeight() - srcY - height; windowY = srcX; windowWidth = height; windowHeight = width;
	countI = width; startI = srcX; stepI = 1;
	countJ = height; startJ = srcY + height - 1; stepJ = -1;
	x = &i; y = &j;

if (g_SpecialDisplayConfigType == N18)
	for (int i = 0; i < LCD_GetWidth() * LCD_GetHeight() * 2; i += 2)
		Swap(u8 + i, u8 + i + 1);
	SetN18DrawWindow(windowX, windowY, windowWidth, windowHeight);
	//Shortcut for data that can be written straight out as is for maximum performance
	if (srcX == 0 && srcY == 0 && width == LCD_GetWidth() && height == LCD_GetHeight() && g_SpecialDisplayConfigOrientation == ORIENTATION_ROT_0)
		CPU_SPI_nWrite8_nRead8(g_SpecialDisplayConfigSPI, u8, LCD_GetWidth() * LCD_GetHeight() * 2, NULL, 0, 0);
		for (a = 0, i = startI; a < countI; a++, i += stepI)
			for (b = 0, j = startJ; b < countJ; b++, j += stepJ)
				CPU_SPI_nWrite8_nRead8(g_SpecialDisplayConfigSPI, u8 + *y * LCD_GetWidth() * 2 + *x * 2, 2, NULL, 0, 0);
	for (int i = 0; i < (LCD_GetWidth() * LCD_GetHeight() * 2); i += 2)
		Swap(u8 + i, u8 + i + 1);


I know this works because I can invert the screen by using SPI WriteCommand/WriteData combos.

But again, none of this helps me with landscape mode. And I do not care about performance. I am just trying to make a menu w/ settings and such.

When I said it shows how to handle a bitmap, I meant in small pieces. Memory is tight, bitmaps are large, it’s a Cerb… but yes, it does not try to rotate it.

I totally agree with you, a simple example of using the rotation the way GHI envisaged it would be great.

Sorry if you think I’m littering your thread. Leaving you to it now.

Well, I guess I am not smart enough to figure out how to rotate it in pieces. It does have room for 1 bitmap the size of the display. Like it said, the simplegraphics.draw* commands use a class with a class variable of bitmap the size of the display. Unfortunately to rotate a image, you need 2 bitmaps.

Well, if you read my last post, you will see the device itself support rotation commands. All you have to do is have the width and height correct. You can also see in the code, that on landscape they set the width to the height & vv.

Well, I dunno if you really did anything. It was already littered. It just get frustrating when it seems like people are telling you stuff you already know.

If you look at the video, you can clearly see i have had success rotating the image. just not displaying it… :slight_smile:

@ TemperedEnterprises

I just posted an example library on codeshare that shows how to use the rotation functionality on the Cerberus: https://www.ghielectronics.com/community/codeshare/entry/837

The next SDK will also have improved functionality around writing to the display over SPI when rotated. It no longer flushes the bytes in pieces, though it still does if flushing partial images.