![]() |
Forum Index : Microcontroller and PC projects : MM2, MM+: SSD1306 OLED loadable drivers updated
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
Prompted by an question on an old thread I've updated the ssd1306 OLED loadable driver. The driver supports 0.96" 128x64 and 128x32 displays - not the 1.3" I2C versions which simply don't seem to work. To use the driver load the attached code into the Micromite. Edit the code to reflect your usage if required (I2C-address, SCK-pin, SDA-pin, Vertical size (64 or 32), orientation (1 to 4)). Connect the display using the SCK and SDA pins specified in the SSD1306 subroutine call - these can be freely chosen as the I2C bus is bit-banged. Then type "LIBRARY SAVE". Reset the Micromite and you should see the banner "SSD1306 I2C driver loaded". If this isn't pretty much instantaneous your wiring is incorrect and the I2C bus has timed out. You can now use all the graphics commands specified in the Micromite manual. Note that any non-zero colour will be white and zero will be black (unlit) ![]() sub mm.startup SSD1306(&H3C,2,15,64,1) 'I2C-address, SCK-pin, SDA-pin, Vertical size (64 or 32), orientation (1 to 4) End Sub CSUB SSD1306 00000395 'Delay 40024800 00442021 40024800 0044102B 1440FFFD 00000000 03E00008 00000000 'BBStart 27BDFFE0 AFBF001C AFB10018 AFB00014 00808821 3C109D00 8E030090 8E02001C 8064002E 0040F809 2405FFFE 8E030090 8E02001C 8064002C 0040F809 2405FFFE 40034800 00711821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFD 40034800 00711821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFD 40024800 00518821 40024800 0051102B 1440FFFD 8FBF001C 8FB10018 8FB00014 03E00008 27BD0020 'BBStop 27BDFFE0 AFBF001C AFB10018 AFB00014 00808821 3C109D00 8E030090 8E02001C 8064002C 0040F809 2405FFFD 8E030090 8E02001C 8064002E 0040F809 2405FFFD 40034800 00711821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFE 40034800 00711821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFE 40024800 00518821 40024800 0051102B 1440FFFD 8FBF001C 8FB10018 8FB00014 03E00008 27BD0020 'BBWriteBit 27BDFFE0 AFBF001C AFB20018 AFB10014 AFB00010 00809021 10C00009 00A08821 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFE 10000008 3C029D00 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFE 00001021 40824800 10000005 3C109D00 40024800 0051102A 10400013 8FBF001C 8E030090 8E020020 0040F809 8064002C 1040FFF7 00000000 40024800 00529021 40024800 0052102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFD 8FBF001C 8FB20018 8FB10014 8FB00010 03E00008 27BD0020 'BBReadBit 27BDFFE0 AFBF001C AFB10018 AFB00014 00808021 00A08821 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFE 40034800 00701821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFE 40024800 00508021 40024800 0050102B 1440FFFD 00000000 40824800 10000005 3C109D00 40024800 0051102A 50400014 00008021 8E030090 8E020020 0040F809 8064002C 1040FFF7 00000000 3C119D00 8E230090 8E220020 0040F809 8064002E 00408021 8E230090 8E22001C 8064002C 0040F809 2405FFFD 10000002 02001021 02001021 8FBF001C 8FB10018 8FB00014 03E00008 27BD0020 'BBWriteByte 27BDFFD0 AFBF002C AFB60028 AFB50024 AFB40020 AFB3001C AFB20018 AFB10014 AFB00010 0080B021 00A08821 00C09821 00009021 3C109D00 0000A021 24150008 32620080 10400007 8E030090 8E02001C 8064002E 0040F809 2405FFFE 10000006 8E030090 8E02001C 8064002E 0040F809 2405FFFD 8E030090 8E02001C 8064002C 0040F809 2405FFFE 02801021 40824800 10000006 8E030090 40024800 0051102A 50400013 26520001 8E030090 8E020020 0040F809 8064002C 1040FFF7 00000000 40034800 00761821 40024800 0043102B 1440FFFD 00000000 8E030090 8E02001C 8064002C 0040F809 2405FFFD 26520001 1655FFD3 00139840 3C029D00 8C430090 8C42001C 8064002E 0040F809 2405FFFE 40034800 00761821 40024800 0043102B 1440FFFD 3C029D00 8C430090 8C42001C 8064002C 0040F809 2405FFFE 40024800 0056B021 40024800 0056102B 1440FFFD 00000000 40824800 10000005 3C109D00 40024800 0051102A 50400014 00008021 8E030090 8E020020 0040F809 8064002C 1040FFF7 00000000 3C119D00 8E230090 8E220020 0040F809 8064002E 00408021 8E230090 8E22001C 8064002C 0040F809 2405FFFD 10000002 2E020001 2E020001 8FBF002C 8FB60028 8FB50024 8FB40020 8FB3001C 8FB20018 8FB10014 8FB00010 03E00008 27BD0030 'writei2c 27BDFFD0 AFBF002C AFB60028 AFB50024 AFB40020 AFB3001C AFB20018 AFB10014 AFB00010 0080B021 00A0A821 00C08821 3C029D00 8C420000 8C500000 3C140018 26946A00 0214001B 028001F4 0000A012 00009812 00002012 0411FE97 00000000 240207D0 0202001B 004001F4 00008012 00101080 001029C0 00A22823 00B08021 00102880 02058021 001028C0 00A09021 02802021 00153040 0411FF5F 00000000 10400013 00001821 02C08021 10000007 2415FFFF 02402821 92260000 0411FF56 00000000 10400009 26310001 2610FFFF 1615FFF8 02602021 02802021 0411FEA6 00000000 10000002 24030001 00001821 00601021 8FBF002C 8FB60028 8FB50024 8FB40020 8FB3001C 8FB20018 8FB10014 8FB00010 03E00008 27BD0030 'oled_write_command 27BDFFE0 AFBF001C A3A00010 A3A40011 3C029D00 8C420090 24040002 8045003D 27A60010 0411FFAF 00000000 8FBF001C 03E00008 27BD0020 'OLED_setxy 27BDFFE8 AFBF0014 AFB00010 00808021 24A4FFB0 308400FF 0411FFEB 00000000 7E041900 34840010 0411FFE7 00000000 3204000F 0411FFE4 00000000 8FBF0014 8FB00010 03E00008 27BD0018 'updatedisplay 27BDFFD8 AFBF0024 AFB40020 AFB3001C AFB20018 AFB10014 AFB00010 3C029D00 8C43008C 8C700000 8C420090 8042003C 000211C0 24430007 28440000 0064100B 000210C3 24420001 02021021 80430000 10600022 8FBF0024 A0400000 3C029D00 8C420090 8042003C 28420008 1440001A 00008821 24140040 3C129D00 00002021 02202821 0411FFCB 00000000 82130000 A2140000 8E420090 24040081 8045003D 02003021 0411FF6E 00000000 A2130000 26310001 8E420090 8042003C 24430007 28440000 0064100B 000210C3 0222102A 1440FFEA 26100080 8FBF0024 8FB40020 8FB3001C 8FB20018 8FB10014 8FB00010 03E00008 27BD0028 'DrawRectangleMEM 27BDFFD0 AFBF002C AFB50028 AFB40024 AFB30020 AFB2001C AFB10018 AFB00014 00808821 00A09821 00C09021 00E0A021 3C029D00 8C42008C 8C420000 90440000 240300F5 10830010 8FB00040 3C159D00 8EA20090 8042003C 000211C0 24430007 28440000 0064100B 000220C3 8EA2003C 0040F809 24840400 8EA3008C AC620000 2403FFF5 A0430000 3C039D00 8C630090 80640015 24050002 14850009 24050003 2404007F 00942823 00932023 0220A021 02409821 00809021 10000015 00A08821 14850009 24050004 2404007F 00918823 00929023 8064003C 2484FFFF 00939823 1000000B 0094A023 1485000A 0232202A 8064003C 2484FFFF 00912823 00922023 02809021 0080A021 02608821 00A09821 0232202A 14800005 0274202A 02202021 02408821 00809021 0274202A 14800005 2A240000 02602021 02809821 0080A021 2A240000 0004880B 2404007F 2A250080 0085880A 2A450000 0005900B 2A450080 0085900A 2A640000 0004980B 8063003C 0263282A 2464FFFF 0085980A 2A840000 0004A00B 0283202A 2463FFFF 0064A00A 0251182A 10600025 0293482A 10000029 3C039D00 24640007 28650000 0065200A 000428C3 000529C0 00E52821 000327C3 00042742 00643021 30C60007 00C42023 00882004 12000006 308400FF 00452821 90A60000 00862025 10000006 A0A40000 00452821 00042027 90A60000 00C42024 A0A40000 24630001 0283202A 1080FFE6 24640007 26310001 0251182A 50600005 02601821 10000007 3C039D00 24080001 02601821 1120FFDB 26270001 1000FFF6 26310001 8C630090 8063003C 000319C0 24640007 28650000 0085180B 000318C3 00431021 24030001 A0430001 8FBF002C 8FB50028 8FB40024 8FB30020 8FB2001C 8FB10018 8FB00014 03E00008 27BD0030 'DrawBitmapMEM 27BDFFB0 AFBF004C AFBE0048 AFB70044 AFB60040 AFB5003C AFB40038 AFB30034 AFB20030 AFB1002C AFB00028 AFA40050 00A0A821 00C09021 AFA7005C 8FB00060 8FB10068 3C029D00 8C42008C 8C420000 90440000 240300F5 10830010 8FB3006C 3C149D00 8E820090 8042003C 000211C0 24430007 28440000 0064100B 000220C3 8E82003C 0040F809 24840400 8E83008C AC620000 2403FFF5 A0430000 8FA3005C 18600096 0200F021 AFB5001C 00122023 AFA40020 70721802 2463FFFF AFA30014 AFB20024 0000B821 AFA00018 24140001 3C099D00 240A0002 240C0003 10000083 240E0004 8D280090 81050015 14AA0007 00602021 8D240098 8C840000 2484FFFF 00603821 10000013 008D2023 14AC000A 00000000 8D240094 8C840000 2484FFFF 00832023 8D250098 8CA70000 24E7FFFF 10000008 00ED3823 14AE0006 01603821 8D250094 8CA70000 24E7FFFF 00E33823 01602021 2C850080 50A00033 24C60001 04E20031 24C60001 8105003C 00E5282A 50A0002D 24C60001 24840001 24E50007 28E80000 00E8280A 000528C3 000529C0 00852021 000747C3 00084742 00E83821 30E70007 00E82823 00B42804 30A500FF 00054027 92C70000 00F53824 10E0000C 310800FF 8FA70064 10E00005 00442021 90870000 00A72825 10000012 A0850000 90850000 01054024 1000000E A0880000 1A200006 00000000 00442021 90870000 00A72825 10000007 A0850000 56200006 24C60001 00442021 90850000 01052824 A0850000 24C60001 14D0FFAE 24630001 25EF0001 2718FFFF 11F20010 033EC821 01F71821 24640007 28760000 0096180B 0003B0C3 0276B021 00181FC3 00031F42 0303A821 32B50007 02A3A823 02B4A804 03201821 1000FF9B 00003021 8FA30010 24630001 AFA30010 14700004 25AD0001 10000008 8FA40018 AFA00010 1A40FFF7 01A05821 8FB90050 8FB80014 1000FFE4 00007821 24840001 AFA40018 8FA7001C 00FE3821 AFA7001C 8FA30014 8FA40020 00641821 AFA30014 8FA70024 8FA30018 8FA4005C 10640005 02E7B821 1E00FFEA 8FAD001C 1000FFEF 8FA40018 3C039D00 8C630090 8063003C 000319C0 24640007 28650000 0085180B 000318C3 00431021 24030001 A0430001 8FBF004C 8FBE0048 8FB70044 8FB60040 8FB5003C 8FB40038 8FB30034 8FB20030 8FB1002C 8FB00028 03E00008 27BD0050 'getFPC 27BDFFF8 AFBF0004 00852023 03E42021 ACC40000 8FBF0004 03E00008 27BD0008 'pstring 27BDFFE0 AFBF001C AFB00018 00808021 00002021 3C059D00 24A50E30 27A60010 0411FFEF 00000000 8FA40010 3C029D00 8C42002C 0040F809 02042021 8FBF001C 8FB00018 03E00008 27BD0020 'main 27BDFFC8 AFBF0034 AFB40030 AFB3002C AFB20028 AFB10024 AFB00020 0080A021 00A09821 00C09021 00E08821 00002021 3C059D00 24A50E98 27A60018 0411FFD5 00000000 3C109D00 8E020090 8E230000 A043003C 8E020090 8051003C 8E430000 A043002E 8E020090 8E630000 A043002C 8E020090 24030014 A0430014 8E020090 8E830000 A043003D 8E020090 8FA30048 8C630000 A0430015 8E020090 8042003C 000211C0 24430007 28440000 0064100B 000220C3 8E02003C 0040F809 24840400 8E03008C AC620000 2403FFF5 A0430000 8E030090 8E02001C 8064002E 0040F809 24050005 8E030090 8E020010 8064002E 24050008 0040F809 00003021 8E030090 8E020010 8064002E 24050065 0040F809 00003021 8E030090 8E02001C 8064002C 0040F809 24050005 8E030090 8E020010 8064002C 24050008 0040F809 00003021 8E030090 8E020010 8064002C 24050065 0040F809 00003021 240400AE 0411FDB4 00000000 240400D5 0411FDB1 00000000 24040080 0411FDAE 00000000 240400A8 0411FDAB 00000000 8E020090 8043003C 24020040 54620006 2404001F 2404003F 0411FDA3 00000000 10000004 240400D3 0411FD9F 00000000 240400D3 0411FD9C 00000000 00002021 0411FD99 00000000 24040040 0411FD96 00000000 2404008D 0411FD93 00000000 24040014 0411FD90 00000000 24040020 0411FD8D 00000000 00002021 0411FD8A 00000000 240400A1 0411FD87 00000000 240400C8 0411FD84 00000000 240400DA 0411FD81 00000000 3C029D00 8C420090 8043003C 24020040 54620006 24040002 24040012 0411FD78 00000000 10000004 24040081 0411FD74 00000000 24040081 0411FD71 00000000 240400CF 0411FD6E 00000000 240400D9 0411FD6B 00000000 240400F1 0411FD68 00000000 240400DB 0411FD65 00000000 24040040 0411FD62 00000000 240400A4 0411FD5F 00000000 240400A6 0411FD5C 00000000 240400AF 0411FD59 00000000 3C029D00 8C420090 90420015 30420001 10400007 3C029D00 8C430094 24040080 AC640000 8C420098 10000006 AC510000 8C430098 24040080 AC640000 8C420094 AC510000 8FA50018 3C029D00 8C430048 3C049D00 24840800 00852021 AC640000 8FA50018 8C43004C 3C049D00 24840A90 00852021 AC640000 8FA50018 8C4300A4 3C049D00 24840708 00852021 AC640000 8C430048 8C440094 8C860000 8C420098 8C470000 AFA00010 8C620000 00002021 00002821 24C6FFFF 0040F809 24E7FFFF 3C049D00 24841214 0411FF06 00000000 8FBF0034 8FB40030 8FB3002C 8FB20028 8FB10024 8FB00020 03E00008 27BD0038 '.rodata 'startup 31445353 20363033 20433249 76697264 6C207265 6564616F 000A0D64 End CSub |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Many thanks! So, after a reset, if I see the message "SSD1306 I2C driver loaded", it means the display is connected in the right way and it already replied to your initialization sequence? |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
yes as long as you see it immediately |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
In my case, the message is immediate but then the display remains dark, no matter if I type some command like: text 10,10,"hello" line 0,0,100,30 nothing on the screen, shoud I type before some specific command to enable the display? |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
No, should just work. I tested on 128x64 and 128x32 as pictured using a 28 pin MM2. Note 1.3" I2C versions are wired incorrectly and don't work. I'm not aware of any faulty 128x32 displays. |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Ok, all working now! ![]() ![]() |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
I2C devices have a 7-bit address and the 8th bit defines read or write. There are two conventions, one treats the addresses as 0-254 in steps of 2 and the other 0-127 in steps of one. MMBasic uses the second, your display is using the first. hex 78 / 2 = hex 3C |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Ok, it's clear now. Thank you. There is a way to reduce the light by software in this display? What do you mean? As I know the 1.3 version has a different controller with the need to adjust a little the graphic map. |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Another question, Peter: I noticed the diplays are working even without the pull up resistors. May be you have configured the bit-banged ports with an internal pull-up? (by the way, if you disconnect the entire display stuff, your library immediately pass the start-up test, so I wont state it as a sign of "hardware is ok") |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
Yes, but may not always be adequate not AFAIK 1.3" displays need 2-pixel offset on X. This works fine on SPI versions but I have never got one of the 1.3" I2C only displays to work - not something I'm going to spend any more time on. |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Arggh!! I just ordered one yesterday! In the product page there is a statement: Does this add some new information about the problem? I explain better: I mean if is possible to adjust globally the luminosity of the display, for example to fade-in a graphic image. In the topic "Display drivers in Basic" (here the Link ) I seen the command: OLED.SCmd(&H81)'SETCONTRAST OLED.SCmd(&HCF) so I was hoping a global luminosity was possible. Or can be decided only once at the startup sequence? |
||||
ceptimus Senior Member ![]() Joined: 05/07/2019 Location: United KingdomPosts: 130 |
I've got some Arduino (C++) code I wrote to drive I2C displays that initializes either the SSH1106 or the SSD1306 interface depending on a #define. You have to send a slightly different bunch of initialization commands, and thereafter, as you say, there is a 2-pixel X offset, and also a slightly different set-up routine before sending the actual pixel bytes. The 1106 is actually more sensible (apart from the 2-pixel offset) in that you only need to send 3 bytes of 'position' information rather than the 6 bytes to send the same information to the 1306. There might be some #defines here that don't apply to either the 1106 or 1306 as this display driver could also handle two other types of display - but I've tried to edit out the unnecessary parts. #define SH1106_ADDR 0x3C #define SSD1306_ADDR 0x3C #define DISPLAY_LCDWIDTH 128 #define DISPLAY_LCDHEIGHT 64 // display chars assuming 6x8 font #define DISPLAY_CHARWIDTH (DISPLAY_LCDWIDTH / 6) #define DISPLAY_CHARHEIGHT (DISPLAY_LCDHEIGHT / 8) #define DISPLAY_NUMCHARS (DISPLAY_CHARWIDTH * DISPLAY_CHARHEIGHT) // there may be unused pixels down each side of the display - for example with a 128 pixel-width display and a 6-bit-wide font there are 21 characters per row with 1 unused pixel down each edge #define DISPLAY_LEFTMARGIN ((DISPLAY_LCDWIDTH - DISPLAY_CHARWIDTH * 6) / 2) // (unlikely to need a TOPMARGIN as displays are all likely to be a multiple of 8 pixels high - in any case we'll manage okay without) #define DISPLAY_SETCONTRAST 0x81 #define DISPLAY_DISPLAYALLON_RESUME 0xA4 #define DISPLAY_DISPLAYALLON 0xA5 #define DISPLAY_NORMALDISPLAY 0xA6 #define DISPLAY_INVERTDISPLAY 0xA7 #define DISPLAY_DISPLAYOFF 0xAE #define DISPLAY_DISPLAYON 0xAF #define DISPLAY_SETDISPLAYOFFSET 0xD3 #define DISPLAY_SETCOMPINS 0xDA #define DISPLAY_SETVCOMDETECT 0xDB #define DISPLAY_SETDISPLAYCLOCKDIV 0xD5 #define DISPLAY_SETPRECHARGE 0xD9 #define DISPLAY_SETMULTIPLEX 0xA8 #define DISPLAY_SETLOWCOLUMN 0x00 #define DISPLAY_SETHIGHCOLUMN 0x10 #define DISPLAY_COLUMNADDR 0x21 #define DISPLAY_PAGEADDR 0x22 #define DISPLAY_SETSTARTLINE 0x40 #define DISPLAY_SETSTARTPAGE 0XB0 #define DISPLAY_MEMORYMODE 0x20 #define DISPLAY_COMSCANINC 0xC0 #define DISPLAY_COMSCANDEC 0xC8 #define DISPLAY_SEGREMAP 0xA0 #define DISPLAY_CHARGEPUMP 0x8D #define DISPLAY_EXTERNALVCC 0x1 #define DISPLAY_SWITCHCAPVCC 0x2 // queue up the initial setup commands for the display #ifdef SH1106 uint8_t commandQueue[23] = { DISPLAY_DISPLAYOFF, 0x40, // display start line DISPLAY_SETCONTRAST, 0x80, DISPLAY_SEGREMAP | 0x01, DISPLAY_NORMALDISPLAY, DISPLAY_SETMULTIPLEX, 0x3F, 0xAD, 0x8B, // charge pump enable, external VCC 0x30, // VPP 9V DISPLAY_COMSCANDEC, DISPLAY_SETDISPLAYOFFSET, 0x00, DISPLAY_SETDISPLAYCLOCKDIV, 0x80, DISPLAY_SETPRECHARGE, 0x22, DISPLAY_SETCOMPINS, 0x12, DISPLAY_SETVCOMDETECT, 0x40, DISPLAY_DISPLAYON }; uint8_t dataStart = queueCommands(dataBuffer, 23, commandQueue); #endif #ifdef SSD1306 uint8_t commandQueue[24] = { DISPLAY_SETMULTIPLEX, 0x3F, DISPLAY_SETDISPLAYOFFSET, 0x00, DISPLAY_SETSTARTLINE, DISPLAY_SEGREMAP | 0x01, DISPLAY_COMSCANDEC, DISPLAY_SETCOMPINS, 0x12, DISPLAY_SETCONTRAST, 0xFF, DISPLAY_DISPLAYALLON_RESUME, DISPLAY_NORMALDISPLAY, DISPLAY_SETDISPLAYCLOCKDIV, 0x80, DISPLAY_CHARGEPUMP, 0x14, DISPLAY_SETPRECHARGE, 0x22, DISPLAY_MEMORYMODE, 0x01, DISPLAY_SETVCOMDETECT, 0x20, DISPLAY_DISPLAYON }; uint8_t dataStart = queueCommands(dataBuffer, 24, commandQueue); #endif void _display::transmitCharSmall(uint8_t row, uint8_t x, uint8_t c) { #if defined(NEGATIVE_DISPLAY) && (defined(SH1106) || defined(SSD1306)) uint8_t xorMask = c & 0x80 ? 0x00 : 0xFF; // if MSB set display character reverse field #else uint8_t xorMask = c & 0x80 ? 0xFF : 0x00; // if MSB set display character reverse field #endif #ifdef SH1106 x += 2; uint8_t commandQueue[3] = {(uint8_t)(0xB0 + row), (uint8_t)(x & 0x0F), (uint8_t)(((x >> 4) & 0x0F) | 0x10)}; uint8_t dataStart = queueCommands(dataBuffer, 3, commandQueue); dataBuffer[dataStart++] = 7; // now append a 7-byte data packet dataBuffer[dataStart++] = 0x40; // tell display we're sending data not commands #endif #ifdef SSD1306 uint8_t commandQueue[6] = {DISPLAY_PAGEADDR, row, row, DISPLAY_COLUMNADDR, x, x < DISPLAY_LCDWIDTH - 6 ? x + 5 : DISPLAY_LCDWIDTH - 1}; uint8_t dataStart = queueCommands(dataBuffer, 6, commandQueue); dataBuffer[dataStart++] = 7; // now append a 7-byte data packet dataBuffer[dataStart++] = 0x40; // tell display we're sending data not commands #endif Edited 2019-08-27 04:22 by ceptimus |
||||
MipsyKing Newbie ![]() Joined: 12/02/2015 Location: ItalyPosts: 17 |
Very intersting ceptimus. Would be possible to translate this code into MM Basic (only the part about the 1,3" controller sh1106)in order to let Peter test his i2C display? Mine is ordered, but it will take a month (at least) untill I will receive it! And what about the idea to regulate the global light of the display (for example to simulate a fading between two screens), is possible or not? |
||||
ceptimus Senior Member ![]() Joined: 05/07/2019 Location: United KingdomPosts: 130 |
It would certainly be possible to drive the display wholly from MMBASIC - but it would need a whole lot of BASIC SUB-routines and would be much slower and less convenient than using Peter's C driver. It's not really MMBASIC we need: it's a C function for MMBASIC - that's what all the magic hex codes in Peter's code are. I've not written any of those for MicroMites yet, so I need to figure out how to set up the C compiler and such. I might have a go at it after I've completed my current game project, assuming no one else has already done it by then! Regarding fading between two screens - I don't think that will be possible. You can do a sort of fade transition by changing the pixels from the previous to the new values in a seemingly random order - but that requires having the 'before' and 'after' screens stored in RAM buffers. Playing with the SETCONTRAST and CHARGEPUMP constants might allow one to vary the brightness, but I don't remember trying it. I vaguely remember something in the display data sheet that implied changing the chargepump thing might be a bad idea. These little OLED displays don't really need their brightness changing, in my opinion: they're not bright enough to dazzle, even in the dark. It would be nice to be able to turn them up much brighter when outdoors - they're not really visible in direct sunlight - but unfortunately, they're not capable of that. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
The initialisation in my code works fine with 1.3" SPI displays. The issue is almost certainly the I2C implementation on the 1.3" display. This has been a known issue on many of these boards. To get I2C to work you need to connect together the pins that in SPI mode are MOSI and MISO to make the composite I2C SDA connection. Many boards only connect MOSI and this means the boards don't send the ACK and NACK I2C handshake messages. Arduino types have got round this by implementing a bastardised version of I2C which doesn't need ACK and NACK. Us Micromite types don't do that sort of thing ![]() |
||||
ceptimus Senior Member ![]() Joined: 05/07/2019 Location: United KingdomPosts: 130 |
Are you talking about the dedicated I2C interface 1.3" displays? I know there are some that support both SPI and I2C, but the ones I use are I2C only. I'm not using the Arduino Wire library which is inefficient and time wasting - my code communicates directly with the Atmel Mega's TWI registers: it's interrupt driven and non-blocking. It's a while since I wrote it. The callback that happens at the end of either a successful or unsuccessful master transmit no longer sends anything back to the calling routine to indicate success or failure - you can see where I've commented out the status code return, and now the callback passes no parameters. I seem to remember in testing that when the code did use different return values to indicate different varieties of 'fail' I could never make any of them happen, short of disconnecting the display - and then what is the calling code going to do anyhow? The main application was where the processor was sending critical real-time data via a radio link - and if the display failed for some reason it was best for the device to continue operating without the display working. There are lots of devices out in the field though, running this code, and no one has reported back any display problems. (yet) ![]() /* TWI (I2C) non-blocking interrupt driven. Currently only supports master transmit mode * ceptimus. September 2016 */ #ifndef TWI_h #define TWI_h #include "config.h" typedef void (*callbackPtr)(/* uint8_t */ void); class TWI { public: static void TWIstart(void); // configure TWI registers (sets communication speed) static void nonBlockingTWImasterTransmit(uint8_t slaveAddr, uint8_t data[], uint8_t length, callbackPtr callback); // following are only public so they can be accessed by the (non-member) ISR static uint8_t slaveAddr; static uint8_t *data; // data pointer for non-blocking interrupt routine static uint8_t remaining; // count of remaining data bytes to be sent by non-blocking interrupt routine static callbackPtr callback; }; #endif ========================================================= /* TWI (I2C) non-blocking interrupt driven. Currently only supports master transmit mode * ceptimus. September 2016 */ #include "TWI.h" uint8_t TWI::slaveAddr; uint8_t *TWI::data; uint8_t TWI::remaining; callbackPtr TWI::callback; void TWI::TWIstart(void) { // configure for two wire interface operation // for 'standard' 400 kHz SCL frequency, set TWSR = 1 and TWBR = 3. TWSR = 1; // set prescaler to 4 TWBR = 3; // SCL = CPU clock / (16 + 2 * TWBR * prescaler) 16M / (16 + 2 * 3 * 4) = 400kHz } void TWI::nonBlockingTWImasterTransmit(uint8_t slave, uint8_t bytes[], uint8_t length, callbackPtr cback) { slaveAddr = slave; callback = cback; remaining = length; data = bytes; TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE); // send START condition and enable TWI interrupts } ISR(TWI_vect) { // TWI interrupt has occurred meaning that TWINT flag has been set uint8_t statusCode = TWSR & 0xF8; switch(statusCode) { case 0x08: // normal response to a START TWDR = TWI::slaveAddr << 1; // send slave address (and enter master transmit mode) TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // transmit address break; case 0x10: // normal response to a repeated START break; case 0x18: // normal response to slave address TWI::remaining--; TWDR = *TWI::data++; // send first byte of data TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // send data byte break; case 0x28: // normal response to data byte if (TWI::remaining) { // still have more data to transmit TWI::remaining--; TWDR = *TWI::data++; // send next byte of data TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // send data byte } else { // all data sent TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN) | (1 << TWIE); // send STOP condition sei(); // allow interrupts during callback TWI::callback(/* 1 */); // this can't be a response code as the Status Register is anded with F8 } break; case 0x38: // arbitration lost TWCR = (1 << TWINT) | (1 << TWEN); // disable further interrupts, release TW serial bus and enter slave mode sei(); // allow interrupts during callback TWI::callback(/* statusCode */); break; default: // unexpected response TWCR = TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // disable further interrupts, send STOP condition sei(); // allow interrupts during callback TWI::callback(/* statusCode */); break; } } . Edited 2019-08-29 00:45 by ceptimus |
||||
ajkw Senior Member ![]() Joined: 29/06/2011 Location: AustraliaPosts: 290 |
Peter, Is the source code for the SD1306 i2c driver for a Micromite available please? I would like to see if I can adapt it to make a SH1106 I have work correctly. With the all-basic-driver the SH1106 will , with a mod, work but and I can change the contrast too, however it is just not fast enough to draw a screen, so there is some hope. Perhaps I can make a change to the Csub version and then learn how to compile it. Regards, Anthony. Edited 2021-10-31 12:45 by ajkw |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
I've attached the complete MPLabX project SSD1306loadable.X.zip |
||||
ajkw Senior Member ![]() Joined: 29/06/2011 Location: AustraliaPosts: 290 |
Thank you Peter. I have identified the change I think I need to make and have gone on to install Mplab X. The first tutorial on creating Csub's mentions MPlab 3.10 and the compiler 1.33 however opening the project with this version generates a error has the project was created in something later. What versions should I be using please? Anthony. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10008 |
I'm currently running MPLabX V5.2 and compilers 1.33 and 1.44. This project was last built with V1.33 |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |