<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Search Results for &#8220;ssd1306&#8221; &#8211; IoT Expert</title>
	<atom:link href="https://iotexpert.com/search/ssd1306/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>https://iotexpert.com</link>
	<description>Engineering for the Internet of Things</description>
	<lastBuildDate>Thu, 13 May 2021 15:24:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://iotexpert.com/wp-content/uploads/2017/01/cropped-Avatar-32x32.jpg</url>
	<title>Search Results for &#8220;ssd1306&#8221; &#8211; IoT Expert</title>
	<link>https://iotexpert.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>ModusToolbox 2.0 &#8211; Libraries an Example for emWin &#038; Super Manifests</title>
		<link>https://iotexpert.com/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/</link>
					<comments>https://iotexpert.com/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 30 Mar 2020 09:22:24 +0000</pubDate>
				<category><![CDATA[ModusToolbox]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=8380</guid>

					<description><![CDATA[Summary In this article I will walk you through creating a library for ModusToolbox 2.0 that will glue the Cypress RTOS Abstraction layer, emWin, the SSD1306 and the PSoC 6 together.  In the end, the library will become available in the Modus Toolbox Library Manager by creating a Super Manifest file. NOTE:  This blog was [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will walk you through creating a library for ModusToolbox 2.0 that will glue the Cypress RTOS Abstraction layer, emWin, the SSD1306 and the PSoC 6 together.  In the end, the library will become available in the Modus Toolbox Library Manager by creating a Super Manifest file.</p>
<p><span style="color: #ff0000;"><strong>NOTE:  This blog was originally written about the Modus Toolbox 2.0 library scheme.  With the release of Modus Toolbox 2.2 this scheme was changed and this blog is now obsolete! Instead, you can use the Infineon display-oled-ssd1306 library.</strong></span></p>
<h1>The Story</h1>
<p>I like using the Segger emWin graphics library.  And, I have always hated getting the &#8220;glue&#8221; into my project that makes the library work.  The glue includes the configuration files for emWin plus the hardware driver functions to talk to the SSD1306 screen.  I have always thought that it would be really nice to have a simple library scheme &#8211; yes I know that there are lots of schemes out there but I wanted one that was neatly integrated into our tools.  Well, with ModusToolbox 2.0 my wish was granted.</p>
<p>In ModusToolbox 2.0 if you create a file called &#8220;someLibraryName.lib&#8221; that contains a URL to a GitHub (or Git) repository, the make system will know how to bring that library into your project.  The make target &#8220;getlibs&#8221; does exactly that.  And, once it is on your computer in your project the Modus Toolbox make system will know how to include it as part of your project.</p>
<p>For this article I will create a library called &#8220;<span>p6sdk-ssd1306-emWin-freerots-config&#8221; which will contain:</span></p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Files</th>
<th >Purpose</th>
</tr>
</thead>
<tbody>
<tr><td >GUIConf.h</td>
<td >Configures emWins abilities, fonts etc.</td>
</tr>

<tr><td >GUIConf.c</td>
<td >Defines &amp; Assigns RAM for the GUI,initializes the font</td>
</tr>

<tr><td ><span>GUI_X_CYRTOS.c</td>
<td >Makes a connection between emWin and Cypress RTOS abstraction for things like timing, semaphore etc.</span></td>
</tr>

<tr><td ><span>LCDConf.h</td>
<td >A blank file</span></td>
</tr>

<tr><td ><span>LCDConf.c</td>
<td >Functions to configure screen,connect the emWin APIs to the I2C write functions, configures the display driver</span></td>
</tr>

<tr><td >SSD1306Driver.h</td>
<td >Functions prototypes to initialize the I2C and read/write the I2C</td>
</tr>

<tr><td >SSD1306Driver.c</td>
<td >Initialize the SSD1305 driver, write commands, write data, write datastream functions which are called by the LCDConf.c functions</td>
</tr>

<tr><td >template</td>
<td >A directory (which is not compiled) that contains template c files for use as an example</td>
</tr>
</tbody></table></div>
<h1>SSD1306 Driver</h1>
<p>In order to glue the hardware to the emWin library you need to provide functions that</p>
<ol>
<li>Initialize the driver &#8211; (Tell it what I2C hardware and I2C address the display is connected to)</li>
<li>Write data/command bytes and streams</li>
<li>Read data streams (which it actually never does)</li>
</ol>
<p>The SSD1306Driver.h provides a public interface for these functions which are used in the LCDConf.c file.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#ifndef SSD1306_DRIVER_H
#define SSD1306_DRIVER_H
#include "cyhal.h"


void SSD1306DriverInit(cyhal_i2c_t *obj,uint8_t oledAddress);


void          SSD1306_WriteCommandByte(unsigned char c);
void          SSD1306_WriteDataByte(unsigned char c);
void          SSD1306_WriteDataStream(unsigned char * pData, int NumBytes);
void          SSD1306_ReadDataStream(unsigned char * pData, int NumBytes);

#endif
</pre>
<p>The first part of SSD1306Driver.c makes a pointer to and Cypress HAL I2C object.  In the initialization code, it connects the provided I2C object and the static pointer.  The purpose of this is to allow the application developer to use the I2C for other devices on the bus, in other words the I2C bus is shared.  On most of my screens the I2C address is 0x3C,  so I let the user not provide an I2C address.  Probably in hindsight I should have just made them always provide an I2C address.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "SSD1306Driver.h"
#include "GUI.h"
#include "cyhal.h"
#include "cybsp.h"
#include &lt;stdlib.h&gt;

/*********************************************************************
*
*       Defines: Configuration
*
**********************************************************************
  Needs to be adapted to custom hardware.
*/
/* I2C port to communicate with the OLED display controller */
static cyhal_i2c_t *I2C=0;

/* I2C slave address, Command and Data byte prefixes for the display controller */
#define OLED_CONTROL_BYTE_CMD       (0x00)
#define OLED_CONTROL_BYTE_DATA      (0x40)
static uint8_t OLED_I2C_ADDRESS     =    (0x3C);

void SSD1306DriverInit(cyhal_i2c_t *obj,uint8_t oledAddress)

{
	CY_ASSERT(obj);
	I2C=obj;
	if(oledAddress)
		OLED_I2C_ADDRESS = oledAddress;
}</pre>
<p>In order for emWin to update a display it needs to be able to write data to the display via &#8220;commands&#8221; and &#8220;data&#8221; writes.  However, it doesn&#8217;t know anything about the fact that these displays are typically attached via I2C.  The function SSD1306_WriteCommandByte uses the Cypress HAL master write API to send a command byte to the display.  This function is called by emWin via the configuration in LCDConf.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void SSD1306_WriteCommandByte(unsigned char c)
{
    uint8_t buff[2];

    /* The first byte of the buffer tells the display that the following byte
        is a command */
    buff[0] = OLED_CONTROL_BYTE_CMD;
    buff[1] = (char)c;

    /* Write the buffer to display controller */
    cyhal_i2c_master_write(I2C, OLED_I2C_ADDRESS, buff, 2, 0, true);
}</pre>
<p>And the write data byte function works exactly the same way as the write command byte, except it send a different first byte.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void SSD1306_WriteDataByte(unsigned char c)
{
	uint8_t buff[2];

    /* First byte of the buffer tells the display controller that the following byte
        is a data byte */
    buff[0] = OLED_CONTROL_BYTE_DATA;
    buff[1] = c;

    /* Write the buffer to display controller */
    cyhal_i2c_master_write(I2C, OLED_I2C_ADDRESS, buff, 2, 0, true);
}</pre>
<h1>emWin Configuration Files</h1>
<p>I have written extensively about how to configure emWin and specifically how to setup the files for the SSD1306.  You can see the articles <a href="https://iotexpert.com/?s=ssd1306" target="_blank" rel="noopener noreferrer">here</a>.  So, I am not going to describe those files in detail except to say that the ones that you need are GUIConf.h/.c, LCDConf.h/.c and GUI_X_CYRTOS.c.  The only changes from the previous configurations of LCDConf.c is to hookup the APIs we defined in the previous section.</p>
<pre class="start-line:235 EnlighterJSRAW" data-enlighter-language="c">    PortAPI.pfWrite8_A0  = SSD1306_WriteCommandByte;
    PortAPI.pfWrite8_A1  = SSD1306_WriteDataByte;
    PortAPI.pfWriteM8_A1 = SSD1306_WriteDataStream;</pre>
<h1>GitHub</h1>
<p>I checked in all of these files into GitHub at git@github.com:iotexpert/p6sdk-ssd1306-emwin-cyrtos-config.git  Now they can be used as a Modus Toolbox library.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-2-51-55-pm/" rel="attachment wp-att-8960"><img fetchpriority="high" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-1024x809.png" alt="" width="1024" height="809" class="alignnone size-large wp-image-8960" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-1024x809.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-600x474.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-300x237.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-768x606.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM-1536x1213.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-2.51.55-PM.png 1864w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Test Library</h1>
<p>Lets build a test project.  Start by creating  new project.  Notice that I am not using the built in project creator, but a standalone project creator which does not require Eclipse.  This is automatically installed for you as part of the Modus Toolbox installation (so, if you are one of the legions of people who don&#8217;t like Eclipse you don&#8217;t have to use it).  Run it from the start menu.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-06-12-am/" rel="attachment wp-att-8926"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-1024x681.png" alt="" width="1024" height="681" class="alignnone size-large wp-image-8926" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-1024x681.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-600x399.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-300x199.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-768x511.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM-1536x1021.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.12-AM.png 1994w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>For this demo I will use the CY8CKIT-062-WiFi-Bt kit&#8230; but this works on all of of our PSoC 6 kits with Arduino headers.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-06-24-am/" rel="attachment wp-att-8927"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-1024x681.png" alt="" width="1024" height="681" class="alignnone size-large wp-image-8927" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-1024x681.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-600x399.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-300x200.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-768x511.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM-1536x1021.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.24-AM.png 2006w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I start using the IoT Expert FreeRTOS template.   And I store the project in the directory &#8220;~/iotexpert-projects/xxx&#8221;.  A long time ago I started using directories named &#8220;xxx&#8221; to mean that I can &#8220;rm -rf xxx&#8221; and I never store anything that matters in those files/directories.  Give the project a name then press next.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-06-52-am/" rel="attachment wp-att-8928"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-1024x678.png" alt="" width="1024" height="678" class="alignnone size-large wp-image-8928" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-1024x678.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-600x397.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-300x199.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-768x508.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM-1536x1016.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.06.52-AM.png 2004w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now you have everything setup.  So click &#8220;Create&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-07-05-am/" rel="attachment wp-att-8929"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-1024x680.png" alt="" width="1024" height="680" class="alignnone size-large wp-image-8929" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-1024x680.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-600x398.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-300x199.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-768x510.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM-1536x1020.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.05-AM.png 1994w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And our software will do its thing.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-07-51-am/" rel="attachment wp-att-8930"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-1024x679.png" alt="" width="1024" height="679" class="alignnone size-large wp-image-8930" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-1024x679.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-600x398.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-300x199.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-768x509.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM-1536x1018.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.07.51-AM.png 1998w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now if I look in the directory, I will have a complete project.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-09-34-am/" rel="attachment wp-att-8931"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM-1024x720.png" alt="" width="1024" height="720" class="alignnone size-large wp-image-8931" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM-1024x720.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM-600x422.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM-300x211.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM-768x540.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.09.34-AM.png 1498w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now lets manually add the .lib for the p6sdk-ssd1306-emWin-cyrtos-config.  You can use whatever editor you want, but it&#8217;s emacs for me.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-07-43-pm/" rel="attachment wp-att-8966"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-1024x97.png" alt="" width="1024" height="97" class="alignnone size-large wp-image-8966" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-1024x97.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-600x57.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-300x28.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-768x73.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-1536x145.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.07.43-PM-2048x194.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Enter the URL for the library.  Then put a &#8220;/&#8221;.  Then a branch.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-08-35-pm/" rel="attachment wp-att-8967"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM-1024x982.png" alt="" width="1024" height="982" class="alignnone size-large wp-image-8967" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM-1024x982.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM-600x576.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM-300x288.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM-768x737.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.08.35-PM.png 1176w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now that the file is updated you can run &#8220;make getlibs&#8221; which will search for all of the &#8220;.lib&#8221; files.  Then make sure those libraries are part of your project.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-09-28-pm/" rel="attachment wp-att-8968"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-1024x717.png" alt="" width="1024" height="717" class="alignnone size-large wp-image-8968" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-1024x717.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-600x420.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-300x210.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-768x538.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-1536x1076.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.09.28-PM-2048x1435.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After the make getlibs is run you can see that the p6sdk-ssd1306-emWin-cyrtos-config directory is in your libs directory, with all of the stuff you need.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-10-41-pm/" rel="attachment wp-att-8969"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-1024x815.png" alt="" width="1024" height="815" class="alignnone size-large wp-image-8969" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-1024x815.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-600x477.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-300x239.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-768x611.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM-1536x1222.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.10.41-PM.png 1704w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next step is to edit your main.  I like to use vscode.  If you run  &#8220;make vscode&#8221; our build system will create a vscode project for you.  You can start vscode by running &#8220;code .&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-11-50-pm/" rel="attachment wp-att-8970"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-1024x468.png" alt="" width="1024" height="468" class="alignnone size-large wp-image-8970" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-1024x468.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-600x274.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-300x137.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-768x351.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM-1536x702.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.11.50-PM.png 1898w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Before the emWin library work you will need to add the EMWIN_OSNTS and FREERTOS components to your Makefile.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">COMPONENTS=EMWIN_OSNTS FREERTOS</pre>
<p>Here is what it looks like in vscode</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-13-19-pm/" rel="attachment wp-att-8971"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-1024x877.png" alt="" width="1024" height="877" class="alignnone size-large wp-image-8971" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-1024x877.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-600x514.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-300x257.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-768x658.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-1536x1315.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.13.19-PM-2048x1753.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now, write the your main.c code to display a little message.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cybsp.h"
#include "GUI.h"
#include "SSD1306Driver.h"

int main(void)
{
        /* Set up the device based on configurator selections */
        cybsp_init();

        cyhal_i2c_t I2C;

        /* Configuration to initialize the I2C block */
        static cyhal_i2c_cfg_t i2c_config = {
                .is_slave = false,
                .frequencyhal_hz = 400000
        };
        cyhal_i2c_init(&amp;I2C, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL);
        cyhal_i2c_configure(&amp;I2C, &amp;i2c_config);

        SSD1306DriverInit(&amp;I2C,0x3C);

        GUI_Init();
        GUI_SetColor(GUI_WHITE);
        GUI_SetBkColor(GUI_BLACK);
        GUI_SetFont(GUI_FONT_8_ASCII);
        GUI_SetTextAlign(GUI_TA_CENTER);
        GUI_DispStringAt("Hello World", GUI_GetScreenSizeX()/2,GUI_GetScreenSizeY()/2 - GUI_GetFontSizeY()/2);
}
</pre>
<p>You can build your project by running &#8220;Build&#8221; from vscode or your can built it on the command line with &#8220;make build&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-30-51-am/" rel="attachment wp-att-8945"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-1024x501.png" alt="" width="1024" height="501" class="alignnone size-large wp-image-8945" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-1024x501.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-600x294.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-300x147.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-768x376.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-1536x752.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.30.51-AM-2048x1002.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After building you should have output like this:</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-14-36-pm/" rel="attachment wp-att-8972"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-1024x585.png" alt="" width="1024" height="585" class="alignnone size-large wp-image-8972" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-1024x585.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-600x343.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-300x171.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-768x439.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM-1536x877.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.14.36-PM.png 1562w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>You can program by Pressing selecting or by pressing F5 or selecting &#8220;Run-&gt;Start Debugging&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-34-54-am/" rel="attachment wp-att-8950"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM-1024x158.png" alt="" width="1024" height="158" class="alignnone size-large wp-image-8950" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM-1024x158.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM-600x93.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM-300x46.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM-768x118.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.54-AM.png 1336w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now you can press the play button and you are off to the races</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-34-02-am/" rel="attachment wp-att-8949"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-1024x903.png" alt="" width="1024" height="903" class="alignnone size-large wp-image-8949" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-1024x903.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-600x529.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-300x265.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-768x678.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-1536x1355.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.34.02-AM-2048x1807.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Or on the command line you can program with &#8220;make program&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-32-44-am/" rel="attachment wp-att-8947"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-1024x348.png" alt="" width="1024" height="348" class="alignnone size-large wp-image-8947" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-1024x348.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-600x204.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-300x102.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-768x261.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-1536x522.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.44-AM-2048x696.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-9-32-54-am/" rel="attachment wp-att-8948"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-1024x769.png" alt="" width="1024" height="769" class="alignnone size-large wp-image-8948" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-1024x769.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-600x451.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-300x225.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-768x577.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-1536x1154.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-9.32.54-AM-2048x1538.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>OK.  Looks like the library works!</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/img_1350/" rel="attachment wp-att-8637"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/02/IMG_1350.jpg" alt="" width="800" height="560" class="alignnone size-full wp-image-8637" srcset="https://iotexpert.com/wp-content/uploads/2020/02/IMG_1350.jpg 800w, https://iotexpert.com/wp-content/uploads/2020/02/IMG_1350-600x420.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/02/IMG_1350-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/02/IMG_1350-768x538.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<h1>Updating the IoT Expert MTB2 Manifests</h1>
<p>I showed you how to manually add a library to your project.  But what if you want to have the library you built show up in the Library manager?  In the picture below you can see that is exactly what I did by adding a new category called &#8220;iotexpert&#8221;</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-24-at-3-36-32-pm/" rel="attachment wp-att-8973"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-1024x811.png" alt="" width="1024" height="811" class="alignnone size-large wp-image-8973" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-1024x811.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-600x475.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-300x238.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-768x608.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-1536x1216.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-24-at-3.36.32-PM-2048x1622.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To make this work you need a &#8220;Super Manifest&#8221; which is just a XML file that contains URLs references to your custom Application Templates manifest file(s), Middleware manifests file(s), and BSP manifest file(s). A &#8220;manifest&#8221; file is just an XML file with a list of URLs to Git Repos and some meta data.</p>
<p>In words you need:</p>
<ol>
<li>A file in your home directory called ~/.modustoolbox/manifest.loc which contains a URL for your cusom super manifest file</li>
<li>A super manifest file that optionally contains a references to your application templates manifest file(s)</li>
<li>And/Or contains a reference to your middleware manifest file(s)</li>
<li>And/Or contains a reference to your board support manifest(s)</li>
</ol>
<p>I start by creating the manifest.loc file to refer to a specific file on GitHub. &#8220;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-super-manifest.xml&#8221;.  Notice that it is stored in &#8220;.modustoolbo&#8221; which is a directory that starts with a &#8220;.&#8221; which is a PITA on Windows.  The only way I know how to edit/create this is by using the &#8220;modus shell&#8221; (which we provided as part of the Modus Toolbox installation.  Here is a screenshot from my Mac.  Notice that I use the GitHub URL mechanism to get to the &#8220;raw&#8221; file.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-10-00-20-am/" rel="attachment wp-att-8952"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM-1024x136.png" alt="" width="1024" height="136" class="alignnone size-large wp-image-8952" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM-1024x136.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM-600x80.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM-300x40.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM-768x102.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.00.20-AM.png 1534w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In my SuperManifest file I create references to the</p>
<ul>
<li>board-manifest-list (of which I have none)</li>
<li>app-manifest-list which links to my application template manifest</li>
<li>middleware-manifest which links to my middleware manifest file</li>
</ul>
<p>Notice that both of these files are on the same GitHub repository.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">&lt;super-manifest&gt;
  &lt;board-manifest-list&gt;
  &lt;/board-manifest-list&gt;
  
  &lt;app-manifest-list&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-app-manifest.xml&lt;/uri&gt;
      &lt;/app-manifest&gt;
   &lt;/app-manifest-list&gt;
  &lt;board-manifest-list&gt;
  &lt;/board-manifest-list&gt;
  &lt;middleware-manifest-list&gt;
    &lt;middleware-manifest&gt;
      &lt;uri&gt;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
  &lt;/middleware-manifest-list&gt;
&lt;/super-manifest&gt;</pre>
<p>Then if you look at the actual middleware manifest you will see that I have two (currently) middleware repositories</p>
<ul>
<li>(The NTSHell) https://github.com/iotexpert/middleware-ntshell</li>
<li>(The SSD1306 Middleware in this article) https://github.com/iotexpert/p6sdk-ssd1306-emWin-cyrtos-config</li>
</ul>
<p>The rest of the XML is meta data which specifies how the middleware is presented by the library manager.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">&lt;middleware&gt;
  &lt;middleware&gt;
    &lt;name&gt;ntshell&lt;/name&gt;
    &lt;id&gt;ntshell&lt;/id&gt;
    &lt;uri&gt;https://github.com/iotexpert/middleware-ntshell&lt;/uri&gt;
    &lt;desc&gt;NT Shell&lt;/desc&gt;
    &lt;category&gt;iotexpert&lt;/category&gt;
    &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
    &lt;versions&gt;
      &lt;version&gt;
        &lt;num&gt;Latest 1.X release&lt;/num&gt;
        &lt;commit&gt;master&lt;/commit&gt;
        &lt;desc&gt;Latest 1.X release&lt;/desc&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/middleware&gt;
  &lt;middleware&gt;
    &lt;name&gt;SSD1306-emwin-cyrtos-config&lt;/name&gt;
    &lt;id&gt;SSD1306-emwin-cyrtos-config&lt;/id&gt;
    &lt;uri&gt;https://github.com/iotexpert/p6sdk-ssd1306-emwin-cyrtos-config&lt;/uri&gt;
    &lt;desc&gt;SSD1306-emwin-cyrtos-config&lt;/desc&gt;
    &lt;category&gt;iotexpert&lt;/category&gt;
    &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
    &lt;versions&gt;
      &lt;version&gt;
        &lt;num&gt;Latest 1.X release&lt;/num&gt;
        &lt;commit&gt;master&lt;/commit&gt;
        &lt;desc&gt;Latest 1.X release&lt;/desc&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/middleware&gt;
&lt;/middleware&gt;</pre>
<p>You can see that my GitHub repository contains</p>
<ol>
<li>iotexpert-super-manifest.xml  &#8211; amazingly enough the super manifest</li>
<li>iotexpert-mw-manifest.xml &#8211; my middleware manifest file</li>
<li>iotexpert-app-manifest.xml &#8211; my application template manifest file</li>
</ol>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-10-14-26-am/" rel="attachment wp-att-8953"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-1024x937.png" alt="" width="1024" height="937" class="alignnone size-large wp-image-8953" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-1024x937.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-600x549.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-300x274.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-768x703.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM-1536x1405.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.14.26-AM.png 1928w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now if you look at the bottom of the library manager you will see that when it starts up it read the Cypress Super Manifest file, as well as the IoT Expert Super Manifest.</p>
<p><a href="https://iotexpert.com/2020/03/30/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/screen-shot-2020-03-22-at-10-16-20-am/" rel="attachment wp-att-8954"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-1024x170.png" alt="" width="1024" height="170" class="alignnone size-large wp-image-8954" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-1024x170.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-600x100.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-300x50.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-768x128.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM-1536x255.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-22-at-10.16.20-AM.png 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To be clear.  If you add my &#8220;manifest.loc&#8221; file to your ~/.modustoolbox directory you will access to all of my libraries.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/modustoolbox-2-0-libraries-an-example-for-emwin-super-manifests/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MBEDOS Libraries &#038; emWin Configuration Files</title>
		<link>https://iotexpert.com/mbedos-libraries-emwin-configuration-files/</link>
					<comments>https://iotexpert.com/mbedos-libraries-emwin-configuration-files/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 02 Sep 2019 11:36:31 +0000</pubDate>
				<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[MBED OS]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=7851</guid>

					<description><![CDATA[Summary I have written a fair amount about Graphics Displays, using the Segger emWin graphics library and MBED OS.  I have found it irritating to do all of the configuration stuff required to get these kinds of projects going.  I inevitably go back, look at my old articles, find the github repository of my example [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>I have written a fair amount about Graphics Displays, using the <a href="https://www.segger.com/products/user-interface/emwin/" target="_blank" rel="noopener noreferrer">Segger emWin</a> graphics library and MBED OS.  I have found it irritating to do all of the configuration stuff required to get these kinds of projects going.  I inevitably go back, look at my old articles, find the github repository of my example projects etc.  This week I wanted to write some programs for the new CY8CKIT-062S2-43012 development kit so I thought that I would try all of the Cypress displays using that development kit.  Rather than starting with example projects, this time I decided to build configurable mbedos libraries. In this article I will show you how to build configurable mbed os libraries which will allow you to use the emWin Graphics Library with all of the Cypress display shields.</p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/img_0806/" rel="attachment wp-att-7852"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0806-1024x718.jpg" alt="" width="1024" height="718" class="alignnone size-large wp-image-7852" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0806-1024x718.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0806-600x421.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0806-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0806-768x538.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/img_0804/" rel="attachment wp-att-7853"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0804-1024x745.jpg" alt="" width="1024" height="745" class="alignnone size-large wp-image-7853" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0804-1024x745.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0804-600x436.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0804-300x218.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0804-768x559.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/img_0805/" rel="attachment wp-att-7854"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0805-1024x729.jpg" alt="" width="1024" height="729" class="alignnone size-large wp-image-7854" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0805-1024x729.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0805-600x427.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0805-300x214.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0805-768x547.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In this article I will walk you through:</p>
<ul>
<li>The CY8CKIT-032 &amp; SSD1306 Display Driver &amp; emWin</li>
<li>MBED OS Libraries</li>
<li>MBED OS Configuration</li>
<li>Configuration Overrides</li>
<li>The SSD1306 emWin Configuration</li>
<li>Using the SSD1306 Configuration Library</li>
<li>emWin Configuration Libraries</li>
</ul>
<h1>The CY8CKIT-032 &amp; SSD1306 Display Driver &amp; emWin</h1>
<p>The CY8CKIT-032 has a little 0.96&#8243; OLED display that is attached to the Salomon Systech SSD1306 Display Driver.  I have <a href="https://iotexpert.com/?s=ssd1306" target="_blank" rel="noopener noreferrer">written</a> quite a bit about this little screen as it is cheap and fairly easy to use.  It became even easier when we released the Segger emWin SPAGE display driver.  And with my new library it should be trivial to use and configure for your setup.</p>
<p>You can read in detail about the functionality <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/" target="_blank" rel="noopener noreferrer">here</a> but in short:</p>
<ul>
<li>The display driver chip is attached to the PSoC via I2C</li>
<li>You need to provide the Segger emWin driver
<ul>
<li>GUIConfig.h/cpp &#8211; Segger GUI configuration</li>
<li>LCDConf.h/cpp &#8211; Setup files for the LCD</li>
<li>GUI_X_Mbed.cpp &#8211; RTOS control functions for delays etc.</li>
<li>ssd1306.h/c &#8211; physical interface to the SSD1306 controller</li>
</ul>
</li>
<li>You need to initialize the PSoC I2C before talking to the display</li>
<li>You need to initialize the display driver chip before drawing on the screen</li>
</ul>
<p>In general all of this configuration will be the same from project to project to project.  However, you may very will find that you have the display connected to a different set of pins.  I suppose that would put all of these files into some directory.  Then you could copy that directory into your project every time.  Which would leave you with modifying the configuration to meet your specific board connection.  The problem with that is you have now deeply intertwined your project with those files.</p>
<p>MBED OS has given us a really cool alternative.  Specifically the Library and <a href="https://os.mbed.com/docs/mbed-os/v5.13/reference/configuration.html" target="_blank" rel="noopener noreferrer">configuration</a> systems.</p>
<h1>MBED OS Libraries</h1>
<p>An MBED OS library is simply a git repository.  Just a directory of source files.  When you run the command &#8220;mbed add repository&#8221; it does two basic things</p>
<ol>
<li>It does a &#8220;git clone&#8221; to make a copy of the repository inside of your project.</li>
<li>It creates a file with the repository name.lib which contains the URL to the version of the repository</li>
</ol>
<p>Here is a an MBED add of my graphics configuration library for the SSD1306</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">(mbed CLI) ~/Mbed Programs/test032 $ mbed add git@github.com:iotexpert/mbed-os-emwin-ssd1306.git
[mbed] Working path "/Users/arh/Mbed Programs/test032" (program)
[mbed] Adding library "mbed-os-emwin-ssd1306" from "ssh://git@github.com/iotexpert/mbed-os-emwin-ssd1306" at latest revision in the current branch
[mbed] Updating reference "mbed-os-emwin-ssd1306" -&gt; "https://github.com/iotexpert/mbed-os-emwin-ssd1306/#7986006c17bd572da317257640f35ec3b232414e"
(mbed CLI) ~/Mbed Programs/test032 $ ls mbed-os-emwin-ssd1306
GUIConf.cpp    GUI_X_Mbed.cpp LCDConf.h      mbed_lib.json  ssd1306.h
GUIConf.h      LCDConf.cpp    README.md      ssd1306.cpp
(mbed CLI) ~/Mbed Programs/test032 $ more mbed-os-emwin-ssd1306.lib 
https://github.com/iotexpert/mbed-os-emwin-ssd1306/#7986006c17bd572da317257640f35ec3b232414e
(mbed CLI) ~/Mbed Programs/test032 $ 
</pre>
<p>Notice that when I &#8220;ls&#8217;d&#8221; the directory that all of file required to confiugure emWin for the SSD1306 became part of my project.  And the file mbed-os-emwin-ssd1306.lib was created with the URL of the github repository.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">https://github.com/iotexpert/mbed-os-emwin-ssd1306/#7986006c17bd572da317257640f35ec3b232414e
</pre>
<p>When you run &#8220;mbed compile&#8221; the build system just searches that directory for cpp and h files turns them into .0&#8217;s and add them to the the BUILD directory.  However, before it compiles it run the configuration system.</p>
<h1>MBED OS Configuration System</h1>
<p>The configuration system takes the file &#8220;mbed_lib.json&#8221; parses it and turns it into a C-header file called mbed_config.h.  The format of this file is</p>
<ul>
<li>The name of the component &#8211; in this case &#8220;SSD1306_OLED&#8221;</li>
<li>The parameters of the component SDA, SCL, I2CADDRESS and I2CFREQ</li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">{
    "name" : "SSD1306_OLED",
    "config": {
        "SDA":"P6_1",
        "SCL":"P6_0",
        "I2CADDRESS":"0x78",
        "I2CFREQ":"400000"
    }
}
</pre>
<p>This header file is then placed into the BUILD directory of your project and is included as part of #include &#8220;mbed.h&#8221;</p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/screen-shot-2019-08-24-at-10-50-52-am/" rel="attachment wp-att-7860"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM-957x1024.png" alt="" width="957" height="1024" class="alignnone size-large wp-image-7860" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM-957x1024.png 957w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM-600x642.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM-280x300.png 280w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM-768x822.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-10.50.52-AM.png 1022w" sizes="(max-width: 957px) 100vw, 957px" /></a></p>
<p>If you open mbed_config.h you will find that it creates #defines of the component parameters</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define MBED_CONF_SSD1306_OLED_I2CADDRESS                                     0x78                                                                                             // set by library:SSD1306_OLED
#define MBED_CONF_SSD1306_OLED_I2CFREQ                                        400000                                                                                           // set by library:SSD1306_OLED
#define MBED_CONF_SSD1306_OLED_SCL                                            P6_0                                                                                             // set by library:SSD1306_OLED
#define MBED_CONF_SSD1306_OLED_SDA                                            P6_1</pre>
<p>This is really nice because I can then reference those #defines in my source code.</p>
<h1>Configuration Overrides</h1>
<p>When you are building the library you can create an arbitrary number of these parameters which are then applied to all of the uses of that library.  Or if there is some reason why one target is different you can specify the parameters for that specific target by changing the mbed_lib.json.  For instance if the CY8CKIT_062S2_43012 need a 100K I2C frequency instead of 400K (it doesn&#8217;t), you could do this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">{
    "name" : "SSD1306_OLED",
    "config": {
        "SDA":"P6_1",
        "SCL":"P6_0",
        "I2CADDRESS":"0x78",
        "I2CFREQ":"400000"
    },
    "target_overrides" : {
        "CY8CKIT_062S2_43012" : {
            "I2CFREQ":"100000"
        }
    }
}
</pre>
<p>The application developer is also allowed to over-ride the parameter by providing the target overrides in the MBED OS file &#8220;mbed_app.json&#8221;.  Notice that the way you specify the parameter name is different in this file than the mbed_lib.json.  In this case you give it the name of the library.parametername.  Here is an example setting the I2CFrequency to 100K</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">{
	"target_overrides": {
        "*": {
            "target.components_add": ["EMWIN_OSNTS"]
        },
        "CY8CKIT_062S2_43012" : {
            "SSD1306_OLED.I2CFREQ": "1000000"
        }
	}
}</pre>
<p>Which would result in a change to the generated #define in mbed_config.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define MBED_CONF_SSD1306_OLED_I2CFREQ                                        1000000</pre>
<p>Notice that you can specify a &#8220;*&#8221; to match all of the targets, or you can specify the exact target.</p>
<h1>The SSD1306 emWin Configuration</h1>
<p>I use the configuration system to generate #defines for the</p>
<ul>
<li>SCL/SDA Pin Numbers</li>
<li>I2C Address</li>
<li>I2C Frequency</li>
</ul>
<p>Which lets my use those #defines in ssd1306.cpp</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">I2C Display_I2C(MBED_CONF_SSD1306_OLED_SDA, MBED_CONF_SSD1306_OLED_SCL);</pre>
<p>And</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">void ssd1306_Init(void) 
{
    Display_I2C.frequency(MBED_CONF_SSD1306_OLED_I2CFREQ);
}</pre>
<h1>Using the SSD1306 Configuration Library</h1>
<p>Lets make an example project that uses the CY8CKIT_062S2_43012 and the CY8CKIT032 using the Segger graphics library and my configuration library.</p>
<p>Start by make a new project, adding the emWin library and the configuration library.  It should look something like this</p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/screen-shot-2019-08-24-at-11-39-40-am/" rel="attachment wp-att-7863"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM-1024x470.png" alt="" width="1024" height="470" class="alignnone size-large wp-image-7863" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM-1024x470.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM-600x275.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM-300x138.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM-768x352.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.39.40-AM.png 1674w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now edit the mbed_app.json to add the emWin library</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">{
	"target_overrides": {
        "*": {
            "target.components_add": ["EMWIN_OSNTS"]
        }
	}
}</pre>
<p>Create the main.cpp which simply initializes the display and displays &#8220;hello world&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "mbed.h"
#include "GUI.h"

int main()
{
  GUI_Init();
  GUI_SetColor(GUI_WHITE);
  GUI_SetBkColor(GUI_BLACK);
  GUI_SetFont(GUI_FONT_13B_1);
  GUI_SetTextAlign(GUI_TA_CENTER);
  GUI_DispStringAt("Hello World", GUI_GetScreenSizeX()/2,GUI_GetScreenSizeY()/2 - GUI_GetFontSizeY()/2);
}</pre>
<p>When you compile it with</p>
<ul>
<li><span>mbed compile -t GCC_ARM -m CY8CKIT_062S2_43012 -f</span></li>
</ul>
<p>You should get something like this:</p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/screen-shot-2019-08-24-at-11-43-40-am/" rel="attachment wp-att-7864"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM-1024x985.png" alt="" width="1024" height="985" class="alignnone size-large wp-image-7864" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM-1024x985.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM-600x577.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM-300x288.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM-768x738.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-24-at-11.43.40-AM.png 1664w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And your screen should look like this (notice I made the font bigger than the original screen shot)</p>
<p><a href="https://iotexpert.com/2019/09/02/mbedos-libraries-emwin-configuration-files/img_0807/" rel="attachment wp-att-7866"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0807-1024x876.jpg" alt="" width="1024" height="876" class="alignnone size-large wp-image-7866" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0807-1024x876.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0807-600x513.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0807-300x257.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0807-768x657.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>emWin Configuration Libraries</h1>
<p>Finally I created libraries for all of the Cypress displays.  You can use these to make your project easier to get going.</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Kit</th>
<th >Driver Chip</th>
<th >Library Link</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://www.cypress.com/documentation/development-kitsboards/tft-display-shield-board-cy8ckit-028-tft" target="_blank" rel="noopener noreferrer">CY8CKIT-028-TFT</a></td>
<td >ST7789V</td>
<td ><a href="https://github.com/iotexpert/mbed-os-emwin-st7789v" target="_blank" rel="noopener noreferrer">git@github.com:iotexpert/mbed-os-emwin-st7789v.git</a></td>
</tr>

<tr><td ><a href="https://www.cypress.com/documentation/development-kitsboards/cy8ckit-032-psoc-analog-front-end-afe-arduino-shield" target="_blank" rel="noopener noreferrer">CY8CKIT-032</a></td>
<td >SSD1306</td>
<td ><a href="https://github.com/iotexpert/mbed-os-emwin-ssd1306" target="_blank" rel="noopener noreferrer">git@github.com:iotexpert/mbed-os-emwin-ssd1306.git</a></td>
</tr>

<tr><td ><a href="https://www.cypress.com/documentation/development-kitsboards/e-ink-display-shield-board-cy8ckit-028-epd" target="_blank" rel="noopener noreferrer">CY8CKIT-028-EPD</a></td>
<td >Pervasive EPD</td>
<td > <a href="https://github.com/iotexpert/mbed-os-emwin-epd" target="_blank" rel="noopener noreferrer">git@github.com:iotexpert/mbed-os-emwin-epd.git</a></td>
</tr>
</tbody></table></div>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/mbedos-libraries-emwin-configuration-files/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Debugging SSD1306 Display Problems</title>
		<link>https://iotexpert.com/debugging-ssd1306-display-problems/</link>
					<comments>https://iotexpert.com/debugging-ssd1306-display-problems/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Wed, 07 Aug 2019 13:19:13 +0000</pubDate>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[MBED OS]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=7593</guid>

					<description><![CDATA[Summary This article explains in detail how to use and debug SSD1306 displays.  In this article, I use the Segger emWin library and MBEDOS, but for all practical purposes this discussion applies to all other interfaces to the board including Arduino, Raspberry Pi, Adafruit, etc.  I will say from the outset that I spent far [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This article explains in detail how to use and debug SSD1306 displays.  In this article, I use the Segger emWin library and MBEDOS, but for all practical purposes this discussion applies to all other interfaces to the board including Arduino, Raspberry Pi, Adafruit, etc.  I will say from the outset that I spent far far too much time digging into the inner workings of an 11 year old graphics driver.  Oh well, hopefully someone will get some benefit.</p>
<p>A year ago (or so) I designed a user interface board called the CY8CKIT-032 to go with my Cypress WICED WiFi book and class.  This board uses a PSoC 4 Analog co-processor which can do a bunch of cool stuff.  I have a series of articles planned about that board, but that will be for another day.  One of the things that I did was put a 0.96&#8243; I2C OLED Display based on a SSD1306 driver on the board.  These displays are widely available from Alibaba and eBay for &lt;$2.  I think that the displays are being used in inexpensive cells phones in China so there are tons of them and they are CHEAP!  The bad news is that if you google &#8220;ssd1306 problems&#8221; you will find an absolute rogues gallery of unpleasantness.  It seems that tons of people struggle to get these things working.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0744/" rel="attachment wp-att-7604"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0744-1024x842.jpg" alt="" width="1024" height="842" class="alignnone size-large wp-image-7604" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0744-1024x842.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0744-600x493.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0744-300x247.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0744-768x631.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This whole thing started last week as Cypress released and update to our MBED OS implementation.  This update included releasing a complete set of the Segger emWin drivers.  I had been wanting to step up to a more robust graphics library than the Adafruit library that I used in this <a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/" target="_blank" rel="noopener noreferrer">article</a>.  I was pleased to see that our release included the emWin SPAGE driver which knows how to talk to a bunch of different page based displays including the SSD1306.</p>
<p>But, as always, I had to wrestle with the display a little bit before I got everything working.  This time I wrote down what I did/learned.  So, for this article I will describe</p>
<ul>
<li>The SSD1306 Electrical Interface</li>
<li>The SSD1306 Software Interface</li>
<li>The SSD1306 Driver Registers</li>
<li>The SSD1306 Graphics Data RAM</li>
<li>Reading from the Frame Buffer</li>
<li>My Initialization Sequence</li>
<li>Some Other Initialization Sequences</li>
<li>A Bunch of Screen Problems &amp; How To Fix</li>
</ul>
<h1>The Electrical Interface</h1>
<p>There is not a lot to know about the electrical interface.  The data sheet specifies that the device can use I2C, SPI, 6800 and 8080.  I have not seen either the 6800 or 8080 interface put onto any of these OLED displays.  Like all driver chips, the SSD1306 has an absolute boatload of pins, in fact, 281.  The chip is long and skinny and was made to be mounted either on the display under the glass or on the flex connector.  Of the 281 pins, 128+64=196 are connected to the segments and commons in the display.  The rest of the pins are either capacitors, no-connects, power/ground or data signals.  The data signals are</p>
<ul>
<li>D0-D7 either parallel data for 8080/6800 or SDA/SCL for I2C or MOSI/MISO for SPI</li>
<li>E &#8211; enable signal for 6800 or RD for 8080</li>
<li>R/W# &#8211; Read Write for 6800/8080</li>
<li>CS &#8211; Chip Select for SPI, 8080, 6800</li>
<li>D/C# &#8211; Data or Command for SPI, 6800, 8080 or Slave Address Select for I2C</li>
<li>Reset &#8211; Chip reset</li>
</ul>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-07-28-at-7-28-49-am/" rel="attachment wp-att-7632"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM-1024x281.png" alt="" width="1024" height="281" class="alignnone size-large wp-image-7632" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM-1024x281.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM-600x165.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM-300x82.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM-768x211.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-7.28.49-AM.png 1936w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>For the I2C configurations it is common to tie the reset pin High and not bring the pin to a connector.  The SA0 is also typically connected via a 0-ohm resistor to either 0 or 1 which configures the device to have the 7-bit address 0x3C or 0x3D or 8-bit 0x78 or 0x7A.  Here is a picture of the back of one of my boards where you can see the 0ohm resistor.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0758/" rel="attachment wp-att-7633"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758-967x1024.jpg" alt="" width="967" height="1024" class="alignnone size-large wp-image-7633" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758-967x1024.jpg 967w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758-600x636.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758-283x300.jpg 283w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758-768x814.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0758.jpg 1059w" sizes="(max-width: 967px) 100vw, 967px" /></a></p>
<p>Sometimes all of the data pins are available on the back of the board.  This lets you move/add/change the 0-ohm resistors to configure the mode of the chip.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/sku_340467_1-2/" rel="attachment wp-att-7636"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/sku_340467_1-1.jpg" alt="" width="479" height="455" class="alignnone size-full wp-image-7636" srcset="https://iotexpert.com/wp-content/uploads/2019/07/sku_340467_1-1.jpg 479w, https://iotexpert.com/wp-content/uploads/2019/07/sku_340467_1-1-300x285.jpg 300w" sizes="(max-width: 479px) 100vw, 479px" /></a> <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/b9d2d39952c19f77d0cc89703b80c0a0-image-600x600-2/" rel="attachment wp-att-7637"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/b9d2d39952c19f77d0cc89703b80c0a0.image_.600x600-1.jpg" alt="" width="377" height="373" class="alignnone size-large wp-image-7637" srcset="https://iotexpert.com/wp-content/uploads/2019/07/b9d2d39952c19f77d0cc89703b80c0a0.image_.600x600-1.jpg 377w, https://iotexpert.com/wp-content/uploads/2019/07/b9d2d39952c19f77d0cc89703b80c0a0.image_.600x600-1-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/b9d2d39952c19f77d0cc89703b80c0a0.image_.600x600-1-300x297.jpg 300w" sizes="(max-width: 377px) 100vw, 377px" /></a></p>
<p>One thing you should be careful about is the I2C connections.  I looked around on eBay and Alibaba to find a few pictures of the I2C displays.  You should notice that all three of these displays are I2C, but all three of them have a different position and ORDER of VCC/GND/SCL/SDL  When we ordered displays from China to go onto the CY8CKIT-032 we found displays in the same BATCH that had different orders of the VCC/GND.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/muadz9bapvnzwizfk-ndhbg/" rel="attachment wp-att-7626"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/mUADz9BApvNzwiZfK-Ndhbg.jpg" alt="" width="225" height="225" class="alignnone size-full wp-image-7626" srcset="https://iotexpert.com/wp-content/uploads/2019/07/mUADz9BApvNzwiZfK-Ndhbg.jpg 225w, https://iotexpert.com/wp-content/uploads/2019/07/mUADz9BApvNzwiZfK-Ndhbg-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/mUADz9BApvNzwiZfK-Ndhbg-150x150.jpg 150w" sizes="(max-width: 225px) 100vw, 225px" /></a>  <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/mjvbbenrakthvstgdwuagew/" rel="attachment wp-att-7629"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/mjVBBeNrakthvSTgdwuAGEw.jpg" alt="" width="225" height="225" class="alignnone size-large wp-image-7629" srcset="https://iotexpert.com/wp-content/uploads/2019/07/mjVBBeNrakthvSTgdwuAGEw.jpg 225w, https://iotexpert.com/wp-content/uploads/2019/07/mjVBBeNrakthvSTgdwuAGEw-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/mjVBBeNrakthvSTgdwuAGEw-150x150.jpg 150w" sizes="(max-width: 225px) 100vw, 225px" /></a> <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/s-l225-2/" rel="attachment wp-att-7630"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/s-l225-2.jpg" alt="" width="225" height="225" class="alignnone size-full wp-image-7630" srcset="https://iotexpert.com/wp-content/uploads/2019/07/s-l225-2.jpg 225w, https://iotexpert.com/wp-content/uploads/2019/07/s-l225-2-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/s-l225-2-150x150.jpg 150w" sizes="(max-width: 225px) 100vw, 225px" /></a></p>
<p>Here is a SPI version that has reset and data/command pin brought out.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/s-l225/" rel="attachment wp-att-7627"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/s-l225.jpg" alt="" width="225" height="225" class="alignnone size-large wp-image-7627" srcset="https://iotexpert.com/wp-content/uploads/2019/07/s-l225.jpg 225w, https://iotexpert.com/wp-content/uploads/2019/07/s-l225-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/s-l225-150x150.jpg 150w" sizes="(max-width: 225px) 100vw, 225px" /></a>  <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/miivqcnyakhfayi4kzkqyuq/" rel="attachment wp-att-7628"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/miiVQcnyakhfaYI4KZKqYUQ.jpg" alt="" width="225" height="225" class="alignnone size-large wp-image-7628" srcset="https://iotexpert.com/wp-content/uploads/2019/07/miiVQcnyakhfaYI4KZKqYUQ.jpg 225w, https://iotexpert.com/wp-content/uploads/2019/07/miiVQcnyakhfaYI4KZKqYUQ-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/miiVQcnyakhfaYI4KZKqYUQ-150x150.jpg 150w" sizes="(max-width: 225px) 100vw, 225px" /></a></p>
<h1>The Software Interface</h1>
<p>There are two parts to the software interface.</p>
<p>The first part is the command interface.  Inside of the chip there are a bunch of logic circuits which which configure the charge pumps, sequence COMs and SEGs, charge and discharge capacitors etc.  All of these things are configurable to allow for different configurations of screens e.g. different x-y sizes, configuration of what wires are connected to what places on the glass etc.  Before you can get the display to work correctly you must initialize all of these values by sending commands.  All the commands are 1-byte followed by 0 or more command parameters.</p>
<p>The second part is the data interface.  Inside of the SSD1306 chip there is a Graphics Display DRAM &#8211; GDDRAM which has 1 bit for every pixel on the screen. The state machine inside of the chip called the Display Controller will loop through the bits one by one and display them on the correct place on the screen.  This means that your MCU does not need to do anything to keep the display up to date.  When you want a pixel lit up on the screen you just need to write the correct location in the GDDRAM.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-07-28-at-5-04-06-pm/" rel="attachment wp-att-7676"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM-917x1024.png" alt="" width="917" height="1024" class="alignnone size-large wp-image-7676" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM-917x1024.png 917w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM-600x670.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM-269x300.png 269w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM-768x857.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.04.06-PM.png 1516w" sizes="(max-width: 917px) 100vw, 917px" /></a></p>
<p>For the rest of this article I will focus on the serial interface, I2C.  How do you send commands and data?  Simple.  When you start a transaction you send a control byte which tells the controller what to expect next.  There are four legal control bytes.</p>
<ul>
<li>0b10000000 = 0x80 = multiple commands</li>
<li>0b00000000 = 0x00 = one command</li>
<li>0b11000000 = 0xC0 = multiple data</li>
<li>0b01000000 = 0x40 = one data byte</li>
</ul>
<p>Here is the picture from the datasheet (which I don&#8217;t find particularly illuminating) but it does describe the control byte.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-07-28-at-5-21-23-pm/" rel="attachment wp-att-7677"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM-1024x614.png" alt="" width="1024" height="614" class="alignnone size-large wp-image-7677" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM-1024x614.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM-600x360.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM-300x180.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM-768x461.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-5.21.23-PM.png 1394w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To send commands you write to the I2C bus with a control byte, then you send the command, then you send the optional parameters.  If you want to send multiple commands you send the control byte 0x80, the command + parameters as many as you need.</p>
<h1>The SSD1306 Driver Registers</h1>
<p>In order for the driver chip to drive the screen you need to configure:</p>
<ol>
<li>How the driver is electrically connected to the OLED Screen</li>
<li>What are the electrical parameters of the screen</li>
<li>What are the electrical parameters of the system</li>
<li>How you want to address the frame buffer</li>
<li>The automatic scroll configuration settings</li>
<li>The pixel data for the frame buffer, though it will happily display noise.</li>
</ol>
<p>If you bought this screen from eBay, Adafruit, Alibaba etc. then you will get no say in 1-3, the electrical parameters of the system.  Your screen will come prewired with all of the capacitors, OLED etc already attached to your driver commons and segments.  If you didn&#8217;t buy the screen prepackaged, then it is highly unlikely you are reading this article.  What this means is that you need to know the initializing sequence required to get the screen to work properly, then you just send the sequence down the wire from your MCU to the screen.  From looking around on the internet, it appears to me that there in only one parameter that is different in any of the screens that I could find.  Specifically the number of lines on the screen &#8211; either 32 or 64.  Which means that all of these initialization implementations should really on have one difference register 0xA8 should be set to either n-1 aka 31 or 63</p>
<p>The other difference that you will see between different implementations is the memory address mode.  In other words, how do you want to write data into the frame buffer from the MCU.  Many of the open source graphics libraries use &#8220;Horizontal&#8221; mode.  The Segger emWin library that I am using uses &#8220;Page&#8221; mode.  More on this later.</p>
<p>When you look in the data sheet, unfortunately they mix and match the order of the information.  However, from the data sheet, the categories are:</p>
<ol>
<li>Fundamental Commands</li>
<li>Scrolling Commands</li>
<li>Address Setting Commands</li>
<li>Hardware Configuration</li>
<li>Timing and Driving Scheme</li>
<li>Charge Pump</li>
</ol>
<p>I won&#8217;t put screen shots of the whole data sheet into this article, but I will show the command table and make a few clarifications on the text.  Or at least I will clarify places where I got confused.</p>
<p>As to the fundamental commands.  I tried a bunch of different contrast settings on my screens and could not tell the difference between them.  I tried from 0x10 to 0xFF and they all looked the same to me.  The best course of action is to use the default 0x7F.  I don&#8217;t really know why there is a command 0xA5 &#8220;Entire Display ON ignore RAM&#8221;.  The data sheet says &#8220;A5h command forces the entire display to be “ON”, regardless of the contents of the display data RAM&#8221;.  I can&#8217;t think of a single use case for this.  I suppose that if you issue 0xAE the screen will be all black&#8230; and if you issue 0xA5 the screen will be all white?  But why?</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-17-14-am/" rel="attachment wp-att-7690"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM-1024x476.png" alt="" width="1024" height="476" class="alignnone size-large wp-image-7690" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM-1024x476.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM-600x279.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM-300x139.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM-768x357.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.17.14-AM.png 1610w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And my definitions in the C driver file:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">////////////////////////////////////////////////////////////////////////
// Fundamental Command Table Page 28
////////////////////////////////////////////////////////////////////////
#define OLED_SETCONTRAST                              0x81
// 0x81 + 0-0xFF Contrast ... reset = 0x7F

// A4/A5 commands to resume displaying data
// A4 = Resume to RAM content display
// A5 = Ignore RAM content (but why?)
#define OLED_DISPLAYALLONRESUME                       0xA4
#define OLED_DISPLAYALLONIGNORE                       0xA5

// 0xA6/A7 Normal 1=white 0=black Inverse 0=white  1=black
#define OLED_DISPLAYNORMAL                            0xA6
#define OLED_DISPLAYINVERT                            0xA7

// 0xAE/AF are a pair to turn screen off/on
#define OLED_DISPLAYOFF                               0xAE
#define OLED_DISPLAYON                                0xAF</pre>
<p>In the next section of the command table are the &#8220;Scrolling&#8221; commands.  It appears that this graphics chip was setup to display text that is 8-pixels high.  The scrolling commands will let you move the screen up/down and left/right to scroll automatically without having to update the the frame buffer.  In other words it can efficiently scroll the screen without a bunch of load on your MCU CPU or on the data bus between them.  The Adafruit graphics library provides the scrolling commands.  However, I am not using them with the Segger Library.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-8-41-09-am/" rel="attachment wp-att-7698"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM-1024x577.png" alt="" width="1024" height="577" class="alignnone size-large wp-image-7698" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM-1024x577.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM-600x338.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM-300x169.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM-768x433.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-8.41.09-AM.png 1692w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next section has the commands to configure how your MCU writes data into the Graphics RAM aka the frame buffer. These commands fall into two categories.  First the address mode.  The address modes help you efficiently write the GDDRAM.  When you send data to the frame buffer you really don&#8217;t want to send</p>
<ul>
<li>address, pixel, address, pixel, &#8230;</li>
</ul>
<p>What you really would like to do is send</p>
<ul>
<li>Address, pixel, pixel, pixel &#8230; (and have the address be automatically incremented</li>
</ul>
<p>At first blush you might think&#8230; why do I need a mode?  Well there are some people who want the x address incremented&#8230; there are some people who want the y-address incremented and there are some people who want to have page address access.  And what do you do when you get to the end of a line? or a column or a page? and what does the end mean?</p>
<p>The second set of commands in this table are the commands to set the starting address before you write data.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-16-11-am/" rel="attachment wp-att-7687"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM-1024x733.png" alt="" width="1024" height="733" class="alignnone size-large wp-image-7687" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM-1024x733.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM-600x430.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM-300x215.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM-768x550.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.11-AM.png 1634w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>  <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-16-33-am/" rel="attachment wp-att-7689"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM-1024x409.png" alt="" width="1024" height="409" class="alignnone size-large wp-image-7689" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM-1024x409.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM-600x240.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM-300x120.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM-768x307.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.16.33-AM.png 1642w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">////////////////////////////////////////////////////////////////////////
// Address Setting Command Table
////////////////////////////////////////////////////////////////////////

// 00-0F - set lower nibble of page address
// 10-1F - set upper niddle of page address

#define OLED_SETMEMORYMODE                            0x20
#define OLED_SETMEMORYMODE_HORIZONTAL                 0x00
#define OLED_SETMEMORYMODE_VERTICAL                   0x01
#define OLED_SETMEMORYMODE_PAGE                       0x02

// 0x20 + 00 = horizontal, 01 = vertical 2= page &gt;=3=illegal

// Only used for horizonal and vertical address modes
#define OLED_SETCOLUMNADDR                            0x21
// 2 byte Parameter
// 0-127 column start address 
// 0-127 column end address

#define OLED_SETPAGEADDR                              0x22
// 2 byte parameter
// 0-7 page start address
// 0-7 page end Address

// 0xB0 -0xB7 ..... Pick page 0-7</pre>
<p>The hardware configuration registers allow the LED display maker to hookup the common and segment signals in an order that makes sense for the placement of the chip on the OLED glass.  For a 128&#215;64 display there are at least 196 wires, so the routing of these wires may be a total pain in the ass depending on the location of the chip.  For instance the left and right might be swapped&#8230; or half the wires might come out on one side and the other half on the other side.  These registers allow the board designer flexibility in making these connections.  Commands 0xA0, 0xA1, 0xA8, 0xC0, 0xC8, 0xD3, 0xDa will all be fixed based on the layout.  You have no control and they need to be set correctly or something crazy will come out.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-15-41-am/" rel="attachment wp-att-7686"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM-1024x768.png" alt="" width="1024" height="768" class="alignnone size-large wp-image-7686" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM-1024x768.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM-600x450.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM-300x225.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM-768x576.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.15.41-AM.png 1662w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">////////////////////////////////////////////////////////////////////////
// Hardware Configuration
////////////////////////////////////////////////////////////////////////

// 40-7F - set address startline from 0-127 (6-bits)
#define OLED_SETSTARTLINE_ZERO                        0x40

// Y Direction
#define OLED_SEGREMAPNORMAL                           0xA0
#define OLED_SEGREMAPINV                              0xA1

#define OLED_SETMULTIPLEX                             0xA8
// 0xA8, number of rows -1 ... e.g. 0xA8, 63

// X Direction
#define OLED_COMSCANINC                               0xC0
#define OLED_COMSCANDEC                               0xC8

// double byte with image wrap ...probably should be 0
#define OLED_SETDISPLAYOFFSET                         0xD3

// Double Byte Hardware com pins configuration
#define OLED_SETCOMPINS                               0xDA
// legal values 0x02, 0x12, 0x022, 0x032
</pre>
<p>The next sections of commands are part of the electrical configuration for the glass.</p>
<p>0xD5 essentially sets up the display update rate by 1) setting the display update clock frequency and 2) setting up a divider for that clock.</p>
<p>0xDB and 0xD9 sets up a parameter that is display dependent.  That being said I tried a bunch of different values and they all look the same to me.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-13-52-am/" rel="attachment wp-att-7685"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM-1024x655.png" alt="" width="1024" height="655" class="alignnone size-large wp-image-7685" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM-1024x655.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM-600x384.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM-300x192.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM-768x491.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.13.52-AM.png 1642w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">////////////////////////////////////////////////////////////////////////
// Timing and Driving Scheme Settings
////////////////////////////////////////////////////////////////////////

#define OLED_SETDISPLAYCLOCKDIV                       0xD5
#define OLED_SETPRECHARGE                             0xD9

#define OLED_SETVCOMDESELECT                          0xDB
#define OLED_NOP                                      0xE3
</pre>
<p>These displays require a high voltage to program the liquid crystal in the display.  That voltage can either be supplied by an external pin or by an internal charge pump.  All the displays that I have seen use an internal charge pump.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-01-at-6-09-12-am/" rel="attachment wp-att-7684"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM-1024x373.png" alt="" width="1024" height="373" class="alignnone size-large wp-image-7684" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM-1024x373.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM-600x218.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM-300x109.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM-768x280.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-01-at-6.09.12-AM.png 1478w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">////////////////////////////////////////////////////////////////////////
// Charge Pump Regulator
////////////////////////////////////////////////////////////////////////

#define OLED_CHARGEPUMP                               0x8D
#define OLED_CHARGEPUMP_ON                            0x14
#define OLED_CHARGEPUMP_OFF                           0x10
</pre>
<h1>The SSD1306 Graphics Data RAM</h1>
<p>In order to actually get data to display on the screen you need to write 1&#8217;s and 0&#8217;s into the Graphics Data RAM that represents your image.  The memory is actually organized into 8 pages that are each 128 bits wide and 8 bits tall.  This means that if you write 0b10101010 to location (0,0) you will get the first 8 pixels in a column on the screen to be on,off,on,off,on,off,on,off.  Notice that I said vertical column and not row.  Here is a picture from the data sheet.  That shows the pages:</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-9-33-51-am/" rel="attachment wp-att-7709"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM-1024x614.png" alt="" width="1024" height="614" class="alignnone size-large wp-image-7709" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM-1024x614.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM-600x360.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM-300x180.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM-768x461.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.33.51-AM.png 1604w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And then they show you in the data sheet that the pixels go down from the first row of the page.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-9-50-34-am/" rel="attachment wp-att-7712"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM-1024x303.png" alt="" width="1024" height="303" class="alignnone size-large wp-image-7712" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM-1024x303.png 1024w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM-600x177.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM-300x89.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM-768x227.png 768w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.50.34-AM.png 1542w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In order to make the writing process easier and lower bandwidth the SSD1306 has three automatic addressing modes.</p>
<ul>
<li>Horizontal &#8211; Set the page address start, end and the column start and end&#8230; bytes write 8 vertical pixels on the page. Each byte write advances the column until it wraps to the next page and resets the column to the &#8220;start&#8221;</li>
<li>Vertical &#8211; Set the page address start, end and the column start and end&#8230; bytes write 8 vertical pixels on the page.  Each byte write advances the page until it wraps vertically where it increments the column and resets the page back to the start page.</li>
<li>Page &#8211; Set the page address and column start/end.  Each byte writes vertically.  Wraps back onto the same page when it hits the end column.</li>
</ul>
<p>In Horizontal and Vertical mode you</p>
<ul>
<li>Set the range of columns that you want to write (using 0x22)</li>
<li>Set the range of pages you want to write (using 0x21)</li>
<li>Write bytes</li>
</ul>
<p>In the page mode you</p>
<ul>
<li>Set the page (remember you can only write one page at a time in page mode) using 0xB0-0xB7</li>
<li>Set the start column using 0x0? and 0x1?</li>
</ul>
<p>Here is a picture from the data sheet of horizontal address mode:</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-9-41-58-am/" rel="attachment wp-att-7710"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.41.58-AM.png" alt="" width="976" height="334" class="alignnone size-full wp-image-7710" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.41.58-AM.png 976w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.41.58-AM-600x205.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.41.58-AM-300x103.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.41.58-AM-768x263.png 768w" sizes="(max-width: 976px) 100vw, 976px" /></a></p>
<p>In this bit of example code I am saying to iterate through the pages 0-&gt;7&#8230; in other words all of the pages.  And to start in column 0.  This example will make 12 columns of pixels each 8 high starting a (0,0) on the screen&#8230;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    char horizontalExample[]= {
            0xAE,
            0x20, /// address mode
            0x00, // Horizontal
            0xA4,
            0xAF,
            0x22, //Set page address range
            0,
            7,
            0x21, // column start and end address
            0,
            127,
    };

    I2C_WriteCmdStream(horizontalExample, sizeof(horizontalExample));
    // Write twelve bytes onto screen with 0b10101010
    for(int i=0;i&lt;12;i++)
        I2C_WriteData(0xAA);</pre>
<p>Here is a picture of what it does.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0774-2/" rel="attachment wp-att-7719"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2-1024x1005.jpg" alt="" width="1024" height="1005" class="alignnone size-large wp-image-7719" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2-1024x1005.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2-600x589.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2-300x294.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2-768x754.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0774-2.jpg 1075w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is a picture from the data sheet of vertical address mode:</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-9-42-06-am/" rel="attachment wp-att-7711"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.42.06-AM.png" alt="" width="952" height="352" class="alignnone size-large wp-image-7711" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.42.06-AM.png 952w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.42.06-AM-600x222.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.42.06-AM-300x111.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-9.42.06-AM-768x284.png 768w" sizes="(max-width: 952px) 100vw, 952px" /></a></p>
<p>This example code sets the page range to 0&#8211;&gt;7  (the whole screen) and the column range 0&#8211;&gt;127 (the whole screen).  Then writes 12 bytes.  You can see it wrap at the bottom and move back to page 0 column 1.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    char verticalExample[]= {
            0xAE,
            0x20, /// address mode
            0x01, //  vertical
            0xA4,
            0xAF,
            0x22, //Set page address range
            0,
            7,
            0x21, // column start and end address
            0,
            127,
    };

    I2C_WriteCmdStream(verticalExample, sizeof(verticalExample));
    // Write twelve bytes onto screen with 0b10101010
    for(int i=0;i&lt;12;i++)
        I2C_WriteData(0xAA); 
</pre>
<p>&nbsp;</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0773/" rel="attachment wp-att-7717"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773-1024x943.jpg" alt="" width="1024" height="943" class="alignnone size-large wp-image-7717" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773-1024x943.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773-600x552.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773-300x276.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773-768x707.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0773.jpg 1058w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>&nbsp;</p>
<p>In page mode you just set the page and the start and end column.  0xB0 means page 0, 0xB1 means page 1&#8230; 0xB7 means page 7.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-08-03-at-11-01-46-am/" rel="attachment wp-att-7716"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-11.01.46-AM.png" alt="" width="932" height="304" class="alignnone size-full wp-image-7716" srcset="https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-11.01.46-AM.png 932w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-11.01.46-AM-600x196.png 600w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-11.01.46-AM-300x98.png 300w, https://iotexpert.com/wp-content/uploads/2019/08/Screen-Shot-2019-08-03-at-11.01.46-AM-768x251.png 768w" sizes="(max-width: 932px) 100vw, 932px" /></a></p>
<p>You can see that I started from column 0x78 (meaning column 120) and that it wraps back to column 0 on the SAME page.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    char pageExample[]= {
            0xAE,
            0x20, // address mode
            0x02, // Page mode
            0xA4, // Resume from ram
            0xAF, // Screen on
            0xB0, // Start from page 0
            // Start from column 0x78 aka 120
            0x08, // Column lower nibble address
            0x17  // Column upper nibble address
    };

    I2C_WriteCmdStream(pageExample, sizeof(pageExample));

    // Write twelve bytes onto screen with 0b10101010
    for(int i=0;i&lt;12;i++)
        I2C_WriteData(0xAA);</pre>
<p>Here is what it looks like.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0772/" rel="attachment wp-att-7714"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-1024x1009.jpg" alt="" width="1024" height="1009" class="alignnone size-large wp-image-7714" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-1024x1009.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-600x591.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-300x296.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772-768x757.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0772.jpg 1155w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Reading from the Frame Buffer</h1>
<p>Now that you know how to write to the Frame Buffer, the next question is how do you read?  For instance if you want to turn on 1 pixel (of a byte) but leave the others alone can you do this? The answer is NO.  In serial mode the device only writes.  In all of the Graphics libraries that I have seen they handle this by having a Frame Buffer in the MCU as well.  Duplicated resources&#8230; oh well.</p>
<h1>My Initialization Sequence</h1>
<p>I have a function that writes an array of bytes to the command registers.  So for me to initialize the screen I just need to set up that array.  Here is my best known setup.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    const char initializeCmds[]={
        //////// Fundamental Commands
        OLED_DISPLAYOFF,          // 0xAE Screen Off
        OLED_SETCONTRAST,         // 0x81 Set contrast control
        0x7F,                     // 0-FF ... default half way

        OLED_DISPLAYNORMAL,       // 0xA6, //Set normal display 

        //////// Scrolling Commands
        OLED_DEACTIVATE_SCROLL,   // Deactive scroll

        //////// Addressing Commands
        OLED_SETMEMORYMODE,       // 0x20, //Set memory address mode
        OLED_SETMEMORYMODE_PAGE,  // Page

        //////// Hardware Configuration Commands
        OLED_SEGREMAPINV,         // 0xA1, //Set segment re-map 
        OLED_SETMULTIPLEX,        // 0xA8 Set multiplex ratio
        0x3F,                     // Vertical Size - 1
        OLED_COMSCANDEC,          // 0xC0 Set COM output scan direction
        OLED_SETDISPLAYOFFSET,    // 0xD3 Set Display Offset
        0x00,                     //
        OLED_SETCOMPINS,          // 0xDA Set COM pins hardware configuration
        0x12,                     // Alternate com config &amp; disable com left/right
   
        //////// Timing and Driving Settings
        OLED_SETDISPLAYCLOCKDIV,  // 0xD5 Set display oscillator frequency 0-0xF /clock divide ratio 0-0xF
        0x80,                     // Default value
        OLED_SETPRECHARGE,        // 0xD9 Set pre-changed period
        0x22,                     // Default 0x22
        OLED_SETVCOMDESELECT,     // 0xDB, //Set VCOMH Deselected level
        0x20,                     // Default 

        //////// Charge pump regulator
        OLED_CHARGEPUMP,          // 0x8D Set charge pump
        OLED_CHARGEPUMP_ON,       // 0x14 VCC generated by internal DC/DC circuit

        // Turn the screen back on...       
        OLED_DISPLAYALLONRESUME,  // 0xA4, //Set entire display on/off
        OLED_DISPLAYON,           // 0xAF  //Set display on
    };
</pre>
<h1>Some Other Initialization Sequences</h1>
<p>If you look around you will find many different SSD1306 libraries.  You can run <a href="https://github.com/search?q=ssd1306" target="_blank" rel="noopener noreferrer">this</a> search on github.</p>
<p>Here is one example from https://github.com/vadzimyatskevich/SSD1306/blob/master/src/ssd1306.c  This is pretty much the same as mine except that the author put them in some other order than the data sheet.  I am not a huge fan of &#8220;ssd1306Command( SSD1306_SEGREMAP | 0x1)&#8221; but it does work.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void  ssd1306Init(uint8_t vccstate)
{
  _font = (FONT_INFO*)&amp;ubuntuMono_24ptFontInfo;
  
    // Initialisation sequence
    ssd1306TurnOff();
    //  1. set mux ratio
    ssd1306Command(   SSD1306_SETMULTIPLEX );
    ssd1306Command(   0x3F );
    //  2. set display offset
    ssd1306Command(   SSD1306_SETDISPLAYOFFSET );
    ssd1306Command(   0x0 );
    //  3. set display start line
    ssd1306Command(   SSD1306_SETSTARTLINE | 0x0 ); 
    ssd1306Command( SSD1306_MEMORYMODE);                    // 0x20
    ssd1306Command( 0x00);                                  // 0x0 act like ks0108
    //  4. set Segment re-map A0h/A1h    
    ssd1306Command(   SSD1306_SEGREMAP | 0x1);
    //   5. Set COM Output Scan Direction C0h/C8h
    ssd1306Command(   SSD1306_COMSCANDEC);
    //  6. Set COM Pins hardware configuration DAh, 12
    ssd1306Command(   SSD1306_SETCOMPINS);
    ssd1306Command(   0x12);
    //  7. Set Contrast Control 81h, 7Fh
    ssd1306Command(   SSD1306_SETCONTRAST );
    if (vccstate == SSD1306_EXTERNALVCC) { 
        ssd1306Command(   0x9F );
    } else { 
        ssd1306Command(   0xff );
    }
    //  8. Disable Entire Display On A4h
    ssd1306Command(   SSD1306_DISPLAYALLON_RESUME);
    //  9. Set Normal Display A6h 
    ssd1306Command(   SSD1306_NORMALDISPLAY);
    //  10. Set Osc Frequency  D5h, 80h 
    ssd1306Command(   SSD1306_SETDISPLAYCLOCKDIV);
    ssd1306Command(   0x80);
    //  11. Enable charge pump regulator 8Dh, 14h 
    ssd1306Command(   SSD1306_CHARGEPUMP );
    if (vccstate == SSD1306_EXTERNALVCC) { 
        ssd1306Command(   0x10);
    } else { 
        ssd1306Command(   0x14);
    }
    //  12. Display On AFh 
    ssd1306TurnOn();

}</pre>
<p>Here is another example from git@github.com:lexus2k/ssd1306.git</p>
<p>https://github.com/lexus2k/ssd1306/blob/master/src/lcd/oled_ssd1306.c</p>
<p>Honestly if I had found this originally I would not have gone to all the trouble.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static const uint8_t PROGMEM s_oled128x64_initData[] =
{
#ifdef SDL_EMULATION
    SDL_LCD_SSD1306,
    0x00,
#endif
    SSD1306_DISPLAYOFF, // display off
    SSD1306_MEMORYMODE, HORIZONTAL_ADDRESSING_MODE, // Page Addressing mode
    SSD1306_COMSCANDEC,             // Scan from 127 to 0 (Reverse scan)
    SSD1306_SETSTARTLINE | 0x00,    // First line to start scanning from
    SSD1306_SETCONTRAST, 0x7F,      // contast value to 0x7F according to datasheet
    SSD1306_SEGREMAP | 0x01,        // Use reverse mapping. 0x00 - is normal mapping
    SSD1306_NORMALDISPLAY,
    SSD1306_SETMULTIPLEX, 63,       // Reset to default MUX. See datasheet
    SSD1306_SETDISPLAYOFFSET, 0x00, // no offset
    SSD1306_SETDISPLAYCLOCKDIV, 0x80,// set to default ratio/osc frequency
    SSD1306_SETPRECHARGE, 0x22,     // switch precharge to 0x22 // 0xF1
    SSD1306_SETCOMPINS, 0x12,       // set divide ratio
    SSD1306_SETVCOMDETECT, 0x20,    // vcom deselect to 0x20 // 0x40
    SSD1306_CHARGEPUMP, 0x14,       // Enable charge pump
    SSD1306_DISPLAYALLON_RESUME,
    SSD1306_DISPLAYON,
};</pre>
<h1>Debug: Test the Hardware</h1>
<p>If a your screen is not working, the first thing to do is use a multimeter and make sure that VCC=SCL=SDA=3.3V.  (in the picture below my camera caught the screen refresh partially through&#8230; It looks fine at normal speed).  I have the red probe attached to the SCL.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0759/" rel="attachment wp-att-7641"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0759-1024x870.jpg" alt="" width="1024" height="870" class="alignnone size-large wp-image-7641" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0759-1024x870.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0759-600x510.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0759-300x255.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0759-768x653.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I would then run the <a href="https://iotexpert.com/?s=bridge+control" target="_blank" rel="noopener noreferrer">bridge control panel</a> and make sure that the device is responding.  You can do this by pressing &#8220;List&#8221;.  In the picture below you can see that there are two devices attached to the bus,  my screen is set to 0x78/0x3C.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-07-28-at-8-51-00-am/" rel="attachment wp-att-7640"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM-1024x818.png" alt="" width="1024" height="818" class="alignnone size-large wp-image-7640" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM-1024x818.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM-600x480.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM-300x240.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM-768x614.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-8.51.00-AM.png 1674w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>If you don&#8217;t have the bridge control panel then you can implement I2Cdetect using your development kit.   Read about it <a href="https://iotexpert.com/2019/08/05/i2c-detect-with-psoc-6/" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p><a href="https://iotexpert.com/2019/08/05/i2c-detect-with-psoc-6/screen-shot-2019-07-28-at-10-50-21-am/" rel="attachment wp-att-7658"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM-1024x852.png" alt="" width="1024" height="852" class="alignnone size-large wp-image-7658" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM-1024x852.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM-600x499.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM-300x250.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM-768x639.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-10.50.21-AM.png 1214w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next thing to do is attach a logic analyzer and make sure that the startup commands are coming out of your MCU correctly.  Notice that the 00, 0xAE, 0x81&#8230; are exactly the configuration sequence that I wrote in the driver code above.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/screen-shot-2019-07-28-at-11-46-45-am/" rel="attachment wp-att-7674"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.46.45-AM-1024x558.png" alt="" width="1024" height="558" class="alignnone size-large wp-image-7674" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.46.45-AM-1024x558.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.46.45-AM-600x327.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.46.45-AM-300x163.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.46.45-AM-768x418.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Debug: Test the Firmware</h1>
<p>If your screen is still not working here are some problems and what to do about them.</p>
<ul>
<li><strong>Speckled Screen</strong></li>
<li><strong>Solid Screen</strong></li>
<li><strong>Screen Flipped in the Y direction</strong></li>
<li><strong>Screen Flipped in the X Direction</strong></li>
<li><strong>Screen Flipped in both Directions</strong></li>
<li><strong>Screen is Inverted</strong></li>
<li><strong>Image is Partially off the Screen</strong></li>
<li><strong>Image is Wrapped on the Screen</strong></li>
<li><strong>Black Screen</strong></li>
<li><strong>Screen Has Gone Crazy</strong></li>
</ul>
<p><span style="text-decoration: underline;"><strong>Speckled Screen</strong></span></p>
<p>If you have the speckled screen this means that your screen is displaying an uninitialized frame buffer which the SSD people call the GDDRAM.  These are basically the random 0 and 1s that are the startup values in the SSD1306.  If this is happening then your graphic data is probably not being transferred between your MCU and the SSD1306.  This almost certainly means you have a problem in your porting layer.</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0743/" rel="attachment wp-att-7594"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0743-1024x931.jpg" alt="" width="1024" height="931" class="alignnone size-large wp-image-7594" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0743-1024x931.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0743-600x545.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0743-300x273.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0743-768x698.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<div>
<div>
<p><span style="text-decoration: underline;"><strong>Speckled Screen</strong></span></p>
<p>If your screen is solid white that probably means you turned the screen back on without resuming from the graphics ram.  You did this:</p>
</div>
</div>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">OLED_DISPLAYALLONIGNORE,  // 0xA5, //Set entire display on/off</pre>
<p>instead of this:</p>
<div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="c">OLED_DISPLAYALLONRESUME,  // 0xA4, //Set entire display on/off</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0771/" rel="attachment wp-att-7702"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771-1024x824.jpg" alt="" width="1024" height="824" class="alignnone size-large wp-image-7702" srcset="https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771-1024x824.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771-600x483.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771-300x241.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771-768x618.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/08/IMG_0771.jpg 1556w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><span style="text-decoration: underline;"><strong>Screen Flipped in the Y direction</strong></span></p>
</div>
<div>The commands C0/C8 set the direction in which the com lines are scanned.  Either from top to bottom or bottom to top.  Change C0&#8211;&gt;C8 to the other way.</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define OLED_COMSCANINC                               0xC0
#define OLED_COMSCANDEC                               0xC8</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0746/" rel="attachment wp-att-7607"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746-1024x924.jpg" alt="" width="1024" height="924" class="alignnone size-large wp-image-7607" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746-1024x924.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746-600x542.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746-300x271.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746-768x693.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0746.jpg 1667w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
</div>
</div>
<p><span style="text-decoration: underline;"><strong>Screen Flipped in the X Direction</strong></span></p>
<p>In the X-Direction the A0/A1 set the configuration of scanning.  Try using A0&#8211;&gt;A8 or the other way.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// X Direction Scanning 
#define OLED_SEGREMAPNORMAL                           0xA0
#define OLED_SEGREMAPINV                              0xA1</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0745/" rel="attachment wp-att-7608"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745-1024x781.jpg" alt="" width="1024" height="781" class="alignnone size-large wp-image-7608" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745-1024x781.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745-600x458.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745-300x229.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745-768x586.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0745.jpg 1597w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><span style="text-decoration: underline;"><strong>Screen Flipped in both Directions</strong></span></p>
<p>If it is flipped in both X and Y direction then flip both of the direction registers.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">// Y Direction
#define OLED_SEGREMAPNORMAL                           0xA0
#define OLED_SEGREMAPINV                              0xA1

// X Direction
#define OLED_COMSCANINC                               0xC0
#define OLED_COMSCANDEC                               0xC8</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0748/" rel="attachment wp-att-7610"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748-947x1024.jpg" alt="" width="947" height="1024" class="alignnone size-large wp-image-7610" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748-947x1024.jpg 947w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748-600x649.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748-277x300.jpg 277w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748-768x831.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0748.jpg 1249w" sizes="(max-width: 947px) 100vw, 947px" /></a></p>
<p><span style="text-decoration: underline;"><strong>Screen is Inverted</strong></span></p>
<p>If your screen is inverted then try A8&#8211;&gt;A6</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define OLED_DISPLAYNORMAL                            0xA6
#define OLED_DISPLAYINVERT                            0xA7</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0749/" rel="attachment wp-att-7611"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749-1024x972.jpg" alt="" width="1024" height="972" class="alignnone size-large wp-image-7611" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749-1024x972.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749-600x570.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749-300x285.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749-768x729.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0749.jpg 1370w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><span style="text-decoration: underline;"><strong>Image is Partially off the Screen</strong></span></p>
<p>If your image is off the screen the you probably have the wrong value for MULTIPLEX.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define OLED_SETMULTIPLEX                             0xA8</pre>
<p>The parameter is supposed to be the number of lines on the screen -1.  In my case the screen is 128&#215;64 so my valued should be 63 aka 0x3F</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        OLED_SETMULTIPLEX,        // 0xA8 Set multiplex ratio
        0x3F,                     // Vertical Size - 1</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0750/" rel="attachment wp-att-7613"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750-1024x984.jpg" alt="" width="1024" height="984" class="alignnone size-large wp-image-7613" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750-1024x984.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750-600x577.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750-300x288.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750-768x738.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0750.jpg 1389w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><span style="text-decoration: underline;"><strong>Image is Wrapped on the Screen</strong></span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// Double byte CMD image wrap ...probably should be 0
#define OLED_SETDISPLAYOFFSET                         0xD3</pre>
<p>The offset value allows the board designer to hook up the rows in a crazy fashion.   My screen has the top row to the top row number.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">        OLED_SETDISPLAYOFFSET,    // 0xD3 Set Display Offset
        0x00,                     //
</pre>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0751/" rel="attachment wp-att-7614"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-1024x1012.jpg" alt="" width="1024" height="1012" class="alignnone size-large wp-image-7614" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-1024x1012.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-600x593.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-300x296.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751-768x759.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0751.jpg 1351w" sizes="(max-width: 1024px) 100vw, 1024px" />\</a></p>
<p><span style="text-decoration: underline;"><strong>Black Screen</strong></span></p>
<p>If you screen is totally dead&#8230;</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0752/" rel="attachment wp-att-7615"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752-953x1024.jpg" alt="" width="953" height="1024" class="alignnone size-large wp-image-7615" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752-953x1024.jpg 953w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752-600x644.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752-279x300.jpg 279w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752-768x825.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0752.jpg 1352w" sizes="(max-width: 953px) 100vw, 953px" /></a></p>
<p>Then the charge pump may be off</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">        //////// Charge pump regulator
        OLED_CHARGEPUMP,          // 0x8D Set charge pump
        0x14,                     // VCC generated by internal DC/DC circuit
</pre>
<p>or maybe the screen is off&#8230; try turning it on.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">        OLED_DISPLAYON,           // 0xAF  //Set display on</pre>
<p>or maybe you haven&#8217;t displayed anything. The screen is off trying sending a screen invert</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define OLED_DISPLAYINVERT                            0xA7
</pre>
<p><span style="text-decoration: underline;"><strong>The Screen Has Gone Crazy</strong></span></p>
<p>The register 0xDA SetComPins register will make some crazy results of it isn&#8217;t set correctly.  For my 0.96&#8243; inch screen it needs to be set to 0x12</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// Double Byte Hardware com pins configuration
#define OLED_SETCOMPINS                               0xDA
// legal values 0x02, 0x12, 0x022, 0x032</pre>
<p>This is what happens with 0x02 [If you see the note below from Ivan, 0x02 is apparently for 128&#215;32 and this screen is 128&#215;64=0x12]</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0755/" rel="attachment wp-att-7617"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-1024x1016.jpg" alt="" width="1024" height="1016" class="alignnone size-large wp-image-7617" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-1024x1016.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-600x595.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-150x150.jpg 150w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-300x298.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755-768x762.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0755.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0757/" rel="attachment wp-att-7618"></a></p>
<p>And 0x22</p>
<p><a href="https://iotexpert.com/?attachment_id=7619" rel="attachment wp-att-7619"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756-999x1024.jpg" alt="" width="999" height="1024" class="alignnone size-large wp-image-7619" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756-999x1024.jpg 999w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756-600x615.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756-293x300.jpg 293w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756-768x787.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0756.jpg 1345w" sizes="(max-width: 999px) 100vw, 999px" /></a></p>
<p>Finally 0x32</p>
<p><a href="https://iotexpert.com/2019/08/07/debugging-ssd1306-display-problems/img_0757/" rel="attachment wp-att-7618"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-1024x1024.jpg" alt="" width="1024" height="1024" class="alignnone size-large wp-image-7618" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-1024x1024.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-300x300.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-100x100.jpg 100w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-600x600.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-150x150.jpg 150w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757-768x768.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0757.jpg 1238w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This was absolutely the craziest rabbit hole that I have ventured down. Nicholas has talked to me 10 times about doing this and he thinks I’m crazy.  Oh well.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/debugging-ssd1306-display-problems/feed/</wfw:commentRss>
			<slash:comments>53</slash:comments>
		
		
			</item>
		<item>
		<title>MBED OS &#038; PSoC 6 &#038; SSD1306</title>
		<link>https://iotexpert.com/mbed-os-psoc-6-ssd1306/</link>
					<comments>https://iotexpert.com/mbed-os-psoc-6-ssd1306/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Sun, 17 Feb 2019 16:29:44 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[Embedded World 2019]]></category>
		<category><![CDATA[MBED OS]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=6600</guid>

					<description><![CDATA[Summary As I wrote about in the last article I have been working to get ready for Embedded World 2019 in a week and a bit.  For my demo, I will be handing out remote controls that have a 128&#215;64 monochrome OLED display that is driven by an I2C SSD1306.  This whole board is controlled [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>As I wrote about in the <a href="https://iotexpert.com/2019/02/11/mbedos-ble/" target="_blank" rel="noopener">last article</a> I have been working to get ready for Embedded World 2019 in a week and a bit.  For my demo, I will be handing out remote controls that have a 128&#215;64 monochrome OLED display that is driven by an I2C SSD1306.  This whole board is controlled by a PSoC 6 &amp; a 4343W WiFi / Bluetooth Combo.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/img_0227/" rel="attachment wp-att-6602"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-493x1024.jpg" alt="" width="493" height="1024" class="alignnone size-large wp-image-6602" srcset="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-493x1024.jpg 493w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-600x1246.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-144x300.jpg 144w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-768x1595.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0227-e1550413744346-scaled.jpg 1233w" sizes="(max-width: 493px) 100vw, 493px" /></a></p>
<p>This morning I started to port the <a href="https://iotexpert.com/?s=u8g2" target="_blank" rel="noopener">U8G2</a> library to MBEDOS&#8230; but ran into some problems, so I i decided to see what ports were already out there.  I immediately found a port of the <a href="https://os.mbed.com/users/nkhorman/code/Adafruit_GFX/" target="_blank" rel="noopener">Adafruit_GFX library</a>.  This article talks about using it on my CY8CPROTO_062_4343W board.  As part of this journey I also wanted to be able to draw the Cypress logo on the screen&#8230; so I had to figure out how to create a logo in a format that could be drawn on the screen.</p>
<p>I will follow these steps:</p>
<ol>
<li>Create a new project &amp; add the Adafruit_GFX_library</li>
<li>Create a main.cpp, configure the library and test</li>
<li>Make a Cypress logo using GIMP</li>
<li>Create a function to draw X11 bitmaps &amp; test</li>
</ol>
<h1>Create a new project &amp; add the Adafruit_GFX_library</h1>
<p>The first step to get everything going by running</p>
<ol>
<li>mbed new .</li>
<li>mbed add http://os.mbed.com/users/nkhorman/code/Adafruit_GFX/</li>
</ol>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-9-41-48-am/" rel="attachment wp-att-6603"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.48-AM.png" alt="" width="797" height="465" class="alignnone size-full wp-image-6603" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.48-AM.png 797w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.48-AM-600x350.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.48-AM-300x175.png 300w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.48-AM-768x448.png 768w" sizes="(max-width: 797px) 100vw, 797px" /></a></p>
<p>The way to figure out how to add the library is by going to the library webpage on the mbedos website.  Then clicking the arrow on &#8220;Import into Compiler&#8221; where you will see two options, &#8220;Import into Compiler&#8221; and &#8220;Import with mbed CLI&#8221;</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-9-41-03-am/" rel="attachment wp-att-6606"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM-1024x278.png" alt="" width="1024" height="278" class="alignnone size-large wp-image-6606" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM-1024x278.png 1024w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM-600x163.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM-300x81.png 300w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM-768x209.png 768w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.03-AM.png 1182w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you select that option you will get a window that tells you the exact command to run.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-9-41-15-am/" rel="attachment wp-att-6605"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.15-AM.png" alt="" width="402" height="161" class="alignnone size-large wp-image-6605" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.15-AM.png 402w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.41.15-AM-300x120.png 300w" sizes="(max-width: 402px) 100vw, 402px" /></a></p>
<p>I have been using <a href="https://atom.io" target="_blank" rel="noopener">Atom</a> as an editor (and sort of IDE).  When you open the lcd-example directory using Atom you will see your project including</p>
<ol>
<li>The mbed-os directory with all of the mbed stuff in it.</li>
<li>The Adafruit_GFX library</li>
</ol>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-9-46-14-am/" rel="attachment wp-att-6609"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.46.14-AM.png" alt="" width="815" height="662" class="alignnone size-full wp-image-6609" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.46.14-AM.png 815w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.46.14-AM-600x487.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.46.14-AM-300x244.png 300w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-9.46.14-AM-768x624.png 768w" sizes="(max-width: 815px) 100vw, 815px" /></a></p>
<h1>Create a main.cpp, configure the library and test</h1>
<p>The next step is to create a main.cpp.</p>
<ol>
<li>Setup the I2C.  In order to use the graphics library you need to setup a communication vehicle.  In my case that is an I2C bus that is connected to P6[0] and P6[1] on my development board.  Lines 6-15 create the communication class of I2CPreInit, configure it to 400kbs and connect the I2C master to P6[0]/P6[1]</li>
<li>Line 16 actually setups up the graphics library and get it going.</li>
<li>The main simply prints out some information about the display on lines 22-23</li>
<li>Line 24 causes the current frame buffer to be displayed (more on this in a second)</li>
<li>The main loop blinks the LED and prints a counter on the top of the screen.</li>
</ol>
<pre class="lang:c++ decode:true">#include "mbed.h"
#include "Adafruit_SSD1306.h"

DigitalOut myled(LED1);

class I2CPreInit : public I2C
{
public:
    I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
    {
        frequency(400000);
        start();
    };
};
I2CPreInit gI2C(P6_1,P6_0);
Adafruit_SSD1306_I2c gOled2(gI2C,P0_2,0x78,64,128);

int main()
{   uint16_t x=0;

    printf("Started\n");
    printf("%ux%u OLED Display\r\n", gOled2.width(), gOled2.height());
    printf("Rotation = %u\n",gOled2.getRotation());
    gOled2.display();
    while(1)
    {
        x += 1;
        myled = !myled;
        gOled2.printf("%u\r",x);
        gOled2.display();
        wait(1.0);
    }
}
</pre>
<p>In order to build this thing I run &#8220;mbed compile -t GCC_ARM -m CY8CPROTO_062_4343w&#8221;.  When I run the project it looks like this:</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/img_0228/" rel="attachment wp-att-6612"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0228-e1550416310771-1024x768.jpg" alt="" width="1024" height="768" class="alignnone wp-image-6612 size-large" srcset="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0228-e1550416310771-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0228-e1550416310771-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0228-e1550416310771-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0228-e1550416310771-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>There are several things to notice about this picture.  First, there is an Adafruit logo on the screen.  Where did this come from?  Simple on line 152 of Adafruit_ssd1306.cpp there is a function called &#8220;splash&#8221; which is called by the constructor.  The spash function just copies a bitmap into the frame buffer of the Adafruit_SSD1306 object.</p>
<pre class="start-line:152 EnlighterJSRAW" data-enlighter-language="c" ">void Adafruit_SSD1306::splash(void)
{
#ifndef NO_SPLASH_ADAFRUIT
	uint8_t adaFruitLogo[64 * 128 / 8] =
	{ 
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
</pre>
<p>The constructor is in Adafruit_ssd1306.h on line 152</p>
<pre class="start-line:173 lang:c++ decode:true ">	Adafruit_SSD1306_I2c(I2C &amp;i2c, PinName RST, uint8_t i2cAddress = SSD_I2C_ADDRESS, uint8_t rawHeight = 32, uint8_t rawWidth = 128)
	    : Adafruit_SSD1306(RST, rawHeight, rawWidth)
	    , mi2c(i2c)
	    , mi2cAddress(i2cAddress)
	    {
		    begin();
		    splash();
		    display();
	    };</pre>
<p>And if you don&#8217;t want to have this splash screen you can uncomment the #define NO_SPLASH_ADAFRUIT in the file &#8220;Adafruit_GFC_Config.h&#8221;</p>
<pre class="lang:c++ decode:true ">#ifndef _ADAFRUIT_GFX_CONFIG_H_
#define _ADAFRUIT_GFX_CONFIG_H_

// Uncomment this to turn off the builtin splash
#define NO_SPLASH_ADAFRUIT

// Uncomment this to enable all functionality
//#define GFX_WANT_ABSTRACTS

// Uncomment this to enable only runtime font scaling, without all the rest of the Abstracts
//#define GFX_SIZEABLE_TEXT


#endif</pre>
<p>The next thing to notice in the picture is that I have lead wires attached to the LCD pins&#8230; and those wires are attached to a logic analyzer because I typed the I2C incorrectly and I couldn&#8217;t figure out why they didn&#8217;t talk.  And finally notice my grandfathers magnifying glass which I use every day.</p>
<h1>Make a Cypress logo using GIMP</h1>
<p>For my project I am less interested in displaying Adafruits Logo and more interested in displaying Cypress&#8217;.  To do this I loaded up the Cypress logo in <a href="https://www.gimp.org" target="_blank" rel="noopener">Gimp</a>.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-22-23-am/" rel="attachment wp-att-6614"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM-1024x658.png" alt="" width="1024" height="658" class="alignnone size-large wp-image-6614" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM-1024x658.png 1024w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM-600x385.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM-300x193.png 300w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM-768x493.png 768w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.22.23-AM.png 1194w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I then converted it to pure black and white using the &#8220;Image-&gt;Mode-&gt;Indexed&#8230;&#8221;</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-23-11-am/" rel="attachment wp-att-6616"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.11-AM.png" alt="" width="438" height="156" class="alignnone size-large wp-image-6616" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.11-AM.png 438w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.11-AM-300x107.png 300w" sizes="(max-width: 438px) 100vw, 438px" /></a></p>
<p>Then selected &#8220;black and white palette&#8221;</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-23-23-am/" rel="attachment wp-att-6615"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.23-AM.png" alt="" width="367" height="395" class="alignnone size-full wp-image-6615" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.23-AM.png 367w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.23.23-AM-279x300.png 279w" sizes="(max-width: 367px) 100vw, 367px" /></a></p>
<p>Then I scaled the image to 128&#215;40 using the &#8220;Image-&gt;Scale Image&#8221;</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-25-10-am/" rel="attachment wp-att-6619"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.10-AM.png" alt="" width="226" height="194" class="alignnone size-large wp-image-6619" /></a></p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-25-22-am/" rel="attachment wp-att-6618"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.22-AM.png" alt="" width="380" height="385" class="alignnone size-large wp-image-6618" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.22-AM.png 380w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.22-AM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.22-AM-296x300.png 296w" sizes="(max-width: 380px) 100vw, 380px" /></a></p>
<p>Unfortunately it made a bit of a mess of the logo during the scaling process&#8230; so I put my son to editing it.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-25-52-am/" rel="attachment wp-att-6617"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.52-AM.png" alt="" width="654" height="390" class="alignnone size-full wp-image-6617" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.52-AM.png 654w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.52-AM-600x358.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.25.52-AM-300x179.png 300w" sizes="(max-width: 654px) 100vw, 654px" /></a></p>
<p>Which looks like this after he was done.  Pretty good eh?</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-28-26-am/" rel="attachment wp-att-6620"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.28.26-AM.png" alt="" width="542" height="317" class="alignnone size-full wp-image-6620" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.28.26-AM.png 542w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.28.26-AM-300x175.png 300w" sizes="(max-width: 542px) 100vw, 542px" /></a></p>
<p>In order to use the image you need a &#8220;C program&#8221; version of it.  It turns out that there is a format called &#8220;X11&#8221; or &#8220;xbm&#8221; which is exactly that (a c-file).  You can read about the format on <a href="http://www.fileformat.info/format/xbm/egff.htm" target="_blank" rel="noopener">this website</a>.  To get one of these files, just run &#8220;File-&gt;Export As&#8221;</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-29-14-am/" rel="attachment wp-att-6623"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.14-AM.png" alt="" width="204" height="281" class="alignnone size-full wp-image-6623" /></a></p>
<p>Then give it a name with a &#8220;.xbm&#8221; on the end</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-29-45-am/" rel="attachment wp-att-6622"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.45-AM.png" alt="" width="617" height="117" class="alignnone size-large wp-image-6622" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.45-AM.png 617w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.45-AM-600x114.png 600w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.45-AM-300x57.png 300w" sizes="(max-width: 617px) 100vw, 617px" /></a></p>
<p>Make sure and &#8220;de-select the X10 format bitmap&#8221; (and older version of the xbm format)</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/screen-shot-2019-02-17-at-10-29-56-am/" rel="attachment wp-att-6621"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.56-AM.png" alt="" width="321" height="351" class="alignnone size-full wp-image-6621" srcset="https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.56-AM.png 321w, https://iotexpert.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-10.29.56-AM-274x300.png 274w" sizes="(max-width: 321px) 100vw, 321px" /></a></p>
<p>When all that is said and done you will find the xbm file with goodness in it.  Here is the top of it.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define cylogo_width 128
#define cylogo_height 40
static unsigned char cylogo_bits[] = {
   0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
</pre>
<p>The format of this file is unsigned 8-bit integers&#8230; each bit represents the bit of one pixel&#8230; in BIG ENDIAN!!!! format.  In other words this table will be 128&#215;40/8 bytes long.</p>
<h1>Create a function to draw X11 bitmaps &amp; test</h1>
<p>But how do we use this format?  Well, write a new function in the Adafruit library to draw X11 bitmaps.</p>
<p>First add the new function name to the class on line 168 of &#8220;Adafruit_GFX.h&#8221;</p>
<pre class="start-line:72 EnlighterJSRAW" data-enlighter-language="c"">    virtual void drawX11BitMap(const uint8_t bitmap[],uint16_t bitMapWidth,uint16_t bitMapSize,uint16_t posX,uint16_t posY);
</pre>
<p>Then add the code.</p>
<pre class="start-line:152 EnlighterJSRAW" data-enlighter-language="c"">// Write an X11 formatted bitmap to the screen at posX, posY
void Adafruit_GFX::drawX11BitMap(const uint8_t bitmap[],uint16_t bitMapWidth,uint16_t bitMapSize,uint16_t posX,uint16_t posY)
{
  int16_t x1 = posX;
  int16_t y1 = posY;

  for(unsigned int i=0;i&lt;bitMapSize;i++)
  {
    uint8_t val = bitmap[i];

    for(int j=0;j&lt;8;j++)
    {
        uint16_t pixColor;
        if(val&gt;&gt;j &amp; 0x01)
          pixColor = 1;
        else
          pixColor = 0;

        drawPixel(x1,y1, pixColor);
        x1 = x1 + 1;
        if(x1 == posX + bitMapWidth)
        {
          x1 = posX;
          y1 = y1 + 1;
        }
    }
  }</pre>
<p>This may not be the most beautiful code in the world&#8230; which I suppose makes it fit right in with some of the other stuff in this driver.  Oh well it works.</p>
<p>Once you have added the function to the library, lets test it to see if it can draw the logo.  First, copy the &#8220;cylogo.xbm&#8221; into the project and call it &#8220;cylogo.h&#8221;.  Then modify the &#8220;main.cpp&#8221; to use it.  Add an include of the &#8220;cylogo.h&#8221;.  Then on line 26, call the function to draw it at 0,(half way down the screen)</p>
<pre class="lang:c++ decode:true ">#include "mbed.h"
#include "Adafruit_SSD1306.h"
#include "cylogo.h"
DigitalOut myled(LED1);

class I2CPreInit : public I2C
{
public:
    I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
    {
        frequency(400000);
        start();
    };
};
I2CPreInit gI2C(P6_1,P6_0);
Adafruit_SSD1306_I2c gOled2(gI2C,P0_2,0x78,64,128);

int main()
{   uint16_t x=0;

    printf("Started\n");
    printf("%ux%u OLED Display\r\n", gOled2.width(), gOled2.height());
    printf("Rotation = %u\n",gOled2.getRotation());


    gOled2.drawX11BitMap(cylogo_bits,cylogo_width,sizeof(cylogo_bits),0,(64-cylogo_height)/2);

    gOled2.display();
</pre>
<p>When you program this&#8230; everything seems to be good.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/img_0229/" rel="attachment wp-att-6625"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0229-e1550418582969-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-6625" srcset="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0229-e1550418582969-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0229-e1550418582969-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0229-e1550418582969-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0229-e1550418582969-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>By the way if it isn&#8217;t clear by now, I did a solder in a male header onto the board so that I could attach the I2C wires for the display.</p>
<p><a href="https://iotexpert.com/2019/02/17/mbed-os-psoc-6-ssd1306/img_0230/" rel="attachment wp-att-6626"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0230-e1550418732146-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-6626" srcset="https://iotexpert.com/wp-content/uploads/2019/02/IMG_0230-e1550418732146-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0230-e1550418732146-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0230-e1550418732146-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/02/IMG_0230-e1550418732146-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/mbed-os-psoc-6-ssd1306/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6, FreeRTOS &#038; SSD1306 OLED Display</title>
		<link>https://iotexpert.com/psoc-6-freertos-ssd1306-oled-display/</link>
					<comments>https://iotexpert.com/psoc-6-freertos-ssd1306-oled-display/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 05 Dec 2017 11:58:59 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=4751</guid>

					<description><![CDATA[Summary This week I have been working with my friend Hassane El Khoury on his hobby project which has the SSD1306 in it. [if you want to know more about the project, leave a comment and maybe he will answer the question].  I have been helping him get a number of things going including this display [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This week I have been working with my friend <a href="http://www.cypress.com/hassane-el-khoury" target="_blank" rel="noopener">Hassane El Khoury</a> on his hobby project which has the SSD1306 in it. [if you want to know more about the project, leave a comment and maybe he will answer the question].  I have been helping him get a number of things going including this display which I have written <a href="https://iotexpert.com/?s=ssd1306" target="_blank" rel="noopener">about</a> before.  This article describes the integration of the SSD1306 OLED Display into his project with the PSoC 6 &amp; FreeRTOS.<a href="https://iotexpert.com/2017/12/05/psoc-6-freertos-ssd1306-oled-display/img_5897/" rel="attachment wp-att-4753"></a></p>
<h1>Firmware Architecture</h1>
<p>Hassane started his career as an Automotive System Designer, then he worked as an Applications Engineer, so he has &#8220;mad&#8221; skills in this area.  He is building his project with a PSoC 6 and is heavily using FreeRTOS (which is new for him).  He has been distracted with some other thing the last few years, so I have been serving as a consultant on the latest PSoC stuff to smooth the learning curve.  In this case PSoC6, FreeRTOS and the SSD1306 OLED Display.  I have only used the SSD1306 OLED Display with PSoC 4 and WICED, but I ASSUMED (incorrectly assumed&#8230; which I will talk about in the next article) that there would be no problems making it work in that environment.</p>
<p>Hassane is all about reuse and he had copied the design of this section of his project from my <a href="https://iotexpert.com/2017/06/22/psoc-freertos-sharing-the-i2c-bus/" target="_blank" rel="noopener">article</a> on using queues with FreeRTOS.  It looks like this.</p>
<ol>
<li>There is a task that manages the I2C and talks directly to the SCB hardware and the I2C devices</li>
<li>There is a task that manages the OLED</li>
</ol>
<p><a href="https://iotexpert.com/2017/12/05/psoc-6-freertos-ssd1306-oled-display/i2carch/" rel="attachment wp-att-4758"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/12/i2carch.png" alt="ssd1306 oled display architecture" width="987" height="281" class="alignnone wp-image-4758 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/12/i2carch.png 987w, https://iotexpert.com/wp-content/uploads/2017/12/i2carch-600x171.png 600w, https://iotexpert.com/wp-content/uploads/2017/12/i2carch-300x85.png 300w, https://iotexpert.com/wp-content/uploads/2017/12/i2carch-768x219.png 768w" sizes="(max-width: 987px) 100vw, 987px" /></a></p>
<p>Originally the OLED task was talking directly to the I2C via the SCB (the red line on the picture).  Remember from the article on the U8G2 library, the hardware abstraction layer looks like this.  Basically it</p>
<ol>
<li>Sends an I2C Start at the start of the U8G2 transaction</li>
<li>Sends an I2C Stop at the end of the tranaction</li>
<li>Send the number of bytes called for.</li>
</ol>
<pre class="lang:c decode:true">uint8_t u8x8_I2C_HW(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    uint8_t *data;
    switch(msg)
    {
        case U8X8_MSG_BYTE_SEND:            
            data = (uint8_t *)arg_ptr;
            while( arg_int &gt; 0 )
            {
                Cy_SCB_I2C_MasterWriteByte(I2Cm1_HW, *data, I2C_TIMEOUT, &amp;I2Cm1_context);
  	            data++;
	            arg_int--;
            }
        break;
      
        case U8X8_MSG_BYTE_START_TRANSFER:
            Cy_SCB_I2C_MasterSendStart(I2Cm1_HW, u8x8_GetI2CAddress(u8x8)&gt;&gt;1, CY_SCB_I2C_WRITE_XFER, I2C_TIMEOUT, &amp;I2Cm1_context);
         break;
        
        case U8X8_MSG_BYTE_END_TRANSFER:
            Cy_SCB_I2C_MasterSendStop(I2Cm1_HW, I2C_TIMEOUT, &amp;I2Cm1_context);
        break;
    
        default:
            return 0;
    }
    
    return 1;
}
</pre>
<p>The problem with this design is that it takes over the I2C hardware and requires exclusive control.  Moreover, it leaves you program hung while the transaction is happening.  To solve this problem, there are three options</p>
<ol>
<li>&#8220;Assign&#8221; the SCB block to the exclusive use of this task (makes it hard to share with other I2C devices)</li>
<li>Create a mutex for the SCB.  This will work, but it will not allow the task to &#8220;queue&#8221; transactions and move on</li>
<li>Create a task to manage the SCB with a queue (the option that Hassane chose)</li>
</ol>
<p>The I2C message queue holds complete transactions.  Each transaction (which he called I2Cm_transaction_t) looks like this:</p>
<pre class="lang:c decode:true">typedef enum I2Cm_transactionMethod {
    I2CM_READ,
    I2CM_WRITE
} I2Cm_transactionMethod_t;

typedef enum I2Cm_registerAddresType {
    I2CM_NONE, 
    I2CM_BIT8,
    I2CM_BIT16
} i2cm_registerAddressType_t;

typedef struct I2Cm_transaction {
    I2Cm_transactionMethod_t I2Cm_method;        // I2CM_READ or I2CM_WRITE
    uint8_t I2Cm_address;                        // The I2C Address of the slave
    i2cm_registerAddressType_t I2Cm_regType;     // I2CM_8BIT or I2CM_16BIT
    uint16_t I2Cm_register;                      // The register in the slave    
    uint8_t *I2Cm_bytes;                         // A pointer to the data to be written (or a place to save the data)
    uint32_t *I2Cm_bytesProcessed;               // A return value with the number of bytes written
    uint32_t I2Cm_byteNum;                       // How many bytes are in the request
    SemaphoreHandle_t I2Cm_doneSemaphore;        // If you want a semaphore flagging that the transaction is done 
} I2Cm_transaction_t;
</pre>
<p>In order to fix the the HAL you just sets up a transaction at the start of the task:</p>
<pre class="lang:c decode:true">   memset(&amp;OLEDtransaction,0,sizeof(OLEDtransaction));
	OLEDtransaction.I2Cm_method = I2CM_WRITE;
	OLEDtransaction.I2Cm_address = OLED_ADDRESS_1;
	OLEDtransaction.I2Cm_regType = I2CM_NONE;
	OLEDtransaction.I2Cm_bytes = buff;
	OLEDtransaction.I2Cm_bytesProcessed = &amp;numProcessed;	
    OLEDtransaction.I2Cm_doneSemaphore = xSemaphoreCreateBinary();
</pre>
<p>Then queue up the bytes into a buffer, and flush the buffer when the &#8220;U8X8_MSG_BYTE_END_TRANSFER&#8221; message comes</p>
<pre class="lang:c decode:true">uint8_t u8x8_I2C_HW(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    uint8_t *data;
    switch(msg)
    {
        case U8X8_MSG_BYTE_SEND:        
            data = (uint8_t *)arg_ptr;
            while( arg_int &gt; 0 )
            {
                buff[buffCount] = *data;
                buffCount += 1;
                CY_ASSERT(buffCount &lt; BUFFSIZE);              
  	            data++;
	            arg_int--;
            }
        break;
 
        case U8X8_MSG_BYTE_START_TRANSFER:
            buffCount = 0;
         break;
        
        case U8X8_MSG_BYTE_END_TRANSFER:
	        OLEDtransaction.I2Cm_byteNum = buffCount;
            I2Cm1RunTransaction(&amp;OLEDtransaction);
        break;
    
        default:
        return 0;
    }
    
    return 1;
}
</pre>
<h1>SSD1306 OLED Display</h1>
<p>Now, the short block of test code works perfect:</p>
<pre class="lang:c decode:true">    u8x8_Setup(&amp;MyI2Cu8x8, u8x8_d_ssd1306_128x32_univision, u8x8_cad_ssd13xx_i2c, u8x8_I2C_HW, u8x8_gpio_and_delay_PSoC6);
        
    u8x8_InitDisplay(&amp;MyI2Cu8x8);  
    u8x8_SetPowerSave(&amp;MyI2Cu8x8,0);
    u8x8_ClearDisplay(&amp;MyI2Cu8x8);
    u8x8_SetFont(&amp;MyI2Cu8x8,u8x8_font_amstrad_cpc_extended_f);
    u8x8_DrawString(&amp;MyI2Cu8x8,0,0," Killer Mustang ");
    u8x8_DrawString(&amp;MyI2Cu8x8,0,1,"   Test OLED    ");
    u8x8_DrawString(&amp;MyI2Cu8x8,0,2,"________________");</pre>
<p>And I get a nice output (I wonder what a &#8220;Killer Mustang&#8221; is?)</p>
<p><a href="https://iotexpert.com/2017/12/05/psoc-6-freertos-ssd1306-oled-display/img_7530/" rel="attachment wp-att-4770"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/12/IMG_7530-e1512313105277-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-4770" srcset="https://iotexpert.com/wp-content/uploads/2017/12/IMG_7530-e1512313105277-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/12/IMG_7530-e1512313105277-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/12/IMG_7530-e1512313105277-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/12/IMG_7530-e1512313105277-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article Ill talk about the SS1306 and a problem that I created for myself.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-freertos-ssd1306-oled-display/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Pinball: Driving the OLED using the U8G2 Library</title>
		<link>https://iotexpert.com/pinball-driving-oled-using-u8g2-library/</link>
					<comments>https://iotexpert.com/pinball-driving-oled-using-u8g2-library/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Wed, 01 Feb 2017 10:54:26 +0000</pubDate>
				<category><![CDATA[Pinball]]></category>
		<category><![CDATA[PSoC4 BLE]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=2357</guid>

					<description><![CDATA[In the previous Pinball post, I wrote about getting the OLED going and getting the footprint onto my printed circuit board.  Now I need to make PSoC firmware to drive the display.  I turns out that there are a number of different driver chips out there including at least SSD1306, SH1106, LD7032, SSD1325, and ST7920 that [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In the<a href="https://iotexpert.com/2016/12/26/pinball-oled-display/"> previous Pinball post</a>, I wrote about getting the OLED going and getting the footprint onto my printed circuit board.  Now I need to make PSoC firmware to drive the display.  I turns out that there are a number of different driver chips out there including at least <a href="https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf" target="_blank">SSD1306</a>, <a href="https://www.elecrow.com/download/SH1106%20datasheet.pdf" target="_blank">SH1106</a>, <a href="http://www.seeedstudio.com/document/pdf/LD7032%20Device%20Spec%20(Rev%202.0).pdf" target="_blank">LD7032</a>, <a href="http://pdf.masters.com.pl/SOLOMON%20SYSTECH/SSD1325.pdf" target="_blank">SSD1325</a>, and <a href="http://www.fordata.cn/pdf/ic/st7920v30.pdf" target="_blank">ST7920</a> that handle multiplexing the columns/rows, managing frame buffers, power management, etc.  To make matters more fun, these chips support I2C, 3&amp;4 wire SPI and a couple of different parallel interfaces (6800, 8080).  I certainly didn&#8217;t want to go down the rathole of building up a complete driver library.  But I didn&#8217;t have to, as it turns out that that Oliver Kraus built and open-sourced a very nice library that you can get at <a href="https://github.com/olikraus/u8g2" target="_blank">www.github.com/olikraus/u8g2</a>.  This library (and its predecessor u8glib) seem to be in pretty wide use in Arduino and Raspberry Pi.</p>
<p>In order to make the library work with the PSoC I had to do several things</p>
<ol>
<li>Download it from GitHub (git clone git@github.com:olikraus/u8g2.git)</li>
<li>Created a new PSoC4200M project for the CY8CKIT-044 (which was the devkit that I happened to have sitting next to my computer)</li>
<li>Change the build settings (right click on the project and select building settings) then add the directory in &#8220;Additional Include Directories&#8221; and include the &#8220;u8g2/csrc&#8221; directory.<a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM.png" alt="" width="860" height="575" class="alignnone size-full wp-image-2354" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM.png 860w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM-600x401.png 600w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM-300x201.png 300w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.57.43-AM-768x513.png 768w" sizes="(max-width: 860px) 100vw, 860px" /></a></li>
<li>Add the header files to the project by right clicking and selecting &#8220;Add-&gt;Existing item&#8221; so that the project can f<a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-12.00.11-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-12.00.11-PM.png" alt="" width="355" height="232" class="alignnone size-full wp-image-2355" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-12.00.11-PM.png 355w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-12.00.11-PM-300x196.png 300w" sizes="(max-width: 355px) 100vw, 355px" /></a></li>
<li>Add the U8G2 C-Files to the project (same as step 4 but add the C files)</li>
<li>Build a schematic which has an I2C (for the display) and a debugging UART.  The I2C is configured as a master with 400kbs data rate.  The UART uses the default configuration.<a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.10.45-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.10.45-AM.png" alt="" width="742" height="721" class="alignnone size-full wp-image-2374" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.10.45-AM.png 742w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.10.45-AM-600x583.png 600w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.10.45-AM-300x292.png 300w" sizes="(max-width: 742px) 100vw, 742px" /></a></li>
<li>Assign the pins<a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM.png" alt="" width="780" height="126" class="alignnone size-full wp-image-2376" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM.png 780w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM-600x97.png 600w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM-300x48.png 300w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-27-at-6.12.32-AM-768x124.png 768w" sizes="(max-width: 780px) 100vw, 780px" /></a></li>
</ol>
<p>Now I am ready to build some firmware that will drive the display.  In order to use the library with a PSoC I need to create two functions for the U8G2 HAL to use as an interface to the PSoC hardware.  You initialize the U8G2 system with a call to the u8x8_Setup function.  In that call you need to provide function pointers too the two HAL functions</p>
<ol>
<li>The GPIO and Delay Interface</li>
<li>The byte oriented communication interface</li>
</ol>
<p>This is an example of the setup required:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM.png" alt="" width="973" height="40" class="alignnone size-full wp-image-2775" srcset="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM.png 973w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM-600x25.png 600w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM-300x12.png 300w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.20.10-AM-768x32.png 768w" sizes="(max-width: 973px) 100vw, 973px" /></a></p>
<p>The GPIO and Delay interface is used by the byte oriented communication functions to read/write the GPIOs and provide delays.  This function provides the underpinnings of a bit-banged I2C, UART, SPI etc.  Because I am only going to use PSoC Hardware to provide the I2C interface I will only respond to the delay messages.  All of the delay functions are implemented as busy wait loops, which I am not a big fan of.  The input to the function is a &#8220;message&#8221; that is one of a sprawling list of #defines in the file u8x8.h.  I believe that I found all of the possible cases, but I am not sure.</p>
<p>The first message, UX8X8_MSG_GPIO_AND_DELAY_INIT doesnt need to do anything because the GPIOs are configured correctly by the default.</p>
<p>I did not respond to the messages of the form U8X8_MSG_GPIO_X which are the read and write of the GPIOs as I am not going to use the bit-banged interface.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM.png" alt="" width="788" height="804" class="alignnone size-full wp-image-2776" srcset="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM.png 788w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM-600x612.png 600w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM-294x300.png 294w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.21.38-AM-768x784.png 768w" sizes="(max-width: 788px) 100vw, 788px" /></a></p>
<p>The other function that needs to be provided is the byte-oriented communication function.  This function needs to respond to the messages to start, send, and end communication.  I just mapped those messages onto the PSoC hardware APIs.  While I was trying to understand what was happening with the system I implemented a debugging UART which you can see in the #ifdef DEBUG_UART sections.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM.png" alt="" width="797" height="741" class="alignnone size-full wp-image-2777" srcset="https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM.png 797w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM-600x558.png 600w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM-300x279.png 300w, https://iotexpert.com/wp-content/uploads/2018/01/Screen-Shot-2017-01-25-at-6.22.45-AM-768x714.png 768w" sizes="(max-width: 797px) 100vw, 797px" /></a></p>
<p><span><p>You can find all of the source code and files at the <a href="https://github.com/iotexpert/Pinball" target="_blank">IOTEXPERT</a> site on github.</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Index</th>
<th >Description</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2016/09/05/pinball-newtons-attic-pinball/">Pinball: Newton's Attic Pinball</a></td>
<td >An introduction to the project and the goals</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/06/pinball-lotsa-blinking-leds/">Pinball: Lotsa Blinking LEDs</a></td>
<td >Everyone needs a bunch of LEDs on their Pinball Machine</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/07/pinball-matrix-leds-part-1/">Pinball: Matrix LEDs (Part 1)</a></td>
<td >Saving PSoC pins by using a matrix scheme</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/08/pinball-matrix-leds-part-2/" target="_blank">Pinball: Matrix LEDs (Part 2)</a></td>
<td >Solving some problems with the matrix</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/09/pinball-matrix-leds-component/" target="_blank">Pinball: Matrix LEDs Component</a></td>
<td >How to turn the Matrix LED into a component</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/10/pinball-a-switch-matrix/">Pinball: A Switch Matrix</a></td>
<td >Implementing a bunch of switches</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/12/pinball-switch-matrix-component-part-1/" target="_blank">Pinball: Switch Matrix Component (Part 1)</a></td>
<td >The switch matrix component implementation</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/13/pinball-switch-matrix-component-part-2/" target="_blank">Pinball: Switch Matrix Component (Part 2)</a></td>
<td >The firmware for matrix component</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/14/pinball-switch-matrix-component-part-3/" target="_blank">Pinball: Switch Matrix Component (Part 3)</a></td>
<td >Test firmware for the matrix component</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/20/pinball-the-music-player-part-1/" target="_blank">Pinball: The Music Player (Part 1)</a></td>
<td >The schematic and symbol for a Music Player component</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/21/pinball-the-music-player-part-2/" target="_blank">Pinball: The Music Player (Part 2)</a></td>
<td >The Public API for the Music Player component</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/22/pinball-the-music-player-part-3/" target="_blank">Pinball: The Music Player (Part 3)</a></td>
<td >The firmware to make the sweet sweet music</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/23/pinball-the-music-player-part-4/">Pinball: The Music Player (Part 4)</a></td>
<td >The test program for the music player</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/26/pinball-the-motors-hbridge/" target="_blank">Pinball: The Motors + HBridge</a></td>
<td >Using an Bridge to control DC Motors</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/27/pinball-the-eagle-schematic/" target="_blank">Pinball: The Eagle Schematic</a></td>
<td >All of the circuits into an Eagle schematic</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/29/pinball-the-printed-circuit-board-version-1-0/" target="_blank">Pinball: The Printed Circuit Board 1.0</a></td>
<td >The first Eagle PCB layout of the printed circuit board</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2016/09/30/pinball-the-pcb-version-1-0-fail/" target="_blank">Pinball: The PCB Version 1.0 Fail</a></td>
<td >Problems with the first version of the Eagle PCB layout</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/01/05/pinball-pcb-1-2-updates-using-eagle/" target="_blank">Pinball: PCB Layout 1.2 Updates using Eagle</a></td>
<td >Fixing the errors on the first two versions of the Eagle PCB</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/01/12/pinball-pcb-solder-reflow-osh-park-eagle/">Pinball: Assemble and Reflow the 1.2 PCB</a></td>
<td >Assembling the Eagle PCB</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/01/23/pinball-testing-the-eagle-pcb/" target="_blank">Pinball: Testing the Eagle PCB</a></td>
<td > Firmware to test the newly built Pinball printed circuit board</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/02/09/pinball-debugging-psoc-motor-driver/" target="_blank">Pinball: Debugging the Motor Driver</a></td>
<td > Fixing the motor driver PSoC project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/02/13/hot-air-solder-reworking-the-accelerometer/" target="_blank">Pinball: Hot-Air Reworking the Accelerometer Solder</a></td>
<td >Using a Hot-Air Rework tool to reflow a QFN</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/02/16/pinball-debugging-lm317-power-supply-tale-getting-lucky/" target="_blank">Pinball: Debugging the LM317 Power Supply- A Tale of Getting Lucky</a></td>
<td >Debugging the LM317/LM117 power supply</td>
</tr>
</tbody></table></div></p></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/pinball-driving-oled-using-u8g2-library/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
			</item>
		<item>
		<title>Pinball: OLED Display</title>
		<link>https://iotexpert.com/pinball-oled-display/</link>
					<comments>https://iotexpert.com/pinball-oled-display/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 26 Dec 2016 17:50:43 +0000</pubDate>
				<category><![CDATA[Eagle]]></category>
		<category><![CDATA[Pinball]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=2344</guid>

					<description><![CDATA[I screwed up the Pinball board design AGAIN!!!  It is so frustrating.  Ill write about the new design soon (and punish myself for the error.) As I worked on redoing the design I decided to put a footprint on the PCB for a small OLED LCD.   The display has an I2C interface, is about [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I screwed up the Pinball board design AGAIN!!!  It is so frustrating.  Ill write about the new design soon (and punish myself for the error.) As I worked on redoing the design I decided to put a footprint on the PCB for a small OLED LCD.   The display has an I2C interface, is about an inch wide and has 128&#215;64 pixels&#8230; But, best of all can be purchased on <a href="http://www.ebay.com/itm/White-0-96-inch-128X64-OLED-Display-Module-For-arduino-0-96-IIC-SPI-SSD1306-/222297606908?hash=item33c1f84afc:g:DPkAAOSw8w1X7idG" target="_blank">eBay from China for about $3.00</a>.  Here is a picture of the display with a PSoC4M driving it:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2016/12/IMG_3503.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/IMG_3503-e1482770486288.jpg" width="3024" height="4032" class="alignnone wp-image-2345 size-full" /></a></p>
<p>The display will go on the right side of the board.  Here is a rendering of the new board from the OSH Parks website:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c.png" alt="" width="1466" height="831" class="alignnone size-full wp-image-2347" srcset="https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c.png 1466w, https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c-600x340.png 600w, https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c-300x170.png 300w, https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c-768x435.png 768w, https://iotexpert.com/wp-content/uploads/2016/12/64d2f7acd81af523361182740421ae5c-1024x580.png 1024w" sizes="(max-width: 1466px) 100vw, 1466px" /></a></p>
<p>After I decided to put the footprint on the board I bought several displays from Amazon to try out, and to make sure that I knew how to make them work.  I immediately ran into some drama which caused me an evening of frustration.  If you look at the picture closely you can see that the power and ground pins are swapped:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2016/12/IMG_3504-2.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/IMG_3504-2.jpg" alt="" width="4032" height="3024" class="alignnone size-full wp-image-2348" /></a></p>
<p>After I realized that was going to be a potential problem I put in a set of 0 ohm resistors on the upper right hand part of the board so that I could swap power/ground and scl/sda connections.  Here is a snapshot of the schematic and layout:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.49.54-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.49.54-AM.png" alt="" width="332" height="532" class="alignnone size-full wp-image-2350" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.49.54-AM.png 332w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.49.54-AM-187x300.png 187w" sizes="(max-width: 332px) 100vw, 332px" /></a></p>
<p><a href="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM.png" alt="" width="991" height="557" class="alignnone size-full wp-image-2351" srcset="https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM.png 991w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM-600x337.png 600w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM-300x169.png 300w, https://iotexpert.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-26-at-11.51.08-AM-768x432.png 768w" sizes="(max-width: 991px) 100vw, 991px" /></a></p>
<p>This left me with what software to use to drive the display which I will address in the next post.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/pinball-oled-display/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
