<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/38711/controlling-st7789-lcd-with-nrf52-dk</link><description>I am working on a project that requires an LCD and the one I have found is a 240x240px 1.54&amp;quot; LCD from Adafruit (Product ID 3787 https://www.adafruit.com/product/3787 ). I&amp;#39;m communicating with it over SPI and I am powering it externally from my NRF52 DK</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 30 Jun 2023 11:59:01 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/38711/controlling-st7789-lcd-with-nrf52-dk" /><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/433929?ContentTypeID=1</link><pubDate>Fri, 30 Jun 2023 11:59:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cb94547b-88dd-42f1-bb0a-df95de5ee3fa</guid><dc:creator>Bhavesh prajapati</dc:creator><description>&lt;p&gt;&lt;span&gt;Hello&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I have an nRF SDK 17 version and I am trying to configure an ST7789 TFT display with SPI. I referenced Arduino code and implemented it accordingly. However, I am not getting any display operation; the screen is not showing anything or any colors.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;so can you share your library file or driver so i can refer that and start working on that please&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/430882?ContentTypeID=1</link><pubDate>Wed, 14 Jun 2023 05:54:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:974c5d42-28ac-497e-afc1-b22526f627e1</guid><dc:creator>Bhavesh prajapati</dc:creator><description>&lt;p&gt;I need zepher driver for bringup display?&lt;/p&gt;
&lt;p&gt;because i an facing issue&amp;nbsp; not bring up st7789 display with spi interface i have reference Arduino code and change same according this but not getting any output from it can any one provide or suggest how to do this task for st7789 display bring up&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/429789?ContentTypeID=1</link><pubDate>Wed, 07 Jun 2023 13:03:53 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:426ca0cd-0b64-4536-82bd-4d44b814e4a3</guid><dc:creator>Bhavesh prajapati</dc:creator><description>&lt;p&gt;Hello&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I an working with same st7789 tft 240x240 display but i&amp;#39;dont have idea which library file need for this display configuration so can you please help me to give some reference or give library file so that i can start it&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/429145?ContentTypeID=1</link><pubDate>Mon, 05 Jun 2023 05:47:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:db1418e5-560c-454e-9359-41dc4e77abad</guid><dc:creator>Harsh Bhatt</dc:creator><description>&lt;p&gt;Hi I&amp;nbsp;am also used &lt;a href="https://www.banggood.in/1_3-Inch-IPS-TFT-LCD-Display-240+240-Color-HD-LCD-Screen-3_3V-ST7789-Driver-Module-p-1383404.html?BGtranslation_ab=2&amp;amp;rmmds=myorder&amp;amp;cur_warehouse=CN&amp;amp;rmmds=myorder&amp;amp;cur_warehouse=CN"&gt;ST7789&lt;/a&gt; tft display but different part.&lt;/p&gt;
&lt;p&gt;Can you please tell that your code is working fine with our display?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/203736?ContentTypeID=1</link><pubDate>Tue, 13 Aug 2019 07:13:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:de15844b-0f68-4012-80ae-3787d20f0c51</guid><dc:creator>Walther</dc:creator><description>&lt;p&gt;Hi Andy,&lt;/p&gt;
&lt;p&gt;thank you for sharing this! I am also using the ST7789 display driver and your test code helped me a lot. I resolved a bug, where a display rotation of 0&amp;deg; was not working with a 240x240 display. It is quite simple, you have to edit the file st7789.c at three points.&lt;/p&gt;
&lt;p&gt;After&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;//Position setting for 240x240 LCD
#define ST7789_240x240_XSTART 0
#define ST7789_240x240_YSTART 80&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;insert the variables storing the offset:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;uint16_t x_offset = 0;
uint16_t y_offset = 0;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;in function set_addr_window, 4 lines have to be added where the offset is added to the address window:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void set_addr_window(uint16_t x_0, uint16_t y_0, uint16_t x_1, uint16_t y_1)
{
    ASSERT(x_0 &amp;lt;= x_1);
    ASSERT(y_0 &amp;lt;= y_1);

    // Adaption for rotation
    y_0 += y_offset;
    y_1 += y_offset;
    x_0 += x_offset;
    x_1 += x_offset;    

    write_command(ST7789_CASET);
    write_data(x_0 &amp;gt;&amp;gt; 8);
    write_data(x_0);
    write_data(x_1 &amp;gt;&amp;gt; 8);
    write_data(x_1);
    write_command(ST7789_RASET);
    write_data(y_0 &amp;gt;&amp;gt; 8);
    write_data(y_0);
    write_data(y_1 &amp;gt;&amp;gt; 8);
    write_data(y_1);
    write_command(ST7789_RAMWR);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and in function st7789_rotation_set the offset has to be set:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void st7789_rotation_set(nrf_lcd_rotation_t rotation)
{
    write_command(ST7789_MADCTL);
    switch (rotation % 4) {
        case NRF_LCD_ROTATE_0:
            write_data(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB);  //Not working correctly
            //Column address (MX): Right to left
            //Page address (MY): Bottom to top
            //Page/ Column order (MV): normal
            //RGB/BGR order: RGB
            x_offset = 0;
            y_offset = ST7789_240x240_YSTART;
            break;
        case NRF_LCD_ROTATE_90:
            write_data(ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
            //Column address (MX): Left to right
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): reverse
            //RGB/BGR order: RGB
            x_offset = 0;
            y_offset = 0;
            break;
        case NRF_LCD_ROTATE_180:
            write_data(ST7789_MADCTL_RGB);
            //Column address (MX): Left to right
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): normal
            //RGB/BGR order: RGB
            x_offset = 0;
            y_offset = 0;
            break;
        case NRF_LCD_ROTATE_270:
            write_data(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
            //Column address (MX): Right to left
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): reverse
            //RGB/BGR order: RGB
            x_offset = 0;
            y_offset = 0;
            break;
        default:
            break;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#39;s it!&lt;/p&gt;
&lt;p&gt;Maybe you already solved it yourself, but for future users this could be helpful.&lt;/p&gt;
&lt;p&gt;Greetings&lt;/p&gt;
&lt;p&gt;Walther&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/177159?ContentTypeID=1</link><pubDate>Tue, 19 Mar 2019 17:38:41 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:94ed4ac8-4a72-4530-9473-144494d90615</guid><dc:creator>Andy Cruz</dc:creator><description>&lt;p&gt;Hi Constantin,&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s some code from when I was working with drawing two different examples onto the screen:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/communityserver-discussions-components-files/4/ST7789-test-code.zip"&gt;devzone.nordicsemi.com/.../ST7789-test-code.zip&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;Since I modified my gfx library to make the screen work how I wanted it to it would be a good idea to copy the original, unmodified library from your SDK and keep it somewhere in case you need to modify the library even further and then something breaks. There were still a few bugs in my code, such as the program crashing if text would be drawn out of bounds vertically instead of just returning in that function. Sorry it&amp;#39;s a few days late but I hope this helps you out.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/176497?ContentTypeID=1</link><pubDate>Fri, 15 Mar 2019 16:06:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a0a99679-1e0d-4848-859d-bda4bc368203</guid><dc:creator>Constantin</dc:creator><description>&lt;p&gt;Hi Andy, would you be so kind and share your final version. We try to use a display with ST7789 aswell. Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/150839?ContentTypeID=1</link><pubDate>Fri, 28 Sep 2018 22:12:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d866e0cb-8e99-4f3d-9756-55297dbfd6ba</guid><dc:creator>Andy Cruz</dc:creator><description>&lt;p&gt;Also I added in that the frame buffer method only&amp;nbsp;&lt;em&gt;almost&lt;/em&gt; always writes faster because in specific situations the default NRF GFX method will be faster, specifically for drawing character with small numbers of pixels like very thin and small fonts or, most regularly, punctuation. Since something like a colon has so few pixels drawn relative to its total area, even when sending 6.5 times as much data per pixel if the number of pixels being drawn is less than the character&amp;#39;s (width*height*8pixels/B / 6.5) it will end up sending fewer total bytes over SPI. I still use the default &amp;quot;nrf_gfx_print&amp;quot; function to draw certain small texts and characters like the clock&amp;#39;s colon because of this. It&amp;#39;s just that the default Nordic libraries were not efficient at drawing large characters to the screen like I needed to do.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/150838?ContentTypeID=1</link><pubDate>Fri, 28 Sep 2018 21:54:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:26ce0859-4cc9-48e8-a6fb-840adf2156a5</guid><dc:creator>Andy Cruz</dc:creator><description>&lt;p&gt;I&amp;#39;ve managed to get the LCD screen working very quickly now with a few tweaks I made to the code in the NRF GFX and NRF LCD libraries. I got a different LCD to test with as well, a 1.44&amp;quot; 132x132 LCD using an ST7735 (Product ID 2088&amp;nbsp;&lt;a href="https://www.adafruit.com/product/2088"&gt;https://www.adafruit.com/product/2088&lt;/a&gt;&amp;nbsp;it says it has 128x128 resolution but it&amp;#39;s not) that showed me where the problems I was mostly having were.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After reading through the datasheet for the ST7789, ILI9341, and ST7735 over and over as well as coming across an LCD test done by &amp;quot;Kbiva&amp;quot; (Article:&amp;nbsp;&lt;a href="https://kbiva.wordpress.com/2016/12/10/nokia-6020-lcd-using-framebuffer/"&gt;https://kbiva.wordpress.com/2016/12/10/nokia-6020-lcd-using-framebuffer/&lt;/a&gt;&amp;nbsp;Video:&amp;nbsp;&lt;a href="https://youtu.be/718ShQZI2rg"&gt;https://youtu.be/718ShQZI2rg&lt;/a&gt;&amp;nbsp;) I found that the NRF GFX library was not utilizing the frame buffer on the LCD drivers efficiently. The function for printing a string &amp;quot;nrf_gfx_print&amp;quot; repeatedly calls &amp;quot;write_character&amp;quot; which in turn repeatedly calls &amp;quot;pixel_draw&amp;quot;. &amp;quot;pixel_draw&amp;quot; will scan through the font file&amp;#39;s bitmap information and check if a bit is a 0 or a 1 for every single pixel and draw that pixel to the screen if it&amp;#39;s a 1 and ignore it if it&amp;#39;s a 0. This is why drawing multiple characters in the same region on the LCD results in a garbled mess, the characters beneath are never erased and essentially both combine, but since that is real easy to fix in multiple ways that&amp;#39;s not an issue. What was an issue is how &amp;quot;pixel_draw&amp;quot; will send 13B of data over SPI for ever pixel it draws. It first sets the address window by sending 1B command (CASET) followed by 4B of data for X start and end positions, 1B command (RASET) followed by 4B of data for Y start and end positions, 1B command (RAMWR) to write data to the frame buffer&amp;#39;s memory, then 2B of data (16-bit 565 RGB color). RAMWR will end when a new command is sent, so sending the next pixel will start with a CASET command and end sending data to the frame buffer abruptly, which results in every pixel being sent to the screen one at a time. These are the major changes I made to the code for an alternate method of writing to the frame buffer:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;//IN NRF_GFX.h
/**
 * @brief Function for displaying data from an internal frame buffer.
 *  modified to write data directly to frame buffer over SPI
 *
 * @param[in] p_instance            Pointer to the LCD instance.
 * @param[in] * dat                 Pointer to data array
 * @param[in] len                   Length of data in array
 * @param[in] x0,y0,x1,y1           Coordinates for setting window address if selected
 */
void nrf_gfx_display(nrf_lcd_t const * p_instance, uint8_t * dat, uint16_t len, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);

//IN NRF_GFX.c
void nrf_gfx_display(nrf_lcd_t const * p_instance, uint8_t * dat, uint16_t len, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    ASSERT(p_instance != NULL);

    p_instance-&amp;gt;lcd_display(dat, len, x0, y0, x1, y1);
}

//IN NRF_LCD.h
void nrf_gfx_display(nrf_lcd_t const * p_instance, uint8_t * dat, uint16_t len, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    ASSERT(p_instance != NULL);

    p_instance-&amp;gt;lcd_display(dat, len, x0, y0, x1, y1);
}

//IN ST7789.c, ST7735.c, etc.
static void st7789_dummy_display(uint8_t * data, uint16_t len, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    if(len == 0xFFFF){
        set_addr_window(x0, y0, x1, y1);
    }
    else{
      //spi_write(&amp;amp;data, len);
      write_data_buffered(data, len);
    }
}

static inline void write_data_buffered(uint8_t * c, uint16_t len)
{
    nrf_gpio_pin_set(ST7789_DC_PIN);

    spi_write(c, len);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This makes use of the normally empty functions for display and allows me to either send data over SPI or to set the address window to some specific values. This avoids needing to reset the address window over and over, sending new commands that break up sending data to the frame buffer. The downside with this method is that now I need to handle the pixels that are 0s in the font bitmaps otherwise I&amp;#39;ll end up with garbage on the display. I added two new functions to &amp;quot;nrf_gfx.c&amp;quot; to take advantage of this:&amp;nbsp;&lt;pre class="ui-code" data-mode="text"&gt;//added in

//#define enable_prints

static void write_character_fast(nrf_lcd_t const * p_instance,  //nrf_lcd_st7789
                            nrf_gfx_font_desc_t const * p_font, //arial_72ptFontInfo
                            uint8_t character,                  //character
                            uint16_t * p_x,                     //x starting point
                            uint16_t y,                         //y starting point
                            uint16_t background_color,          //16-bit color
                            uint16_t font_color)                //16-bit color
{
    uint8_t char_idx = character - p_font-&amp;gt;startChar; //character - 33 (&amp;quot;!&amp;quot; ASCII)
    uint16_t bytes_in_line = CEIL_DIV(p_font-&amp;gt;charInfo[char_idx].widthBits, 8); //# bytes per line

    if (character == &amp;#39; &amp;#39;)           //in case of a space
    {
        *p_x += p_font-&amp;gt;height / 2; //increase x position by half font&amp;#39;s height
        return;
    }
    
    uint8_t font_col[2] = {font_color &amp;gt;&amp;gt; 8, font_color};
    uint8_t background_col[2] = {background_color &amp;gt;&amp;gt; 8, background_color};

    //p_instance-&amp;gt;lcd_pixel_draw(*p_x, y, background_color);
    nrf_gfx_display(p_instance, 0, 0xFFFF, *p_x, y, *p_x + bytes_in_line * 8 - 1, y + p_font-&amp;gt;height);

    for (uint16_t i = 0; i &amp;lt; p_font-&amp;gt;height; i++) //Increment through the rows
    {
        for (uint16_t j = 0; j &amp;lt; bytes_in_line; j++)  //Increment through the columns
        {
            for (uint8_t k = 0; k &amp;lt; 8; k++) //Check 0 to 7 per Byte
            {
                if ((1 &amp;lt;&amp;lt; (7 - k)) &amp;amp; p_font-&amp;gt;data[p_font-&amp;gt;charInfo[char_idx].offset + i * bytes_in_line + j])
                {
                    //pixel_draw(p_instance, *p_x + j * 8 + k, y + i, font_color);
                    //p_instance = nrf_lcd_st7789
                    //p_x = X starting position   -&amp;gt; X starting position + Column * 8 + Bit # 
                    //y = y starting position     -&amp;gt; Y starting position + Row
                    //font_color = 16-bit color
                    
                    nrf_gfx_display(p_instance, font_col, sizeof(font_col),0,0,0,0);
                    #ifdef enable_prints
                    printf(&amp;quot;1&amp;quot;);
                    #endif
                }
                else{

                    nrf_gfx_display(p_instance, background_col, sizeof(background_col),0,0,0,0);
                    #ifdef enable_prints
                    printf(&amp;quot;0&amp;quot;);
                    #endif
                }
            }
        }
        #ifdef enable_prints
        printf(&amp;quot;\n&amp;quot;);
        #endif
    }
    //After through entire character incremented through

    *p_x += p_font-&amp;gt;charInfo[char_idx].widthBits + p_font-&amp;gt;spacePixels;
    //X starting position + character&amp;#39;s width in bits + size of space in pixels
}

ret_code_t nrf_gfx_print_fast(nrf_lcd_t const * p_instance,
                         nrf_gfx_point_t const * p_point,
                         uint16_t background_color,
                         uint16_t font_color,
                         const char * string,
                         const nrf_gfx_font_desc_t * p_font,
                         bool wrap)
{
    ASSERT(p_instance != NULL);
    ASSERT(p_instance-&amp;gt;p_lcd_cb-&amp;gt;state != NRF_DRV_STATE_UNINITIALIZED);
    ASSERT(p_point != NULL);
    ASSERT(string != NULL);
    ASSERT(p_font != NULL);

    uint16_t x = p_point-&amp;gt;x;
    uint16_t y = p_point-&amp;gt;y;

    if (y &amp;gt; (nrf_gfx_height_get(p_instance) - p_font-&amp;gt;height))
    {
        // Not enough space to write even single char.
        return NRF_ERROR_INVALID_PARAM;
    }

    for (size_t i = 0; string[i] != &amp;#39;\0&amp;#39; ; i++)
    {
        if (string[i] == &amp;#39;\n&amp;#39;)
        {
            x = p_point-&amp;gt;x;
            y += p_font-&amp;gt;height + p_font-&amp;gt;height / 10;
        }
        else
        {
            write_character_fast(p_instance, p_font, (uint8_t)string[i], &amp;amp;x, y, background_color, font_color);
        }

        uint8_t char_idx = string[i] - p_font-&amp;gt;startChar;
        uint16_t char_width = string[i] == &amp;#39; &amp;#39; ? (p_font-&amp;gt;height / 2) :
                                                p_font-&amp;gt;charInfo[char_idx].widthBits;

        if (x &amp;gt; (nrf_gfx_width_get(p_instance) - char_width))
        {
            if (wrap)
            {
                x = p_point-&amp;gt;x;
                y += p_font-&amp;gt;height + p_font-&amp;gt;height / 10;
            }
            else
            {
                break;
            }

            if (y &amp;gt; (nrf_gfx_height_get(p_instance) - p_font-&amp;gt;height))
            {
                break;
            }
        }
    }

    return NRF_SUCCESS;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;They function essentially the same as the normal &amp;quot;nrf_gfx_print&amp;quot; and &amp;quot;write_character&amp;quot; functions except they utilize the frame buffer to (almost always) print characters to the screen much faster than the normal functions do. I also need to pass in a second color so I know what to draw the 0s in the font&amp;#39;s bitmap as, and since I am using a consistent and known background color this was never a problem for me. Not intentionally, this also now erases the previous pixels drawn behind any new text which allows me to repeatedly write characters in the same positions without needing to erase the area before (some characters are wide enough that they aren&amp;#39;t completely erased when drawing a new one, but by drawing a small rectangle just offset from the character&amp;#39;s position I was easily able to clean these up). Now I am able to set the address window then sent a continuous stream of data to the LCD&amp;#39;s frame buffer which offsets needing to send data for every single bit. This method will set the address window once (11B) and then send color data for each pixel (2B/pixel) as opposed to sending doing both on every pixel that&amp;#39;s a 1 in the font&amp;#39;s bitmap (13B/pixel). I did a test calculation on paper first then set up a spreadsheet to try to calculate the number of bytes each method would need to send over SPI to write the character.&lt;/p&gt;
&lt;p&gt;For light characters with few pixels like &amp;quot;1&amp;quot; or &amp;quot;I&amp;quot; they are roughly even. For yuGothic_42pt font&amp;#39;s &amp;quot;1&amp;quot; the default method should take ~2.6kB (202 pixels * 13B/pixel = 2,626B). Using the method I implemented the same character would take ~2.3kB (1,152 pixels * 2B/pixel + 11B = 2,315B). This also gave some of the best benefit of the doubt to the default method by using a very thin font and character for the test. When I tested with heavier fonts with a lot of pixels the difference became very significant. For arial_bold_72pt font I imported the hexadecimal bitmap data for the character &amp;quot;8&amp;quot;, found out which pixels were 1s and which were 0s (tables on the upper right) to make sure that it was the same data I was getting from the printf statements in my &amp;quot;fast&amp;quot; functions, and summed them for the total number of pixels being drawn. The number of pixels my implementation draws is just the area of the bitmap, width times height, in pixels.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;img alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/SPI-Pixel-Drawing-Calculations-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/7853.SPI-Pixel-Drawing-Calculations-2.png" /&gt;&lt;/p&gt;
&lt;p&gt;Mine sends ~18k fewer bytes over SPI to draw the same character, resulting in barely if any flashing of basically any character I draw.&lt;/p&gt;
&lt;p&gt;I also couldn&amp;#39;t quite figure out exactly how the function &amp;quot;nrf_gfx_bmp565&amp;quot; was expecting me to pass data to it and I was unable to find an example of the function in action so I made an alternate version to work with data arrays created out of bitmap images from a generator I downloaded online. The converter is &amp;quot;ImageConverter 565 v2.2&amp;quot; from&amp;nbsp;&lt;a href="https://www.14core.com/c-array-generator/"&gt;https://www.14core.com/c-array-generator/&lt;/a&gt;&amp;nbsp;and the bitmaps were PNGs made in paint saved as .bmp files then opened in the converter. I made separate headers for different sizes that included the unsigned char arrays that I passed to my own function &amp;quot;nrf_gfx_bmp565_draw_big_endian&amp;quot; which I didn&amp;#39;t really bother optimizing by also utilizing the frame buffer since these will be drawn to the screen once but the&amp;nbsp;idea is similar to the &amp;quot;write_character_fast&amp;quot; function.&amp;nbsp;&lt;pre class="ui-code" data-mode="text"&gt;ret_code_t nrf_gfx_bmp565_draw_big_endian(nrf_lcd_t const * p_instance,   //LCD screen type instance
                                          nrf_gfx_rect_t const * p_rect,  //Rectangle object
                                          uint16_t const * img_buf)       //Array of color data
{
    ASSERT(p_instance != NULL);
    ASSERT(p_instance-&amp;gt;p_lcd_cb-&amp;gt;state != NRF_DRV_STATE_UNINITIALIZED);
    ASSERT(p_rect != NULL);
    ASSERT(img_buf != NULL);

    if ((p_rect-&amp;gt;x &amp;gt; nrf_gfx_width_get(p_instance)) || (p_rect-&amp;gt;y &amp;gt; nrf_gfx_height_get(p_instance)))
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    //size_t idx;                           //
    uint16_t idx = 0;                        //Offset into data array
    uint16_t pixel;                         //Color to write to pixel
    //uint8_t padding = p_rect-&amp;gt;width % 2;  //No padding

    for (int32_t i = 0; i &amp;lt; p_rect-&amp;gt;height; i++)
    {
        for (uint32_t j = 0; j &amp;lt; p_rect-&amp;gt;width; j++)
        {
            //idx = (uint32_t)((p_rect-&amp;gt;height - i - 1) * (p_rect-&amp;gt;width + padding) + j);

            //pixel = img_buf[idx]; //Color stored in Big Endian

            pixel_draw(p_instance, p_rect-&amp;gt;x + j, p_rect-&amp;gt;y + i, img_buf[idx]);

            idx++;
        }
    }

    return NRF_SUCCESS;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I doubt these are 100% correctly implemented with the biggest issue being if I try to print a string fast to the screen and its address window goes out of the screen&amp;#39;s boundaries my NRF52 hard faults, which I&amp;#39;m sure could be prevented by adding in a check like a bunch of other NRF GFX functions seem to use. For now though, I have the 240x240 screen updating significantly faster than before, especially with the fast SPI library, such that the characters appear to change instantly from one to the next almost every time and updating the entire XX:XX clock happens so fast you can&amp;#39;t see any characters wiping just like they all change back to back very fast. Since this is working well enough for my needs in this project I&amp;#39;m going to consider this part essentially done and move onto other parts of the same project and mark this ticket as answered. I ended up NOT implementing the Adafruit library because when I looked around it looked like A) it would require including a LOT of additional stuff from Arduino libraries that I didn&amp;#39;t want to use or have taking up space and B) it seemed to also suffer from some speed issues that I was already experiencing with Nordic&amp;#39;s libraries and seemed like it would probably have ended up being a large hassle to wind up in the exact same position.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/150342?ContentTypeID=1</link><pubDate>Tue, 25 Sep 2018 21:02:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8c4db88d-58a5-408c-8802-3526904f6e75</guid><dc:creator>Andy Cruz</dc:creator><description>&lt;p&gt;An update on this,&lt;/p&gt;
&lt;p&gt;I&amp;#39;m able to drive the ST7789 much better than previously, although there is still a noticeable delay when I am erasing and drawing 72pt Arial font characters it&amp;#39;s taking no more than 200ms now regardless of the character as opposed to the 300+ms previously. I am making fonts to work with the GFX library&amp;#39;s typedef &amp;quot;nrf_gfx_font_desc_t&amp;quot; with the Dot Factory generator by Eran Duchan (&amp;nbsp;&lt;a href="http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/"&gt;http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/&lt;/a&gt;&amp;nbsp;) and they only require small changes from the default settings to make work. The .h and .c files it generates need &amp;quot;uint_8&amp;quot; changed to &amp;quot;uint8_t&amp;quot;, an include for &amp;quot;nrf_font.h&amp;quot;, character height in the font info struct at the bottom of the .c file changed to be in bits instead of bytes, and the comments for the &amp;quot;\&amp;quot; character need apostrophes around them and an additional space after to prevent a glitch where ASCII characters that come after &amp;quot;\&amp;quot; are shifted over by one. Here&amp;#39;s the contents of one of the .h files I&amp;#39;m using right now.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;// Font data for Arial 72pt
#ifndef _ARIAL_72pt__
#define _ARIAL_72pt__

#include &amp;quot;nrf_font.h&amp;quot;

extern const uint8_t arial_72ptBitmaps[];
extern const FONT_INFO arial_72ptFontInfo;
extern const FONT_CHAR_INFO arial_72ptDescriptors[];
//End
#endif&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;To further reduce the character refresh time I changed how I was erasing characters and added a new SPI library that operates notably faster than the normal NRF SPI. I assumed that the most efficient way of erasing a character was by drawing an identical character the color of the background in the same place to minimize the number of pixels that need to be redrawn, but I&amp;#39;ve found using&amp;nbsp;&amp;quot;lcd_rect_draw&amp;quot; for a rectangle the background&amp;#39;s color takes far less time, ~26ms as opposed to the ~140ms needed for a character in that space. I&amp;#39;m guessing the&amp;quot;nrf_gfx.c&amp;quot; functions like &amp;quot;line_draw&amp;quot; and &amp;quot;write_character&amp;quot; aren&amp;#39;t&amp;nbsp;super efficient (they both call the &amp;quot;nrf_lcd.c&amp;quot; function &amp;quot;lcd_pixel_draw&amp;quot;, not sure if that&amp;#39;s the issue).&lt;/p&gt;
&lt;p&gt;The different SPI library I&amp;#39;m using was linked here by Ovrebekk:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/10330/spi-optimization"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/10330/spi-optimization&lt;/a&gt;&amp;nbsp;, the &amp;quot;spi_master_fast.zip&amp;quot;. I&amp;nbsp;made an option in my &amp;quot;st7789.c&amp;quot; (a heavily modified copy of the external driver &amp;quot;ili9341.c&amp;quot; from the 14.2.0 SDK) to choose between enabling the normal SPI or the fast SPI library by changing some comments in the LCD&amp;#39;s init function. Previously I had a visible delay on my oscilloscope when probing the MOSI &amp;amp; SCK lines between bursts of 8Mbps activity of 16&amp;micro;s (looked just like the delays people were seeing in other threads:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/9636/spi-clock-bug"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/9636/spi-clock-bug&lt;/a&gt;&amp;nbsp;) that with the fast SPI library has been reduced to 8.56&amp;micro;s. I don&amp;#39;t have a gapless clock like is described here:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/6139/spi-master-high-speed-behavior-gapless-transmission"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/6139/spi-master-high-speed-behavior-gapless-transmission&lt;/a&gt;&amp;nbsp;but since I will need a bundle of interrupts later on in this project and users RK and Sam noted that interrupts would interfere with how his SPI was operating so I&amp;#39;m not sure that&amp;#39;s the best idea for me to try out. I am not sure why these delays still exist for the SPI and considering how much reducing them has sped up my LCD&amp;#39;s refresh rate I bet those are the source of most of my problems.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve managed to trim the time down a bit by changing how I was erasing characters and changing my fonts from bold to not but my ultimate goal is still to get a seamless change of characters on the screen. Next I&amp;#39;m going to be testing out drawing bitmap images onto the LCD because that&amp;#39;s another essential task I&amp;#39;ll need to do later on as well as try out 12-bit color mode as it should notably reduce the number of bytes I&amp;#39;ll need to send when using &amp;quot;lcd_rect_draw&amp;quot; and functions that use it, but since text is still drawn ultimately with &amp;quot;lcd_pixel_draw&amp;quot; this likely won&amp;#39;t have much of an impact on the way everything looks. Also to get the ST7789 working more correctly I used parts of an initialization found from New Haven Display intended for an ST7789: &lt;a href="http://www.newhavendisplay.com/app_notes/2-4TFT_ST7789.txt"&gt;http://www.newhavendisplay.com/app_notes/2-4TFT_ST7789.txt&lt;/a&gt;&amp;nbsp;. Here is the initialization function for the LCD:&amp;nbsp;&lt;pre class="ui-code" data-mode="text"&gt;static void command_list(void)
{
//NewHaven&amp;#39;s http://www.newhavendisplay.com/app_notes/2-4TFT_ST7789.txt
    //THIS ONE WORKED THE BEST
    
    write_command(ST7789_SWRESET);  //Software reset
    nrf_delay_ms(125);

    write_command(ST7789_SLPOUT);  //Exit sleep
    nrf_delay_ms(150);

    write_command(ST7789_MADCTL);  //Memory Data Access control
    write_data(0x08); //Bottom to top page address order

    write_command(ST7789_COLMOD); //Color mode
    write_data(0x55); //16-bit, 565 RGB
    //write_data(0x53); //12-bit, 444N RGB (N=col for next byte, uses 1.5B per pixel when mass sending data)

    write_command(ST7789_FRMCTR2);  //Frame rate control in normal mode
    write_data(0x01); //111Hz
    
    //nrf_delay_ms(2000);

    write_command(ST7789_PVGAMCTRL); //+ voltage gamma control
    write_data(0xD0);
    write_data(0x00);
    write_data(0x05);
    write_data(0x0E);
    write_data(0x15);
    write_data(0x0D);
    write_data(0x37);
    write_data(0x43);
    write_data(0x47);
    write_data(0x09);
    write_data(0x15);
    write_data(0x12);
    write_data(0x16);
    write_data(0x09);

    write_command(ST7789_NVGAMCTRL); //- voltage gamma control
    write_data(0xD0);
    write_data(0x00);
    write_data(0x05);
    write_data(0x0D);
    write_data(0x0C);
    write_data(0x06);
    write_data(0x2D);
    write_data(0x44);
    write_data(0x40);
    write_data(0x0E);
    write_data(0x1C);
    write_data(0x18);
    write_data(0x16);
    write_data(0x19);

    write_command(ST7789_INVON);  //Screen inversion on, added in because colors were reversed without

    write_command(ST7789_DISPON);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I still had to change some color and inversion parts for it to work entirely correctly, but I never managed to get the 0&amp;ordm; rotation to work correctly, it always appears offset vertically by ~80 pixels, but 3/4 is flexible enough to get most any orientation for the screen to work. Here&amp;#39;s the modified rotation code I used (typically I&amp;#39;m using 270&amp;ordm;):&amp;nbsp;&lt;pre class="ui-code" data-mode="text"&gt;static void st7789_rotation_set(nrf_lcd_rotation_t rotation)
{
    write_command(ST7789_MADCTL);
    switch (rotation % 4) {
        case NRF_LCD_ROTATE_0:
            write_data(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB);  //Not working correctly
            //Column address (MX): Right to left
            //Page address (MY): Bottom to top
            //Page/ Column order (MV): normal
            //RGB/BGR order: RGB
            break;
        case NRF_LCD_ROTATE_90:
            write_data(ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
            //Column address (MX): Left to right
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): reverse
            //RGB/BGR order: RGB
            break;
        case NRF_LCD_ROTATE_180:
            write_data(ST7789_MADCTL_RGB);
            //Column address (MX): Left to right
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): normal
            //RGB/BGR order: RGB
            break;
        case NRF_LCD_ROTATE_270:
            write_data(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
            //Column address (MX): Right to left
            //Page address (MY): Top to bottom
            //Page/ Column order (MV): reverse
            //RGB/BGR order: RGB
            break;
        default:
            break;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is an image of the oscilloscope signals I am&amp;nbsp;seeing now (Blue is SCK, Yellow is MOSI):&amp;nbsp;&lt;img alt=" " height="380" src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/IMG_5F00_2635.JPG" width="507" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/149885?ContentTypeID=1</link><pubDate>Fri, 21 Sep 2018 18:37:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6f0b9595-587d-4236-a2c9-32cd9fcbc573</guid><dc:creator>Andy Cruz</dc:creator><description>&lt;p&gt;Thanks Jared,&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll work towards implementing the Adafruit library for the ST7789 onto the NRF52. Originally I started prototyping this with a different LCD, their smaller TFT (Product ID 3533&amp;nbsp;&lt;a href="https://www.adafruit.com/product/3533"&gt;https://www.adafruit.com/product/3533&lt;/a&gt;&amp;nbsp;) and an Arduino UNO but since we needed both a higher resolution and wireless communication I moved to the NRF52 DK. It&amp;#39;s odd that I managed to get the display at least partially functioning with the given code considering it&amp;#39;s intended for a different driver. I&amp;#39;ve read that many LCD drivers like the ST7735, ILI9341, ST7781, etc. use some sort of standard but have variation in how they&amp;#39;re initialized, certain commands, etc. (bottom of the page suggests close equivalents for the driver&amp;nbsp;&lt;a href="https://www.ramtex.dk/display-controller-driver/rgb/st7789.htm"&gt;https://www.ramtex.dk/display-controller-driver/rgb/st7789.htm&lt;/a&gt;&amp;nbsp;). I&amp;#39;ve also read the Adafruit library is not particularly optimized (&amp;nbsp;&lt;a href="https://github.com/XarkLabs/PDQ_GFX_Libs"&gt;https://github.com/XarkLabs/PDQ_GFX_Libs&lt;/a&gt;&amp;nbsp;) and that&amp;#39;s mostly why I was staying away from it and switching over to Nordic libraries but if I absolutely need a library designed for my specific driver type I&amp;#39;ll work with what I can get. I&amp;#39;ll post updates here on my status and any issues I run into trying to get the Adafruit code working.&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Controlling ST7789 LCD with NRF52 DK</title><link>https://devzone.nordicsemi.com/thread/149814?ContentTypeID=1</link><pubDate>Fri, 21 Sep 2018 11:30:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4c56e5b7-85bb-4faf-bb88-78e7fc4f76fe</guid><dc:creator>Jared</dc:creator><description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;Unfortunately, we&amp;#39;re limited to what we can help you with since we don&amp;#39;t have any official drivers for that LCD. Maybe the Adafruit help forum is a better place for getting help regarding that LCD screen:&amp;nbsp;&lt;a href="https://forums.adafruit.com/"&gt;https://forums.adafruit.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Good Luck&lt;/p&gt;
&lt;p&gt;Jared&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>