ReservedField/evic-sdk

Issue with examples/helloworld

Closed this issue · 27 comments

Hardware version: 1.02

Tried flashing the example/helloworld with the correct display drivers (SSD1327). Instead of seeing "Hello, world!" I got this.

Any ideas?

I've got the same. I believe that the SSD1327 driver is generally OK. It sets up correctly, command sending etc works.

I believe the problem is related to the bitmap/framebuffer format and how this is parsed&sent to the display. However, I didn't look any further, as there's some discussion regarding the framebuffer format over at #2

I'm working on changing the framebuffer format and refactoring some display code. As soon as I finish I'll commit it so you can test it. I don't have an SSD1327 eVic to test on, but hopefully after those changes we'll have a stabler base to fix this bug.

Sounds good!

Ban3 commented

This is what I get with SSD1327, HW 1.06 and TODO_DATAFLAG = 1.

The mess you get is definitely the remappings not being set up correctly. The HW version you have might require different settings or it could be a timing issue.

Ban3 commented

I'll add that TODO_DATAFLAG set to 0 won't work with the current framebuffer format. I left it pretty much default so it won't enable the needed vertical remap.

The TODO_DATAFLAG maps the beginning of GDDRAM (origin) to the bottom-right
corner. In fact, I swapped the behaviour of TODO_DATAFLAG in the code I'm
working on to get the common (0,0) at top-left. I suspect some units have
the screen mounted upside down so Joyetech introduced the flag. I assumed
@RichusX already tried to change the TODO_DATAFLAG. Did you?

@ReservedField Yes, same result. I'll give it another go though.
EDIT: Yeah, same result.

I just committed some framebuffer changes and font support. Could you try with the latest SDK and helloworld?

@ReservedField Still broken, just different kind of broken http://i.imgur.com/FOBeGmv.jpg

Dataflash support is in, try with the latest commit but I don't think it will solve the problem. You may have to wait for someone with your same display, as I have an SSD1306.

Fair enough, I'll give it a go anyways (edit: still borked)

I have the same problem. Could you please describe the framebuffer format some more? The 0x40 and 0x10 confuses me (is it something specific to the 1306)?

I do understand how to put pixels on the SSD1327 at the coordinates I want, but I don't understand how to parse the framebuf[] array contents to figure out which color a (x,y) coordinate should have. Once I understand this part, I can probably get the code to work properly (at the very least on my device)

I'll add it to the docs, but anyway. The framebuffer is divided into 16 pages. Each page is 64 bytes. The pages are contiguous in the framebuffer (i.e., the address of the start of page N is framebuffer + (N * 0x40), where N is 0-15). Each page is a horizontal row, with an height of 8 pixels and a width of 64 pixels (i.e, it spans the whole screen width). As you might guess, that means it's encoding 8 pixels per byte. The pages are ordered from top to bottom of the screen (imagine slicing it horizontally every 8 pixels).
Each byte encodes a column of 8 pixels. The most significant bit encodes the topmost pixel in the column, the others follow. If the bit is 1, the pixel is on, if it is 0, the pixel is off.
It seems complex, but 1) it is the native format of SSD1306 in column-major mode so it works well for it, but most importantly 2) the tool I use to generate font bitmaps outputs this format and I don't have time to dig in C# code to change it.
In SSD1327 you have 4 bits per pixel because it's grayscale (while the SSD1306 is black/white), so the controller can PWM the OLED display to vary the brightness. We don't need that, so 0x0 (off) is used for pixel off and 0xF (maximum) for pixel on. The SSD1327_Update has to do the conversion. The code works for @Ban3, though, so maybe adding a define/flag is in order.

By the way, now that dataflash support is in LCD_TYPE and TODO_DATAFLAG do not exist anymore. You shouldn't need to change the display type unless something terribly wrong is going on with your hardware version (in any case, it's in src/dataflash/Dataflash.c). The TODO_DATAFLAG has been replaced by the flipDisplay field of the dataflash info. If you want to play with that, just change the if in Display_SSD1327_Init.

I recently merged @Ban3's pull request that should fix this issue. @RichusX @stefan-cornelius could you please pull, rebuild and check?

@ReservedField Just did what you said (cloned, rebuilt & tested) and still broken. 😢

P.S. How do you de-compile official firmware?

For the record, I have hardware version 1.03. As far as I can tell, throughout all the patches, I only ever had garbage. I've tried all sorts of display remap combinations last night, but nothing really kicked in. What I currently suspect is that the display simply refuses to do proper vertical mode. However, I forgot to take proper notes and now I'm more confused than ever sigh

I need to let this settle for a couple hours, and then try again using a more scientific method.

I found a couple things that may have something to do with this.
First, a two-byte command from the original init (set phase length) is missing. Second, the timer module is not working properly (doesn't delay at all, found out while writing some code that used delays).
I'll add the command and work around the timer with a systick delay. Should commit shortly.

@RichusX About reversing: decrypt the firmware with python-evic and you have the raw ROM image. It's an ARM Cortex-M4, so little-endian thumb. I use IDA + Hex-Rays decompiler. Have the M451 datasheet ready for memory maps, and the SDK for library functions and code reused from examples.

Commit 3e13e30 is in and fixes the timing bug and the missing command. Try it out.
Please try filling up the top-left quarter of the screen with zeroes and snapping a photo of the result. Just change the PutText line in the helloworld to:

Display_PutText(0, 0, "0000\n0000\n0000\n0000", FONT_DEJAVU_8PT);

This should help me visualize what's wrong there.

commit 3e13e30 fixed it for me. Thank you, that's awesome!

Ban3 commented

Confirmed still working with 1.06. I see I trusted timer module too much :)

@stefan-cornelius That's great! Could I ask you for a favour? I'm trying to isolate what the problem was, for reference. So If you could run a couple test it'd be great. First, open src/display/Display_SSD1327.c and comment out line 45:

SSD1327_SET_PHASE_LENGTH, 0x31

Rebuild SDK & helloworld, test. Then, uncomment that line to restore it back to the original status, and go to src/timer/Timer.c. Replace line 24:

CLK_SysTickDelay(delay);

With:

TIMER_Delay(TIMER0, delay);

Rebuild SDK & helloworld, test. Then restore the timer code back to original.
What are the results? I'm trying to understand if the culprit was the missing command, the timer, or a combination of both.

@Ban3 I trusted it, too. I guess SSD1306 is more tolerant on bad timing. If it was a timing issue, maybe it can solve the problems you were experiencing with battery?

src/display/Display_SSD1327.c and comment out line 45: does not work at all, display remains black

src/timer/Timer.c. Replace line 24: garbage on display

So, it really was a combination of both. What a nasty issue to debug ... I'm impressed that you figured this out "from remote".

Ban3 commented

@ReservedField It most likely should. I was only able to hit the bug once and only with a battery. The workaround should not be needed anymore and I removed it in 8a26d27

Works like a charm now!

Great. The garbage you were seeing was because of the timing bug. If that was solved, you would have had black screen, which usually means bad init.
The garbage you were seeing did not resemble any graphic elements, so I had the feeling it was a problem with reset and not a mapping issue. Then yesterday I had strange behaviour when using the timer, so I gave it a better look. Trust me, getting the helloworld to work for the first time (completely blind) was much worse :P
Now that @RichusX confirmed it's working, I'm closing this.