<?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;bridge control&#8221; &#8211; IoT Expert</title>
	<atom:link href="https://iotexpert.com/search/bridge+control/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>https://iotexpert.com</link>
	<description>Engineering for the Internet of Things</description>
	<lastBuildDate>Wed, 24 Feb 2021 21:51:17 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.7</generator>

<image>
	<url>https://iotexpert.com/wp-content/uploads/2017/01/cropped-Avatar-32x32.jpg</url>
	<title>Search Results for &#8220;bridge control&#8221; &#8211; IoT Expert</title>
	<link>https://iotexpert.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>EW21: Lesson 0: Introduction &#038; Resources</title>
		<link>https://iotexpert.com/ew21-lesson-0-introduction-resources/</link>
					<comments>https://iotexpert.com/ew21-lesson-0-introduction-resources/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Wed, 24 Feb 2021 15:27:25 +0000</pubDate>
				<category><![CDATA[Embedded World 2021]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10777</guid>

					<description><![CDATA[Summary Hello everyone.  This is lesson 0 of a series of 7 lessons about creating an IoT application using the Infineon ModusToolbox Software Environment to create a WiFi enabled drone.  In the next two hours we will build a remote control that uses the PSoC 6 MCU, WiFi, MQTT, CapSense and a 3-D Magnetic Joystick. [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Hello everyone.  This is lesson 0 of a series of 7 lessons about creating an IoT application using the Infineon ModusToolbox Software Environment to create a WiFi enabled drone.  In the next two hours we will build a remote control that uses the PSoC 6 MCU, WiFi, MQTT, CapSense and a 3-D Magnetic Joystick.  Then we will build the drone which will use a PSoC 6, WiFi, MQTT, CapSense and a BLDC motor controller.</p>
<p>What I will do today is take you lesson by lesson through the class and talk about how it all works and what you need to do.  When I built the class it was absolutely my goal to have every button click and line of code described.  That being said,  it is likely that I made some errors.  So, during the class you will be able to send messages to my team who will answer the questions, or ask me and I&#8217;ll answer live.  If you missed the class, that’s OK, you will be able to watch it on replay.  In addition if you have a question after the live stream is over, leave a comment here and I&#8217;ll answer.</p>
<p>I will attempt to go slowly enough for you to follow along, but if I go to fast, don’t worry you should be able to follow along with the instructions on this website.</p>
<p>Every lesson will have this table in it and you will be able to click to follow along with the different lessons.</p>
<p><span><h1>Embedded World 2021 - Infineon ModusToolbox PSoC 6 Drone </h1>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >#</th>
<th >Description</th>
</tr>
</thead>
<tbody>
<tr><td >0</td>
<td ><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/" target="_blank" rel="noopener">Introduction &amp; Resources</a></td>
</tr>

<tr><td >1</td>
<td ><a href="https://iotexpert.com/ew21-lesson-1-freertos-capsense/" target="_blank" rel="noopener">FreeRTOS &amp; CapSense</a></td>
</tr>

<tr><td >2</td>
<td ><a href="https://iotexpert.com/ew21-lesson-2-joystick/" target="_blank" rel="noopener">3-D Magnetic Sensing XENSIV Joystick</a></td>
</tr>

<tr><td >3</td>
<td ><a href="https://iotexpert.com/ew21-lesson-3-wifi/" target="_blank" rel="noopener">WiFi</a></td>
</tr>

<tr><td >4</td>
<td ><a href="https://iotexpert.com/ew21-lesson-4-mqtt/" target="_blank" rel="noopener">MQTT</a></td>
</tr>

<tr><td >5</td>
<td ><a href="https://iotexpert.com/ew21-lesson-5-low-power/" target="_blank" rel="noopener">Low Power</a></td>
</tr>

<tr><td >6</td>
<td ><a href="https://iotexpert.com/ew21-lesson-6-motor-control/" target="_blank" rel="noopener">BLDC Motor Control</a></td>
</tr>

<tr><td >7</td>
<td ><a href="https://iotexpert.com/ew21-lesson-7-ws2812-led-strip/" target="_blank" rel="noopener">WS2812 Strip LEDs</a></td>
</tr>
</tbody></table></div></p>
<p>&nbsp;</p></span></p>
<p>Here is the overall system architecture:</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/arch-1/" rel="attachment wp-att-10972"><img fetchpriority="high" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-1024x433.png" alt="" width="1024" height="433" class="alignnone size-large wp-image-10972" srcset="https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-1024x433.png 1024w, https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-300x127.png 300w, https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-768x324.png 768w, https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-1536x649.png 1536w, https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1-600x253.png 600w, https://iotexpert.com/wp-content/uploads/2021/02/arch-1-1.png 1631w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>The Remote Control</h1>
<p>The remote control is built with two Infineon development boards</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Kit</th>
<th >Features</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://www.cypress.com/documentation/development-kitsboards/psoc-6-wi-fi-bt-prototyping-kit-cy8cproto-062-4343w" target="_blank" rel="noopener">CY8CPROTO-062-4343W</a></td>
<td >PSoC 6,CYW4343W WiFi Bluetooth Combo Radio,CapSense</td>
</tr>

<tr><td ><a href="https://www.infineon.com/cms/en/product/evaluation-boards/tle493d-w2b6-ms2go/" target="_blank" rel="noopener">TLE493D-W2B6</a></td>
<td >XENSIV 3-D Magnetic Sensor</td>
</tr>
</tbody></table></div>
<p>Here are some pictures.</p>
<p>CY8CPROTO-062-4343W.  The top left of the board is a KitProg programmer.  The middle third on the left is the 4343W and the PSoC 6.  The bottom right are the CapSense buttons.  Just to the right of the programmer is a SD Card holder and S512FL Quad SPI Flash.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0496/" rel="attachment wp-att-11018"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-1024x806.jpg" alt="" width="1024" height="806" class="alignnone size-large wp-image-11018" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-1024x806.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-300x236.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-768x605.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-1536x1210.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-2048x1613.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0496-600x473.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This the the top of the TLE-493D-W2B6 3-D magnetic sensor board.  On the far right, the tiny 6 pin chip is the actual sensor.  The big hole to the left of the sensor is to mount a magnet.  The two chips on the left are used as a bridge to USB (if you are developing).  I attach to this device using the I2C interface pins.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0503/" rel="attachment wp-att-11027"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-1024x402.jpg" alt="" width="1024" height="402" class="alignnone size-large wp-image-11027" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-1024x402.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-300x118.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-768x302.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-1536x604.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-2048x805.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0503-600x236.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is the back where you can see the SCL, SDA, Power and Ground labeled.  Unfortunately, they are in the wrong order to plug directly into the PSoC kit so Greg had to make a little wire switcher.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0504/" rel="attachment wp-att-11026"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-1024x397.jpg" alt="" width="1024" height="397" class="alignnone size-large wp-image-11026" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-1024x397.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-300x116.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-768x297.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-1536x595.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-2048x793.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0504-600x232.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is the board with the really really cool 3-d printed joystick.  Simply two pieces of plastic with a magnet in the bottom.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0494/" rel="attachment wp-att-11020"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-1024x914.jpg" alt="" width="1024" height="914" class="alignnone size-large wp-image-11020" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-1024x914.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-300x268.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-768x686.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-1536x1371.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-2048x1828.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0494-600x536.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This picture show how the magnetic sense board is mounted onto the kit</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0505/" rel="attachment wp-att-11029"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-686x1024.jpg" alt="" width="686" height="1024" class="alignnone size-large wp-image-11029" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-686x1024.jpg 686w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-201x300.jpg 201w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-768x1146.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-1029x1536.jpg 1029w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-1372x2048.jpg 1372w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-600x895.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0505-scaled.jpg 1716w" sizes="(max-width: 686px) 100vw, 686px" /></a></p>
<p>Here is the whole thing assembled.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0493-2/" rel="attachment wp-att-11021"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-1024x595.jpg" alt="" width="1024" height="595" class="alignnone size-large wp-image-11021" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-1024x595.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-300x174.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-768x446.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-1536x893.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-2048x1191.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0493-600x349.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>The Crazy Drone</h1>
<p>The drone was built with</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Kit</th>
<th >Features</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://www.cypress.com/documentation/development-kitsboards/psoc-62s2-wi-fi-bt-pioneer-kit-cy8ckit-062s2-43012" target="_blank" rel="noopener">CY8CKIT-062S2-43012</a></td>
<td >PSoC 6 + CYW43012 Low Power Bluetooth WiFI Combo</td>
</tr>

<tr><td ><span><a href="https://www.infineon.com/cms/en/product/evaluation-boards/bldc_shield_tle9879/" target="_blank" rel="noopener">TLE9879WXA40</a></td>
<td >BLDC Control Shield</span></td>
</tr>
</tbody></table></div>
<p>Here is a picture of the CY8CKIT-062S2-43012.  On the far right in the middle is the PSoC 6 and CYW43012.  In the lower right are the CapSense Buttons and Slider.  The KitProg IC is just below the top Arduino Header.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0495/" rel="attachment wp-att-11017"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-1024x748.jpg" alt="" width="1024" height="748" class="alignnone size-large wp-image-11017" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-1024x748.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-300x219.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-768x561.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-1536x1122.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495-600x438.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0495.jpg 2018w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In order to drive the BLDC motor I use the TLE9879WXA40 Motor Shield.  This has everything needed to do Field Oriented Control of a 3-phase BLDC motor.  The Blue, Green and White wires are the 3-phases of the BLDC.  The Red and Black are simply +12V and Ground.  You interface from the PSoC to the BLDC shield via a SPI interface (attached to the Arduino pins).</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0497/" rel="attachment wp-att-11019"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-1024x781.jpg" alt="" width="1024" height="781" class="alignnone size-large wp-image-11019" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-1024x781.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-300x229.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-768x585.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-1536x1171.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-2048x1561.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0497-600x457.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The BLDC motor is mounted into a 3-d printed holder.  The mount is attached to hollow carbon fiber tubes that run on bearings that you see below.  The wires run down through the tubes.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0502/" rel="attachment wp-att-11016"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-768x1024.jpg" alt="" width="768" height="1024" class="alignnone size-large wp-image-11016" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-768x1024.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-225x300.jpg 225w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-1152x1536.jpg 1152w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-1536x2048.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-600x800.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0502-scaled.jpg 1920w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>At the bottom, the blue box just provides +12v to the drone and the PSoC board.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0500/" rel="attachment wp-att-11015"></a> <a href="https://iotexpert.com/?attachment_id=11014" rel="attachment wp-att-11014"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-1024x662.jpg" alt="" width="1024" height="662" class="alignnone size-large wp-image-11014" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-1024x662.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-300x194.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-768x496.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-1536x993.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-2048x1324.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0501-600x388.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is a closer picture of the BLDC motor.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0499/" rel="attachment wp-att-11013"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-11013" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-768x576.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-1536x1152.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-2048x1536.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0499-600x450.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is a picture of the whole crazy thing running.  If you look in the background you can see a top secret new PSoC motor controller.  Is that an Easter egg?</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0491-2/" rel="attachment wp-att-11024"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-1024x947.jpg" alt="" width="1024" height="947" class="alignnone size-large wp-image-11024" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-1024x947.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-300x277.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-768x710.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-1536x1420.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-2048x1894.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0491-2-600x555.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And yes, it will cut your fingers off if you aren&#8217;t careful.</p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0492-2/" rel="attachment wp-att-11022"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-1024x674.jpg" alt="" width="1024" height="674" class="alignnone size-large wp-image-11022" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-1024x674.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-300x198.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-768x506.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-1536x1012.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2-600x395.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0492-2.jpg 1998w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Resources</h1>
<p>You will need a few things for this class:</p>
<ul>
<li><a href="https://www.cypress.com/products/modustoolbox-software-environment" target="_blank" rel="noopener">ModusToolbox Software Environment</a></li>
<li><a href="https://www.cypress.com/documentation/development-kitsboards/psoc-6-wi-fi-bt-prototyping-kit-cy8cproto-062-4343w" target="_blank" rel="noopener">PSoC 6 WiFi-BT Prototyping Kit (CY8CPROTO-062-4343W)</a></li>
<li>(optional) <a href="https://www.cypress.com/documentation/development-kitsboards/psoc-62s2-wi-fi-bt-pioneer-kit-cy8ckit-062s2-43012" target="_blank" rel="noopener">PSoC 62S2 WiFi-BT Pioneer Kit  (CY8CKIT-062S2-43012)</a></li>
<li>(optional) <a href="https://www.infineon.com/cms/en/product/evaluation-boards/tle493d-w2b6-ms2go/" target="_blank" rel="noopener">XENSIV TLE493D-W2B6 MS2GO and JOYSTICK FOR 3D 2 GO KIT</a></li>
<li>(optional) <a href="https://www.infineon.com/cms/en/product/evaluation-boards/bldc_shield_tle9879/" target="_blank" rel="noopener">BLDC SHIELD TLE9879TOBO1</a></li>
<li>(optional) Readytosky 2212 920KV Brushless Motors and Readytosky 10&#215;4.5 1045 Propeller</li>
</ul>
<h1>ModusToolbox Software Environment</h1>
<p>You can download Modus Toolbox from <a href="https://www.cypress.com/products/modustoolbox-software-environment" target="_blank" rel="noopener">here</a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-7-20-59-am/" rel="attachment wp-att-11041"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-1008x1024.jpg" alt="" width="1008" height="1024" class="alignnone size-large wp-image-11041" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-1008x1024.jpg 1008w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-295x300.jpg 295w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-768x781.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-1511x1536.jpg 1511w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM-600x610.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.20.59-AM.jpg 1716w" sizes="(max-width: 1008px) 100vw, 1008px" /></a></p>
<h1>CY8CPROTO-062-4343W</h1>
<p>You can read all about this development kit on the <a href="https://www.cypress.com/documentation/development-kitsboards/psoc-6-wi-fi-bt-prototyping-kit-cy8cproto-062-4343w" target="_blank" rel="noopener">website</a> or in the <a href="https://www.cypress.com/file/457891/download" target="_blank" rel="noopener">KitGuide</a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-48-47-am/" rel="attachment wp-att-11031"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-817x1024.jpg" alt="" width="817" height="1024" class="alignnone size-large wp-image-11031" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-817x1024.jpg 817w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-239x300.jpg 239w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-768x963.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-1225x1536.jpg 1225w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-1634x2048.jpg 1634w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM-600x752.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.48.47-AM.jpg 1752w" sizes="(max-width: 817px) 100vw, 817px" /></a></p>
<h1>CY8CKIT-062S2-43012</h1>
<p>You can read all about this development kit on the <a href="https://www.cypress.com/documentation/development-kitsboards/psoc-62s2-wi-fi-bt-pioneer-kit-cy8ckit-062s2-43012" target="_blank" rel="noopener">website</a> or in the <a href="https://www.cypress.com/file/487006/download" target="_blank" rel="noopener">KitGuide</a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-55-57-am/" rel="attachment wp-att-11032"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-1024x713.jpg" alt="" width="1024" height="713" class="alignnone size-large wp-image-11032" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-1024x713.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-300x209.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-768x535.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-1536x1070.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-2048x1426.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.55.57-AM-600x418.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-56-23-am/" rel="attachment wp-att-11033"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-1024x745.png" alt="" width="1024" height="745" class="alignnone size-large wp-image-11033" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-1024x745.png 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-300x218.png 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-768x559.png 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-1536x1118.png 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-2048x1490.png 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.23-AM-600x437.png 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-56-41-am/" rel="attachment wp-att-11034"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-1024x668.png" alt="" width="1024" height="668" class="alignnone size-large wp-image-11034" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-1024x668.png 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-300x196.png 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-768x501.png 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-1536x1002.png 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-2048x1336.png 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.41-AM-600x391.png 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-56-48-am/" rel="attachment wp-att-11035"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-1024x714.png" alt="" width="1024" height="714" class="alignnone size-large wp-image-11035" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-1024x714.png 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-300x209.png 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-768x536.png 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-1536x1071.png 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-2048x1428.png 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.48-AM-600x418.png 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-6-56-56-am/" rel="attachment wp-att-11036"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-1024x684.png" alt="" width="1024" height="684" class="alignnone size-large wp-image-11036" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-1024x684.png 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-300x200.png 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-768x513.png 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-1536x1025.png 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-2048x1367.png 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-6.56.56-AM-600x400.png 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>TLE9879QXA40 BLDC Motor Controller</h1>
<p>You can read all about this development kit on the <a href="https://www.infineon.com/cms/en/product/evaluation-boards/bldc_shield_tle9879/" target="_blank" rel="noopener">website</a> or in the <a href="https://www.infineon.com/dgdl/Infineon-TLE9879QXA40-DS-v01_00-EN.pdf?fileId=5546d4625a888733015a89d10a283f20" target="_blank" rel="noopener">KitGuide</a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/img_0506/" rel="attachment wp-att-11037"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-1024x861.jpg" alt="" width="1024" height="861" class="alignnone size-large wp-image-11037" srcset="https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-1024x861.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-300x252.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-768x645.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-1536x1291.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-2048x1721.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/IMG_0506-600x504.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>XENSIV TLE493D</h1>
<p>You can read all about this development kit on the <a href="https://www.infineon.com/cms/en/product/evaluation-boards/tle493d-w2b6-ms2go/" target="_blank" rel="noopener">website</a> or in the <a href="https://www.infineon.com/dgdl/Infineon-Infineon-3DMS2GO_TLE493D-W2B6-UM-v01_01-EN-UserManual-v01_01-EN.pdf?fileId=5546d462636cc8fb016418342fea3f54" target="_blank" rel="noopener">KitGuide</a></p>
<p><a href="https://iotexpert.com/ew21-lesson-0-introduction-resources/screen-shot-2021-02-24-at-7-08-06-am/" rel="attachment wp-att-11038"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-1024x492.jpg" alt="" width="1024" height="492" class="alignnone size-large wp-image-11038" srcset="https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-1024x492.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-300x144.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-768x369.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-1536x738.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-2048x984.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/02/Screen-Shot-2021-02-24-at-7.08.06-AM-600x288.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/ew21-lesson-0-introduction-resources/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Tilt Hydrometer (Part 5) Tilt Simulator &#038; Multi Advertising iBeacons</title>
		<link>https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/</link>
					<comments>https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 01 Feb 2021 14:20:47 +0000</pubDate>
				<category><![CDATA[Tilt Hydrometer Data Collection]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10368</guid>

					<description><![CDATA[Summary Using the PSoC 6 AnyCloud Bluetooth Stack to send out &#8220;multi-adv&#8221; Bluetooth advertising packets with a PSoC 6 and CYW43012.  Multi-adv means sending out multiple different simultaneous Bluetooth Advertising packets.  This includes building a project to simulate a Tilt Hydrometer. Story As I worked on the Tilt project I came to realize that what [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Using the PSoC 6 AnyCloud Bluetooth Stack to send out &#8220;multi-adv&#8221; Bluetooth advertising packets with a PSoC 6 and CYW43012.  Multi-adv means sending out multiple different simultaneous Bluetooth Advertising packets.  This includes building a project to simulate a <a href="https://tilthydrometer.com" target="_blank" rel="noopener noreferrer">Tilt Hydrometer</a>.</p>
<h1>Story</h1>
<p>As I worked on the Tilt project I came to realize that what I really needed what a Tilt Simulator.  That is, a PSoC programmed with a command line interface that could send out the iBeacon messages that looked like the ones that the Tilt actually sent out.  Why?  Simple, all three of my Tilts are busy doing their day job measuring beer and they don&#8217;t have time to fool around being test subjects for my IoT Expert Articles.</p>
<p>The CYW43012 controller that I am using is capable of automatically rotating through a list of at least 8 beacons (maybe more, but I don&#8217;t know the exact number. I suppose I should figure it out).  In other words I can simultaneously simulate 8 Tilts at one time with one PSoC.</p>
<p>For this project, I want the project to be able to</p>
<ol>
<li>Simultaneously broadcast 0-8 of the Tilt iBeacon messages</li>
<li>Have a command line interface to control the Tilt iBeacons</li>
<li>Be able to set a ramp rate for Temperature and Gravity on a per Tilt basis</li>
</ol>
<p>The commands will be:</p>
<ol>
<li>print &#8211; print out the table of the information about the Tilt iBeacons</li>
<li>set &#8211; set the temperature, gravity and txPower e.g. &#8220;set 0 77 1020 99&#8221; would turn on beacon 1 with the temperature set to 77 and the gravity set to 1020 and the txPower set to 99</li>
<li>update &#8211; configure the update rate for temperature and gravity e.g. &#8220;update 6 1000 0 -1&#8221; would set tilt 6 with an update to happen once per 1000ms with a +0 temperature per update and a -1 gravity points per update</li>
</ol>
<p>Here is an example of the display.</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-27-at-7-04-29-am/" rel="attachment wp-att-10395"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM-1024x713.png" alt="" width="1024" height="713" class="alignnone size-large wp-image-10395" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM-1024x713.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM-300x209.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM-768x535.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM-600x418.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.04.29-AM.png 1192w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This series is broken up into the following 12 articles with a few additional possible articles. </p>
<p><a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/" target="_blank" rel="noopener">Tilt Hydrometer (Part 1) Overview &amp; Out-of-Box</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-architecture-part-2/" target="_blank" rel="noopener">Tilt Hydrometer (Part 2) Architecture</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-advertising-scanner-part-3/">Tilt Hydrometer (Part 3) Advertising Scanner</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-4-advertising-packet-error/" target="_blank" rel="noopener">Tilt Hydrometer (Part 4) Advertising Packet Error?</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/">Tilt Hydrometer (Part 5) Tilt Simulator &amp; Multi Advertising iBeacons</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-6-tilt-simulator-an-upgrade/" target="_blank" rel="noopener">Tilt Hydrometer (Part 6) Tilt Simulator an Upgrade</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-7-advertising-database/">Tilt Hydrometer (Part 7) Advertising Database</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-8-read-the-database/">Tilt Hydrometer (Part 8) Read the Database</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-9-an-lcd-display/">Tilt Hydrometer (Part 9) An LCD Display</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-10-the-display-state-machine/">Tilt Hydrometer (Part 10) The Display State Machine</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-11-draw-the-display-screens/">Tilt Hydrometer (Part 11) Draw the Display Screens</a></p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-12-capsense/">Tilt Hydrometer (Part 12) CapSense</a></p>
<p>Tilt Hydrometer: LittleFS &amp; SPI Flash (Part ?)</p>
<p>Tilt Hydrometer: WiFi Introducer (Part ?)</p>
<p>Tilt Hydrometer: WebServer (Part ?)</p>
<p>Tilt Hydrometer: Amazon MQTT (Part ?)</p>
<p>Tilt Hydrometer: Printed Circuit Board (Part ?)</p>
<p>You can get the source code from git@github.com:iotexpert/Tilt2.git  This repository has tags for each of the articles which can be accessed with "git checkout part12"  You can find the Tilt Simulator at  git@github.com:iotexpert/TiltSimulator.git.</p>
<p>&nbsp;</p>
<h1>Build the Basic Project</h1>
<p>Create a new project using the FreeRTOS NT Shell Template called Tilt Simulator</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-11-31-am/" rel="attachment wp-att-10369"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-1024x653.png" alt="" width="1024" height="653" class="alignnone size-large wp-image-10369" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-1024x653.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-300x191.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-768x490.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-1536x980.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-2048x1307.png 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.11.31-AM-600x383.png 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Enable the bluetooth-freertos and btstack libraries.  Also enable the IoT Expert BT Utilities library.</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-19-14-am/" rel="attachment wp-att-10376"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM-899x1024.png" alt="" width="899" height="1024" class="alignnone size-large wp-image-10376" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM-899x1024.png 899w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM-263x300.png 263w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM-768x874.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM-600x683.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.19.14-AM.png 1126w" sizes="(max-width: 899px) 100vw, 899px" /></a></p>
<p>In the command line copy the template bluetoothManager.* into the project</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-14-30-am/" rel="attachment wp-att-10371"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM-1024x104.png" alt="" width="1024" height="104" class="alignnone size-large wp-image-10371" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM-1024x104.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM-300x30.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM-768x78.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM-600x61.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.14.30-AM.png 1398w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Start the Bluetooth configurator with &#8220;make config_bt&#8221; on the command line.  Press the new project file (the blank paper)</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-15-37-am/" rel="attachment wp-att-10372"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-1024x996.png" alt="" width="1024" height="996" class="alignnone size-large wp-image-10372" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-1024x996.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-300x292.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-768x747.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-1536x1493.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM-600x583.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.37-AM.png 1732w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Select the P6 connectivity device</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-15-49-am/" rel="attachment wp-att-10373"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.49-AM.png" alt="" width="806" height="246" class="alignnone size-large wp-image-10373" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.49-AM.png 806w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.49-AM-300x92.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.49-AM-768x234.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.15.49-AM-600x183.png 600w" sizes="(max-width: 806px) 100vw, 806px" /></a></p>
<p>Press save and call your file &#8220;TiltSimulator&#8221; (it actually doesn&#8217;t matter what you call it).  This will generate the configuration structures you need.</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-25-at-11-16-21-am/" rel="attachment wp-att-10374"></a> <a href="https://iotexpert.com/?attachment_id=10375" rel="attachment wp-att-10375"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.16.52-AM.png" alt="" width="900" height="426" class="alignnone size-large wp-image-10375" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.16.52-AM.png 900w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.16.52-AM-300x142.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.16.52-AM-768x364.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-25-at-11.16.52-AM-600x284.png 600w" sizes="(max-width: 900px) 100vw, 900px" /></a></p>
<p>In command line run &#8220;make vscode&#8221;.  Then edit the Makefile to include these components.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">COMPONENTS=FREERTOS WICED_BLE</pre>
<p>You should run a build/program right now as you will have a basic project with a blinking led, the Bluetooth stack running and a command line.</p>
<h1>Multiadv</h1>
<p>The CYW43012 has the ability to automatically rotate through a list of advertising packets.  Each packet can have different data including a different Bluetooth address (how crazy is that?)  Each packet can also be advertised at a different and configurable rate.  It does this all with no intervention by the host.</p>
<p>This functionality is documented in the Bluetooth Stack section called &#8220;MutiAdv&#8221; under Device Management.</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/screen-shot-2020-11-27-at-7-50-32-am/" rel="attachment wp-att-10397"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-1024x593.jpg" alt="" width="1024" height="593" class="alignnone size-large wp-image-10397" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-1024x593.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-300x174.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-768x445.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-1536x890.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-2048x1187.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-27-at-7.50.32-AM-600x348.jpg 600w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Build the Database</h1>
<p>The database is just an array of structures.  There are only 8 entries in the database, one for each color Tilt.  In addition to a string representing the name, the database will have</p>
<ol>
<li>Which advertising slot that this tilt is using (0 means that it isn&#8217;t active)</li>
<li>If the data is &#8220;dirty&#8221; meaning it has changed in this table but has not yet been copied to the controller for broadcast</li>
<li>rate = how often to update the data in the that row</li>
<li>tempUPDATE = how much to change the data by each time an update is called</li>
<li>gravUPDATE = how much to change the gravity by each time an update is called</li>
<li>The actual bytes of the advertising packet</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/*********************************************************************************
*
* Tilt Database Definition
* 
*********************************************************************************/

#define TILT_IBEACON_HEADER_LEN 25
#define TILT_IBEACON_DATA_LEN 5
#define TILT_IBEACON_LEN (TILT_IBEACON_HEADER_LEN + TILT_IBEACON_DATA_LEN)

typedef struct  {
    char *colorName;    // The color string
    int slot;           // Which Bluetooth ADV Slot this Tilt is using
    bool dirty;         // A flag to tell if there has been a change since the adv was last written
    int rate;           // rate in ms
    int tempUpdate;     // The update rate for temperature
    int gravUpdate;     // The update rate for gravity
    uint8_t advData[TILT_IBEACON_LEN];
} tilt_t;

// 02 01 04 = Flags
// 0x1A 0xFF = Manufacturer specific data
// 0x4c 0x00 = Apple
// 0x02 = iBeacon
// 0x15 = remaining data length
#define IBEACON_HEADER 0x02,0x01,0x04,0x1A,0xFF,0x4C,0x00,0x02,0x15

static tilt_t tiltDB [] =
{
    {"Red",    0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x10,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Green" , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x20,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Black" , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x30,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Purple", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x40,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Orange", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x50,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Blue"  , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x60,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Yellow", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x70,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Pink"  , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x80,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
};
#define NUM_TILT (sizeof(tiltDB)/sizeof(tilt_t))

#define IBEACON_TEMP_HI (25)
#define IBEACON_TEMP_LO (26)
#define IBEACON_GRAV_HI (27)
#define IBEACON_GRAV_LO (28)
#define IBEACON_TXPOWER (29)</pre>
<p>Now I will make &#8220;getters and setters&#8221;.  These functions will set the correct bytes in the adverting packets, and can retrieve the current values in those bytes.  Remember in the Apple iBeacon format there are 5 &#8220;user&#8221; bytes</p>
<ol>
<li>Major byte 0 and byte 1</li>
<li>Minor byte 0 and bytes 1</li>
<li>txPower</li>
</ol>
<p>Apple didnt specify what you stored in the major/minor.  In fact they also didnt specify the endianness.  The Tilt guys decided that the would store BIG endian &#8211; oh well.</p>
<ol>
<li>Major = Temperature in degrees F</li>
<li>Minor = Gravity points i.e. 1050 means 1.050</li>
</ol>
<p>If you look in my code the &#8220;set&#8221; of temperature and gravity they will &#8220;wrap around&#8221;.  If you set a value BELOW the minimum it will set the highest value and if you set a value ABOVE the maximum it will set it to the lowest.  This allows my automatic update code to just count one direction.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">int btm_getTemperature(int num)
{
    return (uint16_t)tiltDB[num].advData[IBEACON_TEMP_HI] &lt;&lt; 8 | tiltDB[num].advData[IBEACON_TEMP_LO];
}

void btm_setTemperature(int num,uint16_t temperature)
{
    if(temperature &gt; 150)
        temperature = 10;
    if(temperature&lt;10)
        temperature = 150;

    int oldtemp = btm_getTemperature(num);

    tiltDB[num].advData[IBEACON_TEMP_HI] = (temperature &amp; 0xFF00) &gt;&gt; 8;    
    tiltDB[num].advData[IBEACON_TEMP_LO] = temperature &amp; 0xFF;
    if(temperature != oldtemp)
        tiltDB[num].dirty = true;    
}

int btm_getGravity(int num)
{
    return (uint16_t)tiltDB[num].advData[IBEACON_GRAV_HI] &lt;&lt; 8 | tiltDB[num].advData[IBEACON_GRAV_LO];
}

void btm_setGravity(int num,uint16_t gravity)
{
    // These if's cause the gravity to "wrap around" at 1200 and 900
    if(gravity&gt;1200)
        gravity = 900;
    if(gravity &lt;900)
        gravity = 1200;

    int oldgrav = btm_getGravity(num);
    tiltDB[num].advData[IBEACON_GRAV_HI] = (uint8_t)((gravity &amp; 0xFF00) &gt;&gt; 8);
    tiltDB[num].advData[IBEACON_GRAV_LO] = (uint8_t)(gravity &amp; 0xFF);
    if(oldgrav != gravity)
        tiltDB[num].dirty = true;
}

void btm_setTxPower(int num, int8_t txPower)
{
    tiltDB[num].advData[IBEACON_TXPOWER] = txPower;
    tiltDB[num].dirty = true;
}</pre>
<h1>Transfer Database to Bluetooth Controller</h1>
<p>The next two functions are used to bridge between the database and the controller.  The first function &#8220;btm_setAdvPacket&#8221; probably should have been called &#8220;btm_setAdvPackets&#8221; because its function is to copy the database bytes into the controller for actual broadcast.  This function is simply a loop that looks at each of the Tilts in the database.</p>
<ol>
<li>If they are in a &#8220;slot&#8221;</li>
<li>AND they are dirty (something has been changed since the last time this was called)</li>
<li>Then copy the data into the controller</li>
<li>Set the parameters</li>
<li>Start it advertising</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// btm_setAdvPacket
//
// This function updates what the advertising packets and the state of the BT controller:
// It will loop through the table of iBeacons... then if they are in a slot &amp; they are dirty
// it will move them to the contoller and enable advertisements on that slot

void btm_setAdvPacket()
{
    static wiced_bt_ble_multi_adv_params_t myParams = {
    .adv_int_min       = BTM_BLE_ADVERT_INTERVAL_MIN,
    .adv_int_max       = 96,
    .adv_type          = MULTI_ADVERT_NONCONNECTABLE_EVENT,
    .channel_map       = BTM_BLE_ADVERT_CHNL_37 | BTM_BLE_ADVERT_CHNL_38 | BTM_BLE_ADVERT_CHNL_39,
    .adv_filter_policy = BTM_BLE_ADVERT_FILTER_ALL_CONNECTION_REQ_ALL_SCAN_REQ,
    .adv_tx_power      = MULTI_ADV_TX_POWER_MAX_INDEX,
    .peer_bd_addr      = {0},
    .peer_addr_type    = BLE_ADDR_PUBLIC,
    .own_bd_addr       = {0},
    .own_addr_type     = BLE_ADDR_PUBLIC,
    };

    for(int i=0;i&lt;NUM_TILT;i++)
    {
        if(tiltDB[i].slot &amp;&amp; tiltDB[i].dirty)
        {   
            tiltDB[i].dirty = false;
            wiced_set_multi_advertisement_data(tiltDB[i].advData,sizeof(tiltDB[i].advData),tiltDB[i].slot);
            wiced_set_multi_advertisement_params(tiltDB[i].slot,&amp;myParams);
            wiced_start_multi_advertisements( MULTI_ADVERT_START, tiltDB[i].slot );
        }
    }
}</pre>
<p>In order to &#8220;activate&#8221; a row in the database you need to assign it to a slot.  I do this by keeping track of the number of times I have assigned an entry in &#8220;btm_active&#8221; which is static to this function.  Now, shocker, I check to make sure that the caller didn&#8217;t accidentally call this before.  Finally I assign it to a slot and mark it as dirty (so that when the btm_setAdvPacket function is called the data will be put into the controller.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/* btm_activate
*
* This function will put the tilt in the database entry num
* into the next available advertising slot
*
*/
void btm_activate(int num)
{
    // Keep track of the number of currently active iBeacons
    static int  btm_active=0;
    
    CY_ASSERT(num&lt;NUM_TILT);
    if(tiltDB[num].slot == 0) // Make sure that it is not already in a slow
    {
        btm_active += 1;
        tiltDB[num].slot = btm_active;
        tiltDB[num].dirty = true;
    }
}</pre>
<h1>Command Queue</h1>
<p>The command queue is used by the command line interface to submit changes to the Tilt database.  Specifically set, update and print.  The message is just the values for set &amp; update.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/*********************************************************************************
* 
* Tilt Data Manager External Interface Queue
*
*********************************************************************************/
typedef enum {
    BTM_CMD_SET_DATA,
    BTM_CMD_PRINT_TABLE,
    BTM_CMD_SET_UPDATE,
} btm_cmd_t;

typedef struct {
    btm_cmd_t cmd;
    int num;
    int temperature;
    int gravity;
    int txPower;
} btm_cmdMsg_t;

static QueueHandle_t btm_cmdQueue=0;
static wiced_timer_ext_t btm_processDataTimer;</pre>
<p>The function to process the command queue has two functions in the systems</p>
<ol>
<li>Process commands from the command line</li>
<li>Cause the data to be updated (as configured by the command line)</li>
</ol>
<p>This function is run by a timer that is started when the Bluetooth stack turns on.  I have it set to run every 200ms.  Each time it runs it will read all of the messages in the queue and process them.  Once that is complete it will check to see if the Tilts need to be updated.</p>
<p>In my system there is a &#8220;base rate&#8221; which is set by the frequency of this function.  In other words the &#8220;count&#8221; variable counts the number of times this function has been called.  This is about &#8220;BTM_QUEUE_RATE&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/* btm_processCmdQueue
*
*  This function is called by a timer every BTM_QUEUE_RATE ms (around 200ms)
*  It processes commands from the GUI
*  It also updates the adverting packets if they are being updated at a rate
*
*/
void btm_processCmdQueue( wiced_timer_callback_arg_t cb_params )
{
    static int count = 0; // This counts the numbers of times the callback has happend

    btm_cmdMsg_t msg;
    while(xQueueReceive(btm_cmdQueue,&amp;msg,0) == pdTRUE)
    {
        switch(msg.cmd)
        {
            case BTM_CMD_SET_DATA:
                btm_setGravity(msg.num,msg.gravity);
                btm_setTemperature(msg.num,msg.temperature);
                btm_setTxPower(msg.num,msg.txPower);
                btm_activate(msg.num);
            break;

            case BTM_CMD_PRINT_TABLE:
                btm_printTable();
            break;

            case BTM_CMD_SET_UPDATE:
                tiltDB[msg.num].tempUpdate = msg.temperature;
                tiltDB[msg.num].gravUpdate = msg.gravity;
                tiltDB[msg.num].rate = msg.txPower / BTM_QUEUE_RATE;
            break;
        }
    }
    count = count + 1;

    // This block of code updates the current values with the update rate
    for(int i=0;i&lt;NUM_TILT;i++)
    {
        // If the slot active
        // and the update rate says that it is time
        if(tiltDB[i].slot &amp;&amp; count % tiltDB[i].rate  == 0)
        {
            btm_setTemperature(i,btm_getTemperature(i) + tiltDB[i].tempUpdate);
            btm_setGravity(i,btm_getGravity(i) + tiltDB[i].gravUpdate);
        }
    }
    btm_setAdvPacket();
}</pre>
<h1>Bluetooth Management</h1>
<p>When the Bluetooth Stack is turned on I need to do two things</p>
<ol>
<li>Initialize the command queue</li>
<li>Initialize a periodic timer that calls the &#8220;btm_processCmdQueue&#8221;</li>
</ol>
<p>Notice that every time something changes in the advertising packets the management callback is called with the event type &#8220;BTM_MULTI_ADVERT_RESP_EVENT&#8221;&#8230; to which I do NOTHING.  I suppose that I should check and make sure that whatever I did succeed.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data)
{
    wiced_result_t result = WICED_BT_SUCCESS;

    switch (event)
    {
        case BTM_ENABLED_EVT:
            printf("Started BT Stack Succesfully\n");
            btm_cmdQueue = xQueueCreate(10,sizeof(btm_cmdMsg_t));
            wiced_init_timer_ext(&amp;btm_processDataTimer,btm_processCmdQueue,0,WICED_TRUE);
            wiced_start_timer_ext(&amp;btm_processDataTimer,BTM_QUEUE_RATE);
        break;

        case BTM_MULTI_ADVERT_RESP_EVENT: // Do nothing...
        break;

        default:
            printf("Unhandled Bluetooth Management Event: %s\n", btutil_getBTEventName( event));
        break;
    }

    return result;
}</pre>
<h1>Public Functions</h1>
<p>In the command line I want the ability to</p>
<ol>
<li>Print</li>
<li>Configure the data in Tilt advertising packet</li>
<li>Set the update rate</li>
</ol>
<p>That is what these three functions do.  Notice that I check that the command queue has been initialized.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void btm_printTableCmd()
{
    if(btm_cmdQueue == 0)
        return;
    
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_PRINT_TABLE;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}

void btm_setDataCmd(int num,int temperature,int gravity,int txPower)
{
    if(btm_cmdQueue == 0)
        return;

    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_SET_DATA;
    msg.num = num;
    msg.temperature = temperature;
    msg.gravity = gravity;
    msg.txPower = txPower;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}


void btm_updateDataCmd(int num,int rate ,int temperature,int gravity )
{
    if(btm_cmdQueue == 0)
        return;
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_SET_UPDATE;
    msg.num = num;
    msg.temperature = temperature;
    msg.gravity = gravity;
    msg.txPower = rate;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}
</pre>
<h1>Update the Command Line</h1>
<p>In usrcmd.c I need the three functions which the command line will call.</p>
<ol>
<li>usrcmd_print &#8230; to print out the table</li>
<li>usrcmd_set to set the values in the Tilt database</li>
<li>usrcmd_update to set the update rate</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_print(int argc, char **argv)
{
    btm_printTableCmd();
    return 0;
}

static int usrcmd_set(int argc, char **argv)
{
    int gravity;
    int temperature;
    int txPower;
    int num;
    if(argc == 5)
    {
        sscanf(argv[1],"%d",&amp;num);
        sscanf(argv[2],"%d",&amp;temperature);
        sscanf(argv[3],"%d",&amp;gravity);
        sscanf(argv[4],"%d",&amp;txPower);

        btm_setDataCmd(num,temperature,gravity,txPower);
    }
    return 0;
}

static int usrcmd_update(int argc, char **argv)
{
    int gravity;
    int temperature;
    int rate;
    int num;
    if(argc == 5)
    {
        sscanf(argv[1],"%d",&amp;num);
        sscanf(argv[2],"%d",&amp;rate);
        sscanf(argv[3],"%d",&amp;temperature);
        sscanf(argv[4],"%d",&amp;gravity);

        btm_updateDataCmd(num,rate,temperature,gravity);
    }
    return 0;
}</pre>
<p>And once you have those functions you need to turn them on in the command line</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static const cmd_table_t cmdlist[] = {
    { "help", "This is a description text string for help command.", usrcmd_help },
    { "info", "This is a description text string for info command.", usrcmd_info },
    { "clear", "Clear the screen", usrcmd_clear },
    { "pargs","print the list of arguments", usrcmd_pargs},
#ifdef configUSE_TRACE_FACILITY 
#if configUSE_STATS_FORMATTING_FUNCTIONS ==1
    { "tasks","print the list of RTOS Tasks", usrcmd_list},
#endif
#endif
    { "print", "Print table", usrcmd_print },
    { "set", "set num temperature gravity txpower", usrcmd_set },
    { "update", "update num rate temperature gravity", usrcmd_update },
};</pre>
<p>In the next article I will be back to the &#8220;client&#8221; end of my system and will build a database.</p>
<h1>Full Functions</h1>
<p>Here are the full functions &amp; files.  You can also &#8220;git&#8221; this at git@github.com:iotexpert/TiltSimulator.git</p>
<ol>
<li>bluetoothManager.h</li>
<li>bluetoothManager.c</li>
<li>main.c</li>
<li>usrcmd.c</li>
</ol>
<p><strong>bluetoothManager.h</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once
#include "wiced_bt_stack.h"
#include "wiced_bt_dev.h"

wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data);
void btm_printTable();

void btm_printTableCmd();
void btm_setDataCmd(int num,int temperature,int gravity,int txPower);
void btm_updateDataCmd(int num,int rate ,int temperature,int gravity );
</pre>
<p><strong>bluetoothManager.c</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include "cybsp.h"

#include "FreeRTOS.h"

#include "bluetoothManager.h"
#include "wiced_bt_stack.h"
#include "wiced_bt_dev.h"
#include "wiced_bt_trace.h"
#include "wiced_timer.h"
#include "queue.h"
#include "btutil.h"

// Read the queue
#define BTM_QUEUE_RATE 200

/*********************************************************************************
*
* Tilt Database Definition
* 
*********************************************************************************/

#define TILT_IBEACON_HEADER_LEN 25
#define TILT_IBEACON_DATA_LEN 5
#define TILT_IBEACON_LEN (TILT_IBEACON_HEADER_LEN + TILT_IBEACON_DATA_LEN)

typedef struct  {
    char *colorName;    // The color string
    int slot;           // Which Bluetooth ADV Slot this Tilt is using
    bool dirty;         // A flag to tell if there has been a change since the adv was last written
    int rate;           // rate in ms
    int tempUpdate;     // The update rate for temperature
    int gravUpdate;     // The update rate for gravity
    uint8_t advData[TILT_IBEACON_LEN];
} tilt_t;

// 02 01 04 = Flags
// 0x1A 0xFF = Manufacturer specific data
// 0x4c 0x00 = Apple
// 0x02 = iBeacon
// 0x15 = remaining data length
#define IBEACON_HEADER 0x02,0x01,0x04,0x1A,0xFF,0x4C,0x00,0x02,0x15

static tilt_t tiltDB [] =
{
    {"Red",    0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x10,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Green" , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x20,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Black" , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x30,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Purple", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x40,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Orange", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x50,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Blue"  , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x60,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Yellow", 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x70,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
    {"Pink"  , 0, true, 0,0,0, {IBEACON_HEADER,0xA4,0x95,0xBB,0x80,0xC5,0xB1,0x4B,0x44,0xB5,0x12,0x13,0x70,0xF0,0x2D,0x74,0xDE, 0x00,0x00,0x00,0x00,0x00}},
};
#define NUM_TILT (sizeof(tiltDB)/sizeof(tilt_t))

#define IBEACON_TEMP_HI (25)
#define IBEACON_TEMP_LO (26)
#define IBEACON_GRAV_HI (27)
#define IBEACON_GRAV_LO (28)
#define IBEACON_TXPOWER (29)

/*********************************************************************************
* 
* Tilt Data Manager External Interface Queue
*
*********************************************************************************/
typedef enum {
    BTM_CMD_SET_DATA,
    BTM_CMD_PRINT_TABLE,
    BTM_CMD_SET_UPDATE,
} btm_cmd_t;

typedef struct {
    btm_cmd_t cmd;
    int num;
    int temperature;
    int gravity;
    int txPower;
} btm_cmdMsg_t;

static QueueHandle_t btm_cmdQueue=0;
static wiced_timer_ext_t btm_processDataTimer;


/*********************************************************************************
* 
* These functions are used to interact with the Bluetooth Advertising Controller
*
*********************************************************************************/
// btm_setAdvPacket
//
// This function updates what the advertising packets and the state of the BT controller:
// It will loop through the table of iBeacons... then if they are in a slot &amp; they are dirty
// it will move them to the contoller and enable advertisements on that slot

void btm_setAdvPacket()
{
    static wiced_bt_ble_multi_adv_params_t myParams = {
    .adv_int_min       = BTM_BLE_ADVERT_INTERVAL_MIN,
    .adv_int_max       = 96,
    .adv_type          = MULTI_ADVERT_NONCONNECTABLE_EVENT,
    .channel_map       = BTM_BLE_ADVERT_CHNL_37 | BTM_BLE_ADVERT_CHNL_38 | BTM_BLE_ADVERT_CHNL_39,
    .adv_filter_policy = BTM_BLE_ADVERT_FILTER_ALL_CONNECTION_REQ_ALL_SCAN_REQ,
    .adv_tx_power      = MULTI_ADV_TX_POWER_MAX_INDEX,
    .peer_bd_addr      = {0},
    .peer_addr_type    = BLE_ADDR_PUBLIC,
    .own_bd_addr       = {0},
    .own_addr_type     = BLE_ADDR_PUBLIC,
    };

    for(int i=0;i&lt;NUM_TILT;i++)
    {
        if(tiltDB[i].slot &amp;&amp; tiltDB[i].dirty)
        {   
            tiltDB[i].dirty = false;
            wiced_set_multi_advertisement_data(tiltDB[i].advData,sizeof(tiltDB[i].advData),tiltDB[i].slot);
            wiced_set_multi_advertisement_params(tiltDB[i].slot,&amp;myParams);
            wiced_start_multi_advertisements( MULTI_ADVERT_START, tiltDB[i].slot );
        }
    }
}

/* btm_activate
*
* This function will put the tilt in the database entry num
* into the next available advertising slot
*
*/
void btm_activate(int num)
{
    // Keep track of the number of currently active iBeacons
    static int  btm_active=0;
    
    CY_ASSERT(num&lt;NUM_TILT);
    if(tiltDB[num].slot == 0) // Make sure that it is not already in a slow
    {
        btm_active += 1;
        tiltDB[num].slot = btm_active;
        tiltDB[num].dirty = true;
    }
}

/*********************************************************************************
* 
* This next set of functions is the API to the database
*
*********************************************************************************/


int btm_getTemperature(int num)
{
    return (uint16_t)tiltDB[num].advData[IBEACON_TEMP_HI] &lt;&lt; 8 | tiltDB[num].advData[IBEACON_TEMP_LO];
}

void btm_setTemperature(int num,uint16_t temperature)
{
    if(temperature &gt; 150)
        temperature = 10;
    if(temperature&lt;10)
        temperature = 150;

    int oldtemp = btm_getTemperature(num);

    tiltDB[num].advData[IBEACON_TEMP_HI] = (temperature &amp; 0xFF00) &gt;&gt; 8;    
    tiltDB[num].advData[IBEACON_TEMP_LO] = temperature &amp; 0xFF;
    if(temperature != oldtemp)
        tiltDB[num].dirty = true;    
}

int btm_getGravity(int num)
{
    return (uint16_t)tiltDB[num].advData[IBEACON_GRAV_HI] &lt;&lt; 8 | tiltDB[num].advData[IBEACON_GRAV_LO];
}

void btm_setGravity(int num,uint16_t gravity)
{
    // These if's cause the gravity to "wrap around" at 1200 and 900
    if(gravity&gt;1200)
        gravity = 900;
    if(gravity &lt;900)
        gravity = 1200;

    int oldgrav = btm_getGravity(num);
    tiltDB[num].advData[IBEACON_GRAV_HI] = (uint8_t)((gravity &amp; 0xFF00) &gt;&gt; 8);
    tiltDB[num].advData[IBEACON_GRAV_LO] = (uint8_t)(gravity &amp; 0xFF);
    if(oldgrav != gravity)
        tiltDB[num].dirty = true;
}

void btm_setTxPower(int num, int8_t txPower)
{
    tiltDB[num].advData[IBEACON_TXPOWER] = txPower;
    tiltDB[num].dirty = true;
}

void btm_printTable()
{
    printf("\n# Color   S   Rate T  UpT Grav UpG TxP\n");

    for(int i=0;i&lt;NUM_TILT;i++)
    {
        printf("%d %6s  %d %5d %3d %2d %4d %2d %3d\n",i,
            tiltDB[i].colorName,tiltDB[i].slot,
            tiltDB[i].rate*BTM_QUEUE_RATE,
            btm_getTemperature(i),tiltDB[i].tempUpdate,
            btm_getGravity(i),tiltDB[i].gravUpdate,
            tiltDB[i].advData[29]);
    }
}

/* btm_processCmdQueue
*
*  This function is called by a timer every BTM_QUEUE_RATE ms (around 200ms)
*  It processes commands from the GUI
*  It also updates the adverting packets if they are being updated at a rate
*
*/
void btm_processCmdQueue( wiced_timer_callback_arg_t cb_params )
{
    static int count = 0; // This counts the numbers of times the callback has happend

    btm_cmdMsg_t msg;
    while(xQueueReceive(btm_cmdQueue,&amp;msg,0) == pdTRUE)
    {
        switch(msg.cmd)
        {
            case BTM_CMD_SET_DATA:
                btm_setGravity(msg.num,msg.gravity);
                btm_setTemperature(msg.num,msg.temperature);
                btm_setTxPower(msg.num,msg.txPower);
                btm_activate(msg.num);
            break;

            case BTM_CMD_PRINT_TABLE:
                btm_printTable();
            break;

            case BTM_CMD_SET_UPDATE:
                tiltDB[msg.num].tempUpdate = msg.temperature;
                tiltDB[msg.num].gravUpdate = msg.gravity;
                tiltDB[msg.num].rate = msg.txPower / BTM_QUEUE_RATE;
            break;
        }
    }
    count = count + 1;

    // This block of code updates the current values with the update rate
    for(int i=0;i&lt;NUM_TILT;i++)
    {
        // If the slot active
        // and the update rate says that it is time
        if(tiltDB[i].slot &amp;&amp; count % tiltDB[i].rate  == 0)
        {
            btm_setTemperature(i,btm_getTemperature(i) + tiltDB[i].tempUpdate);
            btm_setGravity(i,btm_getGravity(i) + tiltDB[i].gravUpdate);
        }
    }
    btm_setAdvPacket();
}

/**************************************************************************************************
* Function Name: app_bt_management_callback()
***************************************************************************************************
* Summary:
*   This is a Bluetooth stack event handler function to receive management events from
*   the BLE stack and process as per the application.
*
* Parameters:
*   wiced_bt_management_evt_t event             : BLE event code of one byte length
*   wiced_bt_management_evt_data_t *p_event_data: Pointer to BLE management event structures
*
* Return:
*  wiced_result_t: Error code from WICED_RESULT_LIST or BT_RESULT_LIST
*
*************************************************************************************************/
wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data)
{
    wiced_result_t result = WICED_BT_SUCCESS;

    switch (event)
    {
        case BTM_ENABLED_EVT:
            printf("Started BT Stack Succesfully\n");
            btm_cmdQueue = xQueueCreate(10,sizeof(btm_cmdMsg_t));
            wiced_init_timer_ext(&amp;btm_processDataTimer,btm_processCmdQueue,0,WICED_TRUE);
            wiced_start_timer_ext(&amp;btm_processDataTimer,BTM_QUEUE_RATE);
        break;

        case BTM_MULTI_ADVERT_RESP_EVENT: // Do nothing...
        break;

        default:
            printf("Unhandled Bluetooth Management Event: %s\n", btutil_getBTEventName( event));
        break;
    }

    return result;
}

/*********************************************************************************
* 
* These are publicly callable functions to cause actions by the bluetooth manager
* These are called by the GUI
*
*********************************************************************************/

void btm_printTableCmd()
{
    if(btm_cmdQueue == 0)
        return;
    
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_PRINT_TABLE;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}

void btm_setDataCmd(int num,int temperature,int gravity,int txPower)
{
    if(btm_cmdQueue == 0)
        return;

    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_SET_DATA;
    msg.num = num;
    msg.temperature = temperature;
    msg.gravity = gravity;
    msg.txPower = txPower;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}


void btm_updateDataCmd(int num,int rate ,int temperature,int gravity )
{
    if(btm_cmdQueue == 0)
        return;
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_SET_UPDATE;
    msg.num = num;
    msg.temperature = temperature;
    msg.gravity = gravity;
    msg.txPower = rate;
    xQueueSend(btm_cmdQueue,&amp;msg,0);
}
</pre>
<p>&nbsp;</p>
<p><strong>main.c</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include &lt;stdio.h&gt;
#include "FreeRTOS.h"
#include "task.h"
#include "usrcmd.h"

#include "bluetoothManager.h"
#include "cycfg_bt_settings.h"
#include "bt_platform_cfg_settings.h"

volatile int uxTopUsedPriority ;
TaskHandle_t blinkTaskHandle;


void blink_task(void *arg)
{
    cyhal_gpio_init(CYBSP_USER_LED,CYHAL_GPIO_DIR_OUTPUT,CYHAL_GPIO_DRIVE_STRONG,0);

    for(;;)
    {
    	cyhal_gpio_toggle(CYBSP_USER_LED);
    	vTaskDelay(500);
    }
}


int main(void)
{
    uxTopUsedPriority = configMAX_PRIORITIES - 1 ; // enable OpenOCD Thread Debugging

    /* Initialize the device and board peripherals */
    cybsp_init() ;
    __enable_irq();

    cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);



    cybt_platform_config_init(&amp;bt_platform_cfg_settings);
    wiced_bt_stack_init (app_bt_management_callback, &amp;wiced_bt_cfg_settings);

    // Stack size in WORDs
    // Idle task = priority 0
    xTaskCreate(blink_task, "blinkTask", configMINIMAL_STACK_SIZE,0 /* args */ ,0 /* priority */, &amp;blinkTaskHandle);
    xTaskCreate(usrcmd_task, "usrcmd_task", configMINIMAL_STACK_SIZE*4,0 /* args */ ,0 /* priority */, 0);
    vTaskStartScheduler();
}

/* [] END OF FILE */
</pre>
<p>&nbsp;</p>
<p><strong>usrcmd.c</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/**
 * @file usrcmd.c
 * @author CuBeatSystems
 * @author Shinichiro Nakamura
 * @copyright
 * ===============================================================
 * Natural Tiny Shell (NT-Shell) Version 0.3.1
 * ===============================================================
 * Copyright (c) 2010-2016 Shinichiro Nakamura
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */


#include "ntopt.h"
#include "ntlibc.h"
#include "ntshell.h"
#include &lt;stdio.h&gt;

#include "ntshell.h"
#include "ntlibc.h"
#include "psoc6_ntshell_port.h"

#include "FreeRTOS.h"
#include "task.h"
#include "bluetoothManager.h"

static ntshell_t ntshell;

typedef int (*USRCMDFUNC)(int argc, char **argv);

static int usrcmd_ntopt_callback(int argc, char **argv, void *extobj);
static int usrcmd_help(int argc, char **argv);
static int usrcmd_info(int argc, char **argv);
static int usrcmd_clear(int argc, char **argv);
static int usrcmd_pargs(int argc, char **argv);
#ifdef configUSE_TRACE_FACILITY
#if configUSE_STATS_FORMATTING_FUNCTIONS ==1
static int usrcmd_list(int argc, char **argv);
#endif
#endif
static int usrcmd_print(int argc, char **argv);
static int usrcmd_set(int argc, char **argv);
static int usrcmd_update(int argc, char **argv);

typedef struct {
    char *cmd;
    char *desc;
    USRCMDFUNC func;
} cmd_table_t;

static const cmd_table_t cmdlist[] = {
    { "help", "This is a description text string for help command.", usrcmd_help },
    { "info", "This is a description text string for info command.", usrcmd_info },
    { "clear", "Clear the screen", usrcmd_clear },
    { "pargs","print the list of arguments", usrcmd_pargs},
#ifdef configUSE_TRACE_FACILITY 
#if configUSE_STATS_FORMATTING_FUNCTIONS ==1
    { "tasks","print the list of RTOS Tasks", usrcmd_list},
#endif
#endif
    { "print", "Print table", usrcmd_print },
    { "set", "set num temperature gravity txpower", usrcmd_set },
    { "update", "update num temperature gravity", usrcmd_update },
};


void usrcmd_task()
{

  setvbuf(stdin, NULL, _IONBF, 0);
  printf("Started user command task with NT Shell\n");
  ntshell_init(
	       &amp;ntshell,
	       ntshell_read,
	       ntshell_write,
	       ntshell_callback,
	       (void *)&amp;ntshell);
  ntshell_set_prompt(&amp;ntshell, "AnyCloud&gt; ");
  vtsend_erase_display(&amp;ntshell.vtsend);
  ntshell_execute(&amp;ntshell);
}

int usrcmd_execute(const char *text)
{
    return ntopt_parse(text, usrcmd_ntopt_callback, 0);
}

static int usrcmd_ntopt_callback(int argc, char **argv, void *extobj)
{
    if (argc == 0) {
        return 0;
    }
    const cmd_table_t *p = &amp;cmdlist[0];
    for (unsigned int i = 0; i &lt; sizeof(cmdlist) / sizeof(cmdlist[0]); i++) {
        if (ntlibc_strcmp((const char *)argv[0], p-&gt;cmd) == 0) {
            return p-&gt;func(argc, argv);
        }
        p++;
    }
    printf("%s","Unknown command found.\n");
    return 0;
}

static int usrcmd_help(int argc, char **argv)
{
    const cmd_table_t *p = &amp;cmdlist[0];
    for (unsigned int i = 0; i &lt; sizeof(cmdlist) / sizeof(cmdlist[0]); i++) {
        printf("%s",p-&gt;cmd);
        printf("%s","\t:");
        printf("%s",p-&gt;desc);
        printf("%s","\n");
        p++;
    }
    return 0;
}


static int usrcmd_info(int argc, char **argv)
{
    if (argc != 2) {
        printf("%s","info sys\n");
        printf("%s","info ver\n");
        return 0;
    }
    if (ntlibc_strcmp(argv[1], "sys") == 0) {
        printf("%s","PSoC 6 MBED Monitor\n");
        return 0;
    }
    if (ntlibc_strcmp(argv[1], "ver") == 0) {
        printf("%s","Version 0.0.0\n");
        return 0;
    }
    printf("%s","Unknown sub command found\n");
    return -1;
}


static int usrcmd_clear(int argc, char **argv)
{
    vtsend_erase_display_home(&amp;ntshell.vtsend);
    return 0;
}

static int usrcmd_pargs(int argc, char **argv)
{
    printf("ARGC = %d\n",argc);

    for(int i =0;i&lt;argc;i++)
    {
        printf("argv[%d] = %s\n",i,argv[i]);
    }
    return 0;

}

#ifdef configUSE_TRACE_FACILITY
#if configUSE_STATS_FORMATTING_FUNCTIONS ==1
static int usrcmd_list(int argc,char **argv)
{
    // 40 bytes/task + some margin
    char buff[40*10 + 100];

    vTaskList( buff );
    printf("Name          State Priority   Stack  Num\n");
    printf("------------------------------------------\n");
    printf("%s",buff);

    printf("‘B’ – Blocked\n‘R’ – Ready\n‘D’ – Deleted (waiting clean up)\n‘S’ – Suspended, or Blocked without a timeout\n");
    printf("Stack = bytes free at highwater\n");
    return 0;
}
#endif
#endif


static int usrcmd_print(int argc, char **argv)
{
    btm_printTableCmd();
    return 0;
}

static int usrcmd_set(int argc, char **argv)
{
    int gravity;
    int temperature;
    int txPower;
    int num;
    if(argc == 5)
    {
        sscanf(argv[1],"%d",&amp;num);
        sscanf(argv[2],"%d",&amp;temperature);
        sscanf(argv[3],"%d",&amp;gravity);
        sscanf(argv[4],"%d",&amp;txPower);

        btm_setDataCmd(num,temperature,gravity,txPower);
    }
    return 0;
}

static int usrcmd_update(int argc, char **argv)
{
    int gravity;
    int temperature;
    int rate;
    int num;
    if(argc == 5)
    {
        sscanf(argv[1],"%d",&amp;num);
        sscanf(argv[2],"%d",&amp;rate);
        sscanf(argv[3],"%d",&amp;temperature);
        sscanf(argv[4],"%d",&amp;gravity);

        btm_updateDataCmd(num,rate,temperature,gravity);
    }
    return 0;
}
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/tilt-hydrometer-part-5-tilt-simulator-multi-advertising-ibeacons/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>I2C Detect with PSoC 6</title>
		<link>https://iotexpert.com/i2c-detect-with-psoc-6/</link>
					<comments>https://iotexpert.com/i2c-detect-with-psoc-6/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 05 Aug 2019 12:30:10 +0000</pubDate>
				<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=7642</guid>

					<description><![CDATA[Summary In this article I explain how to use a PSoC 6 SCB to implement I2C Detect. Recently,  I wrote about using the Raspberry PI I2C bus master to talk to a PSoC 4 I2C Slave.  In that project I used a program on the Raspberry Pi called &#8220;I2CDetect&#8221; which probes the I2C bus and [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I explain how to use a PSoC 6 SCB to implement I2C Detect.</p>
<p>Recently,  I wrote about using the Raspberry PI I2C bus master to talk to a PSoC 4 I2C Slave.  In that project I used a program on the Raspberry Pi called &#8220;I2CDetect&#8221; which probes the I2C bus and prints out devices that are attached.  Here is what the output looks like:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">pi@iotexpertpi:~/pyGetData $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- 08 -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@iotexpertpi:~/pyGetData $ 
</pre>
<p>You can do this same thing by using the bridge control panel (which comes as part of PSoC Creator).  I have used this program a bunch of times on this blog and you can search for all of those <a href="https://iotexpert.com/?s=bridge+control+panel" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p><a href="https://iotexpert.com/?attachment_id=7640" 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>But how does it work?  Simple, it uses the I2C bus master to iterate through all of the addresses 0-0x7F and</p>
<ul>
<li>Send a start</li>
<li>Send the address</li>
<li>Send a write</li>
<li>If you get ACK print out the address</li>
<li>If you get a NAK print out &#8212;</li>
<li>Send a stop</li>
</ul>
<p>You can easily do this using the PSoC 6 (or 4) Serial Communication Block.  Here is an implementation in Modus Toolbox 1.1 where I</p>
<ol>
<li>Create the project and configure the middleware</li>
<li>Implement probe</li>
<li>Implement the main loop</li>
<li>Test</li>
</ol>
<h1>Create the Project, Configure the Hardware and Middleware</h1>
<p>Start by creating a new project.  In this case I have a CY8CKIT_062_WIFI_BT.  But this will work on any PSoC6s.</p>
<p><a href="https://iotexpert.com/?attachment_id=7649" rel="attachment wp-att-7649"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM-1024x667.png" alt="" width="1024" height="667" class="alignnone size-large wp-image-7649" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM-1024x667.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM-600x391.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM-300x195.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM-768x500.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.37-AM.png 1842w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I just start with the empty project.</p>
<p><a href="https://iotexpert.com/?attachment_id=7650" rel="attachment wp-att-7650"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM-1024x668.png" alt="" width="1024" height="668" class="alignnone size-large wp-image-7650" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM-1024x668.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM-600x392.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM-300x196.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM-768x501.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.39.59-AM.png 1842w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/?attachment_id=7651" rel="attachment wp-att-7651"></a></p>
<p>Click Finish to make the project.</p>
<p><a href="https://iotexpert.com/?attachment_id=7651" rel="attachment wp-att-7651"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM-1024x667.png" alt="" width="1024" height="667" class="alignnone size-large wp-image-7651" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM-1024x667.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM-600x391.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM-300x195.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM-768x500.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.09-AM.png 1834w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Double click on the &#8220;design.modus&#8221; or click &#8220;Configure Device&#8221; from the quick panel.</p>
<p><a href="https://iotexpert.com/?attachment_id=7661" rel="attachment wp-att-7661"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM.png" alt="" width="832" height="288" class="alignnone size-full wp-image-7661" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM.png 832w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-600x208.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-300x104.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-768x266.png 768w" sizes="(max-width: 832px) 100vw, 832px" /></a></p>
<p>Here is the design.modus</p>
<p><a href="https://iotexpert.com/?attachment_id=7662" rel="attachment wp-att-7662"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.45-AM.png" alt="" width="850" height="456" class="alignnone size-large wp-image-7662" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.45-AM.png 850w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.45-AM-600x322.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.45-AM-300x161.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.45-AM-768x412.png 768w" sizes="(max-width: 850px) 100vw, 850px" /></a></p>
<p>When the configurator starts you need to enable the SCB that is connected to the Kitprog bridge.  You can figure this out by looking on the back of your development kit where there is a little table.  In the picture below you can see that the UART is connected to P5.0 and P5.1</p>
<p><a href="https://iotexpert.com/?attachment_id=7663" rel="attachment wp-att-7663"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760-1024x915.jpg" alt="" width="1024" height="915" class="alignnone size-large wp-image-7663" srcset="https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760-1024x915.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760-600x536.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760-300x268.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760-768x686.jpg 768w, https://iotexpert.com/wp-content/uploads/2019/07/IMG_0760.jpg 1855w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Which SCB is P5.0/P5.1 connected to?  The answer is SCB5.  But how do you figure that out?  Click on the Pins table.  Then select P5[0] and then Digital In/Out and you can see that the SCB 5 UART RX is attached to that pin.</p>
<p><a href="https://iotexpert.com/?attachment_id=7664" rel="attachment wp-att-7664"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-1024x1014.png" alt="" width="1024" height="1014" class="alignnone size-large wp-image-7664" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-1024x1014.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-600x594.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-150x150.png 150w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-300x297.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM-768x760.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.08.41-AM.png 1420w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Cancel that and go to SCB 5.  Enable it.  Select the UART personality.  Give it the name &#8220;STDIO&#8221;.  Pick a clock divider (in this case I picked 1&#8230; but it doesn&#8217;t matter as the configurator will pick the right divide value).  Then pick the Rx/Tx to be P5[0] and P5[1]</p>
<p><a href="https://iotexpert.com/?attachment_id=7652" rel="attachment wp-att-7652"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM-850x1024.png" alt="" width="850" height="1024" class="alignnone size-large wp-image-7652" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM-850x1024.png 850w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM-600x723.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM-249x300.png 249w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM-768x925.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.40.56-AM.png 1532w" sizes="(max-width: 850px) 100vw, 850px" /></a></p>
<p>Next you need to turn on the I2C Master.  On my board the SCB bus that I want to use is connected to P6[0] P6[1].  The bus I want is the standard Arduino I2C pins.  I can see that from the back of the development kit (just like above).  These pins are connected to SCB3 (which I figured out just like I did with the UART).</p>
<p>Enable SCB3. Select the I2C personality.  Give it the name I2CBUS. Select Master. Make it 400kbs.  Assign a clock divider (in this case 0).  Assign the SCL and SDA pins to P6[0] and P6[1]</p>
<p><a href="https://iotexpert.com/?attachment_id=7654" rel="attachment wp-att-7654"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM-935x1024.png" alt="" width="935" height="1024" class="alignnone size-large wp-image-7654" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM-935x1024.png 935w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM-600x657.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM-274x300.png 274w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM-768x841.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.42.41-AM.png 1538w" sizes="(max-width: 935px) 100vw, 935px" /></a></p>
<p>Hit save.</p>
<p>For this example I want to be able to use printf.  So I right click on the &#8220;Select Middleware&#8221; from the quick panel.</p>
<p><a href="https://iotexpert.com/?attachment_id=7661" rel="attachment wp-att-7661"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM.png" alt="" width="832" height="288" class="alignnone size-full wp-image-7661" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM.png 832w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-600x208.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-300x104.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.03.53-AM-768x266.png 768w" sizes="(max-width: 832px) 100vw, 832px" /></a></p>
<p>Then I add &#8220;Retarget I/O&#8221;.</p>
<p><a href="https://iotexpert.com/?attachment_id=7665" rel="attachment wp-att-7665"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM-1024x984.png" alt="" width="1024" height="984" class="alignnone size-large wp-image-7665" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM-1024x984.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM-600x577.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM-300x288.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM-768x738.png 768w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-9.35.24-AM.png 1708w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Once that is done you will have &#8220;stdio_user.h&#8221; and &#8220;stdio_user.c&#8221; in your Source directory:</p>
<p><a href="https://iotexpert.com/?attachment_id=7666" rel="attachment wp-att-7666"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.17.43-AM.png" alt="" width="834" height="550" class="alignnone size-full wp-image-7666" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.17.43-AM.png 834w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.17.43-AM-600x396.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.17.43-AM-300x198.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.17.43-AM-768x506.png 768w" sizes="(max-width: 834px) 100vw, 834px" /></a></p>
<p>In order to turn on printf you need to modify stdio_user.h so that it uses the right SCB for printing.  But what is that SCB?  Simple we called it &#8220;STDIO&#8221; in the configurator.  Here is the change you need to make:</p>
<pre class="start-line:171 EnlighterJSRAW" data-enlighter-language="c" ">#include "cy_device_headers.h"
#include "cycfg.h"

/* Must remain uncommented to use this utility */
#define IO_STDOUT_ENABLE
#define IO_STDIN_ENABLE
#define IO_STDOUT_UART      STDIO_HW
#define IO_STDIN_UART       STDIO_HW</pre>
<p>Edit main.c.  Add a function called &#8220;probe&#8221; which will</p>
<ol>
<li>Print a header (line 15-19)</li>
<li>Iterate through all of the addresses (line 22)</li>
<li>If you have hit the end of a line setup the next line (lines 24-25)</li>
<li>Send a start and write (line 27)</li>
<li>If you get a CY_SCB_SUCCESS then print the address (line 30)</li>
<li>Otherwise print a &#8220;&#8211;&#8221; (line 34)</li>
</ol>
<pre class="start-line:9 lang:c decode:true">// Print the probe table
void probe()
{
	uint32_t rval;

	// Setup the screen and print the header
	printf("\n\n   ");
	for(unsigned int i=0;i&lt;0x10;i++)
	{
		printf("%02X ",i);
	}

	// Iterate through the address starting at 0x00
	for(uint32_t i2caddress=0;i2caddress&lt;0x80;i2caddress++)
	{
		if(i2caddress % 0x10 == 0 )
			printf("\n%02X ",(unsigned int)i2caddress);

		rval = Cy_SCB_I2C_MasterSendStart(I2CBUS_HW,i2caddress,CY_SCB_I2C_WRITE_XFER,10,&amp;I2CBUS_context);
		if(rval == CY_SCB_I2C_SUCCESS ) // If you get ACK then print the address
		{
			printf("%02X ",(unsigned int)i2caddress);
		}
		else //  Otherwise print a --
		{
			printf("-- ");
		}
		Cy_SCB_I2C_MasterSendStop(I2CBUS_HW,0,&amp;I2CBUS_context);
	}
	printf("\n");
}
</pre>
<p>For all of this to work you need to have two context global variables which are used by PDL to save state.</p>
<pre class="start-line:5 EnlighterJSRAW" data-enlighter-language="c"">cy_stc_scb_uart_context_t STDIO_context;
cy_stc_scb_i2c_context_t I2CBUS_context;</pre>
<p>Create a main function to:</p>
<ul>
<li>initialize the two SCBs 45-50</li>
<li>The API call setvbuf on line 47 just turns off buffering on stdin so that every character will come directly to getc</li>
<li>print the header (line 54-56)</li>
<li>the clear screen line just send the VT100 escape sequence to clear the screen and go home.  Almost all terminal programs are essentially VT100 emulators.</li>
<li>run the probe one time (line 57)</li>
<li>go into an infinite loop looking for key presses (line 59-61)</li>
<li>if they press &#8216;p&#8217; then call the probe function (line 64)</li>
<li>if they press &#8216;?&#8217; then printout help (line 69)</li>
</ul>
<pre class="start-line:40 EnlighterJSRAW" data-enlighter-language="c"">int main(void)
{
    /* Set up the device based on configurator selections */
    init_cycfg_all();

    Cy_SCB_UART_Init(STDIO_HW,&amp;STDIO_config,&amp;STDIO_context);
    Cy_SCB_UART_Enable(STDIO_HW);
    setvbuf( stdin, NULL, _IONBF, 0 ); // Turn off stdin buffering

    Cy_SCB_I2C_Init(I2CBUS_HW,&amp;I2CBUS_config,&amp;I2CBUS_context);
    Cy_SCB_I2C_Enable(I2CBUS_HW);

    __enable_irq();

    printf("\033[2J\033[H"); // clear the screen
    printf("I2C Detect\n");
    printf("Press p for probe, ? for help\n");
    probe(); // Do an initial probe

    while(1)
    {
    		char c = getchar();
    		switch(c)
    		{
    		case 'p':
			probe();
    		break;
    		case '?':
    			printf("------------------\n");
			printf("Command\n");
    			printf("p\tProbe\n");
    			printf("?\tHelp\n");

    			break;
    		}

    }
}
</pre>
<p>Once I program this I get a nice output.  Notice that these are all 7-bit addresses.</p>
<p><a href="https://iotexpert.com/?attachment_id=7658" 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>If I connect a logic analyzer you can see the bus behavior.  Start with a bunch of 0 &#8211; nak, 1-nak &#8230;.</p>
<p><a href="https://iotexpert.com/?attachment_id=7671" rel="attachment wp-att-7671"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.41.41-AM-1024x622.png" alt="" width="1024" height="622" class="alignnone size-large wp-image-7671" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.41.41-AM-1024x622.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.41.41-AM-600x364.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.41.41-AM-300x182.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.41.41-AM-768x466.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>until finally it hits 3C when it get an ACK</p>
<p><a href="https://iotexpert.com/?attachment_id=7672" rel="attachment wp-att-7672"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.42.09-AM-1024x623.png" alt="" width="1024" height="623" class="alignnone size-large wp-image-7672" srcset="https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.42.09-AM-1024x623.png 1024w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.42.09-AM-600x365.png 600w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.42.09-AM-300x182.png 300w, https://iotexpert.com/wp-content/uploads/2019/07/Screen-Shot-2019-07-28-at-11.42.09-AM-768x467.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is the whole program</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#include "cy_device_headers.h"
#include "cycfg.h"
#include &lt;stdio.h&gt;

cy_stc_scb_uart_context_t STDIO_context;
cy_stc_scb_i2c_context_t I2CBUS_context;

// Print the probe table
void probe()
{
	uint32_t rval;

	// Setup the screen and print the header
	printf("\n\n   ");
	for(unsigned int i=0;i&lt;0x10;i++)
	{
		printf("%02X ",i);
	}

	// Iterate through the address starting at 0x00
	for(uint32_t i2caddress=0;i2caddress&lt;0x80;i2caddress++)
	{
		if(i2caddress % 0x10 == 0 )
			printf("\n%02X ",(unsigned int)i2caddress);

		rval = Cy_SCB_I2C_MasterSendStart(I2CBUS_HW,i2caddress,CY_SCB_I2C_WRITE_XFER,10,&amp;I2CBUS_context);
		if(rval == CY_SCB_I2C_SUCCESS ) // If you get ACK then print the address
		{
			printf("%02X ",(unsigned int)i2caddress);
		}
		else //  Otherwise print a --
		{
			printf("-- ");
		}
		Cy_SCB_I2C_MasterSendStop(I2CBUS_HW,0,&amp;I2CBUS_context);
	}
	printf("\n");
}

int main(void)
{
    /* Set up the device based on configurator selections */
    init_cycfg_all();

    Cy_SCB_UART_Init(STDIO_HW,&amp;STDIO_config,&amp;STDIO_context);
    Cy_SCB_UART_Enable(STDIO_HW);
    setvbuf( stdin, NULL, _IONBF, 0 ); // Turn off stdin buffering

    Cy_SCB_I2C_Init(I2CBUS_HW,&amp;I2CBUS_config,&amp;I2CBUS_context);
    Cy_SCB_I2C_Enable(I2CBUS_HW);

    __enable_irq();

    printf("\033[2J\033[H"); // clear the screen
    printf("I2C Detect\n");
    printf("Press p for probe, ? for help\n");
    probe(); // Do an initial probe

    while(1)
    {
    		char c = getchar();
    		switch(c)
    		{
    		case 'p':
			probe();
    		break;
    		case '?':
    			printf("------------------\n");
			printf("Command\n");
    			printf("p\tProbe\n");
    			printf("?\tHelp\n");

    			break;
    		}

    }
}
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/i2c-detect-with-psoc-6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mouser Bluetooth Mesh: L5 Bluetooth Mesh Fundamentals</title>
		<link>https://iotexpert.com/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/</link>
					<comments>https://iotexpert.com/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Wed, 29 May 2019 11:37:59 +0000</pubDate>
				<category><![CDATA[CYBT-213043-MESH]]></category>
		<category><![CDATA[CYW20819]]></category>
		<category><![CDATA[Mouser Bluetooth Mesh]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=6984</guid>

					<description><![CDATA[Summary This lesson walks you through the fundamentals of Bluetooth Mesh Networking.  There is actually quite a bit going on from a detail standpoint to make Bluetooth Mesh work as documented in the 713 pages of Bluetooth Mesh specifications: Bluetooth Mesh Profile (333 pages) Bluetooth Mesh Model (317 pages) Bluetooth Device Properties (63 Pages). However, Cypress [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span><h1>How To Design With Bluetooth Mesh</h1>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >#</th>
<th >Lesson</th>
</tr>
</thead>
<tbody>
<tr><td >0</td>
<td ><a href="https://iotexpert.com/2019/05/25/mouser-bluetooth-mesh-l0-introduction/" target="_blank" rel="noopener">Introduction</a></td>
</tr>

<tr><td >1</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l1-developer-resources/" target="_blank" rel="noopener">Developer Resources</a></td>
</tr>

<tr><td >2a</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l2a-using-the-cybt-213043-mesh-building-a-mesh-network-using-the-mesh-lighting-app/" target="_blank" rel="noopener">Using the CYBT-213043-MESH &amp; Building a Mesh Network Using the Mesh Lighting App</a></td>
</tr>

<tr><td >2b</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l2b-building-a-mesh-network-using-the-mesh-client/" target="_blank" rel="noopener">Building a Mesh Network Using the Mesh Client</a></td>
</tr>

<tr><td >3</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l3-making-a-light-switch-using-the-example-code/" target="_blank" rel="noopener">Making a Light Switch Using the Example Code</a></td>
</tr>

<tr><td >4</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l4-integrating-the-modus-toolbox-code-examples/" target="_blank" rel="noopener">Integrating the Modus Toolbox Code Examples</a></td>
</tr>

<tr><td >5</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/" target="_blank" rel="noopener">Bluetooth Mesh Fundamentals</a></td>
</tr>

<tr><td >6</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l6-the-dimmable-light-code/" target="_blank" rel="noopener">The Dimmable Light Code</a></td>
</tr>

<tr><td >7</td>
<td ><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l7-modifying-the-dimmable-light-code-to-add-another-light-element/">Modifying the Dimmable Light Code to Add Another Light Element</a></td>
</tr>
</tbody></table></div><br />You can "git" a workspace will all of these files at https://github.com/iotexpert/MouserVTWBluetoothMesh or git@github.com:iotexpert/MouserVTWBluetoothMesh.git</p></span></p>
<h1>Summary</h1>
<p>This lesson walks you through the fundamentals of Bluetooth Mesh Networking.  There is actually quite a bit going on from a detail standpoint to make Bluetooth Mesh work as documented in the 713 pages of <a href="https://www.bluetooth.com/specifications/mesh-specifications/" target="_blank" rel="noopener noreferrer">Bluetooth Mesh specifications</a>:</p>
<ul>
<li><a href="https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457092" target="_blank" rel="noopener noreferrer">Bluetooth Mesh Profile</a> (333 pages)</li>
<li><a href="https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457091" target="_blank" rel="noopener noreferrer">Bluetooth Mesh Model</a> (317 pages)</li>
<li><a href="https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=429635" target="_blank" rel="noopener noreferrer">Bluetooth Device Properties</a> (63 Pages).</li>
</ul>
<p>However, Cypress has abstracted a significant amount of this complexity into our stack so as to ease your journey.</p>
<p>Specifically in this lesson we will talk about:</p>
<ol>
<li>Topology</li>
<li>Elements</li>
<li>Addressing</li>
<li>Messaging</li>
<li>Subscribe &amp; Publish</li>
<li>Models</li>
<li>State</li>
<li>Complexity</li>
<li>Security</li>
<li>Provisioning &amp; Configuration</li>
<li>Bluetooth Mesh Stack</li>
</ol>
<h1>Bluetooth Mesh Topology</h1>
<p>Let&#8217;s start by examining a prototypical Bluetooth Mesh network:</p>
<p>&nbsp;</p>
<div class="page" title="Page 5"><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/mesh-arch/" rel="attachment wp-att-7211"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/05/mesh-arch.png" alt="" width="862" height="775" class="alignnone size-full wp-image-7211" srcset="https://iotexpert.com/wp-content/uploads/2019/05/mesh-arch.png 862w, https://iotexpert.com/wp-content/uploads/2019/05/mesh-arch-600x539.png 600w, https://iotexpert.com/wp-content/uploads/2019/05/mesh-arch-300x270.png 300w, https://iotexpert.com/wp-content/uploads/2019/05/mesh-arch-768x690.png 768w" sizes="(max-width: 862px) 100vw, 862px" /></a></div>
<div title="Page 5"><strong>Standard Node</strong><br />
The standard node functionality involves sending and receiving mesh messages. Every node in the network must be able to act as a standard node.<br />
<strong>Relay Node</strong><br />
Relay nodes can receive a message for the network and then retransmit it to other devices in range. This is the method by which mesh networks can cover larger distances than the range of any single device. For a network to operate, every node must be within range of at least one relay so that its messages can be forwarded on to nodes that it cannot directly communicate with.<br />
It is common for all except low power nodes to implement a relay feature in order to maximize the possible paths through a mesh network.</div>
<div title="Page 5">Relay nodes keep a cache of messages to prevent messages from cycling.  Each mesh message also has a TTL (time to live) to prevent cycling.<br />
<strong>GATT Proxy Node</strong><br />
Many existing BLE devices support traditional BLE GATT communication but not mesh communication. Most smartphones and tablets fall into this category. Since you may want to interact with a mesh network from one of those devices, the GATT proxy was created. A GATT proxy node has both a mesh interface and a GATT interface. The GATT interface is used to communicate with BLE devices that don&#8217;t possess a mesh stack and then relay those messages to/from the mesh network. That is, the GATT proxy acts as a bridge between the mesh network and the traditional BLE GATT device.<br />
<strong>Friend and Low Power Nodes</strong><br />
Friend and Low Power Nodes are used to optimize power consumption for constrained devices. Devices that are power constrained (e.g. a battery powered device) are designated as low power nodes. Every low power node in the network must be associated with exactly one friend node. Friend nodes are devices which are not power constrained (e.g. a device plugged into AC power) that support 1 or more low power nodes depending on its capabilities (e.g. available RAM).<br />
When a low power node is added to a mesh network it broadcasts a request for a friend. Each friend in range that can handle a new low power node replies and the low power node selects the best friend based on how many messages the friend can store; the RSSI and the timing accuracy.<br />
Once the relationship is established, the friend node will receive and store messages for any low power nodes that it is associated with. The low power node will periodically ask the friend node for any messages that the friend has stored for it. In this way, the low power node does not need to listen continuously for mesh packets. Instead, it can be in a low power mode most of the time and can wake up only periodically for a very short time.<br />
For example, consider a battery powered mesh connected thermostat. It will measure the actual temperature and may publish a mesh message with the temperature once per minute. This can be done with very low power consumption since the device can be sleeping all the time except for a short period each minute to send the value. However, it must also be possible to change the set point of the thermostat. In this case, instead of sending messages, the thermostat must be listening for messages. If it listens constantly for messages the power consumption will be unacceptably high, but if it only listens occasionally for messages it will likely miss messages. By making the thermostat a low power node we get the best of both worlds &#8211; it can send messages once a minute and receive any stored messages regarding the set point from its friend node. No messages are missed even though the thermostat is awake only a very small percentage of the time.</div>
<h1 title="Page 5">Bluetooth Mesh Elements</h1>
<p>An Element is just a &#8220;Thing&#8221; in the network.  For instance a light bulb or a light switch or a temperature sensor.  A physical node can be built up of multiple elements.  Think of a ceiling fan that also has a light bulb.</p>
<p>Each Element in the network will have an address and be uniquely addressable.  This means that a Node may have multiple Bluetooth Mesh addresses, but it will have only one Bluetooth MAC address.</p>
<h1>Bluetooth Mesh Addressing</h1>
<p>Mesh messages have a source address and a destination address. Both addresses are 16-bit values. There are three types of addresses defined for messages. They are:<br />
1. Unicast<br />
2. Group<br />
3. Virtual</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Address Type</th>
<th >Address Range</th>
<th >Number of Addresses</th>
</tr>
</thead>
<tbody>
<tr><td >Unassigned</td>
<td >0b0000000000000000</td>
<td >1</td>
</tr>

<tr><td >Unicast</td>
<td >0b0xxxxxxxxxxxxxxx</td>
<td >32767</td>
</tr>

<tr><td >Group</td>
<td >0b11xxxxxxxxxxxxxx</td>
<td >16384</td>
</tr>

<tr><td >Virtual</td>
<td >0b10xxxxxxxxxxxxxx</td>
<td >16384 hash values</td>
</tr>
</tbody></table></div>
<p><strong>Unicast</strong><br />
A unicast address is used to communicate with a single element in a single node. Each element in a network must have a unicast address that is unique to that network. During provisioning, the primary element in a node is assigned a unique unicast address and each additional element in the node uses the next address.<br />
The source address in any message must be a unicast address. That is, the message must specify the specific element that message was sent by. Group and Virtual addresses are not allowed as the source address.</p>
<p><strong>Group</strong><br />
As the name implies, a group address is used to communicate with one or more elements. Group addresses are either defined by the Bluetooth SIG (known as fixed group addresses) or are assigned dynamically for a given mesh network. There are 16K total group addresses available. The SIG has reserved space for 256 of them to be fixed while the rest can be dynamically chosen by the network.<br />
Of the 256 group addresses that the SIG has reserved for fixed addresses, currently only 4 of them are assigned specific purposes. The rest are reserved for future use. They are:</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Fixed Group Address</th>
<th >Name</th>
</tr>
</thead>
<tbody>
<tr><td >0b1111111100000000 – 0b1111111111111011</td>
<td >Reserved</td>
</tr>

<tr><td >0b1111111111111100</td>
<td >all-proxies</td>
</tr>

<tr><td >0b1111111111111101</td>
<td >all-friends</td>
</tr>

<tr><td >0b1111111111111110</td>
<td >all-relays</td>
</tr>

<tr><td >0b1111111111111111</td>
<td >all-nodes</td>
</tr>
</tbody></table></div>
<p>Other group addresses can be assigned for any logical group in the network. For example, room names such as kitchen, bedroom or living room could be identified as group names to control multiple elements at once. As another example, you can have one switch turn on/off multiple bulbs at the same time with a single message to a group address.</p>
<p><strong>Virtual</strong><br />
A virtual address is assigned to one or more elements across one or more nodes. A virtual address takes the form of a 128-bit UUID that any element can be assigned to, like a label. This 128-bit address is used in calculating the message integrity check.<br />
The 14 LSBs of the virtual address are set to a hash of the label UUID such that each hash represents many label UUIDs. When an access message is received for a virtual address with a matching hash, each corresponding label UUID is compared as part of the authentication to see if there is a matching element.<br />
This may be used by a manufacturer to allow mesh networks including those devices to send messages to all similar devices at one time.</p>
<h1>Bluetooth Mesh Messaging</h1>
<p>The Bluetooth Mesh communication happens using BLE Advertising packets. There are two classes of messages in the Bluetooth Mesh, Control and Access.  By and large the control messages are used for network control, and you never see them as they are handled by the stack.  The Access messages are ones that matter to us as application developers.</p>
<p>We all know that the BLE advertising  packet is only 31 bytes long.  This makes things difficult as most of the packet is used up by network protocol overhead leaving only a few bytes for the actual message.  The good news is that the stack handles splitting up your payload into as many as 32 packets (called segmented) and getting them re-sequenced automatically.</p>
<p>I&#8217;m not very good at limits &#8230; but this is what you have to live with in BLE Mesh:</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Message Type</th>
<th >Max Payload Size (Octets)</th>
</tr>
</thead>
<tbody>
<tr><td >Unsegmented Control or Access</td>
<td >11</td>
</tr>

<tr><td >Segmented Control</td>
<td >256</td>
</tr>

<tr><td >Segmented Access</td>
<td >376 or 380</td>
</tr>
</tbody></table></div>
<p><strong>Acknowledged vs. Unacknowledged</strong><br />
As the name suggests, acknowledged messages require a response from the node that it is addressed to. The response confirms that the message was received and it may also return data back to the sender (e.g. in response to a GET). If a sender does not receive the expected response from a message it may resend it. Messages must be idempotent so that a message received more than once is no different than if it had only been received once.</p>
<p><strong>GET, SET, STATUS</strong><br />
All access messages are of the three broad types of GET, SET, and STATUS.<br />
GET messages request a state value from one or more nodes. A GET message is always acknowledged.<br />
SET messages are used to change the value of a state. A SET message can be either acknowledged or unacknowledged.<br />
STATUS messages are sent in response to a GET, and acknowledged SET, or may also be sent by a node independently, for example, periodically using a timer. A STATUS message is always unacknowledged. Therefore, if a node sends a GET message but never receives a STATUS return message, it may resend the GET message.</p>
<h1>BLE Mesh Publishing</h1>
<p>From the BLE Mesh Spec &#8220;All communication within a mesh network is accomplished by sending messages. Messages operate on states. For each state, there is a defined set of messages that a server supports and a client may use to request a value of a state or to change a state. A server may also transmit unsolicited messages carrying information about states and/or changing states.&#8221;</p>
<p>The BLE Mesh Application communication scheme is based on the Publish/Subscribe &amp; Client/Server paradigm and are embedded automatically into Access messages by the stack.  An Element may publish messages (either to a group or a unicast address).  And an Element may subscribe to messages from one or more groups.</p>
<h1 title="Page 5">Models</h1>
<p>An Element is not very interesting without a mechanism to interact with it.  A Model is exactly that, specifically it is the Bluetooth SIG defined behavior and data/state of an Element.  Each Element in your Node will have one or more Models that are attached to it that you can think of as Servers which hold, send and receive data.</p>
<p>Models fall into three categories. Servers, Clients and Control (hybrid Server/Control)</p>
<p>Server:  Contains data and sends it out in response to Client GET requests or can update the data based on Client SET requests or may send Status based on changes in the Element.</p>
<p>Clients: Send GET requests to Servers or Send SET requests to Servers.</p>
<p>Control: A Hybrid Model that acts both as a Client and a Server.</p>
<p>Here is an example picture from the <a href="https://www.cypress.com/file/473921/download" target="_blank" rel="noopener noreferrer">AN227069 – Getting Started with Bluetooth Mesh</a></p>
<p><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/screen-shot-2019-05-28-at-10-42-08-am/" rel="attachment wp-att-7236"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM-1024x1002.png" alt="" width="1024" height="1002" class="alignnone size-large wp-image-7236" srcset="https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM-1024x1002.png 1024w, https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM-600x587.png 600w, https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM-300x293.png 300w, https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM-768x751.png 768w, https://iotexpert.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-28-at-10.42.08-AM.png 1278w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To make this system work the Bluetooth SIG has also defined the standard behavior for a bunch of different models including:</p>
<h1>States</h1>
<p>From the Bluetooth Spec &#8220;A state is a value representing a condition of an element.&#8221;  States are associated with a particular server model. That is, the spec defines the states that apply to each server model and how they behave.</p>
<h1>Complexity</h1>
<p>There is quite a bit more going on in the Bluetooth Mesh specifications including the abilities to handle:</p>
<ul>
<li>Scenes (e.g. go in a room and have all the lights, sound, hvac go to the right levels)</li>
<li>State binding &#8211; Multiple states are bound together such that when one changes the others change (e.g. you turn the volume so low that it becomes off)</li>
<li>State transition times (e.g. Fade the lights up or down over a set time period)</li>
<li>Alerts (e.g. notify the user with a blinking light)</li>
</ul>
<h1 title="Page 5">Security</h1>
<p>There are three levels of security in a Bluetooth Mesh network and access is governed by three keys.</p>
<div title="Page 5"><strong>NetKey</strong><br />
All nodes in a mesh network must possess the network key. In fact, possession of the NetKey is what makes a node a member of a given mesh network. The NetKey allows a node to decrypt and authenticate messages at the network Layer. The mesh packet header and address are encrypted and authenticated with the network key. This allows a node to perform relay functions, but it does NOT allow the relay node to decrypt the application data that is stored in a message.<br />
<strong>AppKey</strong><br />
The mesh packet payload is encrypted and authenticated with the application key. Therefore, data for a specific application can only be decrypted by nodes that have the AppKey for that application. The AppKeys are used by the upper transport layer to decrypt and authenticate messages before passing them to the access layer.<br />
The existence of AppKeys allows multiple applications to share a mesh network (and therefore gain all the benefits of having more nodes such as increased reliability and range) without each node having access to all messages.<br />
For example, consider a mesh network that has lights, HVAC, and home security devices on it. The light fixtures and light switches would share an AppKey for lighting; the thermostats, furnace, and air conditioner would share an AppKey for HVAC; the door locks and alarm system would share an AppKey for home security. In this way, home security messages can only be decrypted by devices that are part of the home security system, etc.<br />
<strong>DevKey</strong><br />
Each device has its own unique device key known only to itself and the provisioner device. This key is used for secure communication during configuration.</div>
<h1 title="Page 5">Provisioning and Configuration</h1>
<p>When a node turns on for the first time it barely knows its own name.  It definitely does not know any of the security keys, its addresses (unicast or group) or any of its model configuration information.  So what does it do?  Simple &#8211; it starts to send out a BLE Advertising packet in the format of a BLE Mesh Beacon.  Then it waits for a provisioning device to make a BLE GATT connection to provision the node with the network information.  The provisioning process assigns the netkey and the unicast address of the primary  element.</p>
<p>After the device is provisioned it will be able to hear and decode BLE Mesh packets.  But, it won&#8217;t know much else to do until the Elements have been configured.  So, the next step for the provisioning application is to send the rest of the configuration information. e.g. group subscriptions, application keys etc.</p>
<h1 title="Page 5">Bluetooth Mesh Stack</h1>
<div title="Page 5"><a href="https://iotexpert.com/2019/05/29/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/meshstack/" rel="attachment wp-att-7213"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/05/meshstack.png" alt="" width="493" height="472" class="alignnone size-full wp-image-7213" srcset="https://iotexpert.com/wp-content/uploads/2019/05/meshstack.png 493w, https://iotexpert.com/wp-content/uploads/2019/05/meshstack-300x287.png 300w" sizes="(max-width: 493px) 100vw, 493px" /></a></div>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/mouser-bluetooth-mesh-l5-bluetooth-mesh-fundamentals/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>CY8CKIT-028-EPD and Modus Toolbox 1.1</title>
		<link>https://iotexpert.com/cy8ckit-028-epd-and-modus-toolbox-1-1/</link>
					<comments>https://iotexpert.com/cy8ckit-028-epd-and-modus-toolbox-1-1/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 15 Apr 2019 21:50:36 +0000</pubDate>
				<category><![CDATA[CY8CKIT-028-EPD]]></category>
		<category><![CDATA[CY8CKIT-062-BLE]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=6666</guid>

					<description><![CDATA[Summary One of my very influential readers is working on a project where he wants to use the CY8CKIT-028-EPD.  But, he wants to use Modus Toolbox 1.1 instead of PSoC Creator and he observed, correctly, that Cypress doesn&#8217;t have a MTB code example project for the CY8CKIT-028-EPD.  I knew that we had a working code [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>One of my very influential readers is working on a project where he wants to use the <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>.  But, he wants to use Modus Toolbox 1.1 instead of PSoC Creator and he observed, correctly, that Cypress doesn&#8217;t have a MTB code example project for the CY8CKIT-028-EPD.  I knew that we had a working code example in PSoC Creator (<a href="https://www.cypress.com/documentation/code-examples/ce23727-psoc-6-e-ink-display-interface-emwin-graphics-library" target="_blank" rel="noopener noreferrer">CE223727</a>), so I decided to do a port to MTB1.1.  This turned out to be a bit of an adventure which required me to dig out a logic analyzer to solve self inflicted problems.  Here is a picture I took while sorting it out.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/img_0408/" rel="attachment wp-att-6668"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0408-e1555270252695-1024x768.jpg" alt="" width="1024" height="768" class="alignnone wp-image-6668 size-large" srcset="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0408-e1555270252695-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0408-e1555270252695-scaled-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0408-e1555270252695-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0408-e1555270252695-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>There are a few things in the PSoC Creator example code which I didn&#8217;t really like, so, for the final solution, I would like it to be</p>
<ul>
<li>In Modus Toolbox 1.1</li>
<li>Using FreeRTOS</li>
<li>Using the Segger emWin graphics library</li>
<li>Getting the best response time</li>
<li>Using DMA to drive the display</li>
</ul>
<p>For this article I will go through these steps:</p>
<ol>
<li>Build CE223727 EmWin_Eink_Display in PSoC Creator</li>
<li>Explain the PSoC Creator Project</li>
<li>Create a new MTB Project &amp; add the FreeRTOS, Segger emWin and stdio middleware</li>
<li>Configure the device for the correct pins, clocks and peripherals</li>
<li>Setup FreeRTOS and Standard I/O</li>
<li>Copy the driver files into the MTB project from the PSoC Creator workspace</li>
<li>Port the drivers and eInkTask to work in MTB</li>
<li>Program and Test</li>
<li>(Part 2) Update the driver to remove the hardware timer</li>
<li>(Part 2) Update the example to remove polled switch and use a semaphore</li>
<li>(Part 2) Update the driver to use DMA</li>
<li>(Part 2) Explain how the EINK EPD Display Works</li>
</ol>
<p>If you lack patience and you just want a working project, you can download it from the <a href="https://github.com/iotexpert/eink-emwin-mtb1-1" target="_blank" rel="noopener noreferrer">IoT Expert GitHub</a> site. git@github.com:iotexpert/eink-emwin-mtb1-1.git</p>
<h1>First build CE223727 EmWin_Eink_Display in PSoC Creator</h1>
<p>Start by finding the code example project for the Eink Display.  In PSoC Creator on the File-&gt;Code Example menu you will be able to pick out the code example.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-53-44-pm/" rel="attachment wp-att-6679"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.53.44-PM.png" alt="" width="242" height="163" class="alignnone size-large wp-image-6679" /></a></p>
<p>There are a bunch of code examples, so the easiest way to find them is the filter based on &#8220;emwin&#8221;.  I did this because I knew we had used the Segger emWin Graphics library.  Notice in the picture below there are two emWin examples.  One with a &#8220;world&#8221; beside it and one without.  The world symbol means that it is on the internet and you will need to download it.  You can do that by clicking the world button.  Probably, you will find that your CE223727 EmWin_EInk_Display will have a world beside it and you will need to download it before you can make the project.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-53-26-pm/" rel="attachment wp-att-6680"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.53.26-PM.png" alt="" width="626" height="478" class="alignnone size-large wp-image-6680" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.53.26-PM.png 626w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.53.26-PM-600x458.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.53.26-PM-300x229.png 300w" sizes="(max-width: 626px) 100vw, 626px" /></a></p>
<p>Once you click create project it will ask you about the project.  Just click &#8220;next&#8221;</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-54-18-pm/" rel="attachment wp-att-6678"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.18-PM.png" alt="" width="626" height="471" class="alignnone size-large wp-image-6678" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.18-PM.png 626w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.18-PM-600x451.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.18-PM-300x226.png 300w" sizes="(max-width: 626px) 100vw, 626px" /></a></p>
<p>Then give your project (and workspace) a name.  I called the workspace &#8220;EPDExample&#8221; and the project &#8220;CE22&#8230;.&#8221;</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-54-40-pm/" rel="attachment wp-att-6677"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.40-PM.png" alt="" width="626" height="466" class="alignnone size-large wp-image-6677" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.40-PM.png 626w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.40-PM-600x447.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.54.40-PM-300x223.png 300w" sizes="(max-width: 626px) 100vw, 626px" /></a></p>
<p>After all of that is done you will have a schematic (and all of the other stuff required for the project).</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-55-50-pm/" rel="attachment wp-att-6675"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM-1024x791.png" alt="" width="1024" height="791" class="alignnone size-large wp-image-6675" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM-1024x791.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM-600x464.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM-300x232.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM-768x593.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.50-PM.png 1126w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you click the program button it will ask you which MCU target to program (pick either, it doesnt matter)</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-55-28-pm/" rel="attachment wp-att-6676"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.28-PM.png" alt="" width="557" height="394" class="alignnone size-large wp-image-6676" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.28-PM.png 557w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.55.28-PM-300x212.png 300w" sizes="(max-width: 557px) 100vw, 557px" /></a></p>
<p>After a while, your console window should look like this.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-4-59-13-pm/" rel="attachment wp-att-6681"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM-1024x174.png" alt="" width="1024" height="174" class="alignnone size-large wp-image-6681" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM-1024x174.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM-600x102.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM-300x51.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM-768x130.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-4.59.13-PM.png 1198w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And you development kit should do its thing.</p>
<h1><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/img_0429/" rel="attachment wp-att-6682"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0429-1024x632.jpg" alt="" width="1024" height="632" class="alignnone size-large wp-image-6682" srcset="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0429-1024x632.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0429-600x371.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0429-300x185.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0429-768x474.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></h1>
<h1>Explain the PSoC Creator Project</h1>
<p>Now, lets have a look at the project.  Starting on the upper left hand part of the schematic you find that the interface to the EPD is via a SPI.  The SPI slave select is controlled with the Pervasive driver firmware rather than letting the SPI block directly control it.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-12-52-pm/" rel="attachment wp-att-6688"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.12.52-PM.png" alt="" width="436" height="232" class="alignnone size-full wp-image-6688" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.12.52-PM.png 436w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.12.52-PM-300x160.png 300w" sizes="(max-width: 436px) 100vw, 436px" /></a></p>
<p>The SPI is configured to be 16 megabits per second with CPHA=0 and CPOL=0.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-09-40-pm/" rel="attachment wp-att-6686"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.40-PM.png" alt="" width="795" height="892" class="alignnone size-large wp-image-6686" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.40-PM.png 795w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.40-PM-600x673.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.40-PM-267x300.png 267w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.40-PM-768x862.png 768w" sizes="(max-width: 795px) 100vw, 795px" /></a></p>
<p>I didn&#8217;t notice this at first, but in the picture above you can see that the actual speed of the SPI is 8.33 mbs.  That isn&#8217;t 16mbs for sure.  But why the gap?  The first thing to know is that in order for the SPI block to work correctly the input clock must be set at the desired datarate times the oversample.  What is oversample?  That is a scheme to get rid of glitchy-ness in the input signal.  In this case it will take 6 input samples to determine if the input is a 1 or a 0.  (median filter I think).  With this configuration the input clock to the SCB needs to be 16mbs * 6 = 96mhz.</p>
<p>But what is the input clock frequency?  If you click on the dwr-&gt;clocks you will see this screen which shows that the input clock is 50Mhz (the last line highlighted in blue).  Further more you can see that the source clock for the SCB is &#8220;Clk_Peri&#8221;.  When you divide 50mhz source clock rate by 6 oversample you will find that the actual bitrate is 8.33kbs.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-15-57-pm/" rel="attachment wp-att-6691"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM.png" alt="" width="786" height="777" class="alignnone size-large wp-image-6691" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM.png 786w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM-600x593.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM-300x297.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.15.57-PM-768x759.png 768w" sizes="(max-width: 786px) 100vw, 786px" /></a></p>
<p>But where does the 50mhz come from?  Well, the clock system is driven by the &#8220;IMO&#8221;.  IMO stands for internal main oscillator and it is a trimmed RC oscillator built into the chip. (thanks Tim).  This oscillator runs into an FLL which up converts it to 100MHz.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-17-08-pm/" rel="attachment wp-att-6689"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.17.08-PM.png" alt="" width="768" height="554" class="alignnone size-full wp-image-6689" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.17.08-PM.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.17.08-PM-600x433.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.17.08-PM-300x216.png 300w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>That signal is then run into the &#8220;Clk_Peri&#8221; divider which divides it by two to yield a clock of 50MHz.  Which is not all that close to 96MHz&#8230; and means that our SPI runs at the wrong speed.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-16-57-pm/" rel="attachment wp-att-6690"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.16.57-PM.png" alt="" width="779" height="445" class="alignnone size-large wp-image-6690" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.16.57-PM.png 779w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.16.57-PM-600x343.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.16.57-PM-300x171.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.16.57-PM-768x439.png 768w" sizes="(max-width: 779px) 100vw, 779px" /></a></p>
<p>But what does the EPD driver chip actually want?  You can find the documentation for this EPD on the Pervasive <a href="http://www.pervasivedisplays.com/products/271" target="_blank" rel="noopener noreferrer">website</a>.  That web page also has a link to the Product Specification <a href="http://www.pervasivedisplays.com/LiteratureRetrieve.aspx?ID=238025">2.7&#8243; TFT EPD Panel (E2271CS021) Rev.01</a> as well as the driver chip <a href="http://www.pervasivedisplays.com/_literature_220873/COG_Driver_Interface_Timing_for_small_size_G2_V231">COG Driver Interface Timing for small size G2 V231</a></p>
<p>When you look in the timing document you will find that the actual chip can take up to a 20Mhz input clock.  This means that our code example actually updates the screen at 42% (8.33/20) of what it could.  That gives us a chance to make things faster&#8230; which I will do after the port to MTB.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-25-08-pm/" rel="attachment wp-att-6692"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.25.08-PM.png" alt="" width="743" height="207" class="alignnone size-full wp-image-6692" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.25.08-PM.png 743w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.25.08-PM-600x167.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.25.08-PM-300x84.png 300w" sizes="(max-width: 743px) 100vw, 743px" /></a></p>
<p>The next sectin of the schematic has a TCPWM that is configured as a timer.  This has an input clock of 2kHz.</p>
<p>&nbsp;</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-10-00-pm/" rel="attachment wp-att-6685"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.00-PM.png" alt="" width="445" height="255" class="alignnone size-large wp-image-6685" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.00-PM.png 445w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.00-PM-300x172.png 300w" sizes="(max-width: 445px) 100vw, 445px" /></a></p>
<p>And is setup to divide by 2 which will yield a counter that updates every 1ms.  The author of this code example used the TCPWM to time operations inside of the driver (which I will also replace with something better)</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-10-09-pm/" rel="attachment wp-att-6684"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.09-PM.png" alt="" width="626" height="476" class="alignnone size-full wp-image-6684" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.09-PM.png 626w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.09-PM-600x456.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.10.09-PM-300x228.png 300w" sizes="(max-width: 626px) 100vw, 626px" /></a></p>
<p>Lastly there are some GPIOs that control various control pins on the display.  I don&#8217;t really know what all of the pins do, but will sort it out in the next article.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-47-16-pm/" rel="attachment wp-att-6694"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.47.16-PM.png" alt="" width="499" height="639" class="alignnone size-full wp-image-6694" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.47.16-PM.png 499w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.47.16-PM-234x300.png 234w" sizes="(max-width: 499px) 100vw, 499px" /></a></p>
<p>And all of the pins are assigned like this:</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-09-03-pm/" rel="attachment wp-att-6687"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.03-PM.png" alt="" width="670" height="297" class="alignnone size-large wp-image-6687" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.03-PM.png 670w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.03-PM-600x266.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.09.03-PM-300x133.png 300w" sizes="(max-width: 670px) 100vw, 670px" /></a></p>
<h1>Create a new MTB project &amp; Add the Middleware</h1>
<p>It is time to start the project in MTB.  Start up Modus Toolbox 1.1 and select File-&gt;New-&gt;ModusToobox IDE Application    <a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-8-57-36-am/" rel="attachment wp-att-6701"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM-1024x173.png" alt="" width="1024" height="173" class="alignnone size-large wp-image-6701" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM-1024x173.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM-600x101.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM-300x51.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM-768x129.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.57.36-AM.png 1614w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then select the CY8CKIT-062-BLE Development Kit.  This kit comes with the CY8CKIT-028-EPD EINK Shield that you can see in the pictures above.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-8-58-04-am/" rel="attachment wp-att-6700"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM-1024x489.png" alt="" width="1024" height="489" class="alignnone size-large wp-image-6700" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM-1024x489.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM-600x287.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM-300x143.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM-768x367.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.04-AM.png 2030w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I decide to call my project &#8220;EHKEink&#8221; and I derive my project from the &#8220;EmptyPSoC6App&#8221; template.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-8-58-32-am/" rel="attachment wp-att-6699"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM-1024x490.png" alt="" width="1024" height="490" class="alignnone size-large wp-image-6699" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM-1024x490.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM-600x287.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM-300x144.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM-768x367.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.32-AM.png 2032w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Once that is done, Let it rip.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-8-58-51-am/" rel="attachment wp-att-6698"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM-1024x718.png" alt="" width="1024" height="718" class="alignnone size-large wp-image-6698" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM-1024x718.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM-600x421.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM-300x210.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM-768x538.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-8.58.51-AM.png 1224w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And you should end up with a screen that looks like this. On the left in the workspace explorer you see the main app project.  In the middle you see the readme file which explains how this project is configured.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-01-13-am-2/" rel="attachment wp-att-6703"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.01.13-AM-1-1024x626.png" alt="" width="1024" height="626" class="alignnone size-large wp-image-6703" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.01.13-AM-1-1024x626.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.01.13-AM-1-600x367.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.01.13-AM-1-300x183.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.01.13-AM-1-768x469.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next step is to add the &#8220;Middleware&#8221; that we need to make this project work.  You can do this by clicking the select Middleware button from the ModusToolbox quick panel.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-13-02-am/" rel="attachment wp-att-6704"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.13.02-AM.png" alt="" width="708" height="852" class="alignnone size-full wp-image-6704" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.13.02-AM.png 708w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.13.02-AM-600x722.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.13.02-AM-249x300.png 249w" sizes="(max-width: 708px) 100vw, 708px" /></a></p>
<p>For this project we need</p>
<ul>
<li>FreeRTOS</li>
<li>Retarget I/O</li>
<li>Segger emWin Core, OS, no Touch, Soft FP</li>
<li>Segger emWin display driver BitPlains</li>
</ul>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-18-52-am/" rel="attachment wp-att-6708"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM-1024x911.png" alt="" width="1024" height="911" class="alignnone size-large wp-image-6708" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM-1024x911.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM-600x534.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM-300x267.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM-768x683.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.18.52-AM.png 1972w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The middleware selector will bring in all of the drivers you selected into your project.  You can see that it also adds the FreeRTOS configuration file &#8220;FreeRTOSConfig.h&#8221; as well as &#8220;stdio_user.c&#8221; etc.  These files endup in the source folder and are for you to edit.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-19-50-am/" rel="attachment wp-att-6707"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.19.50-AM.png" alt="" width="718" height="788" class="alignnone size-full wp-image-6707" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.19.50-AM.png 718w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.19.50-AM-600x658.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.19.50-AM-273x300.png 273w" sizes="(max-width: 718px) 100vw, 718px" /></a></p>
<p>While I was working on this, I found a bug in the emWin middleware, specifically the the configuration files for BitPlains get included twice.  To fix this you need to change the project properties and remove the path to &#8220;..components/psoc6mw/emWin/code/drivers/BitPlains/config&#8221;.  To do this, select the project in the workspace explorer then right click and select properties.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-22-04-am/" rel="attachment wp-att-6710"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM-543x1024.png" alt="" width="543" height="1024" class="alignnone size-large wp-image-6710" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM-543x1024.png 543w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM-600x1131.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM-159x300.png 159w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM-768x1447.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.04-AM.png 916w" sizes="(max-width: 543px) 100vw, 543px" /></a></p>
<p>Then select &#8220;C/C++ General &#8211;&gt; Paths and Symbols&#8221;.  Select the &#8220;&#8230;BitPlains/config&#8221; path and click &#8220;Delete&#8221;</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-22-43-am/" rel="attachment wp-att-6709"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.43-AM-1024x541.png" alt="" width="1024" height="541" class="alignnone size-large wp-image-6709" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.43-AM-1024x541.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.43-AM-600x317.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.43-AM-300x158.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.22.43-AM-768x405.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Configure the device in MTB</h1>
<p>Modus Toolbox does not have a &#8220;schematic&#8221; or a &#8220;dwr&#8221; like PSoC Creator.  In order to achieve the same functionality we built the &#8220;Configurator&#8221;.  This tool will let you setup all of the peripherals in your project.  To run it select &#8220;Configure Device&#8221; in the MTB Quick Panel.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-29-54-am/" rel="attachment wp-att-6712"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.29.54-AM.png" alt="" width="714" height="938" class="alignnone size-full wp-image-6712" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.29.54-AM.png 714w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.29.54-AM-600x788.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.29.54-AM-228x300.png 228w" sizes="(max-width: 714px) 100vw, 714px" /></a></p>
<p>Remember from the PSoC Creator Schematic we need to have:</p>
<ul>
<li>A bunch of pins</li>
<li>A SPI</li>
<li>A Timer</li>
<li>Plus I want a UART to connect to standard I/O.</li>
</ul>
<p>First, click on the &#8220;Pins&#8221; tab.  This lets you set all of the configuration information for each of the pins on the chip.  I will go one by one enabling the pins and setting them as digital inputs or output.  I am going to give all of the pins that exact same names that they had in the PSoC Creator Project because I know the author of that project used PDL.  When you give a pin a name in the configurator it will generate #defines or c structures based on the name.  This will make the source code the original PSoC Creator author wrote almost exactly compatible with MTB.</p>
<p>Here is an example of the first output pin which is P0[2] and is named CY_EINK_DispIoEn.  For the output pins you need to do four things.</p>
<ol>
<li>Enable the checkbox next to the pin name. (in this case P0[2])</li>
<li>Give the pin a name (CY_EINK_DispIoEn)</li>
<li>Set the drive mode (Strong Drive, Input buffer off)</li>
<li>Set the initial state of the pin (High (1))</li>
</ol>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-48-55-am/" rel="attachment wp-att-6716"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM-1024x889.png" alt="" width="1024" height="889" class="alignnone size-large wp-image-6716" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM-1024x889.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM-600x521.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM-300x260.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM-768x667.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.48.55-AM.png 1726w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now, you need to go one by one turning on all of the output pins (Im not showing you screen shots of all of them)</p>
<p>There are two input pins for this project SW2 P0[4] and CY_EINK_DispBusy P5[3].  For these pins I will:</p>
<ol>
<li>Enable the pin checkbox</li>
<li>Give the pin a name (in this case SW2)</li>
<li>Resistive Pull-Up, Input buffer on.  Note for P5[3] the pullup resistor is not needed</li>
</ol>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-52-01-am/" rel="attachment wp-att-6718"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM-1024x894.png" alt="" width="1024" height="894" class="alignnone size-large wp-image-6718" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM-1024x894.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM-600x524.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM-300x262.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM-768x670.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.52.01-AM.png 1698w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now that the digital pins are configured, you can setup the STDIO Uart.  This will be used to send debugging messages to the console Uart which is attached to your computer via a USB&lt;-&gt;UART bridge in KitProg 3.</p>
<p>Start by enabling SCB5 and giving it the name &#8220;UART&#8221;.  Make sure that the baud rate is set to 115200 and the rest to 8n1<a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-57-26-am/" rel="attachment wp-att-6720"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM-820x1024.png" alt="" width="820" height="1024" class="alignnone size-large wp-image-6720" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM-820x1024.png 820w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM-600x749.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM-240x300.png 240w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM-768x959.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.57.26-AM.png 1190w" sizes="(max-width: 820px) 100vw, 820px" /></a></p>
<p>Scroll down the window and pick out the RX and TX Pins plus the clock (any of the 8-bit clock dividers will do.  In this case I chose Divider 0)</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-9-58-51-am/" rel="attachment wp-att-6721"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM-1024x657.png" alt="" width="1024" height="657" class="alignnone size-large wp-image-6721" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM-1024x657.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM-600x385.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM-300x192.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM-768x493.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-9.58.51-AM.png 1244w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now, you need to setup the SPI.  To do this turn on SCB 6, set it to SPI, give it the name &#8220;CY_EINK_SPIM&#8221;, set it to &#8220;Master&#8221;, fix the data rate to 1000<a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-10-01-18-am/" rel="attachment wp-att-6722"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM-1024x993.png" alt="" width="1024" height="993" class="alignnone size-large wp-image-6722" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM-1024x993.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM-600x582.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM-300x291.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM-768x745.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.01.18-AM.png 1524w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then scroll down to the &#8220;Connections&#8221; section and assign the pins</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-3-48-22-pm/" rel="attachment wp-att-6744"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM-1024x588.png" alt="" width="1024" height="588" class="alignnone size-large wp-image-6744" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM-1024x588.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM-600x345.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM-300x172.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM-768x441.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.48.22-PM.png 1146w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The last bit of hardware we need is a timer with a 1000kHz input clock, in other words a millisecond timer.  To do this start by enabling TCPWM[1] 16-bit counter.  Call it &#8220;CY_EINK_Timer&#8221; which was the same name as the PSoC Creator project.  Then setup</p>
<ul>
<li>As a &#8220;Timer Counter&#8221;.</li>
<li>One shot</li>
<li>Up count</li>
<li>Period is 65535 (aka the max)</li>
<li>And pick &#8220;Clock signal&#8221; as 16 bit Divider</li>
</ul>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-12-26-51-pm/" rel="attachment wp-att-6736"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM-1024x858.png" alt="" width="1024" height="858" class="alignnone size-large wp-image-6736" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM-1024x858.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM-600x503.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM-300x251.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM-768x644.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.26.51-PM.png 1592w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Given that we want it to count milliseconds and the input has a 128 bit pre-divider&#8230; we need for the input clock to be setup to 128khz.  Click on &#8220;Peripheral clocks&#8221; then select &#8220;16 Bit Divider 0&#8221;.  Notice that the input frequency is 72Mhz and we need 128Khz&#8230; to get this a divider of 562 is required.  72mhz/128khz = 562</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-12-35-10-pm/" rel="attachment wp-att-6737"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM-1024x901.png" alt="" width="1024" height="901" class="alignnone size-large wp-image-6737" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM-1024x901.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM-600x528.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM-300x264.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM-768x676.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-12.35.10-PM.png 1412w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Setup FreeRTOS and Standard I/O</h1>
<p>The next step is to setup the &#8220;plumbing&#8221;.  In this projet we are using FreeRTOS and Standard I/O. To configure FreeRTOS just edit the &#8220;FreeRTOSConfig.h&#8221; and remove the &#8220;warning&#8221;</p>
<pre class="start-line:45 EnlighterJSRAW" data-enlighter-language="c"">#warning This is a template. Modify it according to your project and remove this line. 
</pre>
<p>Enable mutexes on line 57</p>
<pre class="start-line:57 EnlighterJSRAW" data-enlighter-language="c"">#define configUSE_MUTEXES                       1
</pre>
<p>Make the heap bigger on line 70</p>
<pre class="start-line:70 EnlighterJSRAW" data-enlighter-language="c"">#define configTOTAL_HEAP_SIZE                   1024*48
</pre>
<p>Change the memory scheme to 4 on line 194</p>
<pre class="start-line:194 EnlighterJSRAW" data-enlighter-language="c"">#define configHEAP_ALLOCATION_SCHEME                (HEAP_ALLOCATION_TYPE4)
</pre>
<p>To enable the UART to be used for Standard I/O, edit &#8220;stdio_user.h&#8221; and add the includes for &#8220;cycfg.h&#8221;.  Then update the output and input Uart to be &#8220;UART_HW&#8221; (which is the name you gave it in the configurator)</p>
<pre class="start-line:172 EnlighterJSRAW" data-enlighter-language="c"">#include "cycfg.h"
/* Must remain uncommented to use this utility */
#define IO_STDOUT_ENABLE
#define IO_STDIN_ENABLE
#define IO_STDOUT_UART      UART_HW
#define IO_STDIN_UART       UART_HW
</pre>
<p>Now make a few edits to main.c to</p>
<ul>
<li>Add includes for the configuration, rtos and standard i/o</li>
<li>Create a context for the UART</li>
<li>Create a blinking LED Task</li>
<li>In main start the UART and start the blinking LED task.</li>
</ul>
<pre class="start-line:27 EnlighterJSRAW" data-enlighter-language="c"">#include "cy_device_headers.h"
#include "cycfg.h"
#include "FreeRTOS.h"
#include "task.h"
#include &lt;stdio.h&gt;

cy_stc_scb_uart_context_t UART_context;

void blinkTask(void *arg)
{
	(void)arg;

    for(;;)
    {
    		vTaskDelay(500);
    		Cy_GPIO_Inv(LED_RED_PORT,LED_RED_PIN);
    		printf("blink\n");
    }
}
int main(void)
{
    init_cycfg_all();
    __enable_irq();

    Cy_SCB_UART_Init(UART_HW,&amp;UART_config,&amp;UART_context);
	Cy_SCB_UART_Enable(UART_HW);

  	xTaskCreate( blinkTask,"blinkTask", configMINIMAL_STACK_SIZE,  0,  1, 0  );
  	vTaskStartScheduler();
  	while(1);// Will never get here
}
</pre>
<p>As I edited the code I notice that it can&#8217;t find &#8220;LED_RED&#8221; which made me realize that I forgot to add the LED_RED attached to P0[3] in the configuration.  So, I go back and update P0[3] to be LED_RED as strong drive digital output.</p>
<p>Finally just to make sure that it is all working lets program the kit.  When I press &#8220;EHKEink Program&#8221; form the quickpanel&#8230;<a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-10-45-20-am/" rel="attachment wp-att-6725"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.45.20-AM.png" alt="" width="710" height="880" class="alignnone size-full wp-image-6725" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.45.20-AM.png 710w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.45.20-AM-600x744.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.45.20-AM-242x300.png 242w" sizes="(max-width: 710px) 100vw, 710px" /></a></p>
<p>I get this message in the console.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-10-46-38-am/" rel="attachment wp-att-6726"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM-1024x493.png" alt="" width="1024" height="493" class="alignnone size-large wp-image-6726" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM-1024x493.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM-600x289.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM-300x145.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM-768x370.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.46.38-AM.png 1100w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>But how can that be?  I have my kit plugged in?  In order to program your kit using Modus you need &#8220;KitProg3&#8221;.  PSoC Creator can program you kit with KitProg3 only if it is in the CMSIS-DAP HID mode.  To switch you development kit to KitProg3, you can use the program &#8220;fw-loader&#8221; which comes with MTB.  You can see what firmware you have by running &#8220;fw-loader &#8211;device-list&#8221;.  To change to KitProg 2 run &#8220;fw-loader &#8211;update-kp2&#8221; and to update to KitProg3 run &#8220;fw-loader &#8211;update-kp3&#8221;</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-14-at-5-35-26-pm/" rel="attachment wp-att-6693"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.35.26-PM.png" alt="" width="980" height="523" class="alignnone size-full wp-image-6693" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.35.26-PM.png 980w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.35.26-PM-600x320.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.35.26-PM-300x160.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-14-at-5.35.26-PM-768x410.png 768w" sizes="(max-width: 980px) 100vw, 980px" /></a></p>
<p>Now when i program I get both the LED blinking and the console printing blink.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-10-37-24-am/" rel="attachment wp-att-6728"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM-1024x700.png" alt="" width="1024" height="700" class="alignnone size-large wp-image-6728" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM-1024x700.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM-600x410.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM-300x205.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM-768x525.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.37.24-AM.png 1190w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Copy the files into the MTB project</h1>
<p>Next, I want to bring over the drivers from the PSoC Creator project.  They reside in folder called &#8220;eInk Library&#8221; inside of the PSoC Creator project.  You can copy them by navigating to the PSoC Creator workspace, then typing ctrl-c in the File Explorer, then clicking the &#8220;Source&#8221; directory in your Eclipse WorkSpace explorer and typing ctrl-v<a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-10-56-36-am/" rel="attachment wp-att-6730"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.56.36-AM-1024x596.png" alt="" width="1024" height="596" class="alignnone size-large wp-image-6730" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.56.36-AM-1024x596.png 1024w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.56.36-AM-600x349.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.56.36-AM-300x174.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-10.56.36-AM-768x447.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>You will also need the four files &#8220;GUIConf.c&#8221;, &#8220;GUIConf.h&#8221;, &#8220;LCDConf.h&#8221; and &#8220;LCDConf.c&#8221;.  Copy and paste them into the emWin_config directory.</p>
<p>For this project I am going to use the code that existed in &#8220;main.c&#8221; from the original PSoC Creator project.  But I want it to be a task (and a few other changes).  To facilitate things, I will copy it as well. Then rename it to eInkTask.c.  And finally, the file &#8220;Cypress Logo Full Color_png1bpp.c&#8221; needs to be copied as well.</p>
<p>After all of those copies you should have your project looking something like this:</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-3-58-04-pm/" rel="attachment wp-att-6745"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.58.04-PM.png" alt="" width="710" height="820" class="alignnone size-full wp-image-6745" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.58.04-PM.png 710w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.58.04-PM-600x693.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-3.58.04-PM-260x300.png 260w" sizes="(max-width: 710px) 100vw, 710px" /></a></p>
<h1>Port the Drivers and eInkTask</h1>
<p>Now we need to fix all of the driver code.  Big picture you will need to take the following actions.</p>
<ul>
<li>Update the Project settings to include the new folders (emWin_config and emWin Library)</li>
<li>Replace the PSoC Creator #include &lt;project.h&gt; with MTB #include &#8220;cycfg.h&#8221;</li>
<li>Update the files to have #include &#8220;FreeRTOS.h&#8221; and &#8220;task.h&#8221; where appropriate</li>
<li>Replace all of the CyDelay&#8217;s with vTaskDelays</li>
<li>Fix the old PSoC Creator component calls for the timer with PDL calls</li>
</ul>
<p>First go to the project settings (remember, click on the project then select properties).  Then pick &#8220;C/C++ Build Settings&#8221; then &#8220;GNU ARM Cross C Compiler&#8221; and &#8220;includes&#8221;  Press the little green &#8220;+&#8221; to add the new directories</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-11-29-00-am/" rel="attachment wp-att-6732"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM-1003x1024.png" alt="" width="1003" height="1024" class="alignnone size-large wp-image-6732" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM-1003x1024.png 1003w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM-600x612.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM-294x300.png 294w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM-768x784.png 768w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.29.00-AM.png 1546w" sizes="(max-width: 1003px) 100vw, 1003px" /></a></p>
<p>You can select both directories at once.</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/screen-shot-2019-04-15-at-11-28-31-am/" rel="attachment wp-att-6733"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.28.31-AM.png" alt="" width="794" height="782" class="alignnone size-large wp-image-6733" srcset="https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.28.31-AM.png 794w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.28.31-AM-600x591.png 600w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.28.31-AM-300x295.png 300w, https://iotexpert.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-15-at-11.28.31-AM-768x756.png 768w" sizes="(max-width: 794px) 100vw, 794px" /></a></p>
<p>Next edit  <strong>eInkTask.c</strong></p>
<p>Update #include &#8220;project.h&#8221; to be #include &#8220;cycfg.h&#8221; on line 59.  Add &#8220;FreeRTOS.h&#8221; and &#8220;task.h&#8221; to the includes.</p>
<pre class="start-line:59 EnlighterJSRAW" data-enlighter-language="c"">#include "cycfg.h"
#include "GUI.h"
#include "pervasive_eink_hardware_driver.h"
#include "cy_eink_library.h"
#include "LCDConf.h"
#include "FreeRTOS.h"
#include "task.h"
#include &lt;stdio.h&gt;</pre>
<p>Find and replace &#8220;CyDelay&#8221; with &#8220;vTaskDelay&#8221;</p>
<p>Update the PSoC Creator component call  _Read with the pdl calls Cy_GPIO_Read on line 661</p>
<pre class="start-line:661 EnlighterJSRAW" data-enlighter-language="c"">void WaitforSwitchPressAndRelease(void)
{
    /* Wait for SW2 to be pressed */
    while(Cy_GPIO_Read(SW2_PORT,SW2_PIN) != 0);
    
    /* Wait for SW2 to be released */
    while(Cy_GPIO_Read(SW2_PORT,SW2_PIN) == 0);
}</pre>
<p>Update the &#8220;int main(void)&#8221; to be &#8220;void eInkTask(void *arg)&#8221; on line 687</p>
<pre class="start-line:687 EnlighterJSRAW" data-enlighter-language="c" ">void eInkTask(void *arg)
{
	(void)arg;</pre>
<p>Remove &#8221; __enable_irq(); /* Enable global interrupts. */&#8221; from the old main on line 695.</p>
<p>In the file <strong>cy_eink_psoc_interface.h</strong></p>
<p>Update the #include &lt;project.h&gt; to be #include &#8220;cycfg.h&#8221; on line 59.</p>
<p>In the file <strong>cy_eink_psoc_interface.c</strong></p>
<p>Create a context for the SPIM by adding on line 58:</p>
<pre class="start-line:58 EnlighterJSRAW" data-enlighter-language="c" ">cy_stc_scb_spi_context_t CY_EINK_SPIM_context;
</pre>
<p>The three timer functions in this file use the old PSoC Creator component timer interface APIs rather than the PDL interface.  So you will need to change Cy_EINK_TimerInit, Cy_EINK_GetTimeTick and Cy_EINK_TimerStop to use PDL.</p>
<p>Here is Cy_EINK_TimerInit</p>
<pre class="start-line:76 EnlighterJSRAW" data-enlighter-language="c" ">void Cy_EINK_TimerInit(void)
{   
    /* Clear the counter value and the counter variable */
    //CY_EINK_Timer_SetCounter(0);

    Cy_TCPWM_Counter_Init (CY_EINK_Timer_HW, CY_EINK_Timer_NUM, &amp;CY_EINK_Timer_config);
    Cy_TCPWM_Counter_SetCounter	(	CY_EINK_Timer_HW, CY_EINK_Timer_NUM,0);
    
    Cy_TCPWM_Enable_Multiple(	CY_EINK_Timer_HW,CY_EINK_Timer_MASK);
    /* Initialize the Timer */
    //CY_EINK_Timer_Start();
    Cy_TCPWM_TriggerStart	(	CY_EINK_Timer_HW,CY_EINK_Timer_MASK);
}
</pre>
<p>And Cy_EINK_GetTimeTick</p>
<pre class="start-line:106 EnlighterJSRAW" data-enlighter-language="c"">uint32_t Cy_EINK_GetTimeTick(void)
{
    /* Variable used to store the time tick */
    uint32_t timingCount;
    
    /* Read the current time tick from the E-INK Timer */
    //timingCount = CY_EINK_Timer_GetCounter();
    timingCount = Cy_TCPWM_Counter_GetCounter	(CY_EINK_Timer_HW, CY_EINK_Timer_NUM);


    /* Return the current value of time tick */
    return(timingCount);
}</pre>
<p>And Cy_EINK_TimerStop</p>
<pre class="start-line:136 EnlighterJSRAW" data-enlighter-language="c"">void Cy_EINK_TimerStop(void)
{
    /* Stop the E-INK Timer */
    //CY_EINK_Timer_Disable();
	Cy_TCPWM_Counter_Disable(CY_EINK_Timer_HW, CY_EINK_Timer_NUM);

}</pre>
<p>In  the file LCDConf.h change the include to stdint.h and make the type uint8_t instead of uint8</p>
<pre class="start-line:48 EnlighterJSRAW" data-enlighter-language="c"">#include  &lt;stdint.h&gt;
    
void LCD_CopyDisplayBuffer(uint8_t * destination, int count);</pre>
<p>In the file <strong>LCDConf.c</strong> remove the #include &#8220;<span>syslib</span>/cy_syslib.h&#8221; (I have no idea why it is/was there) and then add &#8220;<span>#include</span><span> </span>&lt;stdint.h&gt;&#8221;  On line 219 change &#8220;uint8&#8221; to be &#8220;uint8_t&#8221;</p>
<pre class="start-line:219 EnlighterJSRAW" data-enlighter-language="c" ">void LCD_CopyDisplayBuffer(uint8_t * destination, int count)
</pre>
<p>In the file <strong>cy_eink_fonts.h</strong> change the &#8220;#include &lt;project.h&gt;&#8221; to be</p>
<pre class="start-line:56 EnlighterJSRAW" data-enlighter-language="c" ">#include &lt;stdint.h&gt;
#include &lt;stdbool.h&gt;</pre>
<p>In <strong>main.c</strong> add an external reference to the eInkTask on line 36 (yes this is really ugly Alan)</p>
<pre class="start-line:36 EnlighterJSRAW" data-enlighter-language="c" ">extern void eInkTask(void *);
</pre>
<p>And start the eInkTask on line 58.  Notice that I put in 10K for the stacksize&#8230; but I dont actually know how much it takes.</p>
<pre class="start-line:58 EnlighterJSRAW" data-enlighter-language="c"">  	xTaskCreate( eInkTask,"eInkTask", 1024*10,  0,  1, 0  );
</pre>
<h1>Program &amp; Test the MTB Project</h1>
<p>When you program the development kit you should have</p>
<ol>
<li>A blinking RED LED</li>
<li>The ability to scroll through a bunch of screens using the SW2 button.</li>
</ol>
<p>Here is a picture</p>
<p><a href="https://iotexpert.com/2019/04/15/cy8ckit-028-epd-and-modus-toolbox-1-1/img_0433/" rel="attachment wp-att-6747"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0433-1024x608.jpg" alt="" width="1024" height="608" class="alignnone size-large wp-image-6747" srcset="https://iotexpert.com/wp-content/uploads/2019/04/IMG_0433-1024x608.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0433-600x356.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0433-300x178.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/04/IMG_0433-768x456.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article I will:</p>
<ol>
<li>Speed up the SPI</li>
<li>Get rid of the hardware timer</li>
<li>Explain more about the EINK.</li>
</ol>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/cy8ckit-028-epd-and-modus-toolbox-1-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6, DMA &#038; WS2812 LEDs</title>
		<link>https://iotexpert.com/psoc-6-dma-ws2812-leds/</link>
					<comments>https://iotexpert.com/psoc-6-dma-ws2812-leds/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 08 Jan 2019 15:14:32 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=6476</guid>

					<description><![CDATA[Summary At Electronica last fall my project included two strips of WS2812B LEDs.  These LEDs were controlled by a PSoC 4 UDB component that my friend Mark Hastings built.  Here is a link to his project called FunWithLEDs.  That was cool and everything but I wanted to drive the LEDs from my PSoC 6.  The [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>At Electronica last fall my project included two strips of <a href="http://www.world-semi.com/DownLoadFile/108" target="_blank" rel="noopener">WS2812B</a> LEDs.  These LEDs were controlled by a PSoC 4 UDB component that my friend Mark Hastings built.  Here is a <a href="https://community.cypress.com/thread/16543" target="_blank" rel="noopener">link</a> to his project called FunWithLEDs.  That was cool and everything but I wanted to drive the LEDs from my PSoC 6.  The problem that I have is that there are no UDBs in the PSoC 6-2M and I&#8217;m not really a bit-banging kind of guy&#8230; so this gave me a chance to use the PSoC 6 DMA.</p>
<p>In this article I will</p>
<ol>
<li>Show you how the WS2812B LEDs work</li>
<li>Give you a schematic for a PSoC 6 to drive them</li>
<li>Explain how to create and use a frame buffer for the LEDs</li>
<li>Explain the PSoC 6 DMA</li>
<li>Glue it all together in a project</li>
<li>Take you through debugging the code (I made several bugs)</li>
<li>Show you how to calculate and measure the performance</li>
<li>Take you through another layer of debugging</li>
<li>Explain DMA chaining</li>
<li>Automatically send the frameBuffer</li>
<li>Explain why I&#8217;m lucky it works</li>
</ol>
<h1>WS2812B</h1>
<p>The WS2812B LED strips are an almost arbitrary length (not quite true &#8211; more on this later) string of pixels that can be cascaded together via a serial line like this:</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-7-31-13-am/" rel="attachment wp-att-6501"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.31.13-AM.png" alt="" width="944" height="364" class="alignnone size-full wp-image-6501" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.31.13-AM.png 944w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.31.13-AM-600x231.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.31.13-AM-300x116.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.31.13-AM-768x296.png 768w" sizes="(max-width: 944px) 100vw, 944px" /></a></p>
<p>If you look on the internet you can purchase these strings in a whole bunch of different configurations e.g. <a href="https://www.mouser.com/All-Manufacturers/_/N-0?Keyword=WS2812&amp;FS=True" target="_blank" rel="noopener">Mouser</a> and <a href="https://www.adafruit.com/?q=neopixel" target="_blank" rel="noopener">Adafruit NeoPixel</a>.</p>
<p>Each pixel actually has three individual LEDs &#8211; Red, Green and Blue.  And each LED is attached to an 8-bit PWM, giving you 256 values of intensity &#8211; which is also known as 24-bit color because of 3 LEDs times 8-bit color.  Sometimes this is also known as 16 Million Colors.  To set the color of an individual pixel you it send three bytes, one each for Red, Green and Blue.  When the LED receives the reset code it takes the most recent RGB values and turns it on.</p>
<p>The communication protocol is cool.  When communication starts, a pixel takes its Red, Green and Blue value from the data stream, then passes on the rest of the bytes to the next pixels.  Basically each pixel peels off three bytes, then passes the rest through.  This scheme allows you to have almost any length string of pixels.  In the picture below you can see that the first pixels sees 3&#215;3 bytes.  The second sees 2&#215;3 bytes and the final pixel only sees its three bytes.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-7-30-26-am/" rel="attachment wp-att-6500"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM-1024x661.png" alt="" width="1024" height="661" class="alignnone size-large wp-image-6500" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM-1024x661.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM-600x387.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM-300x194.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM-768x496.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.30.26-AM.png 1658w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The only thing that is a bit weird in this protocol is that a &#8220;bit 1&#8221; is actually encoded as a long pulse of 1 followed by a short pulse of 0.  And a &#8220;bit 0&#8221; is short pulse of 1 followed by a long pulse of 0.  Here is a picture from the datasheet:</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-7-35-07-am/" rel="attachment wp-att-6502"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.35.07-AM.png" alt="" width="828" height="534" class="alignnone size-full wp-image-6502" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.35.07-AM.png 828w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.35.07-AM-600x387.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.35.07-AM-300x193.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.35.07-AM-768x495.png 768w" sizes="(max-width: 828px) 100vw, 828px" /></a></p>
<p>There is tons of blab-blabbing on the internet about how hard the timing is to deal with inside of the driver chip.  Here is the exact requirement:</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-7-46-50-am/" rel="attachment wp-att-6504"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM-1024x318.png" alt="" width="1024" height="318" class="alignnone size-large wp-image-6504" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM-1024x318.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM-600x186.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM-300x93.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM-768x238.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-7.46.50-AM.png 1534w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>My guess is that most of the heart ache is a result of people trying to bit-bang the protocol, which causes them to have to create fairly accurate, short timing loops.</p>
<p>But that isn&#8217;t what I am going to do.  But, Alan, what are you going to do?  First, observe from the table above that a T1H is double a T0H and a T0L is almost exactly double a T0H.  That means that the fundamental unit of time in this system is 0.4uS.  Which made me think to use the PSoC 6 to drive 0&#8217;s and 1&#8217;s out to the DI line of the first pixel at a rate of 1/0.4uS = 2.5 MHz using the SPI port.  This will let me encode 1 as 110 and encode 0 as 100.</p>
<h1>Schematic</h1>
<p>To build this project I started by making a new PSoC Creator Project.  I chose PSoC Creator instead of Modus Toolbox because I wanted to be able to use PSoC 4 component as well as PSoC 6.  My schematic has a SPI connected to DMA.  The DMA is connected to an interrupt.  A digital pin called &#8220;Red&#8221; which is attached to P0[3] on the board.  And finally a UART connected to the KitProg bridge.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-5-57-57-pm/" rel="attachment wp-att-6515"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-5.57.57-PM.png" alt="" width="940" height="718" class="alignnone size-full wp-image-6515" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-5.57.57-PM.png 940w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-5.57.57-PM-600x458.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-5.57.57-PM-300x229.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-5.57.57-PM-768x587.png 768w" sizes="(max-width: 940px) 100vw, 940px" /></a></p>
<p>In the SPI Configuration I remove the MISO pin (because we dont need SPI input data).  I could also remove the SCLK pin, but I left it attached so that I could see what was happening with an oscilloscope (which I needed when I was trying to figure out the bugs)</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-9-56-16-am/" rel="attachment wp-att-6512"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM-1024x550.png" alt="" width="1024" height="550" class="alignnone size-large wp-image-6512" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM-1024x550.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM-600x322.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM-300x161.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM-768x413.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.56.16-AM.png 1206w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The Basic SPI is configured with a data rate of 2500kbs which is also known as 0.4uS per bit, as well as an oversample rate of 4.  The state machine of the SPI needs an input clock which is at least 2x the data rate.  If the MISO was still attached it might need an even higher input clock rate in order to oversample the input.  Notice that I also have one slave select line, which I was using to trigger the oscilloscope.  In the real system, there is no slave to select so you can use a 0 there.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-6-29-08-pm/" rel="attachment wp-att-6517"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM-927x1024.png" alt="" width="927" height="1024" class="alignnone size-large wp-image-6517" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM-927x1024.png 927w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM-600x663.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM-272x300.png 272w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM-768x848.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-6.29.08-PM.png 974w" sizes="(max-width: 927px) 100vw, 927px" /></a><br />
<a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-06-at-9-48-18-am/" rel="attachment wp-att-6510"></a></p>
<p>On the Advanced table I enable &#8220;Dma Trigger on Tx Output&#8221; with the Fifo set to &#8220;63&#8221;.  This will cause the DMA trigger to be asserted anytime the transmit FIFO falls below 63 bytes.</p>
<p><a href="https://iotexpert.com/?attachment_id=6509" rel="attachment wp-att-6509"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM-1024x507.png" alt="" width="1024" height="507" class="alignnone size-large wp-image-6509" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM-1024x507.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM-600x297.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM-300x149.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM-768x380.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-06-at-9.48.56-AM.png 1624w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>WS2812 Framebuffer Code</h1>
<p>From the schematic above you can see that my plan is to DMA data out of a buffer into the SPI transmit FIFO.  Given that you need a 1 to be 110 and a 0 to be 100 this will require 3 output bytes for each RGV value.  And each pixel will take 3-bits per bit or 3*3*8 bits or 9 bytes total per pixel.</p>
<p>As an Application developer using the WS2812 library, it will be nice to have functions that let you think in 3-bytes (RGB) and the library will translate those values into the 9-bytes required by the SPI.  OK, lets build the library with that in mind.  First I make some defines to get rid of the magic numbers.  Then I make the frame buffer which will hold the 9-byte formatted information.  Notice that I have a define called &#8220;WS_OFFSET&#8221; which I will talk about in more detail later.</p>
<pre class="start-line:6 EnlighterJSRAW" data-enlighter-language="c"">#define WS_ZOFFSET (1)
#define WS_ONE3  (0b110&lt;&lt;24)
#define WS_ZERO3 (0b100&lt;&lt;24)
#define WS_NUM_LEDS (5)
#define WS_SPI_BIT_PER_BIT (3)
#define WS_COLOR_PER_PIXEL (3)
#define WS_BYTES_PER_PIXEL (WS_SPI_BIT_PER_BIT * WS_COLOR_PER_PIXEL)

static uint8_t WS_frameBuffer[WS_NUM_LEDS*WS_BYTES_PER_PIXEL+WS_ZOFFSET];
</pre>
<p>The next thing I create is a function to turn a 1-byte input into the 3-byte output.  It takes 1 bit at a time and then or&#8217;s in either 110 or 100.  It returns a uint32_t &#8230; but with the first byte is set to 0x0.</p>
<pre class="start-line:69 EnlighterJSRAW" data-enlighter-language="c" ">// Function: convert3Code
// This function takes an 8-bit value representing a color
// and turns it into a WS2812 bit code... where 1=110 and 0=011
// 1 input byte turns into three output bytes of a uint32_t
uint32_t WS_convert3Code(uint8_t input)
{
    uint32_t rval=0;
    for(int i=0;i&lt;8;i++)
    {
        if(input%2)
        {
            rval |= WS_ONE3;
        }
        else
        {
            rval |= WS_ZERO3;
        }
        rval = rval &gt;&gt; 3;
        
        input = input &gt;&gt; 1;
    }
    return rval;
}
</pre>
<p>This first helper function WS_setRGB  will configure a specific pixel in the frameBuffer to be the RGB value encoded as 9-bytes.  Notice that the order in the frameBuffer is Green, Red, Blue (not RGB order)</p>
<pre class="start-line:93 EnlighterJSRAW" data-enlighter-language="c"">// Function: WS_setRGB
// Takes a position and a three byte rgb value and updates the WS_frameBuffer with the correct 9-bytes
void WS_setRGB(int led,uint8_t red, uint8_t green, uint8_t blue)
{
    
    typedef union {
    uint8_t bytes[4];
    uint32_t word;
    } WS_colorUnion;
    
    WS_colorUnion color;
    color.word = WS_convert3Code(green);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+1+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+2+WS_ZOFFSET] = color.bytes[0];
    
    color.word = WS_convert3Code(red);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+3+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+4+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+5+WS_ZOFFSET] = color.bytes[0];

    color.word = WS_convert3Code(blue);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+6+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+7+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+8+WS_ZOFFSET] = color.bytes[0];
}</pre>
<h1>DMA Code &amp; Configuration</h1>
<p>The DMA configuration starts with the defaults.  The channel priority doesn&#8217;t matter as I am only using one channel in this design.  I left the default descriptors set to 1 &#8230; which actually turns out to be a problem later on in my debugging (more on this later)</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-07-at-5-16-07-am/" rel="attachment wp-att-6521"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM-1024x815.png" alt="" width="1024" height="815" class="alignnone size-large wp-image-6521" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM-1024x815.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM-600x477.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM-300x239.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM-768x611.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.07-AM.png 1438w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The descriptor is configured like this.  The configuration includes:</p>
<ol>
<li>The trigger output is unused</li>
<li>An interrupt at the end (which I dont use)</li>
<li>No chaining (meaning only on descriptor)</li>
<li>The channel is disabled at the end (which I reset in software)</li>
<li>One transfer per trigger (1-byte &#8211;&gt; 1 word)</li>
<li>As long as the trigger is active keep triggering (retrigger immediately)</li>
<li>My buffer has bytes&#8230; but the input to the FIFO is words so setup Byte&#8211;&gt;Word</li>
<li>Hardcoded to 4-bytes of transfer, but I change this with the firmware based on the size of the frameBuffer</li>
</ol>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-07-at-5-16-20-am/" rel="attachment wp-att-6520"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM-1024x812.png" alt="" width="1024" height="812" class="alignnone size-large wp-image-6520" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM-1024x812.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM-600x476.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM-300x238.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM-768x609.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-07-at-5.16.20-AM.png 1446w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The first bit of code is an interrupt service routine which is attached to the DMA chain.  When I was trying to debug this originally I used the ISR to toggle an LED when the DMA was complete.  Now it doesnt do anything, but I left it in case I want to add something later.</p>
<pre class="start-line:16 EnlighterJSRAW" data-enlighter-language="c"">// This is the interrupt handler for the WS DMA
// It doesnt do anything... and is just a stub
static void WS_DMAComplete(void)
{
    Cy_DMA_Channel_ClearInterrupt(WS_DMA_HW, WS_DMA_DW_CHANNEL);   
}
</pre>
<p>The function WS_DMAConfigure is used to:</p>
<ol>
<li>Initializes the DMA Descriptor</li>
<li>Initializes the interrupt (which doenst do anything)</li>
<li>Enables the DMA block</li>
</ol>
<pre class="start-line:23 EnlighterJSRAW" data-enlighter-language="c"">static void WS_DMAConfigure(void)
{
    /* Initialize descriptor */
    Cy_DMA_Descriptor_Init(&amp;WS_DMA_Descriptor_1, &amp;WS_DMA_Descriptor_1_config);
     
    /* Set source and destination for descriptor 1 */
    Cy_DMA_Descriptor_SetSrcAddress(&amp;WS_DMA_Descriptor_1, (uint8_t *)WS_frameBuffer);
    Cy_DMA_Descriptor_SetDstAddress(&amp;WS_DMA_Descriptor_1, (void *)&amp;WS_SPI_HW-&gt;TX_FIFO_WR);
    Cy_DMA_Descriptor_SetXloopDataCount(&amp;WS_DMA_Descriptor_1,sizeof(WS_frameBuffer));
    
     /* Initialize and enable the interrupt from WS_DMA */
    Cy_SysInt_Init(&amp;WS_DMA_INT_cfg, &amp;WS_DMAComplete);
    NVIC_EnableIRQ(WS_DMA_INT_cfg.intrSrc);
    Cy_DMA_Channel_SetInterruptMask(WS_DMA_HW, WS_DMA_DW_CHANNEL, WS_DMA_INTR_MASK);
    
    Cy_DMA_Enable(WS_DMA_HW);    
}

</pre>
<p>To actually make the DMA &#8220;go&#8221;, the function WS_DMATrigger sets up the DMA Channel, and then enables it.</p>
<pre class="start-line:41 EnlighterJSRAW" data-enlighter-language="c"">void WS_DMATrigger()
{
        /* Initialize the DMA channel */
    cy_stc_dma_channel_config_t channelConfig;	
    channelConfig.descriptor  = &amp;WS_DMA_Descriptor_1;
    channelConfig.preemptable = WS_DMA_PREEMPTABLE;
    channelConfig.priority    = WS_DMA_PRIORITY;
    channelConfig.enable      = false;
    Cy_DMA_Channel_Init(WS_DMA_HW, WS_DMA_DW_CHANNEL, &amp;channelConfig);
    Cy_DMA_Channel_Enable(WS_DMA_HW,WS_DMA_DW_CHANNEL);
}</pre>
<h1>Gluing it all together</h1>
<p>Now that we have a complete library, the last thing to do is build a command line interface to test it.   Lines 299-306 just get things going.  Then lines 308-310 turn on the systick timer and set it to a 1ms period.  I use the timer to trigger the DMA every 33ms.  The last part allows me to type a character and have it test a part of the system.</p>
<pre class="start-line:299 EnlighterJSRAW" data-enlighter-language="c" ">int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    UART_1_Start();
    setvbuf( stdin, NULL, _IONBF, 0 ); 
    printf("Started\n");   
    WS_Start();
    
    Cy_SysTick_Init(CY_SYSTICK_CLOCK_SOURCE_CLK_IMO,8000);
    Cy_SysTick_Enable();
    Cy_SysTick_SetCallback(0,WS_SysTickHandler);
 
    for(;;)
    {
        char c=getchar();
        switch(c)
        {        
            case 'u':
                printf("Enable auto DMA updating\n");
                Cy_SysTick_SetCallback(0,WS_SysTickHandler);
            break;
            case 'U':
                printf("Disable auto DMA updating\n");
                Cy_SysTick_SetCallback(0,0);
            break;
            case 't':
                printf("Trigger DMA\n");
                WS_DMATrigger();
            break;        
            case 'r':
                WS_setRGB(0,0xFF,0,0);
                printf("Set LED0 Red\n");
                break;
           case 'g':
                WS_setRGB(0,0,0xFF,0);
                printf("Set LED0 Green\n");
                break;            
            case 'O':
                WS_setRange(0,WS_NUM_LEDS-1,0,0,0);
                printf("Turn off all LEDs\n");
                break;
            case 'o':
                WS_setRange(0,WS_NUM_LEDS-1,0xFF,0xFF,0xFF);
                printf("Turn on all LEDs\n");
                break;
            case 'b':
                WS_setRGB(0,0,0,0xFF);
                printf("Set LED0 Blue\n");
                break;        
            case 'R':
                WS_setRange(0,WS_NUM_LEDS-1,0x80,0,0);
                printf("Turn on all LEDs RED\n");
                break;
            case 'G':
                WS_setRange(0,WS_NUM_LEDS-1,0,0x80,0);
                printf("Turn on all LEDs Green\n");
                break;
            case 'B':
                WS_setRange(0,WS_NUM_LEDS-1,0,0,0x80);
                printf("Turn on all LEDs Blue\n");
                break;     
            case 'a':
                WS_initMixColorRGB();
                printf("Turn on all LEDs RGB Pattern\n");
                break;
            case '?':
                printf("u\tEnable Auto Update of LEDs\n");
                printf("U\tDisable Auto Update of LEDs\n");
                printf("t\tTrigger the DMA\n");
                printf("r\tSet the first pixel Red\n");
                printf("g\tSet the first pixel Green\n");
                printf("b\tSet the first pixel Blue\n");
                printf("O\tTurn off all of the pixels\n");
                printf("o\tSet the pixels to white full on\n");
                printf("R\tSet all of the pixels to Red\n");
                printf("G\tSet all of the pixels to Green\n");
                printf("B\tSet all of the pixels to Blue\n");
                printf("a\tSet pixels to repeating RGBRGB\n");
                printf("?\tHelp\n");
                break;
        }
    }
}</pre>
<h1>Why is it not working?</h1>
<p>After all of that I programmed the PSoC&#8230;. and&#8230; I got nothing.  This made me very unhappy because I wondered what the cause was.  Specifically, I was worried that I didn&#8217;t understand how to talk to the WS2812Bs.</p>
<p>My first step in debugging the problem was to get out the oscilloscope.  When I captured the data here is what I got.  The blue trace is the MOSI line which is driving the LED string, and the yellow trace is the SPI clock.  You can see from the measurement that the clock pulses are 392ns = 0.39uS &#8230; thats good.  You can see in the picture that the first &#8220;pulse&#8221; on the blue line  is 2 clocks long, thats good, but it is immediately followed by a 2 clock long 0.  That isn&#8217;t good.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/tek00001-4/" rel="attachment wp-att-6478"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/TEK00001.png" alt="" width="480" height="234" class="alignnone size-large wp-image-6478" srcset="https://iotexpert.com/wp-content/uploads/2019/01/TEK00001.png 480w, https://iotexpert.com/wp-content/uploads/2019/01/TEK00001-300x146.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a></p>
<p>Hang on I need 110 for 1 and 100 for 0&#8230; but I got 110 then 011.  No good.  Here is the code with the bug</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ONE3  (0b110&lt;&lt;24)
#define ZERO3 (0b011&lt;&lt;24)</pre>
<p>Once I fix that to be</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ONE3  (0b110&lt;&lt;24)
#define ZERO3 (0b100&lt;&lt;24)</pre>
<p>Things look good now.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/tek00002-4/" rel="attachment wp-att-6477"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/TEK00002.png" alt="" width="480" height="234" class="alignnone size-full wp-image-6477" srcset="https://iotexpert.com/wp-content/uploads/2019/01/TEK00002.png 480w, https://iotexpert.com/wp-content/uploads/2019/01/TEK00002-300x146.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a></p>
<p>However, this bug is really stupid because I did a partial job putting in unit test.  Here is the stupid part.  I wrote this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    setRGB(0,0,0x80,0);
  
    for(int i=0;i&lt;10;i++)
    {
        printf("%02X ",frameBuffer[i]);
    }
    printf("\n");
    
    printf("Test 0x00 = %0X\n",convert3Code(0));
    printf("Test 0xFF = %0X\n",convert3Code(0xFF));
    printf("Test 0x80 = %0X\n",convert3Code(0x80));
</pre>
<p>Which yielded</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-05-at-10-17-18-am/" rel="attachment wp-att-6486"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.17.18-AM.png" alt="" width="661" height="421" class="alignnone size-full wp-image-6486" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.17.18-AM.png 661w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.17.18-AM-600x382.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.17.18-AM-300x191.png 300w" sizes="(max-width: 661px) 100vw, 661px" /></a></p>
<p>What would have been much better would have been to do this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    setRGB(0,0,0x80,0);
  
    for(int i=0;i&lt;10;i++)
    {
        printf("%02X ",frameBuffer[i]);
    }
    printf("\n");
    
    printf("Test 0x00 = %0X\n",convert3Code(0));
    printf("Test 0xFF = %0X\n",convert3Code(0xFF));
    printf("Test 0x80 = %0X\n",convert3Code(0x80));
    
    CY_ASSERT(convert3Code(0x00) == 0b00000000100100100100100100100100);
    CY_ASSERT(convert3Code(0xFF) == 0b00000000110110110110110110110110);
    CY_ASSERT(convert3Code(0x80) == 0b00000000110100100100100100100100);
</pre>
<p>Which would have put me here when the assert failed:</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-05-at-10-23-40-am/" rel="attachment wp-att-6487"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM-1024x804.png" alt="" width="1024" height="804" class="alignnone size-large wp-image-6487" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM-1024x804.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM-600x471.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM-300x235.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM-768x603.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-10.23.40-AM.png 1046w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>How long does it take to run?</h1>
<p>The next thing that I was curious about is how long does it take to dump one frameBuffer into the LED string.  Well, the simplest thing seems to be to setup a longer transaction (25 LEDs) and then measure.  In the screen shot below you can see that is 721 uS for 25 LEDs or about 29uS per LED.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/tek00005-2/" rel="attachment wp-att-6484"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/TEK00005.png" alt="" width="480" height="234" class="alignnone size-full wp-image-6484" srcset="https://iotexpert.com/wp-content/uploads/2019/01/TEK00005.png 480w, https://iotexpert.com/wp-content/uploads/2019/01/TEK00005-300x146.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a></p>
<p>Which I suppose makes sense as 1 LED is 9 bytes or 9*8=72 bits at 0.4uS per but = 28.8uS.  This means 1000 LEDs is about 29 milliseconds.  Which means that you can easily do 1000 LEDs at 30Hz.</p>
<h1>Why is it &#8220;yellow&#8221;?</h1>
<p>As I was testing the runtime I noticed that the first LED of the chain was always yellow.  Why is that? (Notice that the LEDs are too bright to take a picture of and you can really only see the yellow in the reflection)</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/img_0148/" rel="attachment wp-att-6490"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/IMG_0148-1024x377.jpg" alt="" width="1024" height="377" class="alignnone size-large wp-image-6490" srcset="https://iotexpert.com/wp-content/uploads/2019/01/IMG_0148-1024x377.jpg 1024w, https://iotexpert.com/wp-content/uploads/2019/01/IMG_0148-600x221.jpg 600w, https://iotexpert.com/wp-content/uploads/2019/01/IMG_0148-300x110.jpg 300w, https://iotexpert.com/wp-content/uploads/2019/01/IMG_0148-768x282.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I looked at the oscilloscope trace I notice that the pulse width of the first &#8220;1&#8221; was 1.2uS (the blue line is the data).  This is a result of the Serial Communication Block SPI pulling up the MOSI line a good while before it enables the chip select (the purple trace) which has the effect of making a very long 1 to start with.  This obviously is not a problem for the SPI protocol as it is clocked by the serial clock line.  But in this case where the LEDs are self-clocked it makes for a long 1.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/tek00004-2/" rel="attachment wp-att-6480"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/TEK00004.png" alt="" width="480" height="234" class="alignnone size-full wp-image-6480" srcset="https://iotexpert.com/wp-content/uploads/2019/01/TEK00004.png 480w, https://iotexpert.com/wp-content/uploads/2019/01/TEK00004-300x146.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a></p>
<p>OK, how do I fix that?  The cheap way to fix this is to make the first bit of the sequence a 0.  But, that would be a major pain because that would effectively shift every bit in the frame buffer over by 1-bit which is a pain in the ass.  So, to fix it I just make the entire first byte of the buffer be 0 which means it takes an extra byte and 8&#215;0.4 uS = 3.2uS longer.  No big deal.</p>
<p>The code change is to add 1 byte to the buffer (which I called the WS_ZOFFSET)</p>
<pre class="start-line:11 EnlighterJSRAW" data-enlighter-language="c"">#define WS_ZOFFSET (1)
#define WS_ONE3  (0b110&lt;&lt;24)
#define WS_ZERO3 (0b100&lt;&lt;24)
#define WS_NUM_LEDS (5)
#define WS_SPI_BIT_PER_BIT (3)
#define WS_COLOR_PER_PIXEL (3)
#define WS_BYTES_PER_PIXEL (WS_SPI_BIT_PER_BIT * WS_COLOR_PER_PIXEL)

static uint8_t WS_frameBuffer[WS_NUM_LEDS*WS_BYTES_PER_PIXEL+WS_ZOFFSET];
</pre>
<p>Then offset all of the writes by WS_ZOFFSET</p>
<pre class="start-line:97 EnlighterJSRAW" data-enlighter-language="c"">// Function: WS_setRGB
// Takes a position and a three byte rgb value and updates the WS_frameBuffer with the correct 9-bytes
void WS_setRGB(int led,uint8_t red, uint8_t green, uint8_t blue)
{
    
    typedef union {
    uint8_t bytes[4];
    uint32_t word;
    } WS_colorUnion;
    
    WS_colorUnion color;
    color.word = WS_convert3Code(green);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+1+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+2+WS_ZOFFSET] = color.bytes[0];
    
    color.word = WS_convert3Code(red);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+3+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+4+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+5+WS_ZOFFSET] = color.bytes[0];

    color.word = WS_convert3Code(blue);
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+6+WS_ZOFFSET] = color.bytes[2];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+7+WS_ZOFFSET] = color.bytes[1];
    WS_frameBuffer[led*WS_BYTES_PER_PIXEL+8+WS_ZOFFSET] = color.bytes[0];
}</pre>
<h1>Why did it crash?</h1>
<p>While I was testing the runtime of the DMA loop, I kept increasing the number of LEDs.  When I typed 30, the PSoC crashed and was no longer responsive.  When this happens it is always useful to click on &#8220;Debug-&gt;Attach to Running Target&#8221;.  When I did that I ended up with this screen.  This tells me that there was an assert that was triggered.  When I hovered over the CY_DMA_IS_COUNT_VALID I realized that you can only DMA 256 bytes per descriptor&#8230; and with 30 LEDs I need 270 bytes&#8230; which means that I need to chain descriptors.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-05-at-9-43-04-am/" rel="attachment wp-att-6481"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM-990x1024.png" alt="" width="990" height="1024" class="alignnone size-large wp-image-6481" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM-990x1024.png 990w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM-600x621.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM-290x300.png 290w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM-768x794.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-05-at-9.43.04-AM.png 1046w" sizes="(max-width: 990px) 100vw, 990px" /></a></p>
<h1>Chaining DMA Descriptors</h1>
<p>You are allowed to create multiple DMA descriptors in the component configuration like this:</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-08-at-8-59-21-am/" rel="attachment wp-att-6532"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.21-AM.png" alt="" width="841" height="652" class="alignnone size-large wp-image-6532" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.21-AM.png 841w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.21-AM-600x465.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.21-AM-300x233.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.21-AM-768x595.png 768w" sizes="(max-width: 841px) 100vw, 841px" /></a></p>
<p>Which will give you three descriptors to configure.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-08-at-8-59-33-am/" rel="attachment wp-att-6531"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.33-AM.png" alt="" width="841" height="654" class="alignnone size-full wp-image-6531" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.33-AM.png 841w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.33-AM-600x467.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.33-AM-300x233.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-8.59.33-AM-768x597.png 768w" sizes="(max-width: 841px) 100vw, 841px" /></a></p>
<p>And when you build the code you will find configuration structures for each of the descriptors in the generated source.  Here is a clip of code from then WS_DMA.C (which PSoC Creator generates)</p>
<pre class="start-line:52 EnlighterJSRAW" data-enlighter-language="c" ">const cy_stc_dma_descriptor_config_t WS_DMA_Descriptor_2_config =
{
    .retrigger       = CY_DMA_RETRIG_IM,
    .interruptType   = CY_DMA_1ELEMENT,
    .triggerOutType  = CY_DMA_1ELEMENT,
    .channelState    = CY_DMA_CHANNEL_ENABLED,
    .triggerInType   = CY_DMA_1ELEMENT,
    .dataSize        = CY_DMA_WORD,
    .srcTransferSize = CY_DMA_TRANSFER_SIZE_DATA,
    .dstTransferSize = CY_DMA_TRANSFER_SIZE_DATA,
    .descriptorType  = CY_DMA_SINGLE_TRANSFER,
    .srcAddress      = NULL,
    .dstAddress      = NULL,
    .srcXincrement   = 1L,
    .dstXincrement   = 1L,
    .xCount          = 1UL,
    .srcYincrement   = 1L,
    .dstYincrement   = 1L,
    .yCount          = 1UL,
    .nextDescriptor  = NULL
};

cy_stc_dma_descriptor_t WS_DMA_Descriptor_2 =
{
    .ctl = 0UL,
    .src = 0UL,
    .dst = 0UL,
    .xCtl = 0UL,
    .yCtl = 0UL,
    .nextPtr = 0UL
};
</pre>
<p>The problem is that it will be much better for the user of the WS2812 library to be able to configure the number of LEDs have it adjust the DMA chain automatically.  So, to chain the DMA Descriptors together I created my own descriptor initialization code:</p>
<ol>
<li>Calculate the number of descriptors required by looking at the sizeof the WS_frameBuffer.  You need to have at least 1.</li>
<li>Create an array with enough descriptors</li>
<li>Copy one of the descriptor initialization structures into my code (from the generated source), so that I can use the Cy_DMA_Descriptor_Init function</li>
<li>Loop through all of the descriptors and initialize them.  Notice that I make the next descriptor be the next descriptor in the array</li>
<li>The last descriptor will have less bytes, no next descriptor and you want to disable the channel when it is done</li>
</ol>
<pre class="start-line:23 EnlighterJSRAW" data-enlighter-language="c"">#define WS_NUM_DESCRIPTORS (sizeof(WS_frameBuffer) / 256 + 1)
static cy_stc_dma_descriptor_t WSDescriptors[WS_NUM_DESCRIPTORS];


static void WS_DMAConfigure(void)
{
    // I copies this structure from the PSoC Creator Component configuration 
    // in generated source
    const cy_stc_dma_descriptor_config_t WS_DMA_Descriptors_config =
    {
    .retrigger       = CY_DMA_RETRIG_IM,
    .interruptType   = CY_DMA_DESCR_CHAIN,
    .triggerOutType  = CY_DMA_1ELEMENT,
    .channelState    = CY_DMA_CHANNEL_ENABLED,
    .triggerInType   = CY_DMA_1ELEMENT,
    .dataSize        = CY_DMA_BYTE,
    .srcTransferSize = CY_DMA_TRANSFER_SIZE_DATA,
    .dstTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
    .descriptorType  = CY_DMA_1D_TRANSFER,
    .srcAddress      = NULL,
    .dstAddress      = NULL,
    .srcXincrement   = 1L,
    .dstXincrement   = 0L,
    .xCount          = 256UL,
    .srcYincrement   = 0L,
    .dstYincrement   = 0L,
    .yCount          = 1UL,
    .nextDescriptor  = 0
    };

    for(unsigned int i=0;i&lt;WS_NUM_DESCRIPTORS;i++)
    {
        Cy_DMA_Descriptor_Init(&amp;WSDescriptors[i], &amp;WS_DMA_Descriptors_config);
        Cy_DMA_Descriptor_SetSrcAddress(&amp;WSDescriptors[i], (uint8_t *)&amp;WS_frameBuffer[i*256]);
        Cy_DMA_Descriptor_SetDstAddress(&amp;WSDescriptors[i], (void *)&amp;WS_SPI_HW-&gt;TX_FIFO_WR);
        Cy_DMA_Descriptor_SetXloopDataCount(&amp;WSDescriptors[i],256); // the last
        Cy_DMA_Descriptor_SetNextDescriptor(&amp;WSDescriptors[i],&amp;WSDescriptors[i+1]);
    }
    
    // The last one needs a bit of change
    Cy_DMA_Descriptor_SetXloopDataCount(&amp;WSDescriptors[WS_NUM_DESCRIPTORS-1],sizeof(WS_frameBuffer)-256*(WS_NUM_DESCRIPTORS-1)); // the last
    Cy_DMA_Descriptor_SetNextDescriptor(&amp;WSDescriptors[WS_NUM_DESCRIPTORS-1],0);
    Cy_DMA_Descriptor_SetChannelState(&amp;WSDescriptors[WS_NUM_DESCRIPTORS-1],CY_DMA_CHANNEL_DISABLED);
 
    
     /* Initialize and enable the interrupt from WS_DMA */
    Cy_SysInt_Init(&amp;WS_DMA_INT_cfg, &amp;WS_DMAComplete);
    NVIC_EnableIRQ(WS_DMA_INT_cfg.intrSrc);
    Cy_DMA_Channel_SetInterruptMask(WS_DMA_HW, WS_DMA_DW_CHANNEL, WS_DMA_INTR_MASK);
    
    Cy_DMA_Enable(WS_DMA_HW);    
}
</pre>
<p>With all of that done, the last change is to change the DMA channel initialization code to use the correct first descriptor</p>
<pre class="start-line:76 EnlighterJSRAW" data-enlighter-language="c" ">void WS_DMATrigger()
{
    cy_stc_dma_channel_config_t channelConfig;	
    channelConfig.descriptor  = &amp;WSDescriptors[0];
    channelConfig.preemptable = WS_DMA_PREEMPTABLE;
    channelConfig.priority    = WS_DMA_PRIORITY;
    channelConfig.enable      = false;
    Cy_DMA_Channel_Init(WS_DMA_HW, WS_DMA_DW_CHANNEL, &amp;channelConfig);
    Cy_DMA_Channel_Enable(WS_DMA_HW,WS_DMA_DW_CHANNEL);
}</pre>
<h1>Automatically send the Frame Buffer</h1>
<p>I initially &#8220;triggered&#8221; the DMA using keyboard commands that called the function WS_DMATrigger.  But after I got things working I realized that what I really wanted to do was update the &#8220;screen&#8221; aka the strip of LEDs at about 30Hz.  To do this I turn on the ARM SysTick timer to call my function WS_SysTickHandler every 1ms.</p>
<pre class="start-line:335 EnlighterJSRAW" data-enlighter-language="c" ">    Cy_SysTick_Init(CY_SYSTICK_CLOCK_SOURCE_CLK_IMO,8000);
    Cy_SysTick_Enable();
</pre>
<p>In the WS_SysTickHandler, I count the number of times I have been called and store it in a static variable called &#8220;count&#8221;.  When count gets to 33 (or greater) meaning that 33mS has gone by, I check to make sure that the DMA is disabled and then I call the update function.  I also reset the timer back to 0.</p>
<pre class="start-line:87 EnlighterJSRAW" data-enlighter-language="c"">void WS_SysTickHandler()
{
    static int count=0;
    if((Cy_DMA_Channel_GetStatus(WS_DMA_HW,WS_DMA_DW_CHANNEL) &amp; CY_DMA_INTR_CAUSE_COMPLETION) &amp;&amp; count++&gt;32)
    {
        WS_DMATrigger();
        count = 0;
    }
}</pre>
<p>With that installed I get a nice 30Hz update.  The screenshot below is configured with 144 Pixels and it take 4.15mS to update the screen which is about a 12% duty cycle.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/tek00008/" rel="attachment wp-att-6534"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/TEK00008.png" alt="" width="480" height="234" class="alignnone size-full wp-image-6534" srcset="https://iotexpert.com/wp-content/uploads/2019/01/TEK00008.png 480w, https://iotexpert.com/wp-content/uploads/2019/01/TEK00008-300x146.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a></p>
<h1>I&#8217;m Lucky it Works</h1>
<p>The last thing to observe in all of this is that I am driving the LED string with a 5V wall wart.</p>
<p>And according to the datasheet VIH is 0x7 * VDD = 3.5V &#8230; and I am driving it with a PSoC 6 with 3.3V.  Oh well.</p>
<p><a href="https://iotexpert.com/2019/01/08/psoc-6-dma-ws2812-leds/screen-shot-2019-01-08-at-9-36-17-am/" rel="attachment wp-att-6535"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM-1024x253.png" alt="" width="1024" height="253" class="alignnone size-large wp-image-6535" srcset="https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM-1024x253.png 1024w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM-600x148.png 600w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM-300x74.png 300w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM-768x190.png 768w, https://iotexpert.com/wp-content/uploads/2019/01/Screen-Shot-2019-01-08-at-9.36.17-AM.png 1310w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>All of this source code is available at <a href="https://github.com/iotexpert/WS2812" target="_blank" rel="noopener">GitHub</a> or you can clone git@github.com:iotexpert/WS2812.git</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-dma-ws2812-leds/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Matrix Orbital GTT43A: PSoC 4 Interface</title>
		<link>https://iotexpert.com/matrix-orbital-gtt43a-psoc-4-interface/</link>
					<comments>https://iotexpert.com/matrix-orbital-gtt43a-psoc-4-interface/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Thu, 24 May 2018 12:00:10 +0000</pubDate>
				<category><![CDATA[CY8CKIT-044]]></category>
		<category><![CDATA[Matrix Orbital]]></category>
		<category><![CDATA[PSoC 4200]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=5143</guid>

					<description><![CDATA[Summary In the last several articles I have written about how to use and talk to the Matrix Orbital GTT43A.  Now it is time to write some code.  The PSoC4 program that I am going to show you has evolved over time as I added stuff to it.  For instance, while I was working on [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In the last several articles I have written about how to use and talk to the <a href="https://www.matrixorbital.com/gtt43a" target="_blank" rel="noopener">Matrix Orbital GTT43A</a>.  Now it is time to write some code.  The PSoC4 program that I am going to show you has evolved over time as I added stuff to it.  For instance, while I was working on this program I ran into a problem where the I2C Bus would hang (the subject of the next article).  As such, some of the code that is in this program was written to help me debug that problem.  With that said, I wanted a program that:</p>
<ol>
<li>Is command line driven i.e. I can interact with my program via serial commands through the PC COM Port</li>
<li>Can read 1 byte at a time (like I do on the bridge control panel)</li>
<li>Can test the &#8220;read whole packet&#8221; code</li>
<li>Can selectively send commands via a I2C or the UART</li>
<li>Send test commands to the display e.g. reset, clear</li>
<li>Test the display generated messages (like button presses)</li>
</ol>
<p>All of this code was built to run on the <a href="http://www.cypress.com/documentation/development-kitsboards/cy8ckit-044-psoc-4-m-series-pioneer-kit" target="_blank" rel="noopener">CY8CKIT-044</a> which has a PSoC 4200M MCU</p>
<h1>Schematic &amp; Pin Assignment</h1>
<p>All PSoC 4 projects start with a schematic.  In my schematic I have a UART setup to talk to the KitProg (called UART) and serve as the command processor, an I2C which directly attaches to the I2C bus that drives the display, and a UART that is also attached to the display which I called SCRUART.</p>
<p>The I2CFAIL pin in the schematic I used to help me debug the I2C problem (the subject of the next article)</p>
<p><a href="https://iotexpert.com/?attachment_id=5254" rel="attachment wp-att-5254"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.07-PM.png" alt="PSoC 4200m Schematic" width="347" height="349" class="alignnone wp-image-5254 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.07-PM.png 347w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.07-PM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.07-PM-150x150.png 150w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.07-PM-298x300.png 298w" sizes="(max-width: 347px) 100vw, 347px" /></a></p>
<p>The pin assignment has the UART attached to the KitProg UART, the I2C attached to KitProg and the Display.  The SCRUART is attached to UART on the Display.</p>
<p><a href="https://iotexpert.com/?attachment_id=5253" rel="attachment wp-att-5253"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.18-PM.png" alt="PSoC 4200M Pin Assignment" width="456" height="204" class="alignnone wp-image-5253 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.18-PM.png 456w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-21-at-12.29.18-PM-300x134.png 300w" sizes="(max-width: 456px) 100vw, 456px" /></a></p>
<p>&nbsp;</p>
<h1>Main Event Loop</h1>
<p>The main event loop has the following parts</p>
<ol>
<li>Read a character from the keyboard</li>
<li>Process the keyboard command character</li>
<li>Read data from the screen
<ol>
<li>If you are in packet mode read a whole packet</li>
<li>If you are in streaming mode read one byte</li>
</ol>
</li>
</ol>
<p>There are three system modes.</p>
<ol>
<li>IDLE = Dont read from the screen</li>
<li>PACKET = Read whole packets (poll for complete packets)</li>
<li>STREAMING = read bytes (polling)</li>
</ol>
<p>I also have setup the program to read/write bytes to the UART and I2C.  This is called the &#8220;comInterface&#8221;.</p>
<p>The enumerated type systemMode is used to setup the polling mode (each time through the main loop, what does it do?).</p>
<pre class="start-line:18 lang:c decode:true">typedef enum {
    MODE_IDLE,
    MODE_PACKET,
    MODE_STREAMING
} systemMode_t;

systemMode_t systemMode=MODE_IDLE;

typedef enum {
    INTERFACE_I2C,
    INTERFACE_UART
} cominterface_t;

cominterface_t comInterface=INTERFACE_I2C;
</pre>
<p>The actual main section of the code</p>
<ol>
<li>Starts by initializing the UART, SCRUART and I2C.</li>
<li>On line 299 it reads a character, then switches on the character to figure out which command the user has type.</li>
</ol>
<p>You can see that &#8216;u&#8217; and &#8216;U&#8217; change the communication interface from UART to I2C and back.</p>
<pre class="start-line:285 lang:c decode:true">int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    uint32 returncode;
    
    UART_Start();
    UART_UartPutString("Started\r\n");
    I2C_Start();
    SCRUART_Start();
    
    char c;
     
    for(;;)
    {
        c = UART_UartGetChar();
        switch(c)
        {
            case 0:
            break;
            
            case 'u':
                UART_UartPutString("I2C Mode\r\n");
                comInterface = INTERFACE_I2C;
            break;
            
            case 'U':
                UART_UartPutString("UART Mode\r\n");
                comInterface = INTERFACE_UART;
            break;
</pre>
<p>The end of the loop handles the &#8220;?&#8221; case&#8230; in other words print out all of the commands.  Then based on the system mode, it either reads a whole message packet from the display or it reads only byte.</p>
<pre class="start-line:398 lang:c decode:true">           case '?':
                UART_UartPutString("------Communication Mode------\r\n");
                UART_UartPutString("u\tI2C Mode\r\n");
                UART_UartPutString("U\tUART Mode\r\n");
                
                UART_UartPutString("------GTT43A Commands------\r\n");
                UART_UartPutString("N\tDefault Comm None\r\n");
                UART_UartPutString("I\tDefault Comm I2C\r\n");
                UART_UartPutString("S\tDefault Comm Serial\r\n");
                
                UART_UartPutString("e\tEcho abc\r\n");
                UART_UartPutString("R\tReset\r\n");
                UART_UartPutString("c\tSend Clear Screen\r\n");
                
                UART_UartPutString("------Communcation Commands------\r\n");
                UART_UartPutString("r\tRead one byte if IDLE\r\n");
                UART_UartPutString("p\tRead Packet if IDLE\r\n");
                
                UART_UartPutString("------System Mode------\r\n");
                UART_UartPutString("0\tTurn I2C polling off \r\n");
                UART_UartPutString("1\tTurn on I2C packet polling\r\n");
                UART_UartPutString("2\tRead i2c bytes \r\n");
                
                UART_UartPutString("------I2C Debugging------\r\n");
                UART_UartPutString("s\tPrint SCB Status\r\n");
                UART_UartPutString("z\tSend I2C Reset Sequence\r\n");
                UART_UartPutString("x\tPrint I2C SCL and SDA value\r\n");
            break;
        }
        
        switch(systemMode)
        {
            case MODE_IDLE:
            break;
            
            case MODE_PACKET:
                readPacket();
            break;
                
            case MODE_STREAMING:
                readByte();
            break;
        }</pre>
<p>I created three keys (0,1,2) to change the system mode, from IDLE, to reading whole packets to reading bytes.</p>
<pre class="start-line:361 lang:c decode:true ">            // System Modes
            case '0':
                    I2CFAIL_Write(0);
                    UART_UartPutString("Packet Poling Off\r\n");
                    systemMode = MODE_IDLE;
                break;
               
            case '1':
                    I2CFAIL_Write(0);
                    UART_UartPutString("Packet Poling On\r\n");
                    systemMode = MODE_PACKET;
            break;
            case '2':
                    I2CFAIL_Write(0);
                    UART_UartPutString("Read continuous\r\n");
                    systemMode = MODE_STREAMING;
                    break;
</pre>
<p>While I was trying to figure out how things worked I wanted to be able to do one thing at a time. So I create &#8216;r&#8217; to read one byte (like Bridge Control Panel) and &#8216;p&#8217; to read a whole packet.  Notice that you really really only want to do this why you are not polling the display.</p>
<pre class="start-line:347 EnlighterJSRAW" data-enlighter-language="c" ">            // If you are IDLE you can read 1 byte with 'r' or read a whole packet with 'p'
            case 'r':  // Read byte
                if(systemMode != MODE_IDLE)
                    break;
                readByte(&amp;data);
                
            break;
            case 'p': // read packet
                if(systemMode == MODE_IDLE)
                    readPacketI2C();
            break;
</pre>
<p>The last section of commands send various GTT2.0 commands to the display.  Notice that the writePacket function knows which system interface to use (either I2C or UART).</p>
<p>First, I declare some commands, just an array of bytes.</p>
<pre class="start-line:6 lang:c decode:true ">// These commands come the GTT 2.0 and GTT2.5 Protocol Manuals
uint8 clearCMD[] = { 0x58 };
uint8 resetCMD[] = { 0x01};
uint8 comI2CCMD[] = { 0x05, 0x02};
uint8 comNONECMD[] = { 0x05, 0x00};
uint8 comSERIALCMD[] = { 0x05, 0x01};
uint8 comECHOCMD[] = {0xFF,'a','b','c', 0};
</pre>
<p>Then I use them:</p>
<pre class="start-line:318 EnlighterJSRAW" data-enlighter-language="c" ">            case 'e':
                UART_UartPutString("Send Echo Command\r\n");
                writePacket(sizeof(comECHOCMD) , comECHOCMD);
            break;
                
            case 'c':
                UART_UartPutString("Sent Clear String\r\n");
                writePacket(sizeof(clearCMD),clearCMD);
            break;
            case 'R':
                UART_UartPutString("Sent Reset String\r\n");
                writePacket(sizeof(resetCMD),resetCMD);
            break;
            case 'I':
                UART_UartPutString("I2C Communcation Channel\r\n");
                writePacket(sizeof(comI2CCMD),comI2CCMD);
            break;
            case 'N':
                UART_UartPutString("NONE Communcation Channel\r\n");
                writePacket(sizeof(comNONECMD),comNONECMD);
            break;</pre>
<h1>Read Byte</h1>
<p>In order to read one byte from the display I first determine which mode Im in, then call the appropriate sub-function.</p>
<pre class="start-line:269 lang:c decode:true ">uint32_t readByte(uint8_t *data)
{
    uint32_t returncode=0;
    switch(comInterface)
    {
        case INTERFACE_I2C:
            returncode = readByteI2C(data);
        break;
        case INTERFACE_UART:
            returncode = readByteUART(data);
        break;
    }
    sprintf(buff,"Returncode = %X Data=%d\r\n",(unsigned int)returncode,*data);
    UART_UartPutString(buff);

    return returncode;
}</pre>
<p>The first sub function to read bytes via I2C.  To read a byte with no error checking you have to</p>
<ol>
<li>Send a Start</li>
<li>Send the address</li>
<li>Send the Read bit</li>
<li>Clock it 8 times (this is exactly what the I2CMasterReadByte function does)</li>
<li>Send an NAK</li>
<li>Send a Stop</li>
</ol>
<p>I ran into an I2C issue which I will talk about in the next article, however, if I see an error from any of these commands Ill put the system into MODE_IDLE and throw an error.  In addition I write a 1 to the I2CFAIL pin, which I am using to trigger the Oscilliscope (so I can see what is happening)</p>
<pre class="start-line:221 lang:c decode:true ">uint32_t readByteI2C(uint8_t *data)
{
    uint32 returncode;
    returncode = I2C_I2CMasterSendStart(I2CADDR,I2C_I2C_READ_XFER_MODE , I2CTIMEOUT);
    if(returncode)
    {
        sprintf(buff,"send start error %lX status %lX\r\n",returncode,I2C_I2CMasterStatus());
        UART_UartPutString(buff);
        I2CFAIL_Write(1);
        systemMode = MODE_IDLE;
        goto cnt;
    }
            
    returncode = I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA,data,I2CTIMEOUT);
    if(returncode)
    {
        sprintf(buff,"read byte error %lX status %lX sda=%d scl =%d\r\n",returncode,I2C_I2CMasterStatus(),I2C_sda_Read(),I2C_scl_Read());
        UART_UartPutString(buff);
        I2CFAIL_Write(1);
        systemMode = MODE_IDLE;
        goto cnt;
    }
            
    returncode = I2C_I2CMasterSendStop(I2CTIMEOUT);
    if(returncode)
    {
        sprintf(buff,"send stop error %lX status %lX\r\n",returncode,I2C_I2CMasterStatus());
        UART_UartPutString(buff);
        I2CFAIL_Write(1);
        systemMode = MODE_IDLE;
        goto cnt;
    }
    
    cnt:
    return returncode;
}
</pre>
<h1>Read Packet</h1>
<p>For the packet read code I did the same thing as the byte read code.  Specifically I wrote an overall get packet, then called the correct read packet based on the</p>
<p>If you read the source code that Matrix Orbital gives you for drivers, you will find that it reads one byte at a time.  The problem with doing this is that you</p>
<ol>
<li>Send a start</li>
<li>Send an I2C address</li>
<li>Send a read bit</li>
<li>Read the ACK</li>
<li>Read a byte</li>
<li>Send a NAK</li>
<li>Send a stop</li>
</ol>
<p>The problem with this approach is that it uses 11 bit-times extra per byte of overhead (steps 1-4) which kinda sucks.  So I wanted to write a complete packet reader.  My packet reader will</p>
<ol>
<li>Send a start</li>
<li>Send an I2C address</li>
<li>Send a read bit</li>
<li>Read the ACK</li>
<li>Read a byte  [This is the 254 that marks the start of the packet]</li>
<li>ACK</li>
<li>Read a byte [This is the command which identifies the packet]</li>
<li>ACK</li>
<li>Read a byte [The MSB of the Length]</li>
<li>ACK</li>
<li>Read a byte [The LSB of the Length]</li>
<li>NAK</li>
<li>If there is a length then:</li>
<li>Send the start</li>
<li>Send an I2C address</li>
<li>Send a read bit</li>
<li>Read the ACK</li>
<li>read length -1 bytes</li>
<li>ACK</li>
<li>Read the last byte</li>
<li>Send a NAK</li>
<li>Send a stop</li>
</ol>
<p>By spec you are supposed to NAK your last read byte to indicate that your read transaction is over&#8230; that means you have to NAK the last Length byte because there could be 0 bytes to read, in which case you would need to stop.  It would have been nice if the protocol let you send only one start, but Im pretty sure it was designed for UART, which doesn&#8217;t suffer from this problem.  Also as a side note, Im pretty sure that the MCU they are using doesn&#8217;t really care, but Im not willing to implement it incorrectly.</p>
<p>Here is the code:</p>
<pre class="start-line:93 lang:c decode:true ">void readPacketI2C()
{
    int length;
    int command;
    uint8_t data;
    uint32_t returncode;
    
    returncode = I2C_I2CMasterSendStart(I2CADDR,I2C_I2C_READ_XFER_MODE , I2CTIMEOUT);
    returncode |= I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA,&amp;data,I2CTIMEOUT);
    returncode |= I2C_I2CMasterSendStop(I2CTIMEOUT);
    
    // Something bad happened on the I2C Bus ....
    if(returncode)
    {
        systemMode = MODE_IDLE; 
        sprintf(buff,"I2C Return Code %X\r\n",(unsigned int)returncode);
        UART_UartPutString(buff);
    }
 
    // The screen returns a 0 when there is nothing in the buffer.
    if(data == 0)
    {
        return;
    }

    // This is bad because there was something other than a packet start byte
    if(data != 252)
    {
        sprintf(buff,"bad data = %d\r\n",data);
        UART_UartPutString(buff);
        systemMode = MODE_IDLE; // put it into nothing mode...
        return;
    }
    
    // We know that we have a command
    returncode = I2C_I2CMasterSendStart(I2CADDR,I2C_I2C_READ_XFER_MODE , I2CTIMEOUT);
    returncode |= I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA,&amp;data,I2CTIMEOUT); // command
    command = data;
    
    returncode |= I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA,&amp;data,I2CTIMEOUT); // length
    length = data&lt;&lt;8;
    returncode |= I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA,&amp;data,I2CTIMEOUT); // length
    length = length + data;
    returncode |= I2C_I2CMasterSendStop(I2CTIMEOUT);
    
    // If the packet has any data... then read it.
    if(length != 0)
    {
        returncode |= I2C_I2CMasterSendStart(I2CADDR,I2C_I2C_READ_XFER_MODE , I2CTIMEOUT);
    
        for(int i=0;i&lt;length-1; i++)
        {
            I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA,&amp;data,I2CTIMEOUT); // length
            inbuff[i] = data;
        }

        // Read the last byte
        I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA,&amp;data,I2CTIMEOUT); // length
        inbuff[length-1] = data;
        returncode |= I2C_I2CMasterSendStop(I2CTIMEOUT);
        
        I2C_I2CMasterSendStop(I2CTIMEOUT);
    }
      
    sprintf(buff,"command = %d length = %d bytes= ",command,length);
    UART_UartPutString(buff);
    for(int i=0;i&lt;length;i++)
    {
        sprintf(buff,"%d ",inbuff[i]);
        UART_UartPutString(buff);
    }
    UART_UartPutString("\r\n");
    
}
</pre>
<p><span><p>You can "git" these projects from</p>
<p>https://github.com/iotexpert/GTT43A</p>
<p>And the driver library from </p>
<p>https://github.com/iotexpert/GTT-Client-Library</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Title</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2018/05/15/matrix-orbital-gtt43a-a-cool-display/">Matrix Orbital GTT43: A Cool Display</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/">Matrix Orbital GTT43A: Serial Interface</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/">Matrix Orbital GTT43A: GTT Scripts</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/24/matrix-orbital-gtt43a-psoc-4-interface/" target="_blank" rel="noopener">Matrix Orbital GTT43A: A PSoC 4 Interface</a></td>
</tr>

<tr><td >Matrix Orbital GTT43A: Debugging the I2C</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: PSoC 6 using RTOS and the GTT Driver Library</td>
</tr>
</tbody></table></div></p></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/matrix-orbital-gtt43a-psoc-4-interface/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Matrix Orbital GTT43A: GTT Scripts</title>
		<link>https://iotexpert.com/matrix-orbital-gtt43a-gtt-scripts/</link>
					<comments>https://iotexpert.com/matrix-orbital-gtt43a-gtt-scripts/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 22 May 2018 10:25:43 +0000</pubDate>
				<category><![CDATA[Matrix Orbital]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=5194</guid>

					<description><![CDATA[Summary As I have been working my way through understanding the Matrix Orbital displays, I think that the whole scheme for programming them is very clever.  The bottom line of this article is that Matrix Orbital created a command language for making things work in the display, then the built the rest of their toolset [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>As I have been working my way through understanding the Matrix Orbital displays, I think that the whole scheme for programming them is very clever.  The bottom line of this article is that Matrix Orbital created a command language for making things work in the display, then the built the rest of their toolset around that language.  In this article Ill show you how it is all connected.</p>
<h1>A Buffer Full of Mystery</h1>
<p>While I was trying to understand how the GTT Support Tool works, I send a &#8220;Reset Module&#8221; also known as {254, 1}.  When I ran the script, the screen rebooted, and then the serial monitor dumped out a boat load of stuff.  You can see it in the picture below:</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-26-28-pm/" rel="attachment wp-att-5200"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM-1024x404.png" alt="" width="1024" height="404" class="alignnone size-large wp-image-5200" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM-1024x404.png 1024w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM-600x237.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM-300x118.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM-768x303.png 768w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.26.28-PM.png 1133w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This was not very different than when I first attached to the screen using the Bridge Control Panel.  Here are the first I2C reads after the reboot.</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-23-02-pm/" rel="attachment wp-att-5199"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.23.02-PM.png" alt="" width="868" height="706" class="alignnone size-full wp-image-5199" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.23.02-PM.png 868w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.23.02-PM-600x488.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.23.02-PM-300x244.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.23.02-PM-768x625.png 768w" sizes="(max-width: 868px) 100vw, 868px" /></a></p>
<p>So, what is all of this stuff?  The answer to that question resides in how this whole thing is put together.</p>
<h1>GTT Scripts</h1>
<p>All interactions with the display are done via the command language.  There are multiple paths for sending commands to the screen, the ones we have talked about so far, I2C, USB and UART.  And the one path that I have not specifically talked about but works exactly the same way, the mass storage sd-card.</p>
<p>When you design a screen in GTT Designer, what it does is take that screen, and spit out a text based command language.  Here is a screenshot of that for the test project that I am working on.</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-37-04-pm/" rel="attachment wp-att-5201"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.37.04-PM.png" alt="" width="698" height="644" class="alignnone size-full wp-image-5201" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.37.04-PM.png 698w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.37.04-PM-600x554.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.37.04-PM-300x277.png 300w" sizes="(max-width: 698px) 100vw, 698px" /></a></p>
<p>Then GTT Designer compiles the text into a binary file with the GTT2.0 and GTT2.5 commands.  You can look at the binary file with a binary file editor.  Here it is for Screen1.bin</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-38-45-pm/" rel="attachment wp-att-5202"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.38.45-PM.png" alt="" width="637" height="503" class="alignnone size-full wp-image-5202" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.38.45-PM.png 637w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.38.45-PM-600x474.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.38.45-PM-300x237.png 300w" sizes="(max-width: 637px) 100vw, 637px" /></a></p>
<p>And you should recognize the bytes you see.  Look at the top and you will see {FE, 05, 00} which in decimal is {254, 05, 00} and if you look in the GTT20 manual you will find that is &#8220;Set Communication Channel to None&#8221;.  Here is the screenshot from the manual.</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-40-43-pm/" rel="attachment wp-att-5203"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.40.43-PM.png" alt="" width="811" height="411" class="alignnone size-full wp-image-5203" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.40.43-PM.png 811w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.40.43-PM-600x304.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.40.43-PM-300x152.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.40.43-PM-768x389.png 768w" sizes="(max-width: 811px) 100vw, 811px" /></a></p>
<p>But, what happens when the device boots?  Well, they followed the lead from MS-DOS and created a file called &#8220;autoexec&#8221;.  And, if you look in that file they so graciously tell you what happens.</p>
<p><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/screen-shot-2018-05-15-at-3-42-19-pm/" rel="attachment wp-att-5204"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.42.19-PM.png" alt="" width="595" height="413" class="alignnone size-full wp-image-5204" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.42.19-PM.png 595w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-3.42.19-PM-300x208.png 300w" sizes="(max-width: 595px) 100vw, 595px" /></a></p>
<p>How cool is that?  All of these commands are just the things that you did on the project setting and the display settings.  And the last line of the file launches just launches Screen1.bin, which is just the binary file of the commands it takes to load the Screen1.</p>
<p>Now back to the original question.  What is the buffer full of mystery?  Simple, it is the output of all of the commands (if they make output) that are in the autoexec binary and the screen1 binary.  If you had happened to set the default channel to &#8220;none&#8221; you will find that the buffer doesnt have anything in it&#8230; which should make sense.</p>
<p>So, when the manual says to delete the autoexec at the top level directory in order to reset the board.  All that does it remove all of the settings that you created in your project.</p>
<p>The only thing that I wish is that they gave you access to the txt&#8211;&gt;bin compiler.  But oh well.</p>
<p><span><p>You can "git" these projects from</p>
<p>https://github.com/iotexpert/GTT43A</p>
<p>And the driver library from </p>
<p>https://github.com/iotexpert/GTT-Client-Library</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Title</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2018/05/15/matrix-orbital-gtt43a-a-cool-display/">Matrix Orbital GTT43: A Cool Display</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/">Matrix Orbital GTT43A: Serial Interface</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/">Matrix Orbital GTT43A: GTT Scripts</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/24/matrix-orbital-gtt43a-psoc-4-interface/" target="_blank" rel="noopener">Matrix Orbital GTT43A: A PSoC 4 Interface</a></td>
</tr>

<tr><td >Matrix Orbital GTT43A: Debugging the I2C</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: PSoC 6 using RTOS and the GTT Driver Library</td>
</tr>
</tbody></table></div></p></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/matrix-orbital-gtt43a-gtt-scripts/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Matrix Orbital GTT43A: Serial Interface</title>
		<link>https://iotexpert.com/matrix-orbital-gtt43a-serial-interface/</link>
					<comments>https://iotexpert.com/matrix-orbital-gtt43a-serial-interface/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Thu, 17 May 2018 12:00:46 +0000</pubDate>
				<category><![CDATA[Matrix Orbital]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=5090</guid>

					<description><![CDATA[Summary In this article I will show you how to interact with the Matrix Orbital GTT43A display using the GTT Support Tool via the KitProg UART on a CY8CKIT-044  and the Bridge Control Panel via I2C.  This article will be broken up into four parts Building a Test Project in GTT Designer GTT Protocol 2.0 [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will show you how to interact with the Matrix Orbital <a href="https://www.matrixorbital.com/gtt43a" target="_blank" rel="noopener">GTT43A</a> display using the GTT Support Tool via the KitProg UART on a CY8CKIT-044  and the Bridge Control Panel via I2C.  This article will be broken up into four parts</p>
<ol>
<li>Building a Test Project in GTT Designer</li>
<li>GTT Protocol 2.0</li>
<li>GTT Protocol 2.5</li>
<li>GTT Support Tool</li>
<li>Bridge Control Panel</li>
</ol>
<h1>Build a Test Project</h1>
<p>In order to understand the whole serial interface, I will build a very simple project with two buttons.  You can find this project in my GitHub site at git@github.com:iotexpert/GTT43A</p>
<p>Start up a new project called &#8220;BasicTest&#8221;.  Accept the defaults for Project settings.  On the Display Settings screen change the &#8220;Default Channel&#8221; to Serial and the Flow Control to Off.  I am using the CY8CKIT-044 to talk to the screen.  On that development kit there is a KitProg which serves as a programmer (for the PSoC 4200M) and as a serial bridge.  That serial bridge does not have the flow control pins turned on.  If you leave the flow control on, the screen will never transmit and you will need to poke your eyeballs out trying to figure out why.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-09-44-pm/" rel="attachment wp-att-5153"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.09.44-PM.png" alt="" class="alignnone size-large wp-image-5153" width="286" height="594" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.09.44-PM.png 286w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.09.44-PM-144x300.png 144w" sizes="(max-width: 286px) 100vw, 286px" />  </a><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-10-35-00-am/" rel="attachment wp-att-5170"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.35.00-AM.png" alt="" class="alignnone size-full wp-image-5170" width="285" height="593" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.35.00-AM.png 285w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.35.00-AM-144x300.png 144w" sizes="(max-width: 285px) 100vw, 285px" /></a></p>
<p>Drag a Circle Button (GTT2.5) onto the screen.  Change the Text value (on the right panel) to &#8220;GTT25&#8221;</p>
<p><a href="https://iotexpert.com/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-10-55-pm/" rel="attachment wp-att-5151"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM-1024x718.png" alt="" class="alignnone wp-image-5151 size-large" width="1024" height="718" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM-1024x718.png 1024w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM-600x421.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM-300x210.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM-768x538.png 768w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.10.55-PM.png 1228w" sizes="(max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-03-38-pm/" rel="attachment wp-att-5149"></a></p>
<p>Now click on the &#8220;Legacy&#8221; tab and drag a &#8220;Circle Button&#8221; onto the screen.  Then change the text label to &#8220;Legacy&#8221;.  In addition change the &#8220;ID&#8221; from &#8220;Auto&#8221; to &#8220;2&#8221;.  I noticed that later in this article that if the button ID is &#8220;auto&#8221; it will not be identified in the messages.  Im not sure if this is a bug or my lack of understanding.</p>
<h1><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-03-38-pm/" rel="attachment wp-att-5149"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM-1024x664.png" alt="" class="alignnone size-large wp-image-5149" width="1024" height="664" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM-1024x664.png 1024w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM-600x389.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM-300x195.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM-768x498.png 768w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.03.38-PM.png 1246w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></h1>
<p>When I click &#8220;Deploy&#8221; I end up with this error message.  This appears to be a bug in the GTT Designer.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-12-22-pm/" rel="attachment wp-att-5154"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.12.22-PM.png" alt="" class="alignnone size-full wp-image-5154" width="422" height="270" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.12.22-PM.png 422w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.12.22-PM-300x192.png 300w" sizes="(max-width: 422px) 100vw, 422px" /></a></p>
<p>Click on the &#8220;Font&#8221; and go to the directory where the Font is supposed to be&#8230; and find that it is actually empty.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-15-01-pm/" rel="attachment wp-att-5156"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.01-PM.png" alt="" class="alignnone size-large wp-image-5156" width="769" height="652" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.01-PM.png 769w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.01-PM-600x509.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.01-PM-300x254.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.01-PM-768x651.png 768w" sizes="(max-width: 769px) 100vw, 769px" /></a></p>
<p>So.  I navigate up a directory and then down into &#8220;LibraSans&#8221; instead of &#8220;libra-sans-modern&#8221;.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-15-19-pm/" rel="attachment wp-att-5155"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.19-PM.png" alt="" class="alignnone size-full wp-image-5155" width="771" height="652" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.19-PM.png 771w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.19-PM-600x507.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.19-PM-300x254.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.15.19-PM-768x649.png 768w" sizes="(max-width: 771px) 100vw, 771px" /></a></p>
<p>Once that is done press &#8220;Deploy&#8221;, and I get Success!</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-45-19-pm/" rel="attachment wp-att-5157"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.45.19-PM.png" alt="" class="alignnone size-full wp-image-5157" width="585" height="441" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.45.19-PM.png 585w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.45.19-PM-300x226.png 300w" sizes="(max-width: 585px) 100vw, 585px" /></a></p>
<p>Now that I have the project built I need to wire the whole mess together.  I am going to use a <a href="http://www.cypress.com/documentation/development-kitsboards/cy8ckit-044-psoc-4-m-series-pioneer-kit" target="_blank" rel="noopener">CY8CKIT-044</a>.  This development kit has a PSoC4200M.  Although the project is using a PSoC6, I didnt have any level translators at my house (bad Alan) and I wanted to get going &#8230; so I used the 5V tolerant PSoC 4. [note: it turns out that the MCU used on the display has 5V tolerant serial I/Os but is a 3.3v MCU so I could have used it directly on the PSoC 6 without this work around]  On the far left of the development kit, right next to the USB is the KitProg connector.  This connector has an I2C Master and a UART Bridge.  In addition I can connect the I2C pins to PSoC, the Display and the Bridge.  Here is the schematic for the whole mess.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/schematic-5/" rel="attachment wp-att-5162"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/schematic-1024x595.png" alt="" class="alignnone size-large wp-image-5162" width="1024" height="595" srcset="https://iotexpert.com/wp-content/uploads/2018/05/schematic-1024x595.png 1024w, https://iotexpert.com/wp-content/uploads/2018/05/schematic-600x349.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/schematic-300x174.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/schematic-768x446.png 768w, https://iotexpert.com/wp-content/uploads/2018/05/schematic.png 1165w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you look on the back of the CY8CKIT-044 you can see the same wiring diagram on the silkscreen.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/img_5885/" rel="attachment wp-att-5164"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885-1005x1024.jpg" alt="" class="alignnone size-large wp-image-5164" width="1005" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885-1005x1024.jpg 1005w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885-600x611.jpg 600w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885-294x300.jpg 294w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885-768x783.jpg 768w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5885.jpg 1841w" sizes="(max-width: 1005px) 100vw, 1005px" /></a></p>
<p>Here is a picture of the development kit.  You can see the top green/yellow wires go to P40/P41 (that is the I2C Bus) and the other green/yellow set goes to P12[6] and P12[7] that is the KitProg UART.  I suppose I should have used different colors for I2C and UART&#8230; oh well.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/img_5887/" rel="attachment wp-att-5165"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5887-e1526145924226-1024x768.jpg" alt="" class="alignnone wp-image-5165 size-large" width="1024" height="768" srcset="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5887-e1526145924226-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5887-e1526145924226-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5887-e1526145924226-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5887-e1526145924226-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And finally the whole mess.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/img_5884/" rel="attachment wp-att-5160"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5884-768x1024.jpg" alt="" class="alignnone size-large wp-image-5160" width="768" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2018/05/IMG_5884-768x1024.jpg 768w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5884-600x800.jpg 600w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5884-225x300.jpg 225w, https://iotexpert.com/wp-content/uploads/2018/05/IMG_5884-scaled.jpg 1920w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<h1>GTT43A Protocol 2.0</h1>
<p>They way that the system works is you can send a command data packet to the display via one of the serial interfaces and then if there is a response required,  it will respond with a response data packet.  In addition when some event occurs on the display (like a touch screen button being pressed) it will send you a response data packet.</p>
<p>There are two GTT Protocols, one called 2.0 and one called 2.5.  First the <a href="https://www.matrixorbital.com/index.php?route=extension/module/product_downloads/get&amp;did=17" target="_blank" rel="noopener">2.0 protocol</a>.  You send messages in the GTT2.0 command data packet format.  That format is simple:</p>
<ol>
<li>254 &#8211; 1 byte</li>
<li>Message ID (look in the manual for all of the legal message codes) &#8211; 1 byte</li>
<li>Optional data 0-n bytes</li>
</ol>
<p>If there is a required response, the screen will respond with a data packet in the following format</p>
<ol>
<li>252 &#8211; 1 byte</li>
<li>Message ID &#8211; 1 byte</li>
<li>Length MSB &#8211; 1 byte</li>
<li>Length LSB &#8211; 1 byte</li>
<li>Optional Data &#8211; 0&#8211;&gt;65535 bytes</li>
</ol>
<p>The total length of the response will be (length msb) &lt;&lt; 8 | length lsb &#8211; big endian.</p>
<p>For example a command with no optional data &#8230;. like reset will look like this { 252, 1 }. [obviously dont send the braces or the comma]</p>
<p>A command with some optional data is &#8220;Set Backlight Brightness&#8221;. If you want the brightness set to 23% you would send is {252, 153, 23}.</p>
<p>An example of a command that will respond with a response data packet is &#8220;Get Module Type&#8221; where you would send {254, 55 } and the screen would respond with {252, 55, 00 02 147 01}.  Here is the picture from the manual.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-10-55-02-am/" rel="attachment wp-att-5171"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.55.02-AM.png" alt="" class="alignnone size-full wp-image-5171" width="817" height="365" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.55.02-AM.png 817w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.55.02-AM-600x268.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.55.02-AM-300x134.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-10.55.02-AM-768x343.png 768w" sizes="(max-width: 817px) 100vw, 817px" /></a></p>
<p>When you look at the picture above there are several things to be <strong>VERY</strong> careful about.</p>
<p>First, the Matrix Orbital people appear to think in decimal not hex.  So they show you {252,55,00,02,147,01) instead of (0xFE, 0x37, 0x00, 0x02, 0x93, 0x01}.  Notice that my GTT43A value is decimal 37633 which is also known as Hex 0x9301.  I  often found myself typing hex when I mean decimal and vice versa.</p>
<p>The second thing to be careful about is that they send values in big endian&#8230; so if you are using an ARM processor be aware as ARM is almost always little endian.</p>
<p>The third thing to be careful about is that the length parameter in the message is always 16-bit Big Endian even though the documentation often shortens this to &#8220;Length&#8221;</p>
<p>Lastly, if they send you a 16-bit value it will show up as big endian, and they will probably show it to you in decimal (like table 14 above).  Which can look kinda weird in decimal as it is two bytes.</p>
<h1>GTT43A Protocol 2.5</h1>
<p>As I worked on understanding what the screen is doing, I noticed that I was getting message codes that were not documented in the GTT2.0 Manual.  For example when you press a button you will get {252,235,0,5,21,0,0,1,1}.  When you look at this packet you can recognize the 252&#8230; and the message code 235 &#8230; and the length seems to make sense 5 &#8230; but the rest of the message is less clear.</p>
<p>So I called technical support, which is excellent, and Daniel agreed to send me a prerelease of the new manual.  When you look at the manual you will find:</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-11-23-41-am/" rel="attachment wp-att-5173"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-11.23.41-AM.png" alt="" class="alignnone size-full wp-image-5173" width="421" height="293" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-11.23.41-AM.png 421w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-11.23.41-AM-300x209.png 300w" sizes="(max-width: 421px) 100vw, 421px" /></a></p>
<p>Which makes good sense as I pressed a button, and the object ID was &#8220;1&#8221;.  The pre release version of the manual that I got seems to be missing information, but Im hopeful they will get it done and released soon.  But for now, I can work with it.  If you need a copy of the manual you will need to contact them directly.</p>
<h1>GTT Support Tool</h1>
<p>When you install GTT Designer, it will also install a program called the GTT Support Tool.  This tool will allow you to send and receive GTT messages to/from the screen.   I have the screen attached to the UART on the KitProg Serial bridge (with jumper wires).  This means I will see the screen in the Device Manger under the Ports-&gt;KitProg (see the COM5)</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-14-47-pm/" rel="attachment wp-att-5178"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.14.47-PM.png" alt="" class="alignnone size-full wp-image-5178" width="349" height="572" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.14.47-PM.png 349w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.14.47-PM-183x300.png 183w" sizes="(max-width: 349px) 100vw, 349px" /></a></p>
<p>You can run the GTT Support Tool from the Start menu or from the Tools menu on the GTT Designer.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-09-46-pm/" rel="attachment wp-att-5177"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.09.46-PM.png" alt="" class="alignnone size-large wp-image-5177" width="437" height="303" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.09.46-PM.png 437w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.09.46-PM-300x208.png 300w" sizes="(max-width: 437px) 100vw, 437px" /></a></p>
<p>When the tool starts you can pick out which ComPort to talk to and setup the Flow Control (meaning use or not CTS/RTS).  The KitProg on the 4200M does not have the CTS/RTS so you need to disable it or things will not work.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-10-14-pm/" rel="attachment wp-att-5176"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.14-PM.png" alt="" class="alignnone size-large wp-image-5176" width="752" height="560" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.14-PM.png 752w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.14-PM-600x447.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.14-PM-300x223.png 300w" sizes="(max-width: 752px) 100vw, 752px" /></a></p>
<p>When you press the &#8220;Test Connection&#8221; it will send a message via the UART/ComPort and wait for a response. I am not sure, but I suspect that it is sending a &#8220;Get Module&#8221; command.  In the picture below you can see that I got both the send and the receive message to work.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-10-32-pm/" rel="attachment wp-att-5175"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.32-PM.png" alt="" class="alignnone size-full wp-image-5175" width="755" height="559" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.32-PM.png 755w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.32-PM-600x444.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.10.32-PM-300x222.png 300w" sizes="(max-width: 755px) 100vw, 755px" /></a></p>
<p>I was struggling over the weekend to get the communication to work correctly.  Specifically I was not getting return messages.  It turned out that the project that you build in the GTT Designer must have &#8220;Flow Control&#8221; turned off and the Default Channel set to Serial or the serial communication responses will not work.  Remember you can set this on the &#8220;Display Settings&#8221;</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-26-36-pm/" rel="attachment wp-att-5180"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.26.36-PM.png" alt="" class="alignnone size-full wp-image-5180" width="281" height="214" /></a></p>
<p>You can also send the commands to set the communication channel and flow control, but I found it easier to get the project to the correct settings in the GTT Designer.</p>
<p>One you have a functional connection you can click on the &#8220;Commands&#8221; tab.  On the left of the screen you will see a list of commands (well&#8230; actually on GTT2.0 commands).  On the right side of the screen you will see your &#8220;script&#8221;, which obviously starts blank.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-29-50-pm/" rel="attachment wp-att-5181"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.29.50-PM.png" alt="" class="alignnone size-full wp-image-5181" width="714" height="746" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.29.50-PM.png 714w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.29.50-PM-600x627.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.29.50-PM-287x300.png 287w" sizes="(max-width: 714px) 100vw, 714px" /></a></p>
<p>The first thing that you should do is press the little split screen button just to the right of the red &#8220;X&#8221;.  When you do this it will bring up a new window that will show what is sent, and what is received.  Obviously it starts blank.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-32-44-pm/" rel="attachment wp-att-5182"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.32.44-PM.png" alt="" class="alignnone size-full wp-image-5182" width="639" height="441" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.32.44-PM.png 639w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.32.44-PM-600x414.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.32.44-PM-300x207.png 300w" sizes="(max-width: 639px) 100vw, 639px" /></a></p>
<p>Now you can double click on a command, like &#8220;Get Module Version&#8221; and it will bring up the command.  When you press &#8220;OK&#8221; it will add it to the script.  You CAN change the command and it will add it the script (but with a misleading name)</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-31-37-pm/" rel="attachment wp-att-5184"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.31.37-PM.png" alt="" class="alignnone size-full wp-image-5184" width="711" height="742" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.31.37-PM.png 711w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.31.37-PM-600x626.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.31.37-PM-287x300.png 287w" sizes="(max-width: 711px) 100vw, 711px" /></a></p>
<p>Here is what the window looks like after I add the &#8220;Get Module Type&#8221; command.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-37-29-pm/" rel="attachment wp-att-5185"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.37.29-PM.png" alt="" class="alignnone size-full wp-image-5185" width="716" height="209" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.37.29-PM.png 716w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.37.29-PM-600x175.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.37.29-PM-300x88.png 300w" sizes="(max-width: 716px) 100vw, 716px" /></a></p>
<p>In order to Run the command, you need to click in the script window and then press the green run button.  If you have not clicked in the script window it will not run. Once you have run the command your viewer window will look like this.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-40-35-pm/" rel="attachment wp-att-5187"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.40.35-PM.png" alt="" class="alignnone size-full wp-image-5187" width="639" height="443" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.40.35-PM.png 639w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.40.35-PM-600x416.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.40.35-PM-300x208.png 300w" sizes="(max-width: 639px) 100vw, 639px" /></a></p>
<p>In the window above you can see that I wrote to the serial port a {254,55} and the screen responded {252,55,0,2,147,14}.  When you decode this message don&#8217;t forget that the data above is in decimal.  In this the example the message the 147,14 is actually 0x930E which is 37646.  Unfortunately 37646 is not documented in the GTT 2.0 protocol manual (but my screen is a GTT43A).</p>
<p>Another cool thing that that happens in the Debug view is that it shows events that are initiated from the screen.  For instance in the picture below I pressed the &#8220;GTT25&#8221; button from my example project.  It show the button press and the button release.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-15-at-12-57-06-pm/" rel="attachment wp-att-5192"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.57.06-PM.png" alt="" class="alignnone size-full wp-image-5192" width="328" height="342" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.57.06-PM.png 328w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-15-at-12.57.06-PM-288x300.png 288w" sizes="(max-width: 328px) 100vw, 328px" /></a></p>
<p>&nbsp;</p>
<h1>Bridge Control Panel</h1>
<p>For my real project I want to interact with the GTT43A via I2C.  For this kind of thing I always like to use the Bridge Control Panel first. I have written a bunch of <a href="https://iotexpert.com/?s=bridge+control+panel" target="_blank" rel="noopener">articles</a> about using BCP to debug.  This allows me to act as an I2C Master and see how the device acts as a slave.  The first thing that I do is press &#8220;List Devices&#8221; on the BCP.  It shows me that there are a number of things connected to the I2C bus.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-16-at-10-21-07-am/" rel="attachment wp-att-5209"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.21.07-AM.png" alt="" class="alignnone size-full wp-image-5209" width="867" height="703" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.21.07-AM.png 867w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.21.07-AM-600x487.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.21.07-AM-300x243.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.21.07-AM-768x623.png 768w" sizes="(max-width: 867px) 100vw, 867px" /></a></p>
<p>You might recall that from the Display Settings that the default I2C address is 80.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-16-at-10-25-45-am/" rel="attachment wp-att-5210"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.25.45-AM.png" alt="" class="alignnone size-full wp-image-5210" width="284" height="274" /></a></p>
<p>That 80 is also known as 0x50 (here we go with the Hex / Decimal thing again).  Moreover that 80 (0x50) is an 8-Bit address, in other words shifted left 1 from the 7-bit address of 0x28.</p>
<p>After I verified that the screen was attached to the bridge control panel.  The next thing to do was to set the default communication via I2C.  Here is the section of the documentation</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-01-40-pm/" rel="attachment wp-att-5147"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.01.40-PM.png" alt="" class="alignnone size-full wp-image-5147" width="755" height="375" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.01.40-PM.png 755w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.01.40-PM-600x298.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.01.40-PM-300x149.png 300w" sizes="(max-width: 755px) 100vw, 755px" /></a></p>
<p>This means that I need to send {0xFE, ox05, 0x02}.  When I send that command I get ACKs &#8230; good.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-12-at-12-00-25-pm/" rel="attachment wp-att-5146"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.00.25-PM.png" alt="" class="alignnone size-large wp-image-5146" width="867" height="760" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.00.25-PM.png 867w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.00.25-PM-600x526.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.00.25-PM-300x263.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-12-at-12.00.25-PM-768x673.png 768w" sizes="(max-width: 867px) 100vw, 867px" /></a></p>
<p>The next thing that I do is test to make sure that the legacy button is working correctly.  When I press it and then read some bytes I get</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-16-at-10-31-33-am/" rel="attachment wp-att-5211"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.31.33-AM.png" alt="" class="alignnone size-full wp-image-5211" width="868" height="703" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.31.33-AM.png 868w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.31.33-AM-600x486.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.31.33-AM-300x243.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.31.33-AM-768x622.png 768w" sizes="(max-width: 868px) 100vw, 868px" /></a></p>
<p>Then I press the GTT 25 Button and get {FC,EB,00,05,15,00,00,01,01} and then {FC,EB,00,05,14,00,00,01,00} in other words a press of button ID 1 and then a release of button ID 1.</p>
<p><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/screen-shot-2018-05-16-at-10-33-27-am/" rel="attachment wp-att-5212"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.33.27-AM.png" alt="" class="alignnone size-full wp-image-5212" width="860" height="805" srcset="https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.33.27-AM.png 860w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.33.27-AM-600x562.png 600w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.33.27-AM-300x281.png 300w, https://iotexpert.com/wp-content/uploads/2018/05/Screen-Shot-2018-05-16-at-10.33.27-AM-768x719.png 768w" sizes="(max-width: 860px) 100vw, 860px" /></a></p>
<p>Now that we understand the command protocol and we know how to talk to the screen, in the next article Ill talk about GTT Scripts.</p>
<p><span><p>You can "git" these projects from</p>
<p>https://github.com/iotexpert/GTT43A</p>
<p>And the driver library from </p>
<p>https://github.com/iotexpert/GTT-Client-Library</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Title</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2018/05/15/matrix-orbital-gtt43a-a-cool-display/">Matrix Orbital GTT43: A Cool Display</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/17/matrix-orbital-gtt43a-serial-interface/">Matrix Orbital GTT43A: Serial Interface</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/22/matrix-orbital-gtt43a-gtt-scripts/">Matrix Orbital GTT43A: GTT Scripts</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2018/05/24/matrix-orbital-gtt43a-psoc-4-interface/" target="_blank" rel="noopener">Matrix Orbital GTT43A: A PSoC 4 Interface</a></td>
</tr>

<tr><td >Matrix Orbital GTT43A: Debugging the I2C</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: GTT Driver Library - Part 1</td>
</tr>

<tr><td >Matrix Orbital GTT43A: PSoC 6 using RTOS and the GTT Driver Library</td>
</tr>
</tbody></table></div></p></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/matrix-orbital-gtt43a-serial-interface/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bosch BMI160 w/PSoC 6 CY8CKIT-028-EPD</title>
		<link>https://iotexpert.com/bosch-bmi160-psoc-6-cy8ckit-028-epd/</link>
					<comments>https://iotexpert.com/bosch-bmi160-psoc-6-cy8ckit-028-epd/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 06 Feb 2018 13:00:04 +0000</pubDate>
				<category><![CDATA[CY8CKIT-028-EPD]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=4946</guid>

					<description><![CDATA[Summary I have been working on a bunch of PSoC 6 projects in preparation for some new videos and for use at Embedded World.  For one of those project I need a motion sensitive remote control&#8230; and conveniently enough we put a Bosch BMI160 motion sensor onto the new CY8CKIT-028-EPD shield that comes with the [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>I have been working on a bunch of PSoC 6 projects in preparation for some new videos and for use at Embedded World.  For one of those project I need a motion sensitive remote control&#8230; and conveniently enough we put a <a href="https://www.bosch-sensortec.com/bst/products/all_products/bmi160" target="_blank" rel="noopener">Bosch BMI160</a> motion sensor onto the new CY8CKIT-028-EPD shield that comes with the CY8CKIT-062-BLE development kit.</p>
<p>In this article I will show you how to make a complete test system using PSoC 6 to talk to the BMI160.  The steps are:</p>
<ol>
<li>Clone the Bosch BMI160 Driver Library</li>
<li>Create a new PSoC 6 project &amp; add the driver library</li>
<li>Create the HAL for the Bosch Driver</li>
<li>Create the main firmware and test</li>
</ol>
<h1>Clone the Bosch BMI160 Driver Library</h1>
<p>When I started this, I knew that the board had a motion sensor but I didnt know what kind.  I assumed that it was an I2C based sensor, so I attached the bridge control panel and probed the I2C bus.  But this is what it said:</p>
<p><a href="https://iotexpert.com/?attachment_id=4951" rel="attachment wp-att-4951"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM-1024x818.png" alt="Bridge Control Panel" width="1024" height="818" class="alignnone wp-image-4951 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM-1024x818.png 1024w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM-600x479.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM-300x240.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM-768x614.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.35-AM.png 1692w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>So&#8230; what the hell?  Then I looked at the board to try to figure out what was going on&#8230; and low and behold&#8230; the board that I had was a prototype that was done before we added the motion sensor.  Here it is:</p>
<p><a href="https://iotexpert.com/?attachment_id=4979" rel="attachment wp-att-4979"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/IMG_5716-e1517838436841-1024x768.jpg" alt="" width="1024" height="768" class="alignnone wp-image-4979 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/IMG_5716-e1517838436841-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5716-e1517838436841-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5716-e1517838436841-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5716-e1517838436841-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And here is a board with the sensor on it.</p>
<p><a href="https://iotexpert.com/?attachment_id=4950" rel="attachment wp-att-4950"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/IMG_5692-e1517672737625-1024x768.jpg" alt="CY8CKIT-028-EPD with Bosch BMI160" width="1024" height="768" class="alignnone wp-image-4950 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/IMG_5692-e1517672737625-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5692-e1517672737625-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5692-e1517672737625-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2018/02/IMG_5692-e1517672737625-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I plug in that board and test it with the Bridge Control Panel I get:</p>
<p><a href="https://iotexpert.com/?attachment_id=4952" rel="attachment wp-att-4952"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM-1024x818.png" alt="" width="1024" height="818" class="alignnone wp-image-4952 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM-1024x818.png 1024w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM-600x479.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM-300x240.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM-768x613.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.47.06-AM.png 1696w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next thing that I did was look at the schematics.  OK, you can see that the Inertial Measurement Unit (IMU) is a BMI160 that is connected to the I2C bus.  The other cool thing is that the devkit team hooked up the two interrupt lines.  These lines are typically used for the IMU to signal the PSoC 6 that something has happened (like maybe the user started moving).</p>
<p><a href="https://iotexpert.com/?attachment_id=4947" rel="attachment wp-att-4947"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM-897x1024.png" alt="" width="897" height="1024" class="alignnone wp-image-4947 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM-897x1024.png 897w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM-600x685.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM-263x300.png 263w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM-768x877.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.31.56-AM.png 902w" sizes="(max-width: 897px) 100vw, 897px" /></a></p>
<p>After looking at the schematics, the next step was to look at the BMI160 <a href="https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMI160-DS000-07.pdf" target="_blank" rel="noopener">datasheet</a> and try to figure out how to interface with the device. Typically these devices have a boatload of registers with a mind boggling number of bit fields.  This is always the un-fun part of the process.  But this time when I went to the BMI160 device page on Bosch&#8217;s website, there was a button that says &#8220;Documents and Drivers&#8221; and when you click it, there is a link to GitHub with a <a href="https://github.com/BoschSensortec/BMI160_driver" target="_blank" rel="noopener">BMI160 driver</a>.  Score!</p>
<p><a href="https://iotexpert.com/?attachment_id=4948" rel="attachment wp-att-4948"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM-1024x792.png" alt="" width="1024" height="792" class="alignnone wp-image-4948 size-large" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM-1024x792.png 1024w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM-600x464.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM-300x232.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM-768x594.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-10.40.22-AM.png 1712w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To make this work you just &#8220;git clone <span>git@github.com:BoschSensortec/BMI160_driver.git&#8221;</span></p>
<h1>Create New PSoC 6 project &amp; with Bosch BMI160 driver library</h1>
<p>So, lets get on with testing it.  First create a new PSoC 63 Project</p>
<p><a href="https://iotexpert.com/?attachment_id=4959" rel="attachment wp-att-4959"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.18.53-PM.png" alt="" width="623" height="466" class="alignnone wp-image-4959 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.18.53-PM.png 623w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.18.53-PM-600x449.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.18.53-PM-300x224.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></a></p>
<p>Use a blank schematic</p>
<p><a href="https://iotexpert.com/?attachment_id=4958" rel="attachment wp-att-4958"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.07-PM.png" alt="" width="624" height="465" class="alignnone wp-image-4958 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.07-PM.png 624w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.07-PM-600x447.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.07-PM-300x224.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></a></p>
<p>Give it a name</p>
<p><a href="https://iotexpert.com/?attachment_id=4957" rel="attachment wp-att-4957"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.54-PM.png" alt="" width="622" height="468" class="alignnone wp-image-4957 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.54-PM.png 622w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.54-PM-600x451.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.19.54-PM-300x226.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a></p>
<p>Add the Retarget I/O and FreeRTOS (from the build settings menu)</p>
<p><a href="https://iotexpert.com/?attachment_id=4956" rel="attachment wp-att-4956"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.17-PM.png" alt="" width="698" height="667" class="alignnone wp-image-4956 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.17-PM.png 698w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.17-PM-600x573.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.17-PM-300x287.png 300w" sizes="(max-width: 698px) 100vw, 698px" /></a></p>
<p>Add a UART and an I2C Master</p>
<p><a href="https://iotexpert.com/?attachment_id=4955" rel="attachment wp-att-4955"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.46-PM.png" alt="" width="516" height="454" class="alignnone wp-image-4955 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.46-PM.png 516w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.20.46-PM-300x264.png 300w" sizes="(max-width: 516px) 100vw, 516px" /></a></p>
<p>To get the I2C to be a master you need to double click it and change it into a master</p>
<p><a href="https://iotexpert.com/?attachment_id=4960" rel="attachment wp-att-4960"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.25.19-PM.png" alt="" width="628" height="478" class="alignnone wp-image-4960 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.25.19-PM.png 628w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.25.19-PM-600x457.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.25.19-PM-300x228.png 300w" sizes="(max-width: 628px) 100vw, 628px" /></a></p>
<p>Then assign the pins</p>
<p><a href="https://iotexpert.com/?attachment_id=4954" rel="attachment wp-att-4954"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM.png" alt="" width="1108" height="844" class="alignnone wp-image-4954 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM.png 1108w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM-600x457.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM-300x229.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM-768x585.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.21.08-PM-1024x780.png 1024w" sizes="(max-width: 1108px) 100vw, 1108px" /></a></p>
<p>Run &#8220;Build -&gt; Generate Application&#8221; to get all of the PDL firmware you need.</p>
<p>Edit stdio_user.h to use the UART (scan down the stdio_user.h to find the right place)</p>
<pre class="lang:c decode:true">#include "project.h"
/* Must remain uncommented to use this utility */
#define IO_STDOUT_ENABLE
#define IO_STDIN_ENABLE
#define IO_STDOUT_UART      UART_1_HW
#define IO_STDIN_UART       UART_1_HW</pre>
<p>Add the &#8220;BMI_driver&#8221; directory to the include path of the CM4 project.  (To get to this menu right click the project and pick &#8220;build settings&#8221;)</p>
<p><a href="https://iotexpert.com/?attachment_id=4961" rel="attachment wp-att-4961"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM.png" alt="" width="1052" height="732" class="alignnone wp-image-4961 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM.png 1052w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM-600x417.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM-300x209.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM-768x534.png 768w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.31.53-PM-1024x713.png 1024w" sizes="(max-width: 1052px) 100vw, 1052px" /></a></p>
<p>Add the Bosch Driver files to the project</p>
<p><a href="https://iotexpert.com/?attachment_id=4963" rel="attachment wp-att-4963"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.09-PM.png" alt="" width="442" height="291" class="alignnone wp-image-4963 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.09-PM.png 442w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.09-PM-300x198.png 300w" sizes="(max-width: 442px) 100vw, 442px" /></a></p>
<p>&nbsp;</p>
<p><a href="https://iotexpert.com/?attachment_id=4962" rel="attachment wp-att-4962"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.28-PM.png" alt="" width="957" height="866" class="alignnone wp-image-4962 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.28-PM.png 957w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.28-PM-600x543.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.28-PM-300x271.png 300w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.44.28-PM-768x695.png 768w" sizes="(max-width: 957px) 100vw, 957px" /></a></p>
<h1>Create the HAL for the Bosch driver</h1>
<p>It is simple to use the Bosch driver.  All you need to do is update the HAL.</p>
<ol>
<li>Provide a function to write I2C registers</li>
<li>Provide a function to read I2C registers</li>
<li>Provide a function to delay for a specified number of milliseconds</li>
<li>Create a structure to hold initialization information and function pointers</li>
</ol>
<p>This device implements what Cypress calls the &#8220;EZI2C&#8221; protocol which is also known as an I2C EEPROM protocol.  The device is organized as an array of registers.  Each register has an address from 0-&gt;0xFF (a single byte of addresses).  To write to a register you need to</p>
<ol>
<li>Send an I2C Start</li>
<li>Send the 7-bit I2C address</li>
<li>Send a write bit (aka a 0)</li>
<li>Send the register address you want to write to (dont confuse I2C address with the internal BMI160 address)</li>
<li>Send the 8-bit value that you want to write</li>
<li>Send a stop</li>
</ol>
<p>A cool thing with EZI2C is that it keeps track of the address, and automatically increments the register address each time you write.  This means you can write a sequence of address without having to do a complete transaction for each address.</p>
<p>Given that introduction the write function is simple:</p>
<pre class="lang:c decode:true " title="I2C Write Function">static int8_t BMI160BurstWrite(uint8_t dev_addr, uint8_t reg_addr,uint8_t *data, uint16_t len)
{
    
    Cy_SCB_I2C_MasterSendStart(I2C_1_HW,dev_addr,CY_SCB_I2C_WRITE_XFER,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,reg_addr,0,&amp;I2C_1_context);
    for(int i = 0;i&lt;len; i++)
    { 
        Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,data[i],0,&amp;I2C_1_context);
    }
    
    Cy_SCB_I2C_MasterSendStop(I2C_1_HW,0,&amp;I2C_1_context);
    
    return 0;
}</pre>
<p>In order to read you do a similar transaction to write.  Specifically the steps are:</p>
<ol>
<li>Send an I2C Start</li>
<li>Send the 7-bit I2c address</li>
<li>Send a WRITE bit aka 0</li>
<li>Send the address of the register you want to read</li>
<li>Send an I2C re-start</li>
<li>Read a byte</li>
<li>Send a NAK</li>
<li>Send a stop</li>
</ol>
<p>The read transaction is similar to the write in that you can continue to read sequential bytes by sending an ACK.  The last byte you read should be NAK-ed to tell the remote device that you are done reading. Given that the code is also straight forward.</p>
<pre class="lang:c decode:true " title="I2C Read Function">// This function supports the BMP180 library and read I2C Registers
static int8_t BMI160BurstRead(uint8_t dev_addr, uint8_t reg_addr,uint8_t *data, uint16_t len)
{
    
    Cy_SCB_I2C_MasterSendStart(I2C_1_HW,dev_addr,CY_SCB_I2C_WRITE_XFER,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,reg_addr,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterSendReStart(I2C_1_HW,dev_addr,CY_SCB_I2C_READ_XFER,0,&amp;I2C_1_context);
    for(int i = 0;i&lt;len-1; i++)
    {
        Cy_SCB_I2C_MasterReadByte(I2C_1_HW,CY_SCB_I2C_ACK,&amp;data[i],0,&amp;I2C_1_context);
    }
    Cy_SCB_I2C_MasterReadByte(I2C_1_HW,CY_SCB_I2C_NAK,&amp;data[len-1],0,&amp;I2C_1_context);
    
    Cy_SCB_I2C_MasterSendStop(I2C_1_HW,0,&amp;I2C_1_context);
    
    
    return 0;
}
</pre>
<p>There is one error with both my read and write functions.  And that error is?  No error checking.  I have seen some intermittent weirdness in which the I2C bus gets locked that ends up requiring a reset to fix.  This could be prevented by checking error codes on the I2C functions.</p>
<p>Now that we have a read and write function we can setup our device:  To do this:</p>
<ol>
<li>Setup a structure of type bmi160_dev</li>
<li>Initialize the function pointers</li>
<li>Initialize the settings for the device</li>
<li>Finally send the settings</li>
</ol>
<pre class="lang:c decode:true">static struct bmi160_dev bmi160Dev;

static void sensorsDeviceInit(void)
{

  int8_t rslt;
  vTaskDelay(500); // guess

  /* BMI160 */
  bmi160Dev.read = (bmi160_com_fptr_t)BMI160BurstRead;
  bmi160Dev.write = (bmi160_com_fptr_t)BMI160BurstWrite;
  bmi160Dev.delay_ms = (bmi160_delay_fptr_t)vTaskDelay;
  
  bmi160Dev.id = BMI160_I2C_ADDR;  // I2C device address

  rslt = bmi160_init(&amp;bmi160Dev); // initialize the device
  if (rslt == 0)
    {
      printf("BMI160 I2C connection [OK].\n");
      bmi160Dev.gyro_cfg.odr = BMI160_GYRO_ODR_800HZ;
      bmi160Dev.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
      bmi160Dev.gyro_cfg.bw = BMI160_GYRO_BW_OSR4_MODE;

      /* Select the power mode of Gyroscope sensor */
      bmi160Dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;

      bmi160Dev.accel_cfg.odr = BMI160_ACCEL_ODR_1600HZ;
      bmi160Dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
      bmi160Dev.accel_cfg.bw = BMI160_ACCEL_BW_OSR4_AVG1;
      bmi160Dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;

      /* Set the sensor configuration */
      bmi160_set_sens_conf(&amp;bmi160Dev);
      bmi160Dev.delay_ms(50);
    }
  else
    {
      printf("BMI160 I2C connection [FAIL].\n");
    }
}</pre>
<h1>Create the main firmware and test</h1>
<p>Finally I test the firmware by running an infinite loop that prints out acceleration data.</p>
<pre class="lang:c decode:true">void motionTask(void *arg)
{
    (void)arg;
    I2C_1_Start();
    sensorsDeviceInit();
    struct bmi160_sensor_data acc;

    while(1)
    {
        
        bmi160_get_sensor_data(BMI160_ACCEL_ONLY, &amp;acc, NULL, &amp;bmi160Dev);      
        printf("x=%4d y=%4d z=%4d\r\n",acc.x,acc.y,acc.z,);       
        vTaskDelay(200);
    }
}
</pre>
<p>Now you should have this:</p>
<p><a href="https://iotexpert.com/?attachment_id=4964" rel="attachment wp-att-4964"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.47.49-PM.png" alt="" width="660" height="420" class="alignnone wp-image-4964 size-full" srcset="https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.47.49-PM.png 660w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.47.49-PM-600x382.png 600w, https://iotexpert.com/wp-content/uploads/2018/02/Screen-Shot-2018-02-03-at-2.47.49-PM-300x191.png 300w" sizes="(max-width: 660px) 100vw, 660px" /></a></p>
<p>And finally the whole program in one shot</p>
<pre class="lang:c decode:true ">#include "project.h"
#include "FreeRTOS.h"
#include "task.h"
#include &lt;stdio.h&gt;
#include "bmi160.h"

static struct bmi160_dev bmi160Dev;

static int8_t BMI160BurstWrite(uint8_t dev_addr, uint8_t reg_addr,uint8_t *data, uint16_t len)
{
    
    Cy_SCB_I2C_MasterSendStart(I2C_1_HW,dev_addr,CY_SCB_I2C_WRITE_XFER,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,reg_addr,0,&amp;I2C_1_context);
    for(int i = 0;i&lt;len; i++)
    { 
        Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,data[i],0,&amp;I2C_1_context);
    }
    
    Cy_SCB_I2C_MasterSendStop(I2C_1_HW,0,&amp;I2C_1_context);
    
    return 0;
}

// This function supports the BMP180 library and read I2C Registers
static int8_t BMI160BurstRead(uint8_t dev_addr, uint8_t reg_addr,uint8_t *data, uint16_t len)
{
    
    Cy_SCB_I2C_MasterSendStart(I2C_1_HW,dev_addr,CY_SCB_I2C_WRITE_XFER,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterWriteByte(I2C_1_HW,reg_addr,0,&amp;I2C_1_context);
    Cy_SCB_I2C_MasterSendReStart(I2C_1_HW,dev_addr,CY_SCB_I2C_READ_XFER,0,&amp;I2C_1_context);
    for(int i = 0;i&lt;len-1; i++)
    {
        Cy_SCB_I2C_MasterReadByte(I2C_1_HW,CY_SCB_I2C_ACK,&amp;data[i],0,&amp;I2C_1_context);
    }
    Cy_SCB_I2C_MasterReadByte(I2C_1_HW,CY_SCB_I2C_NAK,&amp;data[len-1],0,&amp;I2C_1_context);
    
    Cy_SCB_I2C_MasterSendStop(I2C_1_HW,0,&amp;I2C_1_context);
    
    
    return 0;
}


static void sensorsDeviceInit(void)
{

  int8_t rslt;
  vTaskDelay(500); // guess

  /* BMI160 */
  bmi160Dev.read = (bmi160_com_fptr_t)BMI160BurstRead;
  bmi160Dev.write = (bmi160_com_fptr_t)BMI160BurstWrite;
  bmi160Dev.delay_ms = (bmi160_delay_fptr_t)vTaskDelay;
  
  bmi160Dev.id = BMI160_I2C_ADDR;  // I2C device address

  rslt = bmi160_init(&amp;bmi160Dev); // initialize the device
  if (rslt == 0)
    {
      printf("BMI160 I2C connection [OK].\n");
      bmi160Dev.gyro_cfg.odr = BMI160_GYRO_ODR_800HZ;
      bmi160Dev.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
      bmi160Dev.gyro_cfg.bw = BMI160_GYRO_BW_OSR4_MODE;

      /* Select the power mode of Gyroscope sensor */
      bmi160Dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;

      bmi160Dev.accel_cfg.odr = BMI160_ACCEL_ODR_1600HZ;
      bmi160Dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
      bmi160Dev.accel_cfg.bw = BMI160_ACCEL_BW_OSR4_AVG1;
      bmi160Dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;

      /* Set the sensor configuration */
      bmi160_set_sens_conf(&amp;bmi160Dev);
      bmi160Dev.delay_ms(50);
    }
  else
    {
      printf("BMI160 I2C connection [FAIL].\n");
    }
}
#define MAXACCEL 8000
void motionTask(void *arg)
{
    (void)arg;
    I2C_1_Start();
    sensorsDeviceInit();
    struct bmi160_sensor_data acc;

    while(1)
    {
        bmi160_get_sensor_data(BMI160_ACCEL_ONLY, &amp;acc, NULL, &amp;bmi160Dev);
        printf("x=%4d y=%4d z=%4d\r\n",acc.x,acc.y,acc.z);
        
        vTaskDelay(200);
    }
}



int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    UART_1_Start();

    xTaskCreate( motionTask, "Motion Task",400,0,1,0);
    vTaskStartScheduler();

    while(1);
}

/* [] END OF FILE */
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/bosch-bmi160-psoc-6-cy8ckit-028-epd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Lesson 3 &#8211; PSoC 6 Introduction: FreeRTOS and a Debugging UART</title>
		<link>https://iotexpert.com/lesson-3-psoc-6-introduction-freertos-and-a-debugging-uart/</link>
					<comments>https://iotexpert.com/lesson-3-psoc-6-introduction-freertos-and-a-debugging-uart/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Thu, 09 Nov 2017 13:04:52 +0000</pubDate>
				<category><![CDATA[Mouser PSoC 6]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=4510</guid>

					<description><![CDATA[Project Description This project will show you how to build a PSoC 6 project that is running FreeRTOS and printing information to the debugging UART How does it work? The PSoC 6 is a very capable, fast dual Coretex-M MCU.  In order to manage your design complexity that can be attacked with this chip, we [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span><h1>PSoC 6 Introduction</h1>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >#</th>
<th >Title</th>
<th >Comment</th>
</tr>
</thead>
<tbody>
<tr><td >0</td>
<td ><a href="https://iotexpert.com/2017/11/07/lesson-0-psoc-6-introduction-a-two-hour-psoc-6-class/">A Two Hour PSoC 6 Class</a></td>
<td >An introduction to the PSoC 6 class with links to all of the documents</td>
</tr>

<tr><td >1</td>
<td ><a href="https://iotexpert.com/2017/11/08/lesson-1-psoc-6-introduction-resources/" rel="noopener">Resources</a></td>
<td >Links to all of the Cypress PSoC 6 information including videos, application notes etc.</td>
</tr>

<tr><td >2</td>
<td ><a href="https://iotexpert.com/2017/11/08/lesson-2-psoc-6-introduction-first-project/">Your First Project</a></td>
<td >Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit</td>
</tr>

<tr><td >3</td>
<td ><a href="https://iotexpert.com/2017/11/09/lesson-3-psoc-6-introduction-freertos-and-a-debugging-uart/" rel="noopener">FreeRTOS and a Debugging UART</a></td>
<td >Build a project using FreeRTOS including a debug console with the UART</td>
</tr>

<tr><td >4</td>
<td ><a href="https://iotexpert.com/2017/11/09/lesson-4-psoc-6-introduction-capsense/" rel="noopener">CapSense</a></td>
<td >Build a project using the Mutual Cap Buttons and Self Cap Slider</td>
</tr>

<tr><td >5</td>
<td ><a href="https://iotexpert.com/2017/11/09/lesson-5-psoc-6-introduction-bluetooth-low-energy/" rel="noopener">Bluetooth Low Energy</a></td>
<td >Build a CapSense project using BLE and CySmart</td>
</tr>
</tbody></table></div></p>
<p>Since I did the webinar several things have happened</p>
<ol>
<li>Lesson 4: I fixed an error in the stack size for FreeRTOS</li>
<li>Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function</li>
</ol>
<p>All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or <a href="https://github.com/iotexpert/psoc-6-introduction" target="_blank" rel="noopener">www.github.com/iotexpert/psoc-6-introduction</a></p></span></p>
<h1>Project Description</h1>
<p>This project will show you how to build a PSoC 6 project that is running FreeRTOS and printing information to the debugging UART</p>
<h1>How does it work?</h1>
<p>The PSoC 6 is a very capable, fast dual Coretex-M MCU.  In order to manage your design complexity that can be attacked with this chip, we gave you the ability to use a Real Time Operating System &#8211; FreeRTOS.  With a few simple clicks it will startup for you.</p>
<p>The CY8CKIT-062-BLE has a KitProg-2 Debugger/Programmer on board.  In addition to Program/Debug it can also serve as a USB &lt;&#8211;&gt; UART bridge which will allow you to open a terminal program on your PC to do Input/Output with a UART in the PSoC 6.</p>
<h1>How am I going to do it?</h1>
<ol>
<li>Copy &#8220;MyFirstDesign&#8221; to Start a New Project</li>
<li>Modify the Build Settings to add Debug Printing and FreeRTOS</li>
<li>Add the UART to the Schematic and Assign the Pins</li>
<li>Create the UART Test Firmware</li>
<li>Program and Test the Debug UART</li>
<li>Modify firmware for FreeRTOS</li>
<li>Program and Test</li>
<li>A Tour of PDL for the TCPWM</li>
</ol>
<h1>Copy &#8220;MyFirstDesign&#8221; to Start a New Project</h1>
<p>Right click on &#8220;MyFirstDesign&#8221; and select &#8220;Copy&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.13-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.13-PM.png" alt="PSoC Creator Copy Project" width="458" height="722" class="alignnone wp-image-4515 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.13-PM.png 458w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.13-PM-190x300.png 190w" sizes="(max-width: 458px) 100vw, 458px" /></a></p>
<p>Then right click on the workspace and select &#8220;Paste&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.31-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.31-PM.png" alt="PSoC Creator Copy/Paste" width="396" height="480" class="alignnone wp-image-4514 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.31-PM.png 396w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.31-PM-248x300.png 248w" sizes="(max-width: 396px) 100vw, 396px" /></a></p>
<p>Then right click on &#8220;MyFirstDesign_Copy_01&#8221; and select rename.  Then type in a reasonable name like &#8220;FreeRTOS-UART&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM.png"></a> <a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.50-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.50-PM.png" alt="PSoC Creator Copy / Paste" width="448" height="742" class="alignnone wp-image-4513 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.50-PM.png 448w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.28.50-PM-181x300.png 181w" sizes="(max-width: 448px) 100vw, 448px" /></a></p>
<p>PSoC Creator will ask you about some files.  Just click &#8220;Rename&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM.png" alt="PSoC Creator Rename" width="629" height="482" class="alignnone wp-image-4512 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM.png 629w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM-600x460.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.29.18-PM-300x230.png 300w" sizes="(max-width: 629px) 100vw, 629px" /></a></p>
<p>Now you will have three projects in your workspace.  I typically click &#8220;Program&#8221; which will build the copied project and program the development kit&#8230; just to make sure that stuff still works.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM-1024x820.png" alt="PSoC Creator Workspace" width="1024" height="820" class="alignnone wp-image-4516 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM-1024x820.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM-600x481.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM-300x240.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM-768x615.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.33.04-PM.png 1273w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Modify the build settings to add debug printing and FreeRTOS</h1>
<p>You can build massively complex systems with PSoC 6.  In order to help manage that complexity I like to turn on debug printing so that &#8220;printf&#8221; works.  I also like to use a Real Time Operating System (FreeRTOS).  PSoC Creator has both of these things built in.  We called the printf functionality &#8220;Retarget I/O&#8221; because you need to &#8220;target&#8221; the Input / Output of the printf &#8230; aka STDIN and STDOUT to a peripheral in the PSoC.  The best peripheral to use for printf is the UART that is attached to your computer via kitprog2.</p>
<p>To add printf and FreeRTOS to your project you need to: Right click on the project and select &#8220;Build Settings&#8230;&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.30-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.30-PM.png" alt="PSoC Creator Modify Build Settings" width="467" height="715" class="alignnone wp-image-4521 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.30-PM.png 467w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.30-PM-196x300.png 196w" sizes="(max-width: 467px) 100vw, 467px" /></a></p>
<p>Click on the Peripheral Driver Library and then select &#8220;FreeRTOS&#8221; and &#8220;Memory Management heap_4&#8221;.  Then select &#8220;Retarget I/O&#8221;.  When you build your project this will cause PSoC Creator to add both of these to your project.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM-1024x729.png" alt="PSoC Creator Build Settings FreeRTOS" width="1024" height="729" class="alignnone wp-image-4520 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM-1024x729.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM-600x427.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM-300x214.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM-768x547.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.40.59-PM.png 1046w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Select Build-&gt;Generate Application and notice that PSoC Creator added a number of files to your project including the FreeRTOS, stdio_user.c/.h and retarget_io</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.42.13-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.42.13-PM.png" alt="PSoC Creator retarget_io.c" width="508" height="914" class="alignnone wp-image-4519 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.42.13-PM.png 508w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.42.13-PM-167x300.png 167w" sizes="(max-width: 508px) 100vw, 508px" /></a></p>
<h1>Add the UART to the Schematic and Assign the Pins</h1>
<p>In order to printf, getchar and putchar  you need to attach c standard library stdin and stdout to &#8220;something&#8221;.  The best &#8220;something&#8221; is the UART that is attached to the KitProg2 which is attached to your computer.  Then you can open a terminal program (like Putty) and read and write to the PSoC.</p>
<p>So, to do this you need to add a UART to your design schematic from the component catalog.  In the picture below I just typed &#8220;uart&#8221; in the search box.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM-1024x820.png" alt="PSoC Creator Debug UART" width="1024" height="820" class="alignnone wp-image-4524 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM-1024x820.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM-600x480.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM-300x240.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM-768x615.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.03-PM.png 1275w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>What pins on the PSoC 6 BLE is the UART attached to?  Well&#8230; if you turn over your CY8CKIT-062-BLE you will find a little map that show that the PSoC 6 BLE UART is attached to the PSoC 5LP UART.  The PSoC 5LP is programmed with the KitProg2 firmware.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091-e1509742204438-1024x768.jpg" alt="PSoC 6 CY8CKIT-062-BLE" width="1024" height="768" class="alignnone wp-image-4525 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091-e1509742204438-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091-e1509742204438-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091-e1509742204438-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/11/IMG_5091-e1509742204438-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To attach those pins in your firmware you just double click on the &#8220;Pins&#8221; tab in the DWR.  Then you can select &#8220;Port&#8221; for the UART RX and TX.  Look at the picture below.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM-1024x821.png" alt="PSoC 6 PSoC Creator Pin Settings" width="1024" height="821" class="alignnone wp-image-4523 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM-1024x821.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM-600x481.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM-300x241.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM-768x616.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.47.49-PM.png 1273w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now that I have all of that done, I run &#8220;Build-&gt;Generate Application&#8221; to get all of the new settings into my project.</p>
<h1>Create the UART Test Firmware</h1>
<p>The next step in making the printf work is to &#8220;retarget&#8221; it to the UART we just put in the schematic.  Open &#8220;stdio_user.h&#8221; and add &#8220;include &lt;project.h&gt;&#8221; (line 130) and change IO_STDOUT_UART and IO_STDIN_UART to be UART_1_HW.  The name &#8220;UART_1&#8221; on lines 136-137</p>
<pre class="start-line:130 lang:c decode:true" title="stdio_user.h">#include &lt;project.h&gt;
#include "cy_device_headers.h"

/* Must remain uncommented to use this utility */
#define IO_STDOUT_ENABLE
#define IO_STDIN_ENABLE
#define IO_STDOUT_UART      UART_1_HW
#define IO_STDIN_UART       UART_1_HW</pre>
<p>Now edit your main_cm4.c to:</p>
<ul>
<li>Turn on the UART with UART_1_Start() on line</li>
<li>Then a couple of printfs lines 24-25</li>
</ul>
<p>Note that &#8220;\033[2J\033[H&#8221; is just a <a href="http://ascii-table.com/ansi-escape-sequences-vt-100.php" target="_blank" rel="noopener">VT100 escape sequence</a> for clear screen and go home.</p>
<pre class="start-line:12 lang:c decode:true" title="main_cm4.c">#include "project.h"
#include &lt;stdio.h&gt;

int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    PWM_1_Start();
    UART_1_Start();
    
    printf("\033[2J\033[H"); // Clear Screen
    printf("Test\r\n");
    
    
    for(;;)
    {
        /* Place your application code here. */
    }
}</pre>
<h1>Program and Test the Debug UART</h1>
<p>You need to figure out which com port that the KitProg2 is attached to.  To do this run the device manager by pressing the &#8220;windows&#8221; button then typing &#8220;device manger&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.08-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.08-PM.png" alt="Device Manager" width="385" height="616" class="alignnone wp-image-4527 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.08-PM.png 385w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.08-PM-188x300.png 188w" sizes="(max-width: 385px) 100vw, 385px" /></a></p>
<p>Click on ports.  Then you can see that the programmer is &#8220;KitProg2&#8221; and that the UART is attached to COM9 (everyone will have a different number)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM.png" alt="Device Manager" width="776" height="575" class="alignnone wp-image-4526 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM.png 776w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM-600x445.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM-300x222.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.56.27-PM-768x569.png 768w" sizes="(max-width: 776px) 100vw, 776px" /></a></p>
<p>Run <a href="http://www.putty.org" target="_blank" rel="noopener">Putty</a> (or  your favorite terminal program)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.58.21-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.58.21-PM.png" alt="Putty" width="448" height="437" class="alignnone wp-image-4530 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.58.21-PM.png 448w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-4.58.21-PM-300x293.png 300w" sizes="(max-width: 448px) 100vw, 448px" /></a></p>
<p>Press the program button on PSoC Creator and you should see your test print</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-5.01.09-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-5.01.09-PM.png" alt="Putty PSoC 6 UART" width="661" height="418" class="alignnone wp-image-4528 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-5.01.09-PM.png 661w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-5.01.09-PM-600x379.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-03-at-5.01.09-PM-300x190.png 300w" sizes="(max-width: 661px) 100vw, 661px" /></a></p>
<h1>Modify firmware for FreeRTOS</h1>
<p>When I look out the output window from the previous step you can see that there is a warning message from FreeRTOS.  Lets fix that warning (by deleting line 83).  While we are at it, lets change the heap size to 48K (48*1024)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM-1024x627.png" alt="" width="1024" height="627" class="alignnone size-large wp-image-4649" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM-1024x627.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM-600x367.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM-300x184.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM-768x470.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-08-at-6.14.24-AM.png 1970w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now lets turn on FreeRTOS. Double click on main_cm4.c to open it in the code editor.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.41.27-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.41.27-AM.png" alt="Modify FreeRTOS Firmware" width="336" height="762" class="alignnone wp-image-4533 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.41.27-AM.png 336w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.41.27-AM-132x300.png 132w" sizes="(max-width: 336px) 100vw, 336px" /></a></p>
<p>Add the following firmware to your project.</p>
<p>The uartTask is function that FreeRTOS uses to create a Task.  This task will control the uart. (which is amazingly enough why I named it uartTask)</p>
<ul>
<li>The function call &#8220;setvbuff&#8221; turns of buffering on stdin&#8230; which means every character will immediately come through to your program</li>
<li>getchar just gets a character from the terminal</li>
<li>the &#8216;s&#8217; and &#8216;S&#8217; will start and stop the PWM (more to follow)</li>
</ul>
<p>In main I</p>
<ul>
<li>Create a task for the uartTask (line 56)</li>
<li>Start FreeRTOS (line 57)</li>
</ul>
<pre class="lang:c decode:true " title="main_cm4.c">/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
#include &lt;stdio.h&gt;
#include "FreeRTOS.h"
#include "task.h"

// uartTask - the function which handles input from the UART
void uartTask(void *arg)
{
    (void)arg;
    char c;
    setvbuf(stdin,0,_IONBF,0);
    while(1)
    {
        c = getchar();
        switch(c)
        {
            case 's': // Stop the PWM
                printf("Stopped PWM\r\n");
                Cy_TCPWM_PWM_Disable(PWM_1_HW,PWM_1_CNT_NUM);
                
            break;
            case 'S': // Start the PWM
                printf("Started PWM\r\n");
                Cy_TCPWM_PWM_Enable(PWM_1_HW,PWM_1_CNT_NUM);
                Cy_TCPWM_TriggerStart(PWM_1_HW, PWM_1_CNT_MASK);
            break;
        }
    }
}


int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    PWM_1_Start();
    UART_1_Start();
    
    printf("\033[2J\033[H"); // VT100 Clear Screen
    printf("Test\r\n");
 
    // Mask a FreeRTOS Task called uartTask
    xTaskCreate(uartTask,"UART Task",configMINIMAL_STACK_SIZE,0,3,0);
    vTaskStartScheduler();  // Will never return
    
    for(;;) // It will never get here
    {
    }
}</pre>
<p>How did I figure out how to start/stop the PWM?  To find the documentation for &#8220;PDL&#8221; aka the Peripheral Driver Library, you can right click on the component in the schematic and select &#8220;Open PDL Documentation&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.18.26-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.18.26-AM.png" alt="PSoC 6 TCPWM" width="450" height="561" class="alignnone wp-image-4532 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.18.26-AM.png 450w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.18.26-AM-241x300.png 241w" sizes="(max-width: 450px) 100vw, 450px" /></a></p>
<p>Or you can open &#8220;Help &#8211;&gt; Documentation &#8211;&gt; Peripheral Driver Library&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.51.42-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.51.42-AM.png" alt="PSoC Creator Help" width="603" height="646" class="alignnone wp-image-4534 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.51.42-AM.png 603w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.51.42-AM-600x643.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.51.42-AM-280x300.png 280w" sizes="(max-width: 603px) 100vw, 603px" /></a></p>
<p>In the documentation I can see all kind of functions, including &#8220;Cy_TCPWM_PWM_Disable&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM-1024x690.png" alt="PSoC 6 PDL" width="1024" height="690" class="alignnone wp-image-4531 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM-1024x690.png 1024w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM-600x405.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM-300x202.png 300w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM-768x518.png 768w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-7.19.35-AM.png 1317w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Program and Test</h1>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-9.30.49-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-9.30.49-AM.png" alt="PSoC 6 FreeRTOS Test" width="651" height="414" class="alignnone wp-image-4545 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-9.30.49-AM.png 651w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-9.30.49-AM-600x382.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-9.30.49-AM-300x191.png 300w" sizes="(max-width: 651px) 100vw, 651px" /></a></p>
<h1>A Tour of PDL for the TCPWM</h1>
<p>How did I figure out that the TCPWM_Type *base should be &#8220;UART_1_HW&#8221;?  &#8230;.. well &#8230;. You might ask yourself, &#8220;What does PWM_1_Start()&#8221; do?  It just calls PDL start function.  OK&#8230; so what does that do?  To find out you can right click on the &#8220;PWM_1_Start&#8221; function and select &#8220;Go To Definition&#8221; which will take you to the source code.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.00.20-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.00.20-AM.png" alt="PSoC 6 Tour of PDL" width="509" height="491" class="alignnone wp-image-4536 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.00.20-AM.png 509w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.00.20-AM-300x289.png 300w" sizes="(max-width: 509px) 100vw, 509px" /></a></p>
<p>You will end up in a file called &#8220;PWM_1.c&#8221;.  This file was created for you automatically by PSoC Creator.   This function is really simple.</p>
<ul>
<li>If it has never been initialized then it calls init (lines 15-19)</li>
<li>Then it enables the TCPWM (line 22)</li>
<li>Then if there not an external pin on the PWM, then it causes a software trigger (line 25)</li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/*******************************************************************************
* Function Name: PWM_1_Start
****************************************************************************//**
*
*  Calls the PWM_1_Init() when called the first time and enables 
*  the PWM_1. For subsequent calls the configuration is left 
*  unchanged and the component is just enabled.
*
* \globalvars
*  \ref PWM_1_initVar
*
*******************************************************************************/
void PWM_1_Start(void)
{
    if (0U == PWM_1_initVar)
    {
        (void) Cy_TCPWM_PWM_Init(PWM_1_HW, PWM_1_CNT_NUM, &amp;PWM_1_config);

        PWM_1_initVar = 1U;
    }

    Cy_TCPWM_Enable_Multiple(PWM_1_HW, PWM_1_CNT_MASK);
    
    #if (PWM_1_INPUT_DISABLED == 7UL)
        Cy_TCPWM_TriggerStart(PWM_1_HW, PWM_1_CNT_MASK);
    #endif /* (PWM_1_INPUT_DISABLED == 7UL) */    
}
</pre>
<p>So, you might ask yourself what is &#8220;PWM_1_HW&#8221;?  Well this is just the base address of the registers for the PWM_1.  Lets follow that.  Right click on it and go to definition.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.01.48-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.01.48-AM.png" alt="PSoC 6 PDL" width="623" height="463" class="alignnone wp-image-4537 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.01.48-AM.png 623w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.01.48-AM-600x446.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.01.48-AM-300x223.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></a></p>
<p>This will take you to PWM_1.h and you will see PWM_1_HW is setup as PWM_1_TCPWM_HW.  What is that?  Well do the right click thing again and find out.</p>
<pre class="lang:c decode:true" title="PWM_1.h">/***************************************
*           API Constants
***************************************/

/**
* \addtogroup group_macros
* @{
*/
/** This is a ptr to the base address of the TCPWM instance */
#define PWM_1_HW                 (PWM_1_TCPWM__HW)

/** This is a ptr to the base address of the TCPWM CNT instance */
#define PWM_1_CNT_HW             (PWM_1_TCPWM__CNT_HW)

/** This is the counter instance number in the selected TCPWM */
#define PWM_1_CNT_NUM            (PWM_1_TCPWM__CNT_IDX)

/** This is the bit field representing the counter instance in the selected TCPWM */
#define PWM_1_CNT_MASK           (1UL &lt;&lt; PWM_1_CNT_NUM)
/** @} group_macros */

#define PWM_1_INPUT_MODE_MASK    (0x3U)
#define PWM_1_INPUT_DISABLED     (7U)
</pre>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.04.51-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.04.51-AM.png" alt="PSoC 6 PDL" width="650" height="421" class="alignnone wp-image-4538 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.04.51-AM.png 650w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.04.51-AM-600x389.png 600w, https://iotexpert.com/wp-content/uploads/2017/11/Screen-Shot-2017-11-04-at-8.04.51-AM-300x194.png 300w" sizes="(max-width: 650px) 100vw, 650px" /></a></p>
<p>This will take you to &#8220;cyfitter.h&#8221; which is the output of the place and route.  It tell you that PWM_1_TCP is really TCPWM0</p>
<pre class="start-line:28 lang:c decode:true" title="cyfitter.h">/* PWM_1_TCPWM */
#define PWM_1_TCPWM__CNT_HW TCPWM0_CNT0
#define PWM_1_TCPWM__CNT_IDX 0u
#define PWM_1_TCPWM__HW TCPWM0
#define PWM_1_TCPWM__IDX 0u</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/lesson-3-psoc-6-introduction-freertos-and-a-debugging-uart/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>FreeRTOS FAT SL FileSystem &#8211; Using the FM24V10 FRAM</title>
		<link>https://iotexpert.com/freertos-fat-sl-filesystem-part-1/</link>
					<comments>https://iotexpert.com/freertos-fat-sl-filesystem-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Wed, 11 Oct 2017 13:41:41 +0000</pubDate>
				<category><![CDATA[CY8CKIT-044]]></category>
		<category><![CDATA[FreeRTOS]]></category>
		<category><![CDATA[FreeRTOS FAT SL]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=4110</guid>

					<description><![CDATA[Summary Last week while working on a PSoC FreeRTOS Project, I looked at the CY8CKIT-044 Development kit that I was using and remembered that right under the Ambient Light Sensor there is a Cypress FM24V10 FRAM.  Way back, I started pushing our Development Kit team to put other Cypress parts onto the dev kits&#8230;. and [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Last week while working on a PSoC FreeRTOS Project, I looked at the CY8CKIT-044 Development kit that I was using and remembered that right under the Ambient Light Sensor there is a <a href="http://www.cypress.com/file/41666/download" target="_blank" rel="noopener">Cypress FM24V10</a> FRAM.  Way back, I started pushing our Development Kit team to put other Cypress parts onto the dev kits&#8230;. and because they are awesome, they aggressively started doing that.  One of those chips is the FM24V10 FRAM.  As I looked at the chip, I realized again that I had never really written anything into the FM24V10 FRAM on any of our dev kits, which seems silly after I pushed the dev kit team for them.  I realized that the reason I had never used the FM24V10 FRAM was I didn&#8217;t have a nifty way to write files.  But, while working on the other FreeRTOS projects, I noticed the <a href="http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT_SL/FreeRTOS_Plus_FAT_SL.shtml" target="_blank" rel="noopener">FreeRTOS FAT SL</a> Filesystem is built into FreeRTOS.  The next couple (3?) articles I will talk about making the FreeRTOS FAT SL Filesystem work on a PSoC4200M with a FM24V10 I2C FRAM.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575-1024x768.jpg" alt="CY8CKIT-044 with FM24V10 FRAM" width="1024" height="768" class="alignnone wp-image-3789 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4575-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>The Cypress FM24V10 FRAM</h1>
<p>The &#8220;F&#8221; in FRAM stands for ferroelectric.  What that means is each of the memory cells is a little magnet.  So what you say?  Well the &#8220;what&#8221; is that FRAMs don&#8217;t wear out (unlike Flash), you can write individual cells (unlike Flash), and it is super low power, it is plenty fast (I2C = 3.4MBS), and it retains data for a long long time (151 years).</p>
<p>That list sounds great.  Actually really great.  But, what is the but?  There are two answers to that question.  The first answer is there is a density penalty, the biggest I2C FRAM is 1Mb where you can buy a 1Gb NOR Flash or even bigger NAND Flash.  The next issue is price.  The digikey pricing for a 128Kb FRAM is $12.76 or 9.9c/kb and a 1GB NOR Flash is $14.97 or <span>0.0014c/kb.  That means an FRAM is 6724 x as expensive per bit.</span></p>
<p>How do I use it?  The FRAM is attached to the I2C pins on the CY8CKIT-044.  That means that I can talk to it with either the <a href="https://iotexpert.com/?s=bridge+control+panel" target="_blank" rel="noopener">Bridge Control Panel</a>, or with the PSoC.  To start with I will show you the Bridge Control Panel.  First, I probe the I2C bus, and I see that there are three I2C devices.</p>
<ul>
<li>0x0F = The I2C Accelerometer (which I wrote about <a href="https://iotexpert.com/2017/06/29/psoc-freertos-kionix-kxtj2-accelerometer/" target="_blank" rel="noopener">here</a>)</li>
<li>0x50= The first 64K of FRAM</li>
<li>0x51 = The second 64K of FRAM</li>
</ul>
<p>The 128K FRAM is divided into two banks which are accessed on separate I2C addresses.  By splitting 128K into two blocks of 64K the chip designers optimized the addressing of the memory.  In order to access 64K you need 16-bits, which means to access 128K you need 17-bits.  This would have required sending a whole extra byte of address when you really only needed 1 of those 8 bits.  They avoid this problem by having two addresses.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM-1024x797.png" alt="" width="1024" height="797" class="alignnone size-large wp-image-4198" srcset="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM-1024x797.png 1024w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM-600x467.png 600w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM-300x234.png 300w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM-768x598.png 768w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-03-at-8.24.44-AM.png 1736w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The FM24V10 FRAM is easy to use as it implements an EzI2C (like) protocol.  EZI2C keeps an internal address pointer.  The pointer is automatically incremented each time you do an I2C transaction.  When you do a write transaction, the first two bytes you write are placed into the address pointer.  I say &#8220;EZI2C like&#8221; because the pointer is not retained between transactions.  Some examples:</p>
<p>If I want to write 0x56 into location 0x0123 I would issue</p>
<ul>
<li>I2C Start</li>
<li>I2C Write to I2C address 0x50</li>
<li>Send 0x01, 0x02 (which write the address pointer)</li>
<li>Send 0x56</li>
<li>I2C Stop</li>
</ul>
<p>I can do that sequence with the Bridge Control Panel command &#8220;W 50 01 23 56 P;&#8221;  The &#8220;W&#8221; stands for &#8220;send a start and send the 7-bit address 0x50 (left shifted 1) and send a &#8216;0&#8217; for write&#8221;.  For some reason the engineers at Philips decided that the I2C protocol would have 7-bit addressing and then 1 bit to represent write or read.  When you talk about I2C there is always confusion about &#8220;8-bit address&#8221; versus &#8220;7-bit address&#8221;.  When they talk about 8-bit address they are talking about the 7-bit address shifted left 1 bit and then or-ed with the read or write bit.  Here is a picture from the bridge control panel:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM.png" alt="" width="839" height="680" class="alignnone size-full wp-image-4204" srcset="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM.png 839w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM-600x486.png 600w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM-300x243.png 300w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.32.38-AM-768x622.png 768w" sizes="(max-width: 839px) 100vw, 839px" /></a></p>
<p>And the same thing from the logic analyzer.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM-1024x372.png" alt="" width="1024" height="372" class="alignnone size-large wp-image-4205" srcset="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM-1024x372.png 1024w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM-600x218.png 600w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM-300x109.png 300w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM-768x279.png 768w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.33.49-AM.png 1108w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Once I have written 0x56 into address 0x0123, I can read it back by a &#8220;w 50 01 23 r 50 x p;&#8221; which sends:</p>
<ul>
<li>I2C Start</li>
<li>I2C Write to I2C address 0x50</li>
<li>Send 0x01, 0x02 (which write the address pointer)</li>
<li>I2C Restart</li>
<li>Sends 0x50 (shifted left) or-ed with &#8220;read&#8221;</li>
<li>Reads the byte</li>
<li>I2C Stop</li>
</ul>
<p>In the transaction output window below, you can see that the &#8220;x&#8221; is replaced with &#8220;56&#8221; meaning that it read the previously written value back.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM.png" alt="" width="836" height="672" class="alignnone size-full wp-image-4206" srcset="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM.png 836w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM-600x482.png 600w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM-300x241.png 300w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.39.40-AM-768x617.png 768w" sizes="(max-width: 836px) 100vw, 836px" /></a></p>
<p>The only other interesting thing about the protocol is that once you have sent and address, you can keep reading, or writing without sending the address again.  For instance to write 01, 02, 03, 04 to address 23, 23,25 and 26 you can send &#8220;W 50 00 23 01 02 03 04 p&#8221;, then you can read it back with &#8220;W 50 00 23 r 50 x x x x p;&#8221;</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM.png" alt="" width="838" height="674" class="alignnone size-full wp-image-4207" srcset="https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM.png 838w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM-600x483.png 600w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM-300x241.png 300w, https://iotexpert.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-11-at-8.43.24-AM-768x618.png 768w" sizes="(max-width: 838px) 100vw, 838px" /></a></p>
<p>In the next Article I will start the process of using the Free RTOS File System to write and read from the I2C FRAM.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/freertos-fat-sl-filesystem-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CY3280 MBR3 &#038; WICED CYW943907</title>
		<link>https://iotexpert.com/cy3280-mbr3-wiced-cyw943907/</link>
					<comments>https://iotexpert.com/cy3280-mbr3-wiced-cyw943907/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Thu, 14 Sep 2017 11:14:55 +0000</pubDate>
				<category><![CDATA[CY943907]]></category>
		<category><![CDATA[PSoC Creator]]></category>
		<category><![CDATA[WICED]]></category>
		<category><![CDATA[WIFI]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=4134</guid>

					<description><![CDATA[Summary In the last Article I talked about the GE Megahackathon.  One of the groups at the event got interested in using a CY3280 MBR3 to send signals via a WICED CYW943907 to the Particle IO server which was connected to a Particle Photon.  I helped them with the implementation and thought that it would [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In the last Article I talked about the <a href="https://iotexpert.com/2017/09/11/cypress-development-kits-ge-mega-hackthon/" target="_blank" rel="noopener">GE Megahackathon</a>.  One of the groups at the event got interested in using a CY3280 MBR3 to send signals via a WICED CYW943907 to the Particle IO server which was connected to a <a href="https://iotexpert.com/category/devkits/particle-photon/" target="_blank" rel="noopener">Particle Photon</a>.  I helped them with the implementation and thought that it would be useful to show here.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892-e1505331571825-768x1024.jpg" alt="CYW3280 &amp; WICED CYW943907" width="768" height="1024" class="alignnone wp-image-4139 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892-e1505331571825-768x1024.jpg 768w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892-e1505331571825-600x800.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892-e1505331571825-225x300.jpg 225w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4892-e1505331571825-scaled.jpg 1920w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<h1>Cypress CY3280 MBR3</h1>
<p>The CY3280 MBR development kit is a CapSense demonstration kit that shows the Mechanical Button Replacement 3 chip.  It features 4 CapSense buttons with LEDs, a proximity sensor, and a buzzer.  It is connected to another MCU via the Arduino pins. of the WICED CYW943907.  The device sits on the I2C bus and acts as an I2C Slave.  You configure it using EZ Click.</p>
<p>When you run EZ Click you can setup the configure the internal registers of the MBR3 to make the board act like a bunch of different things.  In this case I turned on</p>
<ul>
<li>The MBR buttons 1-4 (you can see them in the picture above)</li>
<li>The Flanking Sensor rejection which makes it so that you can only press one button at a time.</li>
<li>All of the automatic tuning features.</li>
</ul>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM.png" alt="EZ-Click CY3280" width="904" height="771" class="alignnone wp-image-4137 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM.png 904w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM-600x512.png 600w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM-300x256.png 300w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.41-PM-768x655.png 768w" sizes="(max-width: 904px) 100vw, 904px" /></a></p>
<p>Once the main CapSense is configured, I moved to the other part of the configuration where I setup</p>
<ul>
<li>The 4 LEDs to toggle and be full brightness when on</li>
<li>The buzzer to buzz for 100ms at 4kHz when something happens</li>
<li>The host interrupt pin as CS15/SH/HI.  This made the Arduino pin D2 be an interrupt when something happened so that WICED would poll the MBR3</li>
</ul>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM.png" alt="EZ-Click CY3280" width="905" height="768" class="alignnone wp-image-4136 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM.png 905w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM-600x509.png 600w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM-300x255.png 300w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-2.16.55-PM-768x652.png 768w" sizes="(max-width: 905px) 100vw, 905px" /></a></p>
<p>Once these settings were all done, I downloaded the firmware configuration via the KitProg USB connector.  Then I tested it using the <a href="https://iotexpert.com/?s=bridge+control+panel" target="_blank" rel="noopener">bridge control panel</a> which I have shown you a bunch of different times in the past.  The MBR3 acts as an I2C slave.  To find out what the state of the buttons are you need to read register 0xAA.  The only little trick is that the chip goes to sleep to save power.  In order to wake it up you need to send an I2C transaction, which ends up getting NAK&#8217;d.  But the next transaction you send will be ACKd.  In the screenshot below you can see that I tried two of the buttons (0x08 and 0x20)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM.png" alt="Bridge Control Panel" width="850" height="672" class="alignnone wp-image-4144 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM.png 850w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM-600x474.png 600w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM-300x237.png 300w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-4.06.59-PM-768x607.png 768w" sizes="(max-width: 850px) 100vw, 850px" /></a></p>
<p>One problem that I had is that the power system of this board is setup to take 5V from the Arduino base board but the WICED development kit gives only 3.3v.  Here is a picture of the power system from the MBR3 schematic.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM-1024x522.png" alt="CY3280 Power Supply" width="1024" height="522" class="alignnone wp-image-4141 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM-1024x522.png 1024w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM-600x306.png 600w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM-300x153.png 300w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM-768x391.png 768w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-3.36.57-PM.png 1125w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The MBR3 can run on 3.3Vs.  In fact it can run all the way down to 1.7v and up to 5.5v, but for some reason (which I can&#8217;t remember) we made the board only work with 5.0v.  To fix this problem I removed J12 and then wired a wire from the 3.3V Arduino pin.  The wire is soldered onto the 3.3v pin, but has a female connector on the other side so that it can be plugged into J12.  Here is a picture:</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890-e1505327051755-1024x768.jpg" alt="CY3280" width="1024" height="768" class="alignnone wp-image-4138 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890-e1505327051755-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890-e1505327051755-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890-e1505327051755-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4890-e1505327051755-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The last thing that I needed to do was move the jumpers to position &#8220;A&#8221; which made the host interrupt pin be connected to D2, and move the I2C jumpers so that the MBR3 was connected to the Arduino instead of the P5LP kitprog.  You can see that in the J3_scl and J3_sda in the picture above.</p>
<h1>WICED CYW943907</h1>
<p>The <a href="http://www.cypress.com/documentation/development-kitsboards/cyw943907aeval1f-evaluation-kit" target="_blank" rel="noopener">CYW934907AEVAL1F</a> is an development kit for the Cypress 43907 MCU+WiFi module.  The WICED CYW943907 board can do dual band (2.4 and 5Ghz), 802.11 a/b/g/n,  Ethernet and a whole bunch of other stuff.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893-e1505333784420-1024x768.jpg" alt="WICED CYW943907" width="1024" height="768" class="alignnone wp-image-4145 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893-e1505333784420-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893-e1505333784420-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893-e1505333784420-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/09/IMG_4893-e1505333784420-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The first firmware that I wrote in WICED Studio:</p>
<ul>
<li>Sets up an ISR to unlock a semaphore when the interrupt occurs</li>
<li>Initialized WICED_GPIO_9 to be an input and connected to an ISR &#8230; this is also known as Arduino D2</li>
<li>Setup the I2C Master Hardware in the 43907</li>
<li>Wait for a semaphore (from the ISR)</li>
<li>Read the I2C register 0xAA from the MBR</li>
</ul>
<p>The only trick in the firmware is that I read the I2C with a &#8220;do&#8221; loop until I get a valid result, meaning that the MBR3 has woken up.</p>
<pre class="lang:c decode:true">#include "wiced.h"

#define I2C_ADDRESS (0x37)
#define BUTTON_REG (0xAA)

wiced_semaphore_t buttonPress;

/* Interrupt service routine for the button */
void button_isr(void* arg)
{
    wiced_rtos_set_semaphore(&amp;buttonPress);
}

/* Main application */
void application_start( )
{
    wiced_init();	/* Initialize the WICED device */
    WPRINT_APP_INFO(("Started\n"));

    wiced_result_t result;
    wiced_rtos_init_semaphore(&amp;buttonPress);

    // WICED_GPIO_9 is the MBR3 Interrupt Pin
    wiced_gpio_init(WICED_GPIO_9,INPUT_PULL_UP);
    wiced_gpio_input_irq_enable(WICED_GPIO_9, IRQ_TRIGGER_FALLING_EDGE, button_isr, NULL); /* Setup interrupt */

    /* Setup I2C master */
    const wiced_i2c_device_t i2cDevice = {
            .port = WICED_I2C_2,
            .address = I2C_ADDRESS,
            .address_width = I2C_ADDRESS_WIDTH_7BIT,
            .speed_mode = I2C_STANDARD_SPEED_MODE
    };

    wiced_i2c_init(&amp;i2cDevice);

    /* Tx buffer is used to set the offset */
    uint8_t tx_buffer[] = {BUTTON_REG};
    uint8_t buttonStatus;

    while ( 1 )
    {

        wiced_rtos_get_semaphore(&amp;buttonPress,WICED_WAIT_FOREVER);

        // Do this until the MBR3 is alive.  It goes into deep sleep and wakes when you
        // send the first command.
        do {
            result = wiced_i2c_write(&amp;i2cDevice, WICED_I2C_START_FLAG | WICED_I2C_STOP_FLAG, tx_buffer, sizeof(tx_buffer));
        }
        while(result != WICED_SUCCESS);

        result=wiced_i2c_read(&amp;i2cDevice, WICED_I2C_START_FLAG | WICED_I2C_STOP_FLAG, &amp;buttonStatus, sizeof(buttonStatus));
        WPRINT_APP_INFO(("Button State = %X\n", buttonStatus)); /* Print data to terminal */
    }
}
</pre>
<p>Once that is programmed I program and test the firmware.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM.png" alt="Testing WICED CYW943907" width="877" height="522" class="alignnone wp-image-4135 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM.png 877w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM-600x357.png 600w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM-300x179.png 300w, https://iotexpert.com/wp-content/uploads/2017/09/Screen-Shot-2017-09-13-at-1.46.36-PM-768x457.png 768w" sizes="(max-width: 877px) 100vw, 877px" /></a></p>
<p>In the next article I will modify all of this firmware and make the WICED CYW943907 send data via HTTP to the Cloud.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/cy3280-mbr3-wiced-cyw943907/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Percepio Tracealyzer PSoC UART Streamport</title>
		<link>https://iotexpert.com/percepio-tracealyzer-psoc-uart-streamport/</link>
					<comments>https://iotexpert.com/percepio-tracealyzer-psoc-uart-streamport/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 01 Aug 2017 10:20:35 +0000</pubDate>
				<category><![CDATA[CY8CKIT-044]]></category>
		<category><![CDATA[Tracealyzer]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=3920</guid>

					<description><![CDATA[Summary In the last Article I showed you how to use the JLINK RTT Streamport to make Tracealyzer work.  When I did that port I didn&#8217;t really like having to use a JLink, it seemed like a pain to have another box.  I knew that it was possible to make a UART based Streamport.  So, [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In the last <a href="https://iotexpert.com/2017/07/25/perception-tracelyzer-rtt-streamport-psoc4200m/" target="_blank" rel="noopener">Article</a> I showed you how to use the JLINK RTT Streamport to make <a href="https://percepio.com/tz/" target="_blank" rel="noopener">Tracealyzer</a> work.  When I did that port I didn&#8217;t really like having to use a JLink, it seemed like a pain to have another box.  I knew that it was possible to make a UART based Streamport.  So, that is what I am going to do, create a Tracealyzer PSoC Streamport.  This Article is going to be broken up into two parts.  In Part 1 I will show you a software based port and the problems that it creates.  In Part 2 I will show you how to use DMA to hopefully (as I haven&#8217;t done the work yet) make it work much better.  I was hoping this morning when I started working on this Article that it would only take me a couple of hours, but that did not turn out to be the case as I ran into a PSoC Creator bug which made it hard to figure out what was going on.</p>
<h1>Cypress USB Serial Bridge &amp; CY8CKIT-049</h1>
<p>If you remember from the last article, the Tracealyzer needs to stream about 20KBs.  That is a big B as in Bytes.  Which means that a 115200 Kbs (aka 14.4 KBs) UART probably won&#8217;t do the trick.  That is OK as the PSoC SCB UART can run at up to 921600 aka 115.2 KBs.  The problem is the Kitprog bridge on my development kit is limited to 115200 (I&#8217;m not sure why)  I didn&#8217;t realize that limitation this morning when I started working on this problem.  But it turns out that the <a href="http://www.cypress.com/documentation/development-kitsboards/psoc-4-cy8ckit-049-4xxx-prototyping-kits" target="_blank" rel="noopener">CY8CKIT-049</a> has a Cypress <a href="http://www.cypress.com/products/usb-serial-bridge-controller" target="_blank" rel="noopener">USB Serial Bridge.</a>which is used to boatload the PSoC4200.  And&#8230; it is designed to break off the kit.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img.jpg" alt="CY8CKIT-049" width="942" height="250" class="alignnone wp-image-3928 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img.jpg 942w, https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img-600x159.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img-300x80.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/07/CY8CKit-049_full_img-768x204.jpg 768w" sizes="(max-width: 942px) 100vw, 942px" /></a></p>
<p>So I broke it off and gave it to my lab assistant to solder (he isn&#8217;t normally that grumpy, but he stayed up all night at a birthday party)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2-768x1024.jpg" alt="Nicholas the Lab Tech" width="768" height="1024" class="alignnone wp-image-3929 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2-768x1024.jpg 768w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2-600x800.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2-225x300.jpg 225w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4689-2-scaled.jpg 1920w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>Now I have two wires which I can use to talk to the CY8CKIT-044 UART.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686-e1501358940465-1024x768.jpg" alt="Cypress USB Serial Bridge" width="1024" height="768" class="alignnone wp-image-3926 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686-e1501358940465-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686-e1501358940465-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686-e1501358940465-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4686-e1501358940465-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After I got the wires on the bridge, I installed the USB Serial Configuration Utility and set the chip up to be 921600 baud.  To do this, run the utility.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM.png" alt="USB Serial Configuration Utility" width="524" height="526" class="alignnone wp-image-3933 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM.png 524w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM-300x300.png 300w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.39-PM-150x150.png 150w" sizes="(max-width: 524px) 100vw, 524px" /></a></p>
<p>Connect to your bridge, in this case the CY7C65211-24LTXI</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.49-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.49-PM.png" alt="USB Serial Configuration Utility" width="518" height="496" class="alignnone wp-image-3932 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.49-PM.png 518w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.10.49-PM-300x287.png 300w" sizes="(max-width: 518px) 100vw, 518px" /></a></p>
<p>Then pick the SCB (which stands for Serial Communication Block)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM.png" alt="USB Serial Configuration Utility" width="523" height="525" class="alignnone wp-image-3931 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM.png 523w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM-300x300.png 300w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.12-PM-150x150.png 150w" sizes="(max-width: 523px) 100vw, 523px" /></a></p>
<p>Click the configure, then set the baud to 921600.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.32-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.32-PM.png" alt="USB Serial Configuration Utility" width="448" height="348" class="alignnone wp-image-3930 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.32-PM.png 448w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-4.11.32-PM-300x233.png 300w" sizes="(max-width: 448px) 100vw, 448px" /></a></p>
<p>Now, I wire the two kits together (the Jlink is just sitting there)</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685.jpg"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685-1024x768.jpg" alt="Percepio Tracelyzer PSoC Setup" width="1024" height="768" class="alignnone wp-image-3927 size-large" srcset="https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685-600x450.jpg 600w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2017/07/IMG_4685-768x576.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Creating a Tracealyzer PSoC UART Streamport</h1>
<p>The first thing to do is modify the previous project to also have a UART.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM.png" alt="PSoC Creator" width="986" height="763" class="alignnone wp-image-3935 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM.png 986w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM-600x464.png 600w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM-300x232.png 300w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.51.36-PM-768x594.png 768w" sizes="(max-width: 986px) 100vw, 986px" /></a></p>
<p>Then connect the UART to Pins P3[0] &amp; P3[1]</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.52.58-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.52.58-PM.png" alt="PSoC Creator" width="433" height="130" class="alignnone wp-image-3936 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.52.58-PM.png 433w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-5.52.58-PM-300x90.png 300w" sizes="(max-width: 433px) 100vw, 433px" /></a></p>
<p>To make the Tracealyzer PSoC Streamport work I make a copy of the TraceRecorder/streamports/USB_CDC and called it PSoC_UART.  After I cut all all of the ST USB crap, I realized that all I need to provide is a</p>
<ul>
<li>A function to receive bytes &#8230; called PSoC_Receive</li>
<li>A function to transmit bytes&#8230; called PSoC_Transmit</li>
</ul>
<p>Next you need to modify these 10 CPP Macros to support the Tracealyzer PSoC Streamport.   (I only had to modify INIT, READ and SEND)</p>
<ul>
<li>TRC_STREAM_PORT_ALLOCATE_FIELDS</li>
<li>TRC_STREAM_PORT_MALLOC</li>
<li>TRC_STREAM_PORT_INIT</li>
<li>TRC_STREAM_PORT_ALLOCATE_EVENT</li>
<li>TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT</li>
<li>TRC_STREAM_PORT_COMMIT_EVENT</li>
<li>TRC_STREAM_PORT_READ_DATA</li>
<li>TRC_STREAM_PORT_PERIODIC_SEND_DATA</li>
<li>TRC_STREAM_PORT_ON_TRACE_BEGIN</li>
<li>TRC_STREAM_PORT_ON_TRACE_END</li>
</ul>
<p>In addition I provide function prototypes for PSoC_Receive and PSoC_Transmit which are called by TRC_STREAM_PORT_READ_DATA and TRC_STREAM_PORT_PERIODIC_SEND_DATA</p>
<pre class="start-line:47 lang:c decode:true">// An Adaption of the Percepio CDC Library to PSoC SCB UART
#include &lt;project.h&gt;

#ifndef TRC_STREAMING_PORT_H
#define TRC_STREAMING_PORT_H

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * Implement the below macros to define your own stream port. If your transfer 
 * method uses RTOS functions, you should not send the data directly but use 
 * the recorder's internal buffer to store the trace data, for later transfer by
 * the TzCtrl task. Check the predefined stream ports for examples on how to use 
 * the internal buffer (e.g., TCP/IP, UART or USB CDC).
 *
 * Read more at http://percepio.com/2016/10/05/rtos-tracing/  
 ******************************************************************************/

int32_t PSoC_Receive(void *data, uint32_t size, int32_t *numOfBytesReceived);
int32_t PSoC_Transmit(void *data, uint32_t size, int32_t *numOfBytesSent );

#if TRC_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char _TzTraceData[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE];       /* Static allocation. */
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
#else
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char* _TzTraceData = NULL;     /* Dynamic allocation. */
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_PAGED_EVENT_BUFFER_PAGE_SIZE);
#endif

#define TRC_STREAM_PORT_INIT() \
        UART_Start(); \
        TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */

#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not needed since we write immediately into the buffer received above by TRC_STREAM_PORT_ALLOCATE_EVENT, and the TRC_STREAM_PORT_PERIODIC_SEND_DATA defined below will take care of the actual trace transfer. */
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) PSoC_Receive(_ptrData, _size, _ptrBytesRead);
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent) prvPagedEventBufferTransfer(PSoC_Transmit, _ptrBytesSent);
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() { prvPagedEventBufferInit(_TzTraceData); }
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */

#ifdef __cplusplus
}
#endif

#endif /* TRC_STREAMING_PORT_H */
</pre>
<p>The last thing to make this work is provide the C function to read and write the UART by modifying trcStreamingPort.c</p>
<pre class="lang:c decode:true">// An adataption of the Percepio USB_CDC Port to PSoC Serial
#include "trcRecorder.h"

#if (TRC_USE_TRACEALYZER_RECORDER == 1)
#if(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)

#include "stdint.h"

int32_t PSoC_Receive(void *data, uint32_t size, int32_t *numOfBytesReceived)
{
  
    uint8_t *myData= (uint8_t *)data;
    
    *numOfBytesReceived = 0;
    while( (*numOfBytesReceived &lt; (int32_t)size) &amp;&amp; UART_SpiUartGetRxBufferSize())
    {
            myData[*numOfBytesReceived] = UART_SpiUartReadRxData();
            *numOfBytesReceived += 1;
    }
	return 0; // Doesnt matter what you return... i dont think that it is checked
}

int32_t PSoC_Transmit(void* data, uint32_t size, int32_t *numOfBytesSent )
{
    UART_SpiUartPutArray((uint8_t *)data,size);
    *numOfBytesSent=size;
    
    return 0; // Doesnt matter what you return... i dont think that it is checked
}

#endif	/*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
#endif  /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
</pre>
<p>There at two things that are a bit goofy.</p>
<ul>
<li>The return values for both of these function is not used by the calling functions&#8230; and is not defined what it means.</li>
<li>The 3rd parameter of both functions is defined as int32_t, but in the TraceRecorder library it is defined as int.  This makes a warning, which I got rid of by fixing the bug in the Percepio code.</li>
</ul>
<h1>Testing</h1>
<p>To test this you need to change the Tracealyzer settings from JLink to Serial and fix the COM port and baud rate.</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-6.17.13-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-6.17.13-PM.png" alt="Percepio Tracelyzer PSoC Setup" width="557" height="442" class="alignnone wp-image-3938 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-6.17.13-PM.png 557w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-6.17.13-PM-300x238.png 300w" sizes="(max-width: 557px) 100vw, 557px" /></a></p>
<p>When I built this code originally, I tried 115200 baud.  But it didn&#8217;t work at all (it locked up FreeRTOS).  Then I tried 921600 which locked up the Tracealyzer.  I am running Tracealyzer and PSoC Creator on a Mac in a VMWare Fusion Windows 7 box and I am pretty sure that there is a USB bridging problem (I am going to try it on a Windows box).  After grinding for a while I found out that both 230400 and 460800 both worked but both showed something very funny, look at the data:</p>
<p>230400 Baud</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.49-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.49-PM.png" alt="Percepio Tracelyzer PSoC - Streaming Data" width="594" height="326" class="alignnone wp-image-3921 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.49-PM.png 594w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.49-PM-300x165.png 300w" sizes="(max-width: 594px) 100vw, 594px" /></a> <a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM.png" alt="Percepio Tracelyzer PSoC - Streaming Data" width="778" height="849" class="alignnone wp-image-3922 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM.png 778w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM-600x655.png 600w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM-275x300.png 275w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.20.29-PM-768x838.png 768w" sizes="(max-width: 778px) 100vw, 778px" /></a></p>
<p>460800 Baud</p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.23.31-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.23.31-PM.png" alt="Percepio Tracelyzer PSoC - Streaming Data" width="596" height="359" class="alignnone wp-image-3925 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.23.31-PM.png 596w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.23.31-PM-300x181.png 300w" sizes="(max-width: 596px) 100vw, 596px" /></a></p>
<p><a href="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM.png"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM.png" alt="Percepio Tracelyzer PSoC - Streaming Data" width="776" height="848" class="alignnone wp-image-3924 size-full" srcset="https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM.png 776w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM-600x656.png 600w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM-275x300.png 275w, https://iotexpert.com/wp-content/uploads/2017/07/Screen-Shot-2017-07-29-at-3.24.02-PM-768x839.png 768w" sizes="(max-width: 776px) 100vw, 776px" /></a></p>
<p>I knew that my implementation of the Percepio Tracealyzer PSoC Streamport would be demanding on the CPU, but I did not predict that it would take 30-50% of the CPU.  This is definitely a problem as the JLink RTT Streamport only takes 0.4% of the CPU.  To fix this I am going to try using the PSoC4200M DMA to automatically transfer the buffers to the UART.  Hopefully that will make my Tracealyzer PSoC streamport better.  But that is for the next Article.</p>
<p><span><p>As always you can find all of these projects on the <a href="https://github.com/iotexpert/PSoC-Tracelyzer" target="_blank" rel="noopener">IotExpert GitHub</a> site or git@github.com:iotexpert/PSoC-Tracelyzer.git</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Description</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2017/07/18/percepio-tracelyzer-psoc-4200m/">Percepio Tracealyzer &amp; PSoC</a></td>
<td >An Introduction to Percepio Tracealyzer on the Cypress PSoC</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/07/25/perception-tracelyzer-rtt-streamport-psoc4200m/">Percepio Tracealyzer RTT Streamport - PSoC4200M</a></td>
<td >Make the JLINK RTT Library work with Tracealyzer</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/08/01/percepio-tracelyzer-psoc-uart-streamport/">Percepio Tracealyzer PSoC UART Streamport</a></td>
<td >Creating a UART Streamport</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/08/03/psoc-tracelyzer-streampoint/">Percepio Tracealyzer - Analyzing the PSoC Tracealyzer Streamport</a></td>
<td >Figure out what is broken in the UART Streamport</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/08/08/percepio-tracelyzer-a-psoc-dma-streamport/">Percepio Tracealyzer - Using PSoC DMA to Fix the UART Streamport</a></td>
<td >Implementing PSoC DMA to improve the CPU Utilization</td>
</tr>

<tr><td ><a href="https://iotexpert.com/2017/08/15/percepio-tracealyzer-on-psoc6/">Percepio Tracealyzer - Running on PSoC6</a></td>
<td >Porting the Percepio Tracealyzer to PSoC6</td>
</tr>
</tbody></table></div></p></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/percepio-tracealyzer-psoc-uart-streamport/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
