goeck Posted July 29, 2013 Report Share Posted July 29, 2013 Hey everyoneI am happy to release my first version of a SSD1306 display driver with nice smooth scrolling.I packed everything together and uploaded it with this post. It was developed using the 1,3" OLED board by adafruit hooked up over I2C.Notes:- Driver works only with SSD1306 hooked up over I2C (at least SPI lld needs to be added)- Driver is written for 128x64 pixel displays (128x32 are only partly suppoerted and need small further work)- after using GFX subsystem gdisp_lld_diaply() hast to be called "by hand" to push over framebuffer to display- for nice scrolling GWIN_CONSOLE_USE_CLEAR_LINES has to be set to FALSE in file console.cPlease someone give it a try.CheersStefanSSD1306.zip Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted July 30, 2013 Report Share Posted July 30, 2013 Hello goeck,Thank you very much for sharing you driver. I took a look and these are the points I have to mention: I see that you have the ChibiOS/RT logo in the framebuffer per default. Since this project is now completely separated from ChibiOS, it's a big no-go. I recommend you using an empty frame buffer. In the source file, what is this?/* Fulfill Adafruit license.*/gfxSleepMilliseconds(1000);The driver source must be as generic as possible and really just LCD controller dependent - not LCD panel or LCD module (adafruit) dependent. In the source file, after the scroll implementation which ends at line 534, you start giving an interface to control several things such as the LCD controllers power states and start addresses. These are things that need to be declared as static and only usable inside your drivers source file. Things like backlight and contrast changes are meant to be made through the gdisp_lld_control() routine. Here's an example.I'd recommend to name the BLACK and WHITE macros in the SSD1306.h a different way, such as SSD1306_BLACK and SSD1306_WHITE so there are no confusions between the rest of the library.The board file mess has been cleaned up in the meantime. All the #ifdef stuff in line 43 of the source file became obsolet. It's now appropriate to just #include gdisp_lld_board.g there.Beside these things, your driver works seems to be very solid and consistent. Good work!~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted July 30, 2013 Author Report Share Posted July 30, 2013 Hey,thanks for the feedback. Though I was kind of wondering, what semed to have been happening after I started developing the driver. I just took the templates from that time and worked upon them..anyway, I guess I now have changed almost everything accordingly but left the most stuff undone in gdisp_lld_control for now.CheersStefanSSD1306.zip Link to comment Share on other sites More sharing options...
Marco Posted July 30, 2013 Report Share Posted July 30, 2013 Nice work!I ordered 5 ssd1306 oled displays a few days ago I'll try the driver asap when they arrive.Do you plan to implement SPI support in the short term?Marco Link to comment Share on other sites More sharing options...
goeck Posted July 30, 2013 Author Report Share Posted July 30, 2013 I guess adding SPI support shouldn't be that much of an issue. I will do some untested coding, since I don't actually want to rewire my board. But maybe I even do this, because update rates can be much higher using SPI (at least tons of youtube videos point that way)._____________________________________EDIT 1: I just hacked a little and we some support for SPI now, please give it a try. I didn't test it, as I would have to reassemble the wiring then.CheersSSD1306.zip Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted July 31, 2013 Report Share Posted July 31, 2013 I am sorry that this takes so long... I will do this tomorrow, promised! I am currently very busy with real life issues.~ Tectu Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted August 2, 2013 Report Share Posted August 2, 2013 Okay, I finally got the time to look at your new driver. It looks a lot better now! There's only one more thing: Could you please split the I²C and SPI interface into two separate board files named gdisp_lld_board_example_spi.h and gdisp_lld_board_example_i2c.h? If you don't want to waste your time with that, I can do it as soon as I add the driver to the repository.Keep going the good work!~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted August 5, 2013 Author Report Share Posted August 5, 2013 Oh, sorry...I am in some kind of vacation state since Friday actually.I could for sure do that split, but not earlier than in two weeks when beeing back in office.I didn't know about the physical layer extraction into board files, that's why I did it with the PHY_LAYER_xxx define.So that's not needed anymore, How exactly am I gonna do it now?Two board files one assuming SPI is used and one assuming I2C is used, right?Thanks for the hints!CheersStefan Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted August 5, 2013 Report Share Posted August 5, 2013 Two board files one assuming SPI is used and one assuming I2C is used, right?Yes, that's completely right. I will do it and add the driver with the new files. As soon as you are back, you can try the driver and tell me if everything works properly.Enjoy your vacation!~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted August 5, 2013 Author Report Share Posted August 5, 2013 Awesome.Honestky, Tectu, If you have those days left in schedule for uGFX I will do that when beeing back from vacation. I guess you have some stuff left to do...Give me a shout.Cheers Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted August 5, 2013 Report Share Posted August 5, 2013 Sure, sounds good to me. I can wait ~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted August 21, 2013 Author Report Share Posted August 21, 2013 OK, here we go. After fiddeling with the code for a while I created those two board files for SPI and I2C communication with the display and washed out some bugs.Please have a look at it.SSD1306.zip Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted August 21, 2013 Report Share Posted August 21, 2013 Thank you for sharing. I'm sorry but I won't have time before the weekend to check on this.I'll keep you posted.~ Tectu Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted August 25, 2013 Report Share Posted August 25, 2013 Hey man, sorry that this took a bit longer than expected but I finally found time to include it into the repo.It looks good to me so far. Can you please get the latest master and try to use the implemented driver?You may want to tell me your real name for the contributors table.~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted October 17, 2013 Author Report Share Posted October 17, 2013 Hey everyone,I have tuned the driver a little more. This is the small changelog:+ added a thread priority lift for the time data gets stuffed into the display, thus updating display goes faster and looks smoother * now spi and i2c init are done after the pads functions are setHope this makes it into trunk.CheersgoeckSSD1306.rar Link to comment Share on other sites More sharing options...
inmarket Posted October 24, 2013 Report Share Posted October 24, 2013 I have integrated the changes into the GDISPStreaming branch of development (which will soon become version 2.0 of uGFX).There has been significant changes to the GDISP low level driver interface to enable some major new features such as support for multiple displays, a formal gdispFlush() call and even automatic flushing.Can you please test the GDISPStreaming branch for your controller as I don't have equivalent hardware myself.One change you will need to be aware of is that the gdisp_lld_board.h in your project directory should now be called board_SSD1306.h. The interface has also changed so start from one of the template ones provided.Thanks for your contribution. It is appreciated.I also notice that you have started adding a GTimer to your code (although it does nothing yet). I presume this is so you could do flushing using the timer. I really like the idea and now that flushing is officially supported by the new GDISP framework, I think I will add that concept to the framework itself so it can be used by any driver that needs flushing. Link to comment Share on other sites More sharing options...
goeck Posted October 24, 2013 Author Report Share Posted October 24, 2013 Hey,I just took some time to test the new adapted driver and found some issues. It's not working properly because the write_data() implementation has a bug.The display wants to receive one data stream without interruption (i2c Stop condition followed by a new i2c start condition) beginning with DATA indicating start byte and the next consequently following bytes shall be the frame buffer content in x-many pieces.So it has to look like this, this actually works fine.static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {// uint8_t command[1]; (void) g;//// command[0] = 0x40; // Co = 0, D/C = 1//// i2cStart(&I2CD1, &i2cconfig);// i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 1, NULL, 0, MS2ST(10));// i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, data, length, NULL, 0 , MS2ST(10));// i2cStop(&I2CD1); uint8_t command[length+1], txLength = length+1; command[0] = 0x40; // Co = 0, D/C = 1 memmove(&command[1], data, length); i2cStart(&I2CD1, &i2cconfig); i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, txLength, NULL, 0, MS2ST(10)); i2cStop(&I2CD1);}The point is, how to make this more memory optimized, so to append the 0x40 at the beginning. This would mess up the data array if we don't do a temp. copy to work on. All that is needed here, is a way to control the sending of an i2c start/stop condition with hte higl level i2c driver.By now, that's the best and most simple way to do it.Another thing is. I tried to implement native scrolling on top, I activated GDISP_NEED_SCROLL but the scrolling routine doesn't get called. Keep it up.cheersStefan Link to comment Share on other sites More sharing options...
inmarket Posted October 25, 2013 Report Share Posted October 25, 2013 Thanks for the testing.I thought that might be the case with the board file.Does that also apply to the spi interface?I will see if I find another way of including the extra byte as it seems a shame to allocate a whole new buffer and copy the line particularly as stack seems to be a critical resource for most processors. I should have the fix up later today.The GDISP_NEED_SCROLL turns on the gdispVerticalScroll() function - in other words the GDISP API for scrolling. GDISP_HARDWARE_SCROLL says that the controller supports hardware accelerated scrolling. Note with the new code that GDISP_NEED_SCROLL now works even if there is no hardware support for scrolling provided the low level driver provides a read pixel routine (and yours does).With the new code, provided there is a read pixel routine (which there is for your driver) you don't need to specifically implement a scrolling routine any more as the high level code will do it for you.If you want to define a hardware accelerated version you need to specify GDISP_HARDWARE_SCROLL in the gdisp_lld_config.h file for the driver. Note that most controllers only support full screen width scrolling which is not sufficient to support the GDISP vertical scroll method. I think I glanced at the datasheet for your controller and that was the case for the SSD1306 as well (although don't quote me on that - you know the controller much better than I) and if so then the only possible implementation is via the high level code using the read pixel routine.This was actually why I added the vertical scroll handling to the higher level code - it is a common operation but few controllers seem to support a variable width vertical scroll natively. Link to comment Share on other sites More sharing options...
inmarket Posted October 25, 2013 Report Share Posted October 25, 2013 The issue with the command byte has now been fixed.Have a look at the updated code as I found a way of doing it without copying the data onto the stack.The overhead is one byte of RAM per page line (8 bytes total).Can you also please test again. Link to comment Share on other sites More sharing options...
goeck Posted October 25, 2013 Author Report Share Posted October 25, 2013 Hey,I have not had the chance to test the fix. I have some weird hardware flaws since today in my testing system. I can't get it to work until Monday unfortunately.Actually you're just right. It's mess with the temp. buffer, but sending (at least over I2C) in more packets takes more time to transmit the whole frame buffer. That's why I tried to send in as few packages as possible which has shown to be two transmissions each containing half of the frame buffer. I like thy slick way you took a chance on that problem though *thumbs up*When I have the chance to view this with my saleae logic I'll post some performance infos about that topic.Maybe it's the best tradeoff between performance and memory optimization anyways.I'll keep you posted.Cheers Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted October 26, 2013 Report Share Posted October 26, 2013 I took a quick look at the board_SSD1306_spi.h file of the current GDISPStreaming branch:static const SPIConfig spi1config = { NULL, /* HW dependent part.*/ SSD1306_MISO_PORT, SSD1306_MISO_PIN, 0 //SPI_CR1_BR_0};This is actually the CS, not the MISO port and pin.I don't want to touch file in case of inmarket is still working on it - could you please fix this as well?Also note that there's a missing (void)g; in the write_cmd() call.~ Tectu Link to comment Share on other sites More sharing options...
goeck Posted November 5, 2013 Author Report Share Posted November 5, 2013 Hey everyone,No after some days of bedtime due to a heavy cold, I was able to fix my hardware issue and test the memory-fixed SSD1306 driver, which worked like a charm (except scrolling was done in software).Now I updated my local repository clone and found the old code within the driver. Could you, inmarket, please update the branch with the memory size oriented improvements you made? Then I was able to retest this and implement the scrolling again.CheersStefan Link to comment Share on other sites More sharing options...
inmarket Posted November 6, 2013 Report Share Posted November 6, 2013 The master branch is at a point where we have locked it off and stopped making any changes. We are about a week away from merging the GDISPStreaming branch into the master and releasing it as v2.0. The code in the GDISPStreaming branch is ready to go now - Tectu is just busy this week and he needs a bit of time to write release documents and update the website to match.If you have any updates and changes relative to the GDISPStreaming branch I will be happy to incorporate them.I am guessing from your previous post that there are a few changes to be made relative to the spi board file in the GDISPStreaming branch. Can you please post the updated SPI board file and I will integrate it immediately.Note the location for the example board files has now changed. They are now stored in the boards/addons/gdisp directory if they are not specific to a particular base board.Thanks for your work. It is very much appreciated. Link to comment Share on other sites More sharing options...
goeck Posted November 6, 2013 Author Report Share Posted November 6, 2013 OH, now I know what happened. I had a SSD1306_board.h file left in the drivers source folder, where in the GDISPStreaming branch all those board files have been moved, as you just said. I guess I still had it in the editor and accidently saved in nack to the location where it originally was loaded from. There was some older code in it.Now, in the boards/addons/gdisp folder the code is the latest, the version that I just tested as good. So, after trying to compile the latest version in GDISPStreaming I get a compiler error in gdisp_lld_SSD1306.c, the board file is not found.fatal error: board_SSD1306.h: No such file or directoryAlso, I am a little stuck. How can I implement vertical scrolling again. Adding a gdisp_lld_vertical_scroll() doesn't change anything. Please, I need a quick advice on this topic.EDIT: OK, I just had to add GDISP_HARDWARE_SCROLL TRUE to gdisp_lld_config.h to let uGFX run into that function. No I am getting that guy...EDIT 2: Almost there, the only issue that I'm having is: it looks like scrolling only happens if the page is fully written, not after each line has been written, so that I could scroll one line up. That's how my scrolling routine is written ( i use g->p.y1 to grab y height which is to be scroll up).EDIT3: OK, done. That was because I didn't call the flushing routine but just set the need_flush flag. So scrolling was done but the display would just have been updated after "a while"... No that's through.Here's my working implementation (part of gdisp_lld_SSD1306.c) of scrolling for the v2.0 GDISPStreaming branch (Can't push a pull request since I don't have a bitbucket account)#if GDISP_NEED_SCROLL /** * @brief Scroll vertically a section of the screen. * @note Optional. * @note If x,y + cx,cy is off the screen, the result is undefined. * @note If lines is >= cy, it is equivalent to a area fill with bgcolor. * * @param[in] x, y The start of the area to be scrolled * @param[in] cx, cy The size of the area to be scrolled * @param[in] lines The number of lines to scroll (Can be positive or negative) * @param[in] bgcolor The color to fill the newly exposed area. * * @notapi */ LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) { #ifdef GFX_USE_OS_CHIBIOS int32_t thdPriority = (int32_t)chThdGetPriority(); chThdSetPriority(HIGHPRIO); #endif /* See datasheet table T10-1 for this*/ uint8_t fHeight = g->p.y1; write_cmd2(g, SSD1306_SETDISPLAYOFFSET, fHeight-2); write_cmd2(g, SSD1306_SETMULTIPLEX, (GDISP_SCREEN_HEIGHT - fHeight+1)); /* Scrolling animation.*/ for(int i=0; i write_cmd(g, SSD1306_SETSTARTLINE | i); gfxSleepMilliseconds(20); } /* Shift buffer up a font line.*/ for (int i = 0; i < SSD1306_PAGE_WIDTH*(GDISP_SCREEN_HEIGHT/8-1); i++) { if(i % SSD1306_PAGE_WIDTH){ RAM(g)[i] = RAM(g)[i+SSD1306_PAGE_WIDTH*(fHeight/8)] >> fHeight % 8; RAM(g)[i] |= RAM(g)[i+SSD1306_PAGE_WIDTH*(fHeight/8 + 1)] << (8 - fHeight%8); } } /* Clear second last page.*/ for(uint8_t i=0; i<2; i++) memset( RAM(g) + (GDISP_SCREEN_HEIGHT/8 -1)*SSD1306_PAGE_WIDTH - GDISP_SCREEN_WIDTH, 0, GDISP_SCREEN_WIDTH); #ifdef GFX_USE_OS_CHIBIOS chThdSetPriority(thdPriority); #endif /* Update display.*/ gdisp_lld_flush(g); }#endif // GDISP_NEED_SCROLL Link to comment Share on other sites More sharing options...
goeck Posted November 7, 2013 Author Report Share Posted November 7, 2013 OK, here we go.I did change to SPI and made the SPI board working. It's blazing fast, but some scrolling artefacts are not affected by this improvements. I was hoping to get rid of those two flicks every time a line gets scrolled by doing faster communication.Anyway, I hereby have the spi board file and the tweaked "main" file gdisp_lld_SSD1360.cMaybe it's not yet to late to incorporate this in v2.0.CheersStefanCan't upload files?!I have therefor set up an repository on Github, which is my fav. GIT hoster. Please have a look at https://github.com/goeck/SSD1306/ . Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now