{"id":4237,"date":"2020-08-05T20:00:00","date_gmt":"2020-08-05T18:00:00","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4237"},"modified":"2025-12-27T16:20:38","modified_gmt":"2025-12-27T15:20:38","slug":"grayscale-oled-on-ssd1327-part-2","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/grayscale-oled-on-ssd1327-part-2\/","title":{"rendered":"Grayscale OLED on SSD1327 Part 2"},"content":{"rendered":"\n<p>Recently I did a bit of theorizing about an <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">OLED with a 16-level grayscale.<\/a> We already know how those 16 colors are obtained and how the display\u2019s RAM memory is organized. Time to display something on it, right? First, we\u2019ll try using a graphics library from a regular monochrome OLED, which I used for the <a href=\"http:\/\/msalamon.pl\/wyswietlacze-oled-ssd1306-i2c-czy-spi\/\">SSD1306<\/a>. Let\u2019s get to it!<\/p>\n\n\n\n<!--more-->\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=ssd1327\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/OLED-SSD1327-baner.jpg\" alt=\"\" class=\"wp-image-1606\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/OLED-SSD1327-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/OLED-SSD1327-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/OLED-SSD1327-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/OLED-SSD1327-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\"><strong><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">You can buy an OLED like this with grayscale from me.<\/a><\/strong><\/p>\n\n\n\n<p class=\"has-text-align-center\"><span style=\"font-size: 24pt;\"><strong>Table of contents for the entire SSD1327 OLED series:<\/strong><\/span><\/p>\n\n\n\n<p class=\"has-text-align-center\"><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-1\/\">Grayscale OLED on SSD1327 part 1<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-2\/\">Grayscale OLED on SSD1327 part 2<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/jak-przygotowac-obraz-dla-wyswietlacza-lcd-lub-tft\/\">How to prepare an image for an LCD or TFT display?<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-3\/\">Grayscale OLED on SSD1327 part 3<\/a><\/strong><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Wiring and Cube<\/h1>\n\n\n\n<p>For today\u2019s project I used a <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/nucleo-f401re\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">Nucleo F401RE<\/a>.<\/p>\n\n\n\n<p class=\"has-text-align-center\"><span style=\"font-size: 24pt;\"><strong><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/nucleo-f401re\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">You can buy such a Nucleo from me in my store.<\/a><\/strong><\/span><\/p>\n\n\n\n<p>Versions of the programs used:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>STM32CubeIDE 1.3.0<\/li>\n\n\n\n<li>STM32CubeMX 5.6.0 built into the IDE<\/li>\n\n\n\n<li>HAL F4 library\u00a0<\/li>\n<\/ul>\n\n\n\n<p>The wiring is so simple that I won\u2019t draw it. I connected to I\u00b2C1 with pins remapped to those on the Arduino connector.<\/p>\n\n\n\n<p>For now I left I\u00b2C1 in the default 100 kHz configuration. Later there will be time for changes and comparisons.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Initializing the SSD1327 OLED<\/h1>\n\n\n\n<p>At first I wanted to write the initialization procedure myself. After all, it\u2019s just a few registers and with the documentation you can achieve a satisfactory result sooner or later. Well, yes\u2026 later. I thought about it for a while and realized that the controller is connected to the pixels in a rather non-obvious way. The first thing I ran into was the image being displayed upside down by default, but that was fairly easy to fix.<\/p>\n\n\n\n<p>Only later did I notice that the pixels are slightly shifted\u2026 I fought with it for a good 10 minutes, until I decided to give up. I started searching the Internet for some ready-made code from which I could pull the initialization procedure.<\/p>\n\n\n\n<p><strong>Remember that there\u2019s nothing wrong with using ready-made solutions, as long as we know what they do and what they can be used for.<\/strong> Often there\u2019s no point reinventing the wheel. That\u2019s usually why manufacturers provide demo code\u2014to be used. Well, yes\u2014manufacturers. Unfortunately, with an <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">OLED from<\/a> <em><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">No Name<\/a>&nbsp;<\/em> companies, we may not find the manufacturer\u2019s code. So you have to rely on, for example, Arduino libraries.<\/p>\n\n\n\n<p>How surprised I was when I saw that <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">this OLED<\/a> isn\u2019t particularly popular among Arduino folks! Luckily, the <a href=\"https:\/\/github.com\/olikraus\/u8g2\" target=\"_blank\" rel=\"noopener\">u8g2 library<\/a> has the initialization for <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/wyswietlacz-oled-132-skala-szarosci-bialy\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=ssd1327&amp;utm_content=Text\">these OLEDs<\/a> built in. Admittedly it\u2019s written a bit cryptically, but I managed to decipher it into human language. So I took the lib, copied it and\u2026 it worked. Thanks, Arduino friends, for the help! \ud83d\ude42<\/p>\n\n\n\n<p><strong>By the way, someday I\u2019d try to run this library on an STM32 under HAL. What do you think? Let me know in the comments!<\/strong><\/p>\n\n\n\n<p>The commands of the SSD1327 controller itself are very similar to those from the SSD1306, so I kept the convention of writing the library. Thanks to that, a lot of work was saved. This is what the initialization looks like.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void SSD1327_Init(void)\n{\n\tSSD1327_Command(SSD1327_DISPLAYOFF);  \/\/ Display Off\n\n\tSSD1327_Command(SSD1327_SETMULTIPLEX);\n\tSSD1327_Command(0x5F);\n\n\tSSD1327_Command(SSD1327_SETDISPLAYSTARTLINE);\n\tSSD1327_Command(0x00);\n\n\tSSD1327_Command(SSD1327_SETDISPLAYOFFSET);\n\tSSD1327_Command(0x20);\n\n\tSSD1327_Command(SSD1327_SEGREMAP);\n\tSSD1327_Command(0x51);\n\n\tSSD1327_SetContrast(0x7F);\n\n\tSSD1327_Command(SSD1327_SETPHASELENGTH);\n\tSSD1327_Command(0x22);\n\n\tSSD1327_Command(SSD1327_SETFRONTCLOCKDIVIDER_OSCILLATORFREQUENCY);\n\tSSD1327_Command(0x50);\n\n\tSSD1327_Command(SSD1327_SELECTDEFAULTLINEARGRAYSCALETABLE);\n\n\tSSD1327_Command(SSD1327_SETPRECHARGEVOLTAGE);\n\tSSD1327_Command(0x10);\n\n\tSSD1327_Command(SSD1327_SETSETVCOMVOLTAGE);\n\tSSD1327_Command(0x05);\n\n\tSSD1327_Command(SSD1327_SETSECONDPRECHARGEPERTIOD);\n\tSSD1327_Command(0x0a);\n\n\tSSD1327_Command(SSD1327_FUNCTIONSELECTIONB);\n\tSSD1327_Command(0x62);\n\n\tSSD1327_Command(SSD1327_SETCOLUMNADDRESS);\n\tSSD1327_Command(0x00);\n\tSSD1327_Command(0x3F);\n\n\tSSD1327_Command(SSD1327_SETROWADDRESS);\n\tSSD1327_Command(0x00);\n\tSSD1327_Command(0x5F);\n\n\tSSD1327_Command(SSD1327_NORMALDISPLAY);  \/\/ Set Normal Display\n\n\tSSD1327_Command(SSD1327_DISPLAYALLON_RESUME);  \/\/ Entire Display ON\n\n#if GRAPHIC_ACCELERATION_COMMANDS == 1\n\tSSD1327_StopScroll();\n#endif\n\tSSD1327_DisplayON(1);\n}<\/pre>\n\n\n\n<p>After running this code, what appears on the display is\u2026 a galaxy!<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"1000\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic.jpg\" alt=\"\" class=\"wp-image-1617\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic.jpg 1000w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_galactic-768x768.jpg 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>If you still don\u2019t know where it comes from, I\u2019ll explain. <strong>RAM has the property that after applying power, all cells settle into \u201crandom\u201d values. Since the RAM reflects what is visible on the display, we get such an image.<\/strong> So it\u2019s enough to clear this RAM for it to be uniform\u2014e.g. turn off all pixels.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Buffering, setting a pixel, and transfer to the display RAM<\/h2>\n\n\n\n<p><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-1\/\">In the previous post<\/a> I pointed out a small problem with setting the color of a single pixel in this display. It\u2019s that <strong>one RAM byte holds information about two adjacent pixels.&nbsp;<\/strong>So a good solution will be buffering such an image.<\/p>\n\n\n\n<p><strong>The buffer that will be kept in the microcontroller memory has a size of (128 * 96) \/ 2 bytes.<\/strong>&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#define SSD1327_BUFFERSIZE\t(SSD1327_LCDHEIGHT * SSD1327_LCDWIDTH \/ 2)\nstatic uint8_t buffer[SSD1327_BUFFERSIZE];<\/pre>\n\n\n\n<p>Now let\u2019s think about how to set a single pixel in such a buffer. We know that consecutive pixels A and B are stored in a byte like this: 0xAB. So how do we indicate the correct half-byte for the pixel? You can, for example, use the modulo operation. Then even (plus the zeroth) pixels will be addressed to one half, and odd ones to the other.<\/p>\n\n\n\n<p>We also need masking of those pixels that we do not want to modify in the buffer, and selecting the buffer cell. Masking half a byte is fairly obvious. So how do we find the right cell in the buffer array? Based on the coordinates of that pixel, i.e. X and Y.<\/p>\n\n\n\n<p>X is the horizontal position, Y is the vertical one. We scan the display from left to right on each line, moving downward. <strong>If we were to select an array cell only for row zero, the calculation would look like this: buffer[X\/2]<\/strong>. For pixel no. 0 and 1 it will be buffer[0]. The following ones match as well.<\/p>\n\n\n\n<p>So how do we add the row number? We need to shift the cell index by the number of bytes for full lines that are before the given Y. For that we need information about the display width.<\/p>\n\n\n\n<p><strong>The number of bytes for the full lines preceding the selected one with number Y is Y*(SSD1327_LCDWIDTH\/2).<\/strong><\/p>\n\n\n\n<p>Since we need to add, the full buffer cell selection looks like this.<\/p>\n\n\n\n<p><strong>uint8_t SelectedCell = buffer[X\/2 + Y*(SSD1327_LCDWIDTH\/2)];<\/strong><\/p>\n\n\n\n<p>Putting this information together, we get what the function drawing a single pixel in the buffer should contain.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/\n\/\/ Draw pixel in the buffer\n\/\/\nvoid SSD1327_DrawPixel(int16_t x, int16_t y, uint8_t Color)\n{\n\t if ((x &amp;lt; 0) || (x &amp;gt;= SSD1327_LCDWIDTH) || (y &amp;lt; 0) || (y &amp;gt;= SSD1327_LCDHEIGHT))\n\t\t return;\n\n\t uint8_t SelectedCell = buffer[x\/2 + y*(SSD1327_LCDWIDTH\/2)];\n\n\t if(x % 2)\n\t {\n\t\t SelectedCell &amp;amp;= ~(0x0F);\n\t\t SelectedCell |= (0x0F &amp;amp; Color);\n\t }\n\t else\n\t {\n\t\t SelectedCell &amp;amp;= ~(0xF0);\n\t\t SelectedCell |= (0xF0 &amp;amp; (Color&amp;lt;&amp;lt;4));\n\t }\n\n\t buffer[x\/2 + y*(SSD1327_LCDWIDTH\/2)] = SelectedCell;\n}<\/pre>\n\n\n\n<p>Which side in that byte the lower pixel should be on is determined by the initialization. There is a register selecting where the higher of the two goes. I checked it empirically and according to the results, for my initialization the above code is correct.<\/p>\n\n\n\n<p><strong>Now we need to send it to the OLED.<\/strong><\/p>\n\n\n\n<p>The SSD1327 differs from the SSD1306 in that it does not have RAM memory paging. So we don\u2019t have to worry whether initialization enabled that paging. We always have access to the entire RAM.<\/p>\n\n\n\n<p>It\u2019s enough to set the RAM write pointer to the very beginning and push the entire buffer. That\u2019s it!<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/\n\/\/ Send buffer to OLDE GCRAM\n\/\/\nvoid SSD1327_Display(void)\n{\n\tSSD1327_Command(SSD1327_SETCOLUMNADDRESS);\n\tSSD1327_Command(0x00);\n\tSSD1327_Command(0x3F);\n\n\tSSD1327_Command(SSD1327_SETROWADDRESS);\n\tSSD1327_Command(0x00);\n\tSSD1327_Command(0x5F);\n\n\tHAL_I2C_Mem_Write(ssd1337_i2c, SSD1327_I2C_ADDRESS, 0x40, 1, (uint8_t*)&amp;amp;buffer, SSD1327_BUFFERSIZE, 1000);\n}<\/pre>\n\n\n\n<p><strong>Let\u2019s also quickly add a function that clears the entire screen (buffer) to the selected color. You must always remember how the pixels are stored.<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/\n\/\/ Clear the buffer\n\/\/\nvoid SSD1327_Clear(uint8_t Color)\n{\n\tif(Color &amp;gt; WHITE) Color = WHITE;\n\n\tmemset(buffer, (Color &amp;lt;&amp;lt; 4 | Color), SSD1327_BUFFERSIZE);\n}<\/pre>\n\n\n\n<p>Let\u2019s test it! <strong>All photos were taken with fixed camera settings.<\/strong><\/p>\n\n\n\n<p>Color: 15 (max). White.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15-300x300.jpg\" alt=\"\" class=\"wp-image-1620\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color15.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Color 7 (middle). Yep, it\u2019s gray.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7-300x300.jpg\" alt=\"\" class=\"wp-image-1619\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color7.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Color 2 (almost black). Here you can hardly see anything anymore, but believe me that <strong>a slight glow is visible \ud83d\ude42<\/strong> This will be nicely visible e.g. in photos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><figure><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2-300x300.jpg\" alt=\"\" width=\"300\" height=\"300\" class=\"aligncenter size-medium wp-image-1618\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_color2.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\"><\/a><\/figure>GFX library<\/h2>\n\n\n\n<p>You can use a library that is intended for monochrome displays. You just need to attach a pixel-drawing function and the display dimensions to the header.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#define GFX_DrawPixel(x,y,color) SSD1327_DrawPixel(x,y,color)\n#define WIDTH SSD1327_LCDWIDTH\n#define HEIGHT SSD1327_LCDHEIGHT\n#define PIXEL_BLACK\tBLACK\n#define PIXEL_WHITE\tWHITE\n#define PIXEL_INVERSE\tINVERSE<\/pre>\n\n\n\n<p>Then text and shapes work very well. Here is an example with drawing rectangles in all colors.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx-300x300.jpg\" alt=\"\" class=\"wp-image-1621\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_gfx.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p><strong>Unfortunately, drawing images will not work by default. Unfortunately, I wrote this library in such a way that it accepts only two colors\u2014white and black. After all, it\u2019s BW \ud83d\ude42<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo-300x300.jpg\" alt=\"\" class=\"wp-image-1623\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo-1024x1024.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_logo.jpg 1500w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>I\u2019ll move on to generating and drawing images in the next posts. As a little teaser, here is what the msalamon.pl logo or a photo\u2014e.g. my cat\u2014looks like.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><figure><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat-300x300.jpg\" alt=\"\" width=\"300\" height=\"300\" class=\"aligncenter size-medium wp-image-1622\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat-300x300.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat-1024x1024.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat-150x150.jpg 150w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat-768x768.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/08\/ssd1327_cat.jpg 1500w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\"><\/a><\/figure>Summary<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=ssd1327\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg\" alt=\"\" class=\"wp-image-1593\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>The pixel organization can give you something to think about, but if you think it through once and properly, you never have to do it again. Remember to write code in such a way that it helps you at later stages of writing the application.<\/p>\n\n\n\n<p>Also, don\u2019t be afraid to search the Internet and use other people\u2019s work. Just be aware of what someone else\u2019s code does \ud83d\ude42<\/p>\n\n\n\n<p>In the next post I\u2019ll show you which program I use to generate bitmaps for microcontrollers. It\u2019s a 100% free program and it can really do a lot!<\/p>\n\n\n\n<p>Later we\u2019ll upload such images to the microcontroller, and ultimately to the display.<\/p>\n\n\n\n<p><strong>If you liked the article, buy something from me! \ud83d\ude42 <a href=\"https:\/\/sklep.msalamon.pl\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">https:\/\/sklep.msalamon.pl\/<\/a><\/strong><\/p>\n\n\n\n<p>You can find the full project together with the library, as usual, on my GitHub: <a href=\"https:\/\/github.com\/lamik\/OLED_SSD1327_STM32_HAL\" target=\"_blank\" rel=\"noopener\">LINK<\/a><\/p>\n\n\n\n<p><span>If you noticed an error, disagree with something, would like to add something important, or simply feel like you\u2019d like to discuss this topic, write a comment. Remember that the discussion should be polite and comply with the rules of the Polish language.<\/span><\/p>\n\n\n\n<p class=\"has-text-align-center\"><span style=\"font-size: 24pt;\"><strong>Table of contents for the entire SSD1327 OLED series:<\/strong><\/span><\/p>\n\n\n\n<p class=\"has-text-align-center\"><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-1\/\">Grayscale OLED on SSD1327 part 1<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-2\/\">Grayscale OLED on SSD1327 part 2<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/jak-przygotowac-obraz-dla-wyswietlacza-lcd-lub-tft\/\">How to prepare an image for an LCD or TFT display?<\/a><br><\/strong><strong><a href=\"http:\/\/msalamon.pl\/oled-ze-skala-szarosci-na-ssd1327-cz-3\/\">Grayscale OLED on SSD1327 part 3<\/a><\/strong><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4237&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Grayscale OLED on SSD1327 Part 2&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Recently I did a bit of theorizing about an OLED with a 16-level grayscale. We already know how those 16 colors are obtained and how the display\u2019s RAM memory is organized. Time to display something on it, right? First, we\u2019ll try using a graphics library from a regular monochrome OLED, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3474,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[176,174],"class_list":["post-4237","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-programming","tag-stm32"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4237"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4237\/revisions"}],"predecessor-version":[{"id":4240,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4237\/revisions\/4240"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3474"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4237"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4237"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}