![]() |
Forum Index : Microcontroller and PC projects : SSD1331 96x64 colour OLED driver
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10066 |
As requested by WW for MM2. Can compile for MM+ if anyone needs it. ![]() NB: transparent text isn't possible as no MISO pin on display. I've included the 8x6 font as this is definitely needed for this display Sub mm.startup SSD1331 2,9,16, 1' DCpin, RESETpin, CSpin, orientation (1-4) End Sub ' ' File test.bas written 18-Jan-2019 11:22:59 ' CSub SSD1331 0000021E 'spi_write_data 27BDFFE0 AFBF001C AFB10018 AFB00014 309100FF 3C109D00 8E030090 8E02001C 8064002C 0040F809 24050006 8E030090 8E02001C 8064002D 0040F809 24050005 3C02BF80 AC515820 3C03BF80 8C625810 30420080 1040FFFD 3C02BF80 8C425820 3C029D00 8C430090 8C42001C 8064002D 0040F809 24050006 8FBF001C 8FB10018 8FB00014 03E00008 27BD0020 'spi_write_command 27BDFFE0 AFBF001C AFB10018 AFB00014 309100FF 3C109D00 8E030090 8E02001C 8064002C 0040F809 24050005 8E030090 8E02001C 8064002D 0040F809 24050005 3C02BF80 AC515820 3C03BF80 8C625810 30420080 1040FFFD 3C02BF80 8C425820 3C029D00 8C430090 8C42001C 8064002D 0040F809 24050006 8FBF001C 8FB10018 8FB00014 03E00008 27BD0020 'DefineRegion 27BDFFD8 AFBF0024 AFB30020 AFB2001C AFB10018 AFB00014 00808021 00A09021 00C08821 3C029D00 8C420090 90420015 30420001 10400015 00E09821 24040015 0411FFCC 00000000 320400FF 0411FFC9 00000000 322400FF 0411FFC6 00000000 24040075 0411FFC3 00000000 324400FF 0411FFC0 00000000 326400FF 0411FFBD 00000000 10000014 8FBF0024 24040075 0411FFB8 00000000 320400FF 0411FFB5 00000000 322400FF 0411FFB2 00000000 24040015 0411FFAF 00000000 324400FF 0411FFAC 00000000 326400FF 0411FFA9 00000000 8FBF0024 8FB30020 8FB2001C 8FB10018 8FB00014 03E00008 27BD0028 'DrawBitmapSPI 27BDFFB8 AFBF0044 AFBE0040 AFB7003C AFB60038 AFB50034 AFB40030 AFB3002C AFB20028 AFB10024 AFB00020 0080B021 00A0F021 00C0A021 AFA70054 8FA4005C 8FA30060 3C029D00 8C420094 8C420000 02C2102B 104000C3 8FB50064 3C029D00 8C420098 8C420000 00A2102B 104000BD 8FA20058 70462802 00B63021 04C000B9 70471002 005E2821 04A000B6 00003821 2BC50000 03C5380A 00E02821 3C07BF80 8CE85830 AFA80010 8CE85800 AFA80014 8CE85840 AFA80018 ACE05800 3C080001 35088260 ACE85800 ACE05830 24080C00 ACE85840 7C901340 00043C03 2408FFF8 00E83824 02078025 321000FF 7C9120C0 00042143 2407FFE0 00872024 02248825 323100FF 7C721340 00032403 00884024 02489025 325200FF 7C7320C0 00031943 00673824 02679825 327300FF 24A7FFFF 02C02021 24C6FFFF 00E23821 0411FF74 00000000 3C179D00 8EE30090 8EE2001C 8064002C 0040F809 24050006 8EE30090 8EE2001C 8064002D 0040F809 24050005 0014C823 8FA20054 70547802 25EFFFFF 0280B821 00005821 0000C021 8FAD0058 3C069D00 240C0001 1000004D 3C02BF80 27DE0001 27C3FFFF 04600044 00000000 8CC30098 8C630000 007E182B 1460006A 8FBF0044 1E80002D 01E04821 1000003B 00000000 24630001 2464FFFF 04800020 00000000 8CC40094 8C840000 0083202B 1480001B 00000000 91040000 00872024 1080000D 00000000 8C445810 30840002 1480FFFD 00000000 AC505820 8C445810 30840002 1480FFFD 00000000 AC515820 1000000B 00000000 8C445810 30840002 1480FFFD 00000000 AC525820 8C445810 30840002 1480FFFD 00000000 AC535820 5465FFDD 24630001 254A0001 15540005 2529FFFF 10000011 00000000 02C01821 00005021 014B2021 24850007 28880000 00A8200B 000440C3 02A84021 000927C3 00042742 01243821 30E70007 00E43823 00EC3804 1000FFC7 006D2821 57CEFFB9 27DE0001 27180001 01F97821 01775821 8FA40054 0304182A 10600005 8FA50058 1CA0FFAF 03C57021 1000FFF7 27180001 3C02BF80 8C435810 30630080 1060FFFD 00000000 10000002 3C02BF80 8C435820 8C435810 30630020 1060FFFC 00000000 3C02BF80 AC405800 24040040 3C03BF80 AC645814 8FA70010 AC475830 8FA80014 AC485800 8FA30018 AC435840 3C029D00 8C430090 8C42001C 8064002D 0040F809 24050006 8FBF0044 8FBE0040 8FB7003C 8FB60038 8FB50034 8FB40030 8FB3002C 8FB20028 8FB10024 8FB00020 03E00008 27BD0048 'DrawRectangleSPI 27BDFFC0 AFBF003C AFBE0038 AFB70034 AFB60030 AFB5002C AFB40028 AFB30024 AFB20020 AFB1001C AFB00018 8FA30050 3C02BF80 8C575830 8C5E5800 8C485840 AFA80010 AC405800 3C080001 35088260 AC485800 AC405830 24080C00 AC485840 0086102A 14400005 00A7102A 00801021 00C02021 00403021 00A7102A 14400004 28930000 00A01021 00E02821 00403821 0013200B 00809821 3C029D00 8C420094 8C420000 0082402B 2444FFFF 0088980A 28D40000 0014300B 00C0A021 00C2202B 2442FFFF 0044A00A 28B50000 0015280B 00A0A821 3C029D00 8C420098 8C420000 00A2282B 2444FFFF 0085A80A 28F60000 0016380B 00E0B021 00E2202B 2442FFFF 0044B00A 7C711340 00032403 2402FFF8 00821024 02228825 323100FF 7C7020C0 00031943 2402FFE0 00621824 02038025 321000FF 02602021 02A02821 02803021 02C03821 0411FE8D 00000000 3C129D00 8E430090 8E42001C 8064002C 0040F809 24050006 8E430090 8E42001C 8064002D 0040F809 24050005 24020001 00539823 0274A021 00552023 00962021 70942002 1080000E 2484FFFF 3C02BF80 8C435810 30630002 1460FFFD 00000000 AC515820 8C435810 30630002 1460FFFD 00000000 AC505820 1480FFF5 2484FFFF 3C03BF80 8C625810 30420080 1040FFFD 3C02BF80 8C425810 30420020 14400006 3C02BF80 8C435820 8C435810 30630020 1060FFFC 00000000 3C02BF80 AC405800 24040040 3C03BF80 AC645814 AC575830 AC5E5800 8FA30010 AC435840 3C029D00 8C430090 8C42001C 8064002D 0040F809 24050006 8FBF003C 8FBE0038 8FB70034 8FB60030 8FB5002C 8FB40028 8FB30024 8FB20020 8FB1001C 8FB00018 03E00008 27BD0040 'getFPC 27BDFFF8 AFBF0004 00852023 03E42021 ACC40000 8FBF0004 03E00008 27BD0008 'pstring 27BDFFE0 AFBF001C AFB00018 00808021 00002021 3C059D00 24A50854 27A60010 0411FFEF 00000000 8FA40010 3C029D00 8C42002C 0040F809 02042021 8FBF001C 8FB00018 03E00008 27BD0020 'main 27BDFFC0 AFBF003C AFB50038 AFB40034 AFB30030 AFB2002C AFB10028 AFB00024 00809021 00A08821 00C09821 00E0A021 00002021 3C059D00 24A508C0 27A60018 0411FFD4 00000000 3C109D00 8E020090 8E230000 A043002E 8E020090 8E430000 A043002C 8E020090 8E630000 A043002D 8E020090 8E830000 A0430015 8E020090 24030014 A0430014 8E030090 8E020010 8064002E 24050008 0040F809 00003021 8E030090 8E020010 8064002E 24050065 0040F809 00003021 8E030090 8E02001C 8064002E 0040F809 24050006 8E030090 8E020010 8064002C 24050008 0040F809 00003021 8E030090 8E020010 8064002C 24050065 0040F809 00003021 8E030090 8E02001C 8064002C 0040F809 24050006 8E030090 8E020010 8064002D 24050008 0040F809 00003021 8E030090 8E020010 8064002D 24050065 0040F809 00003021 8E030090 8E02001C 8064002D 0040F809 24050006 3C02BF81 8C44F220 7C84D800 3C020661 3442A053 1082000B 24030050 3C02BF81 8C43F220 7C63D800 3C020660 3442A053 00621826 24020050 2404000C 0083100B 00401821 3C029D00 8C420088 00621821 8C640000 24030064 54830007 00008821 3C03BF80 8C715830 8C725800 8C755840 10000003 3C03BF81 00009021 3C03BF81 8C65F220 7CA5D800 3C040661 3484A053 10A4000B 24030050 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00831826 24040050 2405000C 00A3200B 00801821 00621021 8C430000 24020065 1062008E 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 24040014 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 24030014 24050003 00A4180B 00602021 24050008 0040F809 00003021 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 24040014 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 24030014 24050003 00A4180B 00602021 24050065 0040F809 00003021 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 24040029 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 24030029 2405000E 00A4180B 00602021 24050002 0040F809 00003021 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 24040029 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 24030029 2405000E 00A4180B 00602021 24050065 0040F809 00003021 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 2404000E 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 2403000E 24050019 00A4180B 00602021 24050008 0040F809 00003021 3C029D00 8C420010 3C03BF81 8C65F220 7CA5D800 3C030661 3463A053 10A3000B 2404000E 3C03BF81 8C64F220 7C84D800 3C030660 3463A053 00832026 2403000E 24050019 00A4180B 00602021 24050065 0040F809 00003021 3C02BF81 8C43FA84 24040001 7C831804 AC43FA84 3C02BF81 8C43FB04 24040003 7C831804 AC43FB04 3C02BF80 34038060 AC435800 24030003 AC435830 24030C00 AC435840 16200005 3C109D00 8C515830 8C525800 8C555840 3C109D00 8E030090 8E02001C 8064002E 0040F809 24050006 8E020004 0040F809 24042710 8E030090 8E02001C 8064002E 0040F809 24050005 8E020004 0040F809 24042710 8E030090 8E02001C 8064002E 0040F809 24050006 240400AE 0411FCCA 00000000 240400A0 0411FCC7 00000000 8E020090 80420015 24030001 14430006 24030002 24040072 0411FCBF 00000000 10000012 240400A1 14430006 24030003 24040063 0411FCB8 00000000 1000000B 240400A1 54430006 24040071 24040060 0411FCB1 00000000 10000004 240400A1 0411FCAD 00000000 240400A1 0411FCAA 00000000 00002021 0411FCA7 00000000 240400A2 0411FCA4 00000000 00002021 0411FCA1 00000000 240400A4 0411FC9E 00000000 240400A8 0411FC9B 00000000 2404003F 0411FC98 00000000 240400AD 0411FC95 00000000 2404008E 0411FC92 00000000 240400B0 0411FC8F 00000000 2404000B 0411FC8C 00000000 240400B1 0411FC89 00000000 24040031 0411FC86 00000000 240400B3 0411FC83 00000000 240400F0 0411FC80 00000000 2404008A 0411FC7D 00000000 24040064 0411FC7A 00000000 2404008B 0411FC77 00000000 24040078 0411FC74 00000000 2404008A 0411FC71 00000000 24040064 0411FC6E 00000000 240400BB 0411FC6B 00000000 2404003A 0411FC68 00000000 240400BE 0411FC65 00000000 2404003E 0411FC62 00000000 24040087 0411FC5F 00000000 24040006 0411FC5C 00000000 24040081 0411FC59 00000000 24040091 0411FC56 00000000 24040082 0411FC53 00000000 24040050 0411FC50 00000000 24040083 0411FC4D 00000000 2404007D 0411FC4A 00000000 240400AF 0411FC47 00000000 3C029D00 8C420090 90420015 30420001 10400008 3C029D00 8C430094 24040060 AC640000 8C420098 24030040 10000007 AC430000 8C430098 24040060 AC640000 8C420094 24030040 AC430000 8FA50018 3C029D00 8C430048 3C049D00 2484059C 00852021 AC640000 8FA50018 8C43004C 3C049D00 24840208 00852021 AC640000 8C430048 8C440094 8C860000 8C420098 8C470000 AFA00010 8C620000 00002021 00002821 24C6FFFF 0040F809 24E7FFFF 3C02BF80 AC515830 AC525800 AC555840 3C049D00 24841068 0411FDFB 00000000 8FBF003C 8FB50038 8FB40034 8FB30030 8FB2002C 8FB10028 8FB00024 03E00008 27BD0040 '.rodata 'startup 31445353 20313333 76697264 6C207265 6564616F 000A0D64 End CSub DefineFont #8 5C200806 00000000 82200000 00800008 00004551 4F510000 0045F994 2B1CEA21 690000C2 B04C2090 AA104A62 84608046 00000000 40108410 81400081 00841004 A89C8A00 82000080 0080203E 30000000 00000042 0000003E 01000000 21000086 00004208 CAAA2972 82210027 00872008 21842072 42F8800F 00270A04 F824C510 0FFA0041 00270A02 8A3C0831 21F80027 00044108 8A9C2872 28720027 0027089E 61008601 86010080 00846000 40208410 0F000081 0000F880 10028140 20720084 00022084 BA9A2072 28720027 8028FAA2 8ABC28F2 2872002F 00278220 8AA248E2 08FA004E 800F823C 823C08FA 28720008 80278A2E 8ABE288A 82708028 00872008 12044138 4A8A0046 8048A230 82200882 6A8B800F 80288AAA 9AAA2C8A 28728028 00278AA2 82BC28F2 28720008 8046AAA2 A2BC28F2 087A8048 002F081C 200882F8 288A0082 00278AA2 89A2288A 288A0042 00A5AAAA 5208258A 288A8028 00822094 420821F8 0471800F 00074110 A9944AA9 4170804A 00471004 00804821 00000000 800F0000 00008140 07000000 80277A02 8A320B82 0700002F 00278220 8AA62608 07008027 0007FA22 41382431 E8010004 002778A2 8A320B82 06208028 00872008 12040310 09820046 0089C228 20088260 0D000087 8028AA2A 8A320B00 07008028 00278A22 F2220F00 06000008 802078A6 82320B00 07000008 002F7020 41100E41 08000023 80668AA2 89A20800 08000042 00A5AAA2 21940800 08008048 002778A2 21840F00 0400800F 0EE24028 End DefineFont /******************************************************************************* * * Driver for SSD1331 Display written as CSUB * * (c) Peter Mather 2019 with acknowledgements to Peter Carnegie & Geoff Graham * Also thanks to ADAfruit for the initialisation sequence * * * This CSUB MUST be compiled with Optimization Level 1, -O1 * -O2,-O3,-Os will compile successfully, but generate exceptions at runtime. * * When Generating the CSUB, use MERGE CSUB mode, and name the CSUB * SSD1331 * * Entry point is function long long main(long long *DC, * long long *RST, * long long *CS * long long *orientation) * * V1.0 2019-01-18 Peter Mather * ******************************************************************************/ #include <stdarg.h> #define Version 100 //Version 1.00 #define _SUPPRESS_PLIB_WARNING // required for XC1.33 Later compiler versions will need PLIB to be installed #include <plib.h> // the pre Harmony peripheral libraries #include "../cfunctions.h" // Select one of these defines to set the pixel color order #define SSD1331_COLORORDER_RGB // #define SSD1331_COLORORDER_BGR #if defined SSD1331_COLORORDER_RGB && defined SSD1331_COLORORDER_BGR #error "RGB and BGR can not both be defined for SSD1331_COLORODER." #endif // Timing Delays #define SSD1331_DELAYS_HWFILL (3) #define SSD1331_DELAYS_HWLINE (1) // SSD1331 Commands #define SSD1331_CMD_DRAWLINE 0x21 #define SSD1331_CMD_DRAWRECT 0x22 #define SSD1331_CMD_FILL 0x26 #define SSD1331_CMD_SETCOLUMN 0x15 #define SSD1331_CMD_SETROW 0x75 #define SSD1331_CMD_CONTRASTA 0x81 #define SSD1331_CMD_CONTRASTB 0x82 #define SSD1331_CMD_CONTRASTC 0x83 #define SSD1331_CMD_MASTERCURRENT 0x87 #define SSD1331_CMD_SETREMAP 0xA0 #define SSD1331_CMD_STARTLINE 0xA1 #define SSD1331_CMD_DISPLAYOFFSET 0xA2 #define SSD1331_CMD_NORMALDISPLAY 0xA4 #define SSD1331_CMD_DISPLAYALLON 0xA5 #define SSD1331_CMD_DISPLAYALLOFF 0xA6 #define SSD1331_CMD_INVERTDISPLAY 0xA7 #define SSD1331_CMD_SETMULTIPLEX 0xA8 #define SSD1331_CMD_SETMASTER 0xAD #define SSD1331_CMD_DISPLAYOFF 0xAE #define SSD1331_CMD_DISPLAYON 0xAF #define SSD1331_CMD_POWERMODE 0xB0 #define SSD1331_CMD_PRECHARGE 0xB1 #define SSD1331_CMD_CLOCKDIV 0xB3 #define SSD1331_CMD_PRECHARGEA 0x8A #define SSD1331_CMD_PRECHARGEB 0x8B #define SSD1331_CMD_PRECHARGEC 0x8C #define SSD1331_CMD_PRECHARGELEVEL 0xBB #define SSD1331_CMD_VCOMH 0xBE #define LANDSCAPE 1 #define PORTRAIT 2 #define RLANDSCAPE 3 #define RPORTRAIT 4 #define MX170 #if defined(MX170) // SPI pin numbers and registers #define SPI_INP_PIN (HAS_44PINS ? 41 : 14) #define SPI_OUT_PIN (HAS_44PINS ? 20 : 3) #define SPI_CLK_PIN (HAS_44PINS ? 14 : 25) #define SPI_PPS_OPEN PPSInput(2, SDI1, RPB5); PPSOutput(2, RPA1, SDO1) #define SPI_PPS_CLOSE PPSOutput(2, RPA1, NULL) #define SPICON *(volatile unsigned int *)(0xbf805800) //SPI status register #define SPISTAT *(volatile unsigned int *)(0xbf805810) //SPI status register #define SPIBUF *(volatile unsigned int *)(0xbf805820) //SPI output buffer #define SPIBRG *(volatile unsigned int *)(0xbf805830) //SPI output buffer #define SPICON2 *(volatile unsigned int *)(0xbf805840) //SPI status register #define SPISTATCLR *(volatile unsigned int *)(0xbf805814) //SPI status clear register #define ILImode 0x18520 #define ILIbrg 0 #elif defined(MX470) // SPI pin numbers and registers #define SPI_INP_PIN (HAS_100PINS ? 11 : 47) #define SPI_OUT_PIN (HAS_100PINS ? 12 : 5) #define SPI_CLK_PIN (HAS_100PINS ? 10 : 4) #define SPI_PPS_OPEN { if(HAS_100PINS) {PPSInput(2, SDI2, RPG7); PPSOutput(1, RPG8, SDO2); } else {PPSInput(2, SDI2, RPC13); PPSOutput(2, RPG7, SDO2);}} #define SPI_PPS_CLOSE { if(HAS_100PINS) PPSOutput(1, RPG8, NULL); else PPSOutput(2, RPG7, NULL); } #define SPICON *(volatile unsigned int *)(0xbf805A00) //SPI status register #define SPISTAT *(volatile unsigned int *)(0xbf805A10) //SPI status register #define SPIBUF *(volatile unsigned int *)(0xbf805A20) //SPI output buffer #define SPIBRG *(volatile unsigned int *)(0xbf805A30) //SPI output buffer #define SPICON2 *(volatile unsigned int *)(0xbf805A40) //SPI status register #define SPISTATCLR *(volatile unsigned int *)(0xbf805A14) //SPI status clear register #endif #define SPIsend(a) {int j;SPIBUF=a; while((SPISTAT & 0x80)==0); j=SPIBUF;} #define SPIqueue(a) {while(SPISTAT & 0x02){};SPIBUF=a;} // set the chip select for the SPI to low (enabled) // if the SPI is currently set to a different mode or baudrate this will change it accordingly // also, it checks if the chip select pin needs to be changed // set the chip select for SPI1 to high (disabled) void spi_write_data(unsigned char data){ PinSetBit(Option->LCD_CD, LATSET); PinSetBit(Option->LCD_CS, LATCLR); SPIsend(data); PinSetBit(Option->LCD_CS, LATSET); } void spi_write_command(unsigned char data){ PinSetBit(Option->LCD_CD, LATCLR); PinSetBit(Option->LCD_CS, LATCLR); SPIsend(data); PinSetBit(Option->LCD_CS, LATSET); } /******************************************************************************* * * defines start/end coordinates for memory access from host to SSD1963 * also maps the start and end points to suit the orientation * * This function is a modified version of the function inside the MMBasic Interpreter * for MM+ on 'MX470 chips * *******************************************************************************/ void DefineRegion(int x1, int y1, int x2, int y2) { if(Option->DISPLAY_ORIENTATION&1){ spi_write_command(0x15); // Column addr set spi_write_command(x1); spi_write_command(x2); spi_write_command(0x75); // Row addr set spi_write_command(y1); spi_write_command(y2); } else { spi_write_command(0x75); // Row addr set spi_write_command(x1); spi_write_command(x2); spi_write_command(0x15); // Column addr set spi_write_command(y1); spi_write_command(y2); } } //Print the bitmap of a char on the video output // x, y - the top left of the char // width, height - size of the char's bitmap // scale - how much to scale the bitmap // fc, bc - foreground and background colour // bitmap - pointer to the bitmap void DrawBitmapSPI(int x1, int y1, int width, int height, int scale, int fc, int bc, unsigned char *bitmap){ int i, j, k, m; unsigned char fhb, flb, bhb, blb; unsigned int consave=0,brgsave=0,con2save; int vertCoord, horizCoord, XStart, XEnd, YEnd; if(x1>=HRes || y1>=VRes || x1+width*scale<0 || y1+height*scale<0)return; // adjust when part of the bitmap is outside the displayable coordinates vertCoord = y1; if(y1 < 0) y1 = 0; // the y coord is above the top of the screen XStart = x1; if(XStart < 0) XStart = 0; // the x coord is to the left of the left marginn XEnd = x1 + (width * scale) - 1; if(XEnd >= HRes) XEnd = HRes - 1; // the width of the bitmap will extend beyond the right margin YEnd = y1 + (height * scale) - 1; if(YEnd >= VRes) YEnd = VRes - 1;// the height of the bitmap will extend beyond the bottom margin brgsave=SPIBRG; //save any user SPI setup consave=SPICON; con2save=SPICON2; SPICON=0x0; SPICON=0x018260; #ifdef MX470 SPIBRG=0; #else SPIBRG=0; #endif SPICON2=0xC00; // convert the colours to 565 format fhb = ((fc >> 16) & 0b11111000) | ((fc >> 13) & 0b00000111); flb = ((fc >> 5) & 0b11100000) | ((fc >> 3) & 0b00011111); bhb = ((bc >> 16) & 0b11111000) | ((bc >> 13) & 0b00000111); blb = ((bc >> 5) & 0b11100000) | ((bc >> 3) & 0b00011111); DefineRegion(x1, y1, x1 + (width * scale) - 1, y1 + (height * scale) -1); PinSetBit(Option->LCD_CD, LATSET); //set CD high PinSetBit(Option->LCD_CS, LATCLR); for(i = 0; i < height; i++) { // step thru the font scan line by line for(j = 0; j < scale; j++) { // repeat lines to scale the font if(vertCoord++ < 0) continue; // we are above the top of the screen if(vertCoord > VRes) return; // we have extended beyond the bottom of the screen horizCoord = x1; for(k = 0; k < width; k++) { // step through each bit in a scan line for(m = 0; m < scale; m++) { // repeat pixels to scale in the x axis if(horizCoord++ < 0) continue; // we have not reached the left margin if(horizCoord > HRes) continue; // we are beyond the right margin if((bitmap[((i * width) + k)/8] >> (((height * width) - ((i * width) + k) - 1) %8)) & 1) { SPIqueue(fhb); SPIqueue(flb); } else { SPIqueue(bhb); SPIqueue(blb); } } } } } while((SPISTAT & 0x80)==0); //wait for all writes to complete while(!(SPISTAT & 0x20)){i=SPIBUF;} // clean up rx fifo if not empty SPICON=0; #ifdef MX470 SPI2STATCLR=0x40; #else SPI1STATCLR=0x40; #endif SPIBRG=brgsave; //restore user (or my) setup SPICON=consave; SPICON2=con2save; PinSetBit(Option->LCD_CS, LATSET); } // Draw a rectangle // this is the basic drawing primitive used by most drawing routines // x1, y1, x2, y2 - the coordinates // c - the colour void DrawRectangleSPI(int x1, int y1, int x2, int y2, int c){ unsigned int consave=0,brgsave=0,con2save; int i, t; unsigned char hb, lb; brgsave=SPIBRG; //save any user SPI setup consave=SPICON; con2save=SPICON2; SPICON=0x0; SPICON=0x018260; #ifdef MX470 SPIBRG=0; #else SPIBRG=0; #endif SPICON2=0xC00; // make sure the coordinates are kept within the display area if(x2 <= x1) { t = x1; x1 = x2; x2 = t; } if(y2 <= y1) { t = y1; y1 = y2; y2 = t; } if(x1 < 0) x1 = 0; if(x1 >= HRes) x1 = HRes - 1; if(x2 < 0) x2 = 0; if(x2 >= HRes) x2 = HRes - 1; if(y1 < 0) y1 = 0; if(y1 >= VRes) y1 = VRes - 1; if(y2 < 0) y2 = 0; if(y2 >= VRes) y2 = VRes - 1; // convert the colours to 565 format hb = ((c >> 16) & 0b11111000) | ((c >> 13) & 0b00000111); lb = ((c >> 5) & 0b11100000) | ((c >> 3) & 0b00011111); DefineRegion(x1, y1, x2, y2); PinSetBit(Option->LCD_CD, LATSET); //set CD high PinSetBit(Option->LCD_CS, LATCLR); i = x2 - x1 + 1; i *= (y2 - y1 + 1); while(i--){ SPIqueue(hb); SPIqueue(lb); } while((SPISTAT & 0x80)==0); //wait for all writes to complete while(!(SPISTAT & 0x20)){i=SPIBUF;} // clean up rx fifo if not empty SPICON=0; #ifdef MX470 SPI2STATCLR=0x40; #else SPI1STATCLR=0x40; #endif SPIBRG=brgsave; //restore user (or my) setup SPICON=consave; SPICON2=con2save; PinSetBit(Option->LCD_CS, LATSET); } #ifdef MX470 void DrawBufferSPI(int x1, int y1, int x2, int y2, char* p) { unsigned int i, consave=0,brgsave=0,con2save; brgsave=SPIBRG; //save any user SPI setup consave=SPICON; con2save=SPICON2; SPICON=0x0; SPICON=0x018260; #ifdef MX470 SPIBRG=0; #else SPIBRG=0; #endif SPICON2=0xC00; unsigned char hb, lb; union colourmap { char rgbbytes[4]; unsigned int rgb; } c; int xx1=x1, yy1=y1, xx2=x2, yy2=y2, x, y, t ; // make sure the coordinates are kept within the display area if(x2 <= x1) { t = x1; x1 = x2; x2 = t; } if(y2 <= y1) { t = y1; y1 = y2; y2 = t; } if(x1 < 0) xx1 = 0; if(x1 >= HRes) xx1 = HRes - 1; if(x2 < 0) xx2 = 0; if(x2 >= HRes) xx2 = HRes - 1; if(y1 < 0) yy1 = 0; if(y1 >= VRes) yy1 = VRes - 1; if(y2 < 0) yy2 = 0; if(y2 >= VRes) yy2 = VRes - 1; DefineRegion(xx1, yy1, xx2, yy2); PinSetBit(Option->LCD_CD, LATSET); //set CD high PinSetBit(Option->LCD_CS, LATCLR); for(y=y1;y<=y2;y++){ for(x=x1;x<=x2;x++){ if(x>=0 && x<HRes && y>=0 && y<VRes){ c.rgbbytes[0]=*p++; //this order swaps the bytes to match the .BMP file c.rgbbytes[1]=*p++; c.rgbbytes[2]=*p++; // convert the colours to 565 format hb = ((c.rgb >> 16) & 0b11111000) | ((c.rgb >> 13) & 0b00000111); lb = ((c.rgb >> 5) & 0b11100000) | ((c.rgb >> 3) & 0b00011111); SPIqueue(hb); SPIqueue(lb); } else p+=3; } } while((SPISTAT & 0x80)==0); //wait for all writes to complete while(!(SPISTAT & 0x20)){i=SPIBUF;} // clean up rx fifo if not empty SPICON=0; #ifdef MX470 SPI2STATCLR=0x40; #else SPI1STATCLR=0x40; #endif SPIBRG=brgsave; //restore user (or my) setup SPICON=consave; SPICON2=con2save; PinSetBit(Option->LCD_CS, LATSET); } #endif __attribute__((noinline)) void getFPC(void *a, void *b, volatile unsigned int *c) { *c = (unsigned int) (__builtin_return_address (0) - (b -a)) ; } void pstring(const char *s){ volatile unsigned int libAddr ; getFPC(NULL,&&getFPCLab,&libAddr) ; // warning can be ignored, stupid editor getFPCLab: { } unsigned char * testData = (unsigned char *)((void *)s + libAddr ); MMPrintString(testData); } /******************************************************************************* * * ST7735 : Initialise the CFunction Driver Sub-System * * Function called to initialise the driver SubSystem * * ST7735 is ALWAYS called from an MMBasic program * On exit, vectors DrawRectangleVector, and DrawBitmapVector will * be set to point to the CFunctions DrawRectangleSPI and * DrawBitmapSPI respectively * * Entry point is function long long main(long long *MyAddress, * long long *DC, * long long *RST, * long long *CS * long long *orientation) * long long *size) * ******************************************************************************/ //CFunction Driver_SSD1331 void main(long long *CD, long long *RST, long long *CS,long long *orientation){ volatile unsigned int libAddr ; getFPC(NULL,&&getFPCLab,&libAddr) ; // warning can be ignored getFPCLab: { } int HorizontalRes=96,VerticalRes=64; unsigned int consave=0,brgsave=0,con2save; Option->LCD_Reset=*RST; Option->LCD_CD=*CD; Option->LCD_CS=*CS; Option->DISPLAY_ORIENTATION=*orientation; Option->DISPLAY_TYPE=20; ExtCfg(Option->LCD_Reset,EXT_DIG_OUT,0);ExtCfg(Option->LCD_Reset,EXT_BOOT_RESERVED,0); PinSetBit(Option->LCD_Reset, LATSET); ExtCfg(Option->LCD_CD,EXT_DIG_OUT,0);ExtCfg(Option->LCD_CD,EXT_BOOT_RESERVED,0); PinSetBit(Option->LCD_CD, LATSET); ExtCfg(Option->LCD_CS,EXT_DIG_OUT,0);ExtCfg(Option->LCD_CS,EXT_BOOT_RESERVED,0); PinSetBit(Option->LCD_CS, LATSET); if(ExtCurrentConfig[SPI_OUT_PIN] == EXT_RESERVED) { //already open brgsave=SPIBRG; consave=SPICON; con2save=SPICON2; } if(ExtCurrentConfig[SPI_OUT_PIN]!=EXT_BOOT_RESERVED){ ExtCfg(SPI_OUT_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_OUT_PIN, EXT_BOOT_RESERVED, 0); ExtCfg(SPI_INP_PIN, EXT_DIG_IN, 0); ExtCfg(SPI_INP_PIN, EXT_BOOT_RESERVED, 0); ExtCfg(SPI_CLK_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_CLK_PIN, EXT_BOOT_RESERVED, 0); SPI_PPS_OPEN; } SPICON=0x8060; SPIBRG=3; SPICON2=0xC00;// this is defined in IOPorts.h if(!brgsave){ //save my settings brgsave=SPIBRG; consave=SPICON; con2save=SPICON2; } //Reset the SSD1331 PinSetBit(Option->LCD_Reset,LATSET); uSec(10000); PinSetBit(Option->LCD_Reset,LATCLR); uSec(10000); PinSetBit(Option->LCD_Reset,LATSET); spi_write_command(SSD1331_CMD_DISPLAYOFF); // 0xAE spi_write_command(SSD1331_CMD_SETREMAP); // 0xA0 if(Option->DISPLAY_ORIENTATION==1) spi_write_command(0x72); else if(Option->DISPLAY_ORIENTATION==2) spi_write_command(0x63); else if(Option->DISPLAY_ORIENTATION==3) spi_write_command(0x60); else spi_write_command(0x71); spi_write_command(SSD1331_CMD_STARTLINE); // 0xA1 spi_write_command(0x0); spi_write_command(SSD1331_CMD_DISPLAYOFFSET); // 0xA2 spi_write_command(0x0); spi_write_command(SSD1331_CMD_NORMALDISPLAY); // 0xA4 spi_write_command(SSD1331_CMD_SETMULTIPLEX); // 0xA8 spi_write_command(0x3F); // 0x3F 1/64 duty spi_write_command(SSD1331_CMD_SETMASTER); // 0xAD spi_write_command(0x8E); spi_write_command(SSD1331_CMD_POWERMODE); // 0xB0 spi_write_command(0x0B); spi_write_command(SSD1331_CMD_PRECHARGE); // 0xB1 spi_write_command(0x31); spi_write_command(SSD1331_CMD_CLOCKDIV); // 0xB3 spi_write_command(0xF0); // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16) spi_write_command(SSD1331_CMD_PRECHARGEA); // 0x8A spi_write_command(0x64); spi_write_command(SSD1331_CMD_PRECHARGEB); // 0x8B spi_write_command(0x78); spi_write_command(SSD1331_CMD_PRECHARGEA); // 0x8C spi_write_command(0x64); spi_write_command(SSD1331_CMD_PRECHARGELEVEL); // 0xBB spi_write_command(0x3A); spi_write_command(SSD1331_CMD_VCOMH); // 0xBE spi_write_command(0x3E); spi_write_command(SSD1331_CMD_MASTERCURRENT); // 0x87 spi_write_command(0x06); spi_write_command(SSD1331_CMD_CONTRASTA); // 0x81 spi_write_command(0x91); spi_write_command(SSD1331_CMD_CONTRASTB); // 0x82 spi_write_command(0x50); spi_write_command(SSD1331_CMD_CONTRASTC); // 0x83 spi_write_command(0x7D); spi_write_command(SSD1331_CMD_DISPLAYON); //--turn on oled panel if(Option->DISPLAY_ORIENTATION&1){ HRes=HorizontalRes; VRes=VerticalRes; } else { VRes=HorizontalRes; HRes=VerticalRes; } //Set the DrawRectangle vector to point to our function DrawRectangleVector= (unsigned int)&DrawRectangleSPI + libAddr; //Set the DrawBitmap vector to point to our function DrawBitmapVector=(unsigned int)&DrawBitmapSPI + libAddr; #ifdef MX470 DrawBufferVector=(unsigned int)&DrawBufferSPI + libAddr; #endif //CLS DrawRectangle(0,0,HRes-1,VRes-1,0x000000); SPIBRG=brgsave; //restore user (or my) setup SPICON=consave; SPICON2=con2save; static const char startup[]="SSD1331 driver loaded\r\n"; pstring(startup); } |
||||
disco4now![]() Guru ![]() Joined: 18/12/2014 Location: AustraliaPosts: 971 |
I have added this LCD panel to the table I have been creating on the Fruit of the Shed wiki. This page is an attempt to identify and link to the various TBS posts about LCDPANEL drivers available for the various MMBasic platforms. LCD Panel Summary Regards Gerry Latest F4 Latest H7 FotS |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |