Hawkeye

MIOS32 Voxel Space Graphics Demo on 256x64 Graphical OLED

61 posts in this topic

here's the output from two iterations of the main character input loop:


#include font.h

character superpoint_square[] = {

	{

		.bitmap = {0xc000, 0xc000, 0xc000, 0xf800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},

		.left_shift = 0,

		.width = 5

	},

	{

		.bitmap = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},

		.left_shift = 0,

		.width = 0

	}

};

now what? :P

edit: nm, i think i got it.

Edited by ultra

Share this post


Link to post
Share on other sites

i have this working and i'm able to access .bitmap[x], .left_shift, and .width from my mios32 app. i'm assuming the next step is to make a font.c that handles drawing the font from the hex values?

should this somehow implement the standard mios32 display functions? i'm not sure if that would work because we can add parameters such as shade, position, etc, for each character or whatever we want. also i plan on making some general use meters and perhaps some other graphics. so should the standard mios32 display functions be ignored and i write my own display printing code from scratch?

ultra

Share this post


Link to post
Share on other sites

Great progress! I´d recommend to roll font.c on your own, and let it render a rectangular area to a memory buffer (like the voxel demo),

which can then be put to the screen by specialized routines written for different displays (and thus be reused by MIOS users with other graphical displays).

It is a kind of an abstraction layer - font rendering is generic, putting the rendered buffers to screen is specialized.

Possible module layout idea:

font.h/.c (generates rectangular bitmaps, ready for outputting to screen, takes a user-supplied character array pointer - to choose the font)

gfx_1322.h /.c (general purpose gfx routines for this oled, such as outputting a rectangular buffer to screen, putpixel, setpixel, line(), etc... )

Also, I´d put special things like meters, virtual "knobs" like the machinedrum display has, etc. to different modules, as they have nothing to do with a font, they can also render to rectangular buffers and the gfx_1322 routines can output them (so they can too be reused by users with other displays).

Have a great time!

Peter

Edited by Hawkeye

Share this post


Link to post
Share on other sites

so does gfx_1322 call into font.c to get the bitmap data?

here's where i'm confused:

i want to write the text "midibox" to the display, starting at x/y coordinates 16/32 with a shade of 8. i'd assume that the function would have to be specific to this display, since others might not have shades, or might even be rgb and then have a color argument.

so would my function to write text actually call into gfx_1322, like this?

print_text("midibox", 16, 32, 8);

then gfx_1322 loops through the characters, passing each one into font.c and getting back the bitmap data on a character which will then generate the 1322 specific code to write pixel/shade data to the buffer?

if this is correct, then font.c is doing nothing more than translating the hex codes into 1/0 data and returning it to gfx_1322.c for buffer and output.

Share this post


Link to post
Share on other sites

Hi there,

it is your choice, but I would recommend to have better separation, all glued together by main, to keep inter-module dependencies low:

your main.c module includes square_font.h, creates a pointer to it, includes font.h (for rendering) and gfx_1322.h (for output)

the font pointer is passed to functions in font.c, with the to-be rendered string and renders to a render buffer (with 16 shades of grey)

that buffer is then passed to gfx_1322 (or any other low-level gfx engine) to be output on the screen.

possible function calls in main.c:


u8* buf = create_buffer(256, 16); // Allocate, clear and return a 256*16 pixel square output buffer (that can hold 16 shades of grey) = 2048 bytes

character* font = &superpoint_square;

render_text(font, "midibox", 8 /* chosen brightness */, 0, 0 /* in-buffer coordinates */, buf, 256 /* buffer width */);

display_buffer_1322(0, 20 /* screen coordinates */, buf, 256, 16 /* buffer width & height */);

free_buffer(buf);

Bye,

Peter

Edited by Hawkeye

Share this post


Link to post
Share on other sites

Hi chaps,

I've bought a couple of these displays and I'm generally banging my head against the wall trying to get some initialisation code to work on them.

I'm using an Atmel AVR powered by 2.5V which is from stepped-down 5V USB. As far as I can tell my code works, and I've checked it on the scope, but I can't get anything to light up. I'm going to have a look at adding a cap and I'll report back. Essentially my mission at the moment is to write up full documentation for both initialization and the command set because frankly what's provided by Solomon and Newhaven is terrible!

Really looking forward to getting it working, though the micro only has 1K of RAM, so a 256x64 4-byte buffer is a no-no for me (I should point out I'm not involved with MIDI devices, but I really want to get this screen working and I'd be happy to share code/otherwise collaborate!)

The main problem seems to be that Newhaven have taken a completely backwards approach to interpreting the SSD1322 datasheet. The impression I got was that you provide a 3.3V line (VCI) to power the logic and then you turn on an internal 2.5V regulator (VDD). The data pins are set to VDDIO which is 0-VCI, i.e. 3.3V tolerant. So the obvious choice, to me, is to provide a 3.3V interface and regulate VDD internally. They've gone the opposite way and forced you to provide a highly stable 2.5V power signal which also means you need to provide 2.5V data lines, etc.

I'm hoping to get some sample C code working over the next couple of days, but I was annoyed enough that I designed a new backboard for the display which you can see here: http://img23.imageshack.us/img23/1598/screenshot20120412at024.png

It's an 8 pin breakout, 3V3, GND, CS, DC, CLK, SDIN, RES and 12VENABLE. There's an onboard 3.3V-12V step-up converter and you can enable the 12V line using the 12VENABLE pin - based on the datasheet, the OLED power line should be turned on after core logic. Newhaven don't seem to have bothered and it doesn't look like it makes a difference, so you could just tie it to 3V3 and have done with it. Otherwise, I think it's a lot simpler and a lot neater than their board. Not entirely finished - I need to draw up the holes for the display, but otherwise it's done. I don't think many people are interested in programming this in parallel, so I figured go for the minimal number of pins.

Best,

Josh

Edited by Josh

Share this post


Link to post
Share on other sites

Hi Josh,

Welcome to MIDIbox :)

not getting the display to "lighten up" using the default Newhaven datasheet init commands has been experienced by a few people by now - could you try the custom initialization, which I´ve written with TKs help some time ago? See APP_LCD_Init() and try the same Command/Data pairs on your display:

http://svnmios.midib...322%2Fapp_lcd.c

Regarding 2.5V on the data lines, we fed it with 3.3V accidentally for some minutes, would not fry the unit, but that may have been luck - agreed on the need for a stable 2.5V supply though (use caps to buffer).

You would not need a full video buffer for using the display, you can directly draw on the screen, as long as you can write blocks of 4 pixels (2 bytes), overwriting the background pixels on that location.

Bye and best of luck!

Peter

Edited by Hawkeye

Share this post


Link to post
Share on other sites

Ok, so after a bit of fiddling I got it working. I think the problem was with my serial code, rather than the init sequence itself. I had the clock signal with the wrong polarity (idle low rather than idle high)...

I'm running it at 3.3V with the following assumptions:

1. The data pins are 3.3V tolerant in the datasheet

2. The VCC pin on the Newhaven board simultaneously powers VDD, VDDIO and VCI

3. If you power on with 3.3V and turn on the internal 2.5V regulator (via command) for VDD, you're now essentially running the whole board (VDDIO and VCI) at 3.3V hence it's not going to damage anything. Plus, the onboard 2.5 is probably better than what we're slinging into it with cheap LDO regulators.

Anything less than this gives very flickery or dim displays. I've also got 220uF and 0.1uF capacitors in parallel to give it a bit of extra oomph. I'm not particularly concerned about the lifetime of the display, it looks rock solid with all the pixels on at 3.3V so that's where it's going to stay!

The init sequence is essentially yours, I believe, I've set the contrast to 127 after initialisation which looks nice. I've uploaded working C code. It's an extremely simple circuit, 5V USB goes to a 3.3V LDO regulator which powers both the micro and the display. The display is set up in 4-wire serial mode directly to the MOSI/SCK pins on the AVR and a couple of extra GPIOs dealing with Reset, CS and DC.

I'm going to look into getting some fonts and other bits and pieces working today.

Only one other question - high contrast causes a fair amount of banding, not sure if that's normal?

Thanks for this thread, it's a lifesaver!

Josh

oledtest.c

Edited by Josh

Share this post


Link to post
Share on other sites

Hi Josh,

great to hear that it successfully runs on 3.3V and that you can switch it to 2.5V mode - when I continue to work on it, i´d like to try that too, because it would make connecting it much easier, just as you said.

Banding may be because of the "guesswork" timing initialization - I randomly played with the values for a few hours until I got a more or less "stable" picture, could not get one with default Newhaven values.

I played around with the following seven parameters, by manipulating them via mouse on the big computer and sending them to the microcontroller via MIDI (its MIDIbox :), it was TKs idea, without him, these displays would still be dark ;-) - you can get fancy "strobe-like" effects with the right parameters, very demo-like - so if you have a means of external communication with your uC (or some on-board encoders), you could try it :)

1.

APP_LCD_Cmd(0xb3); // Set_Display_Clock(0x91);

APP_LCD_Data((u8)midi_package.value/2);

2.

APP_LCD_Cmd(0xca); // Set_Multiplex_Ratio(0x3F);

APP_LCD_Data((u8)midi_package.value/2);

3.

APP_LCD_Cmd(0xb1); // Set_Phase_Length(0xE2);

APP_LCD_Data((u8)midi_package.value/2);

4.

APP_LCD_Cmd(0xbb); // Set_Precharge_Voltage(0x1F);

APP_LCD_Data((u8)midi_package.value*2);

5.

APP_LCD_Cmd(0xb6); // Set_Precharge_Period(0x08);

APP_LCD_Data((u8)midi_package.value*2);

6.

APP_LCD_Cmd(0xbe); // Set_VCOMH(0x07);

APP_LCD_Data((u8)midi_package.value*2);

7.

APP_LCD_Cmd(0xc1); // Constrast Current

APP_LCD_Data(midi_package.value*2);

Have lots of fun with the display!

Peter

Share this post


Link to post
Share on other sites

I haven't bothered to play with the timings, but attached is my current efforts. I've got a 10 by X variable width font engine working which I'm pleased with. I had it at 8 high to begin with, but 10 lets you have hanging letters and for what I want to do I can have 5x11px rows (10+1 space) and then 9px for a status bar at the top.

Conveniently it takes almost no RAM and doesn't need much in the way of a buffer though it's just fast enough at 1MHz (fine because only a few characters change at any one time), at 8 it's more than quick. Fonts can be stored in program memory space (around 2k out of 32k for 8-bit ASCII) and the engine renders one character at a time into a 4x10 pixel block , compensates for overflow into the next block and adds an (ascii) space afterwards. It also pads up to 4 pixels on the end to ensure the entire string prints. The print string function returns an x-offset so instead of concatenating strings, you could do:


/* printstring(uint8_t * input_string , char intensity, uint8_t x, uint8_t y, uint8_t * x offset); */

printstring("ADC Value", 15,0,0,&offset);

printstring(itoa(ADC), 15, offset,0,&offset);

You might lose up to 3 pixels - as the previous string could have forced 3px of space maximum, but it's not such a big deal.

Ignore the little battery thing at the top right, I was experimenting. You can fit nearly 6 rows of text, allowing for some tails being cut off on the bottom row. The number of characters per line is variable due to the changing letter widths, but you should be able to get at least 32 full width characters worst case, and often more.

It's cool now it works, debugging programs via the screen is so much easier than simulating in Proteus and staring at logic traces!

Apologies for the blurrycam, my SLR is at home :(

post-10817-0-18967100-1335226477_thumb.j

Edited by Josh

Share this post


Link to post
Share on other sites

Great job, man! *smiles* :sorcerer:

Bye,

Peter

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now