Menu

Update to SDD1306 and SH1106 GLCD Driver

Anobium
2017-08-20
2023-04-15
1 2 > >> (Page 1 of 2)
  • Anobium

    Anobium - 2017-08-20

    Joseph Realmuto and I have just updated the SSD1306 and the SH1106 GLCD library to improve performance and to support microcontrollers with limited memory.

    Background

    The SSD1306 and the SH1106 are single-chip CMOS OLED/PLED drivers with controllers for organic / polymer light emitting diode dot-matrix graphic display system. It consists of 128 segments and 64 commons. These IC's are designed for Common Cathode type OLED panel.

    The Great Cow BASIC support is for SPI (SDD1306 only) and I2C hardware & software connectivity. These libraries supports 128 * 64 pixels or 128 * 32 pixels. The default is 128 * 64 pixels.

    Problem.....

    The key problem we needed to address... low memory microcontroller devices. The existing driver requires a buffer of 128 bytes and therefore this excluded many, many microcontroller devices.

    Solution

    We have implemented two new methods to use these display. These are additive to the existing GLCD methods.

    For High memory microcontrollers we now support
    1. Full GLCD Mode: 1024 byte buffer, Random Access, full capabilities [default GLCD mode of operation]
    2. Low GLCD Mode: 128 byte buffer, Write only, page control, constrained capabilities
    3. Text only

    For Low memory microcontroller we now support
    1. Low GLCD Mode: 128 byte buffer, Write only, page control, constrained capabilities
    2. Text only [default GLCD mode of operation]

    Usage

    Full GLCD Mode: As this is the existing usage method - no changes.
    Low GLCD Mode: You must specify a define and enable the new GLCD transaction methods. For High memory microcontrollers you must also specify an additional define.
    Text only. The default for low memory devices, so, no define is required. For High memory microcontrollers you must also specify a define.

    Example Full GLCD Mode

    See the manual.... nothing changed!

    Example Text Mode

    I will explain the Text Mode first as this sets the scene with respect to the page numbering scheme of the GLCD devices.

    Assuming you have a low memory device. Initialise the GLCD as normal. The default operation is text mode only so you can only use character commands such as GLCDPRINT

          GLCDPrint 1, 0, "Meter"
          GLCDPrint 1, 8, "Meter" ;Device Page = Ypos of 8 / 8 (constant factor) = page 1.
    

    The Y position stated in the GLCD commands will be mapped to the GLCD page. Pages are numbered 0 to 7. So, a Y position between 0-7 is mapped to page 0 or row 0 of the GLCD device.a Y position between 8-15 is mapped to page 1 or row 1 of the GLCD device. Essentially, page number = INT(Y position / 8 ).

    You have control the X of the text position as normally.

    To enable this text mode on a high memory device add the following to your user program.
    only.

    #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    

    Example Low GLCD Mode

    Assuming you have a low memory device. Initialise the GLCD as normal. The default operation is text mode only so you can only use character commands such as GLCDPRINT. To enable Low GLCD Mode add the following to your program.

    #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    

    To use Low Memory GLCD use all the normal GLCD (except ReadPixelStatus) but you need to enable the GLCD Transactions. As follows:

      GLCD_Open_PageTransaction 0,7
          GLCDPrint 1, 0, "Great Cow BASIC"
          GLCDPrint 1, 8, "Meter"
          Line 0, 0, 127, 63
          Line 127, 0, 0, 63
      GLCD_Close_PageTransaction
    

    GLCD_Open_PageTransaction and GLCD_Close_PageTransaction as required to update the device. The two parameters on GLCD_Open_PageTransaction are the device pages you wish to update. Calling 0, 7 will update the complete screen. There are excellent use cases for not updating every device page.

    Everything between GLCD_Open_PageTransaction and GLCD_Close_PageTransaction should be GLCD related. Consider commands between GLCD_Open_PageTransaction and GLCD_Close_PageTransaction as a single page update. Including WAITs is not advised - just include GLCD commands.

    To enable this text mode on a high memory device add the following to your user program.
    only.

    #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    

    RAM required

    1. Full GLCD Mode: No changes. Still requires 1024 bytes of memory.
    2. Low GLCD Mode: Requires a 128 byte buffer and the use of the GLCD transaction methods.
    3. Text only: Require RAM only to support basic character operations. No buffer is used.

    Performance

    We have improved the overall performance of the drivers. The Low GLCD mode is comparable to the Full GLCD mode and we still think we can improve further. Joseph has performance statisitics - these are available.

    Summary

    Joseph and I are pretty happy with the outcome. Memory usage is great... Joseph now has GLCD on a 16F628a!! Performance is much improved.

    We will include this driver in the next release of Great Cow BASIC. I have attached an example program that shows all the parameters and let you play with the new commands.

    My thanks to Joseph for his initial question and his great work in testing, writing code and retesting! Thank you.

    WATCH OUT FOR THE NEW ELIPPSE & TRIANGLE METHODS AND THE NEW SPRITE METHOD!

     

    Last edit: Anobium 2017-08-20
  • Joseph Realmuto

    Joseph Realmuto - 2017-08-20

    As Anobium mentioned, I ran some performance tests while we were developing these new drivers. It was important to be able to write the buffer in low GLCD mode as quickly as possible in order to have high screen refresh rates. My testing showed we could write the buffer to the screen in 5 to 6 ms. That means the entire screen can be updated in roughly 40 to 50 ms. Note this was with a baud rate of 400kHz. I've found some of these displays work OK even bringing the baud rate past 1 MHz.

    The primary limitation with low GLCD mode is that we essentially need to go through all the calculations for each screen update 8 times (once for each page). The pixel writes which are outside the current buffer are rejected but this still uses some computation cycles. Overall however the results are very satisfactory. The end user can selectively update only parts of the screen to increase speed if the remainder of the screen isn't changing. Of course, faster clock speeds are especially beneficial in low GLCD mode as the primary limitation seems to be compute speed rather than the actual time to write the buffer.

    Writing characters provides a good way to test speeds. I ran a set of tests where I filled up the entire screen with characters. In low GLCD mode I tried two ways. In one case I used the following code:

      GLCD_Open_PageTransaction 0,7
       For Page = 0 to 56 step 8
        For CharPosition = 0 to 120 step 6
         GLCDDrawChar ( CharPosition, Page, 48)
        Next
       Next
      GLCD_Close_PageTransaction
    

    This is the code you would normally use to fill the screen with characters in full GLCD mode. This means in low GLCD mode you're going through the code 8 times (once for each page) but 7 out of 8 lines are rejected. This is sort of a worst-case scenario but I still achieved 138 characters per second in my tests.

    The second test involved synchronizing the line of text to the current page:

      GLCD_Open_PageTransaction 0,7
       Page = 8 * _GLCDPage
       For CharPosition = 0 to 120 step 6
        GLCDDrawChar ( CharPosition, Page, 48)
       Next
      GLCD_Close_PageTransaction
    

    This gives a best-case scenario for speed. My test results were 472 characters per second.

    In text only mode where you're writing directly to the display things are lightning fast. I was able to write 1774 characters per second ( and 3477 char/sec if I bumped the baud rate up to 1 MHz).

    As Anobium mentioned, the new drivers even let you use a GLCD on devices as limited as the PIC16F628A. The primary limitation here is program memory. I can only do text only with the 628A because there isn't enough program memory for low GLCD routines. However, the 648A, which is essentially the same chip with twice the program memory, can have some basic low GLCD functionality. That said, even having a text only display is very useful with these low-spec devices.

     

    Last edit: Joseph Realmuto 2017-08-20
  • Anobium

    Anobium - 2017-08-21

    An example program - this shows how each mode operatates. This support all three modes. This was one of the test programs developed during the development.

    This uses a Mega328p but this works on any microcontroller. The defines control the GLCD commands in use. This creates three GLCD screens and show the differences between the Text, Lo Memory Mode GLCD and Full Mode GLCD.

    The full code is the attachment.

       ; ----- Define GLCD Hardware settings
      #define GLCD_TYPE GLCD_TYPE_SSD1306
      #define GLCD_I2C_Address 0x78
      #define GLCD_PROTECTOVERRUN
    
      ' Define Hardware I2C settings
      #Define HI2C_BAUD_RATE 400
      #Define HI2C_DATA
      HI2CMode Master
    
    '    #define GLCD_PROTECTOVERRUN
    '    #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    '    #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    
    '  Operational Options
    '
    '  Full GLCD mode - Hi memory device         | No defines required
    '  Low GLCD memory mode - Lo memory device   | GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE ( as GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY will be set automatically)
    '  Low GLCD memory mode - Hi memory device   | GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE and GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY to force mode of operation
    '                                              Note: GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE alone WILL NOT operate as expected.  GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY must be added to user code
    '  Character mode - Lo or Hi memory device   | GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    
    ' Character memory mode - screen addressing
    '     8 lines of text, any GLCDPrint (xpos, YPOS, text) and YPOS will be translated to Address Line #n.
    '     Address Line #0 = YPOS 0 to 7
    '     Address Line #1 = YPOS 8 to 15
    '     Address Line #2 = YPOS 16 to 23
    '     Address Line #3 = YPOS 14 to 31
    '     Address Line #4 = YPOS 32 to 39
    '     Address Line #5 = YPOS 40 to 47
    '     Address Line #6 = YPOS 48 to 55
    '     Address Line #7 = YPOS 56 to 63
    '
    '
    '
    ' Low GLCD memory mode
    '
    '   GLCD_Open_PageTransaction and GLCD_Close_PageTransaction added to support Low memory configuration
    '   Any commands between GLCD_Open_PageTransaction and GLCD_Close_PageTransaction should be GLCD focused only.
    '   Any commands within the transaction WILL BE called 8 (EIGHT) times. So, if you increment variables... they will be incremented 8 times
    '   Any commands between GLCD_Open_PageTransaction and GLCD_Close_PageTransaction should be GLCD focused only.
    '   Methods such as scroll, pixelstatus WILL NOT work in low memory mode.
    '   Print characters first then graphics.
    '
    '   Example of low memory usage
    '    #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY    'This defined will be required on high RAM devices to activate low memory capability
    '    #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    '
    '      GLCD_Open_PageTransaction 0,7
    '        GLCDPrint 0,10, "Great Cow BASIC"
    '        GLCDPrint 0,52, "Page 2"
    '        Box 0,0,127,63
    '      GLCD_Close_PageTransaction
    '
    
     

    Last edit: Anobium 2017-08-21
  • Anobium

    Anobium - 2017-08-21

    And, a demonstration of the capabilities. Three pages all being created using the Low GLCD Mode.

    Page 1 - Text, lines, circles
    Page 2 - Box and text
    Page 3 - Progressive filled box

    And, compare to the Full GLCD Mode. Same commands but uses a 1024 byte buffer.

     

    Last edit: Anobium 2017-08-21
  • Bonkers

    Bonkers - 2023-04-11

    Hi Chaps,
    I took the gcb file above and replaced the processor with a PIC12F1552 (2kW ROM, 256B RAM, HW I2C) - just to see if it compiles, based on the understanding that it works on a similarly constrained PIC16F628.
    The GLCD_TYPE GLCD_TYPE_SSD1306 code should pick-up ChipRAM and force GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY, but it doesn't seem to.
    In fact, seemingly regardless of all combinations of the variables below: #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    ' #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    and even #DEFINE GLCD_DISABLE_OLED_FONT2`

    I get the same ASM output
    Error: Program is too large, cannot fit all subroutines into available program memory

    The html file that shows resource usage is always fixed at 163% of available code memory - in all 8 combinations of the flags above.

    Looking at the SSD 1306 code, it seems that
    GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE is needed to invoke the GLCD_Open_PageTransaction method
    #ifdef GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    GLCD_Open_PageTransaction 0,7
    #endif

    - but this in turn invokes the drawing of a circle. 
        #ifdef GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
          pset 100,31,1
          Circle 63,31,22
          line 0, 0, 127, 63
          line 0, 63, 127, 0
          Circle 63,31,10
          Box 0,0,127,63
        #endif
    

    However I cut it, I get resources used for "circle" and "box":
    Name Code Size (lines) Compiled Size (words)
    BOX 20 147
    CIRCLE 20 230

    I don't mind if OLEDs don't work on PICs this small, It's just that there is a claim on the 16F628, and It'd be great if they did.

     
  • Bonkers

    Bonkers - 2023-04-11

    Hi Chaps,
    I took the gcb file above and replaced the processor with a PIC12F1552 (2kW ROM, 256B RAM, HW I2C) - just to see if it compiles, based on the understanding that it works on a similarly constrained PIC16F628.
    The GLCD_TYPE GLCD_TYPE_SSD1306 code should pick-up ChipRAM and force GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY, but it doesn't seem to.
    In fact, seemingly regardless of all combinations of the variables below: #define GLCD_TYPE_SSD1306_CHARACTER_MODE_ONLY
    ' #define GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    and even #DEFINE GLCD_DISABLE_OLED_FONT2`

    I get the same ASM output
    Error: Program is too large, cannot fit all subroutines into available program memory

    The html file that shows resource usage is always fixed at 163% of available code memory - in all 8 combinations of the flags above.

    Looking at the SSD 1306 code, it seems that
    GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE is needed to invoke the GLCD_Open_PageTransaction method
    #ifdef GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
    GLCD_Open_PageTransaction 0,7
    #endif

    - but this in turn invokes the drawing of a circle. 
        #ifdef GLCD_TYPE_SSD1306_LOWMEMORY_GLCD_MODE
          pset 100,31,1
          Circle 63,31,22
          line 0, 0, 127, 63
          line 0, 63, 127, 0
          Circle 63,31,10
          Box 0,0,127,63
        #endif
    

    However I cut it, I get resources used for "circle" and "box":
    Name Code Size (lines) Compiled Size (words)
    BOX 20 147
    CIRCLE 20 230

    I don't mind if OLEDs don't work on PICs this small, It's just that there is a claim on the 16F628, and It'd be great if they did.

     
  • Anobium

    Anobium - 2023-04-12

    Interesting - your attached file was large in terms of the 'ask'. See attached. I tweaked a few things in your code but the PIC12LF1552 works.

     
    • Anobium

      Anobium - 2023-04-12

      Re the 16F628. This is puzzling as the only difference is the family type. The PIC12F1552 is family15 and the 16F628 is family 14. The memory allocation is different where the PIC12F1552 uses linear addressing ( I can see from the source code.. variables.bi line 952.).

      I am guessing as I do not have tha chip. The 16F628 needs some help to find the correction location for the array. You could try adding Dim SSD1306_BufferAlias(128) at 174 (I am thinking is the start of the memory block in RAM, you need to check the datasheet). Then, the array would sit at the bottom of the third block of RAM).

      EDITED

      The 16F628 has 224 bytes. The largest contiguous block of RAM is 95 bytes ( could be 94 bytes) therefore the 128 byte buffer cannot fit. I could change the library to issue a warning. I guess this would help users. So, essentially family 14 with this physical memory constraint is the root cause of the issue.... it will not support LM Mode GLCD.

      Replace your exiting library with the attached. It will now issue an Error when a familychip 14 and less then 225 of RAM chip is used.


      Then, you would have to change to software I2C. The library supports that, so, this is a minor change.

      But, the it will be slow. 20mHz, software I2C, low memory... all will make this so slow.


      I have a question. Where did you see the claim it would work. I need to caveat that claim, :-)

       

      Last edit: Anobium 2023-04-12
  • Bonkers

    Bonkers - 2023-04-12

    Wow, many thanks for that, firstly your question... the 16F628 claim is made above,

    Last edit: Joseph Realmuto 2017-08-20. As Anobium mentioned, the new drivers even let you use a GLCD on devices as limited as the PIC16F628A. The primary limitation here is program memory. I can only do text only with the 628A because there isn't enough program memory for low GLCD routines.


    I will try the code you sent on a real PIC12LF1552, and maybe a PIC16F628A later, if you wish. You've got it to compile at least, which is great. I do recall seeing something about the GLCD code not working on PIC15 cores but OK with PIC16 cores - so I should have stopped there, but to be honest I've never seen a clear definition of what core is which - uChip refer to them as baseline, extended, 12-bit 14-bit - not the crisp definitions you use. Is there a table?

    Anyway, it's looking like text-only mode might be usable with all sorts of low-memory devices - more than originally declared - and some might find that useful. I certainly will, it's re-inventing the 16x2 type display, low resource, but on a snazzy GLCD/OLED. It it all works out, might be an idea to switch-off some font sizes and reduce the code size - but I'll build a board first and test it.

     
  • Anobium

    Anobium - 2023-04-12

    Re the 16F628... it wont work with library as is. I cant think of way to make it work in less than a 128 bytes RAM buffer.


    PIC12LF1552 is still very tight on RAM. Some of the newer chips have 2048 or more. The more the better.


    Good luck and enjoy.

     
  • Bonkers

    Bonkers - 2023-04-12

    Currently indeed enjoying my favourite programming language - Solder.
    Re 16F628, surely if any device can work RAM-less, in character mode, then all should? - Obvs we need enough program memory, and yes there are some weird PICs with fractured RAM, like the 16F506, give up on those. Happy to park the 16F628 for now.

    I see it as 4 levels of GLCD function:
    full 1024B buffer (for 128 x 64 OLED)
    full 512B buffer (for 128x32 OLED) - I'm guessing this might be the case
    low-memory 128B buffer for any OLED, with more processing cost, but similar graphics
    zero buffer RAM, for character mode only. (with some RAM cost for assembling fonts)

    It's the last one I'm interested in, because you declare it as possible, and it allows 50p OLED GFX displays to be used like old-school character displays.

    Experiment update:
    I ran the code you dropped me above, on 2 boards, but the I2C lines weren't right. Both have 4k7 pullups to 3V3, but the SDA is high, and the SCK sits at half-rail. This isn't right, and i tested it on 2 x 12LF1552, both verified fine, and both LED's on RA4 do blink properly at 1Hz.

    I will look into the HW I2C setup, maybe the defaults don't cover setting-up the pins in all cases - the 12F1552 does have two "pin routing" options, in the APFCON register.

     
  • Anobium

    Anobium - 2023-04-12

    lol re programming language!

    re I2C I did not inspect the harware / pps setup in that code. I do not know if hardware i2c is supported or if pps is needed. Check out these first.

     
  • Bonkers

    Bonkers - 2023-04-12

    Will do.. the HW I2C demands that pins be set as inputs, I'll start with that, if no luck then might switch to SW I2C .

     
  • Bonkers

    Bonkers - 2023-04-12

    Well, here's a thing - I used the example code to set the default I2C pins to inputs, as reqd by the PIC MSSP peripheral (pinout as defined in the JPG image, 2 posts above - and holding my concern that the APFCON register is undefined on POR reset - I will check it gets configured later)

     ' Define HARDWARE I2C settings for PIC MSSP peripheral
    #define HI2C_BAUD_RATE 400
    #define HI2C_DATA PORTA.2
    #define HI2C_CLOCK PORTA.1
    'I2C pins need to be input for SSP module when used on Microchip PIC device
    Dir HI2C_DATA in
    Dir HI2C_CLOCK in
    
    'MASTER MODE
    HI2CMode Master
    
    
    However, the compiler throws an error:
    

    Evan_lowmem_SS130_PIC16F1552#5.gcb (26): Error: GPIO is not a valid I/O pin or port

    and the *.asm file has and incorrect reference to "TRISIO" which doesn't exist on this part, there is only TRISA .

    Define HARDWARE I2C settings for PIC MSSP peripheral
    ;#define HI2C_BAUD_RATE 400
    ;#define HI2C_DATA PORTA.2
    ;#define HI2C_CLOCK PORTA.1
    ;I2C pins need to be input for SSP module when used on Microchip PIC device
    ;Dir HI2C_DATA in
    movlw 255
    movwf TRISIO
    ;Dir HI2C_CLOCK in
    banksel TRISA
    bsf TRISA,1

     
  • Anobium

    Anobium - 2023-04-12

    Attach your code. I cannot visualise the error.

     
  • Bonkers

    Bonkers - 2023-04-12

    the *.asm file has no mention of APF, or APFCON register
    Yes I appreciate that pinswap is just another circle of hell for the poor compiler team, and teh MSSP peripheral is a proper monster, I'll await further comment - if it doesn't work then fine, I'll use the SW I2C, it's a lot simpler, if slower.

     
  • Anobium

    Anobium - 2023-04-12

    Still attach your code - I dont know what that error is.

     
  • Bonkers

    Bonkers - 2023-04-12

    sure - here's the code: - and thank you :)

     
  • Anobium

    Anobium - 2023-04-12

    This is my error. Which is correct.

     Evan_lowmem_SS1306_PIC16F1552#5.gcb (23): Error: CODE/Constant: HI2C_DATA cannot reassigned to PORTA.2
    

    Line 13 has the same constant with no value.


    Rempve line 13 - and, it compiles.

     
  • Bonkers

    Bonkers - 2023-04-12

    I've only added lines 21 to 30 (below) - using the default pinning - but I note that the APFCON register is UUUUUU on POR - and would need to be set properly even to get the default pinning.

     ' Define HARDWARE I2C settings for PIC MSSP peripheral
    #define HI2C_BAUD_RATE 400
    #define HI2C_DATA PORTA.2
    #define HI2C_CLOCK PORTA.1
    'I2C pins need to be input for SSP module when used on Microchip PIC device
    Dir HI2C_DATA in
    Dir HI2C_CLOCK in
    
    'MASTER MODE
    HI2CMode Master
    
     
  • Bonkers

    Bonkers - 2023-04-12

    right - sorry, messages crossed I'll try again...
    many thanks#

     
  • Anobium

    Anobium - 2023-04-12

    Add AFPCON=0 is required to the user program in the startup routine.

     
  • Bonkers

    Bonkers - 2023-04-12

    It did compile and program, but same result - the SCL pin is at half-rail, with no activity, the SDA pin is at rail, similar.

     
  • Bonkers

    Bonkers - 2023-04-12

    It did compile and program, but same result - the SCL pin is at half-rail, with no activity, the SDA pin is at rail, similar.

     
    • Anobium

      Anobium - 2023-04-12

      Still got the programmer attached?

      Checking. You have the i2c pull up resistors fitted?

       
1 2 > >> (Page 1 of 2)

Log in to post a comment.