<?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>PSoC 6 &#8211; IoT Expert</title>
	<atom:link href="https://iotexpert.com/category/devices/psoc-6/feed/" rel="self" type="application/rss+xml" />
	<link>https://iotexpert.com</link>
	<description>Engineering for the Internet of Things</description>
	<lastBuildDate>Wed, 27 Jan 2021 13:07:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://iotexpert.com/wp-content/uploads/2017/01/cropped-Avatar-32x32.jpg</url>
	<title>PSoC 6 &#8211; IoT Expert</title>
	<link>https://iotexpert.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Tilt Hydrometer (Part 1) Overview &#038; Out-of-Box</title>
		<link>https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/</link>
					<comments>https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 04 Jan 2021 12:31:11 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<category><![CDATA[Tilt Hydrometer Data Collection]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9747</guid>

					<description><![CDATA[Summary A discussion of a new series of articles about using the PSoC 6 + 43XXXX Wifi/Bluetooth combo chips to implement a data collection system for the Tilt2 Hydrometer.  Even if you aren&#8217;t specifically interested in hydrometers, this is a general purpose discussion of the design of an IoT device. Story In the middle of [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>A discussion of a new series of articles about using the PSoC 6 + 43XXXX Wifi/Bluetooth combo chips to implement a data collection system for the <a href="https://tilthydrometer.com/products/copy-of-tilt-floating-wireless-hydrometer-and-thermometer-for-brewing" target="_blank" rel="noopener noreferrer">Tilt2 Hydrometer</a>.  Even if you aren&#8217;t specifically interested in hydrometers, this is a general purpose discussion of the design of an IoT device.</p>
<h1>Story</h1>
<p>In the middle of the Covid lockdown my 21-year-old daughter suggested that we start brewing beer.  This was always something that I have been interested in so I said &#8220;Sure!&#8221;.  What does this have to do with IoT you might ask?  I am an engineer and I love data.  Two of the key pieces of <a href="https://en.wikipedia.org/wiki/Beer_measurement" target="_blank" rel="noopener noreferrer">data</a> that you are interested in while fermenting beer are:</p>
<ul>
<li>The gravity of the beer</li>
<li>The temperature of the beer</li>
</ul>
<p>If you don&#8217;t know anything about brewing beer, it is simple (people have been doing it a long time&#8230; even with no IoT)</p>
<ol>
<li>Start with grain</li>
<li>Mill the grain</li>
<li>Heat the grain with water to turn it into sugar water (called wort)</li>
<li>Add yeast</li>
<li>Wait while the yeast converts the sugar in the wort into alcohol and carbon dioxide</li>
<li>Bottle the beer (or keg)</li>
<li>Drink</li>
</ol>
<p>Back to the metrics.  The &#8220;specific gravity&#8221; or just &#8220;gravity&#8221; is just the ratio of the density of your solution to plain water.  This is an indication of sugar in the wort solution.  At the start of the fermentation you will have &#8220;lots&#8221; of sugar, and no alcohol.  By the end you will have &#8220;lots&#8221; of alcohol and not much sugar.  You can tell how things are going by monitoring the gravity of the beer, which is a proxy metric for how much sugar has been converted to alcohol.</p>
<p>There are two common ways to measure the gravity:</p>
<ul>
<li>A <a href="https://en.wikipedia.org/wiki/Hydrometer" target="_blank" rel="noopener noreferrer">float hydrometer</a> &#8211; sugar water is denser then water, so a &#8220;float&#8221; will float lower in the solution as the sugar gets converted to alcohol.</li>
<li>A <a href="https://en.wikipedia.org/wiki/Refractometer" target="_blank" rel="noopener noreferrer">refractometer</a> &#8211; the index of refraction of the solution changes as the sugar concentration changes (this is an amazing old-school technology</li>
</ul>
<p>As I was learning about this whole process I found the <a href="https://tilthydrometer.com" target="_blank" rel="noopener noreferrer">tilt hydrometer</a>.  This device has</p>
<ul>
<li>A Bluetooth MCU (<a href="https://www.u-blox.com/sites/default/files/BMD-300_DataSheet_%28UBX-19033350%29.pdf" target="_blank" rel="noopener noreferrer">u-blox BMD-300</a>)</li>
<li>An I2C accelerometer (<a href="https://www.nxp.com/docs/en/data-sheet/MMA8451Q.pdf" target="_blank" rel="noopener noreferrer">NXP MMA8451Q</a>)</li>
<li>An I2C temperature sensor (<a href="https://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf" target="_blank" rel="noopener noreferrer">Microchip MCP9808</a>)</li>
<li>Enclosed in a sealed plastic tube of known volume and weight (known density)</li>
</ul>
<p>As the gravity of the beer changes, the device floats at a different angle (because it floats lower/higher).  They use the accelerometer to measure the apparent angle of gravity to calculate the angle of the device.  This angle is then used to calculate the density of the solution it is floating in.  They then broadcast the calculated gravity and temperature in Apple Bluetooth iBeacon format.</p>
<p>When I saw this, I thought &#8220;perfect&#8221; I know what to do with that.  I should build a device that can collect all of the data, display it, save it to an SPI flash and put it into the cloud.  It should look something like this: (each Tilt is identified by 1 of 8 colors&#8230; pink in this case).</p>
<p><a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0026/"><img fetchpriority="high" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-1024x711.jpg" alt="" class="alignnone wp-image-10642 size-large" width="1024" height="711" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-1024x711.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-300x208.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-768x533.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-1536x1066.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0026-2048x1422.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Yes, I know they have an iPhone app, but I want to build a single device that sits in my brewery all of the time.  And yes I know they have a Raspberry Pi app, but that isn&#8217;t the point.</p>
<p>My device will have the following characteristics:</p>
<p>A Display with:</p>
<ul>
<li>A Splash Screen</li>
<li>A Table of all Tilts, Gravity and Temperature</li>
<li>Single: One screen per tilt with the specific data including debugging</li>
<li>Single: A graph of the active data for one specific tilt</li>
<li>Single: A table of all of the recordings from that specific tilt</li>
<li>The WiFi Status</li>
<li>The Bluetooth Status</li>
</ul>
<p>Bluetooth System that can:</p>
<ul>
<li>Record tilt data as broadcast in iBeacon advertising packets</li>
<li>Repeat tilt data (maybe)</li>
<li>Introducer WiFi (probably)</li>
</ul>
<p>CapSense button GUI to:</p>
<ul>
<li>Next Screen</li>
<li>Auto Mode</li>
<li>Reset current</li>
<li>Dump recorded data to the SD Card</li>
</ul>
<p>Command Line</p>
<ul>
<li>A UART based command line to debug &amp; learn</li>
</ul>
<p>USB</p>
<ul>
<li>Mass Storage to see files</li>
<li>USB &lt;-&gt; UART Bridge</li>
</ul>
<p>Power Supply via USB Port</p>
<ul>
<li>Plug in Type-C using Cypress BCR</li>
</ul>
<p>WiFi</p>
<ul>
<li>MQTT Publish to AWS</li>
<li>NTP &#8211; to find the time</li>
<li>Local webserver</li>
<li>MDNS</li>
</ul>
<p>RTC</p>
<ul>
<li>Keep Track of current Time</li>
</ul>
<p>SPI NOR Flash</p>
<ul>
<li>Record the data</li>
</ul>
<p>SD CARD</p>
<ul>
<li>Dump the fixed SPI Flash  recordings to a removable SD CARD &amp; remove data from the SPI Flash</li>
</ul>
<p>Here is another picture of what I am thinking (well actually what I implemented for this series of articles)<br />
<a href="https://iotexpert.com/" rel="attachment wp-att-9748"></a><a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0025-2/"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-1024x738.jpg" alt="" class="alignnone wp-image-10645 size-large" width="1024" height="738" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-1024x738.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-300x216.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-768x553.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-1536x1107.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0025-2048x1476.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Un-boxing</h1>
<p>To get this show on the road, I ordered three tilts and two repeaters from Baron Brew Equipment.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0038-2/"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-781x1024.jpg" alt="" class="alignnone wp-image-10656 size-large" width="781" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-781x1024.jpg 781w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-229x300.jpg 229w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-768x1007.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-1172x1536.jpg 1172w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-1562x2048.jpg 1562w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0038-scaled.jpg 1953w" sizes="(max-width: 781px) 100vw, 781px" /></a></p>
<p>It included a neat little quick start picture showing how to get going.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0037-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-778x1024.jpg" alt="" class="alignnone wp-image-10655 size-large" width="778" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-778x1024.jpg 778w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-228x300.jpg 228w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-768x1010.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-1168x1536.jpg 1168w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-1557x2048.jpg 1557w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0037-scaled.jpg 1946w" sizes="auto, (max-width: 778px) 100vw, 778px" /></a></p>
<p>Then the box of goodies.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0036/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-792x1024.jpg" alt="" class="alignnone wp-image-10654 size-large" width="792" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-792x1024.jpg 792w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-232x300.jpg 232w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-768x993.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-1188x1536.jpg 1188w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-1584x2048.jpg 1584w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0036-scaled.jpg 1980w" sizes="auto, (max-width: 792px) 100vw, 792px" /></a></p>
<p>There are 8-possible tilts, Red, Green, Orange, Blue, Black, Yellow, Purpose and Pink (each Tilt his &#8220;hardcoded&#8221; to identify itself as a specific color)<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0028-scaled-e1598972738342/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-1024x513.jpg" alt="" class="alignnone wp-image-10646 size-large" width="1024" height="513" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-1024x513.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-300x150.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-768x385.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-1536x769.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0028-scaled-e1598972738342-2048x1026.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Tilt Hydrometer</h1>
<p>Here is a picture of the &#8220;blue&#8221; one (notice I put the wrong box in the picture)<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0039-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-1024x585.jpg" alt="" class="alignnone wp-image-10657 size-large" width="1024" height="585" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-1024x585.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-300x171.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-768x439.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-1536x877.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0039-2048x1170.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The tilt comes in a plastic tube.  Which has a label to remind you to take it out of the tube (my experience is that you should be embarrassed to have to read most warning labels <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> )<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0033-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-903x1024.jpg" alt="" class="alignnone wp-image-10652 size-large" width="903" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-903x1024.jpg 903w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-264x300.jpg 264w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-768x871.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-1354x1536.jpg 1354w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0033-1805x2048.jpg 1805w" sizes="auto, (max-width: 903px) 100vw, 903px" /></a></p>
<p>It is about 100mm long (about 4 inches).  The bluetooth module is at the top, U3 is the temperature sensor and U2 (which is under the black 3-d printed plastic) is the accelerometer.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0034-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-1024x619.jpg" alt="" class="alignnone wp-image-10653 size-large" width="1024" height="619" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-1024x619.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-300x181.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-768x464.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-1536x928.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0034-2048x1238.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Repeater</h1>
<p>If you put a Bluetooth device floating in a bunch of beer, surrounded by a metal fermentation container, you will not be able to hear the Bluetooth signal.  To solve this problem the Tilt people made a <a href="https://tilthydrometer.com/products/tilt-repeater" target="_blank" rel="noopener noreferrer">repeater</a> which can rest on the top of the fermenter.  It listens for the weak signal, then rebroadcasts with a higher gain antenna.</p>
<p>Here is a picture of the repeater.  Notice that it uses the BMD-301 which has an external SMA antenna.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0045-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-1024x710.jpg" alt="" class="alignnone wp-image-10658 size-large" width="1024" height="710" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-1024x710.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-300x208.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-768x532.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-1536x1065.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0045-2048x1420.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>It also comes in a nice plastic tube.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0029-3/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-1024x524.jpg" alt="" class="alignnone wp-image-10648 size-large" width="1024" height="524" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-1024x524.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-300x154.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-768x393.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-1536x787.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0029-2048x1049.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The repeater can only re-broadcast one color at a time.  The button to switches between the 8 colors and off.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0032/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-1024x740.jpg" alt="" class="alignnone wp-image-10651 size-large" width="1024" height="740" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-1024x740.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-300x217.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-768x555.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-1536x1110.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0032-2048x1479.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Each time you press the button the 3-color LED lights up with the color that represents which tilt color that it is repeating. Red-&gt;Green-&gt;&#8230; Pink-&gt;Off<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0030-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-1024x340.jpg" alt="" class="alignnone wp-image-10649 size-large" width="1024" height="340" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-1024x340.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-300x100.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-768x255.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-1536x510.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0030-2048x680.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>It also has a huge rechargeable battery.<br />
<a href="https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/img_0031-2/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-1024x327.jpg" alt="" class="alignnone wp-image-10650 size-large" width="1024" height="327" srcset="https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-1024x327.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-300x96.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-768x246.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-1536x491.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/09/IMG_0031-2048x655.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>The Plan</h1>
<p>Here is a list of the articles that I plan to write</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>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/tilt-hydrometer-overview-out-of-box-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 8)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 14 Dec 2020 13:00:23 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10220</guid>

					<description><![CDATA[Summary In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 8 I will turn on the ability to filter duplicate advertising packets. Story In the previous article I added the ability to record advertising packets.  The problem [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 8 I will turn on the ability to filter duplicate advertising packets.</p>
<h1>Story</h1>
<p>In the previous article I added the ability to record advertising packets.  The problem is, of course, that many devices are blasting out advertising packets, which will quickly overwhelm you.  I suppose more importantly it will overwhelm the packet buffer.  Most of the device are just advertising their presence, so they send the same data over and over.  Some devices alternate between a small number of different advertising packets, e.g. an iBeacon then and Eddystone beacon.</p>
<p>The way that the filter will work is that I will update the &#8220;add&#8221; function to search through all of the packets that device has launched, then if I have seen the packet before (Ill use a memcmp) then I will just keep a count of how many times I have see that packet.</p>
<p>The other thing that needs to happen is for me to add a &#8220;filter&#8221; command so that I can turn on packet filtering on a device by device basis.</p>
<p>And I need to fix the printing to use the new filtered packet database.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Update the Data Structures</h1>
<p>In order to do the filters, and keep track of the data I will add</p>
<ol>
<li>A &#8220;count&#8221; field to the packet data structure</li>
<li>A &#8220;filter&#8221; boolean field to the device data structure.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    uint8_t *data;
    int count;
    struct adb_adv_data_t *next;
} adb_adv_data_t;

typedef struct {
    wiced_bt_ble_scan_results_t *result;
    bool record;
    bool filter;
    int numSeen;
    int listCount;
    adb_adv_data_t *list;
} adb_adv_t ;</pre>
<h1>Update the Add Function</h1>
<p>In the function &#8220;static void adb_db_add(wiced_bt_ble_scan_results_t *scan_result,uint8_t *data)&#8221; which is called every time I see a new advertising packet I will need to handle four different cases:</p>
<ol>
<li>The first time you see a device</li>
<li>A device you have seen AND you are recording AND have the filtering turned on</li>
<li>A device you are recording but not filtering</li>
<li>A device you have seen, but are not recording or filter.</li>
</ol>
<p>In the first case, a device you haven&#8217;t seen before, you need to</p>
<ol>
<li>Automatically turn on the filtering</li>
<li>Initialize the counts to 1</li>
<li>Do the other initialization (as before)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    // If it is NOT found
    if(entry == -1)
    {
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].listCount = 1;
        adb_database[adb_db_count].record = false;
        adb_database[adb_db_count].filter = true;
        adb_database[adb_db_count].numSeen = 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;
        current-&gt;count = 1;</pre>
<p>In the case where you have</p>
<ol>
<li>See the device before</li>
<li>You have room in the record buffer</li>
<li>And you are in record mode</li>
</ol>
<p>You will then decide if you are filtering.</p>
<p>Then you will iterate through all of the packets and compare the data to the data you just received.  If there is a match then you update the count, free the duplicate data and return.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else if(adb_database[entry].record &amp;&amp; adb_recording_count&lt;ADB_RECORD_MAX &amp;&amp; adb_recording)
    {
        adb_database[entry].numSeen += 1;

        if(adb_database[entry].filter) // if filtering is on.
        {
            int len = btutil_adv_len(data); 
            for(adb_adv_data_t *list = adb_database[entry].list;list;list = (adb_adv_data_t *)list-&gt;next)
            {
                if(memcmp(list-&gt;data,data,len) == 0) // Found the data
                {
                    list-&gt;count += 1;
                    printf("Count = %d\n",list-&gt;count);
                    free(data);
                    free(scan_result);
                    return;
                }
            }
        }
</pre>
<p>If you have not see the data before, then you need to add it to the linked list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = (struct adb_adv_data_t *)adb_database[entry].list;
        current-&gt;data = data;
        current-&gt;count = 1;</pre>
<p>If you are not recording and not filtering, just increment counts.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else
    {
        adb_database[entry].numSeen += 1;
        adb_database[entry].list-&gt;count += 1;</pre>
<h1>Add a &#8220;filter&#8221; Command</h1>
<p>I want the ability for a user to &#8220;filter all&#8221; or &#8220;filter clear&#8221; or &#8220;filter #&#8221; &#8211; just like we did with watch.  So, add the #defines and new function to advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define ADB_FILTER_ALL -1
#define ADB_FILTER_CLEAR -2
void adb_filter(int entry);
</pre>
<p>Then add the new filter command in advDatabase.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT_RAW,
    ADB_PRINT_DECODE,
    ADB_WATCH,
    ADB_ERASE,
    ADB_RECORD,
    ADB_FILTER,
} adb_cmd_t;</pre>
<p>I will use the adb_queueCmd function that I created in the last article.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">inline void adb_filter(int entry) { adb_queueCmd(ADB_FILTER,(void*)entry,(void *)0); }
</pre>
<p>The filter command has three cases</p>
<ol>
<li>All &#8211; turn the bool for all on</li>
<li>Clear &#8211; turn the bool for all off</li>
<li>Just a specific number &#8211; toggle that specific number</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_filter(int entry)
{
    if(entry == ADB_FILTER_ALL)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].filter = true;
        }
        return;
    }

    if(entry == ADB_FILTER_CLEAR)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].filter = false;
        }
        return;
    }

    if(entry &gt; adb_db_count-1 || entry &lt; ADB_WATCH_CLEAR)
    {
        printf("Record doesnt exist: %d\n",entry);
        return;      
    }
    adb_database[entry].filter = !adb_database[entry].filter; 

}
</pre>
<p>And you need to fix up the main command processor</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_FILTER:
                    adb_db_filter((int)msg.data0);
                break;</pre>
<p>Finally add the command to the usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_filter(int argc, char **argv)
{

    if(argc == 2 &amp;&amp; !strcmp(argv[1],"all"))
    {
        adb_filter(ADB_FILTER_ALL); // all
        return 0;
    }


    if(argc == 2 &amp;&amp; !strcmp(argv[1],"clear"))
    {
        adb_filter(ADB_FILTER_CLEAR);
        return 0;
    }

    if(argc == 2)
    {
        int i;
        sscanf(argv[1],"%d",&amp;i);
        adb_filter(i);
        return 0;
    }

    return 0;
}</pre>
<h1>Fix the Printing</h1>
<p>Now we nee to fix the printing.  I want to add an indicate of the filtering to the output.  Remember from the previous article I indicated &#8220;Watch&#8221; with a &#8220;*&#8221;.  When I looked at it, I decided that I should indicate filter with an &#8220;F&#8221; and watch with a &#8220;W&#8221;.  So I fix that.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        printf("%c%c%02d %05d %03d MAC: ",adb_database[i].record?'W':' ',
            adb_database[i].filter?'F':' ',
            i,adb_database[i].numSeen,adb_database[i].listCount);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {</pre>
<p>Then I test the &#8220;filter&#8221; command</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-9-49-32-am/" rel="attachment wp-att-10235"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1024x622.jpg" alt="" class="alignnone size-large wp-image-10235" width="1024" height="622" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1024x622.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-300x182.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-768x466.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1536x933.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-600x364.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM.jpg 2042w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Fix the Printing Part (2)</h1>
<p>As I noodled on how to change the printing I decide that it would be nice to sometimes print out only one packet e.g. no history and sometimes print them all out e.g. history.  So, I add a new parameter to the function called &#8220;history&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_print(adb_print_method_t method,bool history,int entry)
</pre>
<p>As I looked at the printing code, I decided that it would be better to have a new function to print only one entry.  I suppose that I could have left the code inline, but I thought that intent was clearer.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printEntry(adb_print_method_t method, int entry, adb_adv_data_t *adv_data)
{
    printf("%c%c%02d %05d %03d MAC: ",adb_database[entry].record?'W':' ',
    adb_database[entry].filter?'F':' ',
    entry,adb_database[entry].numSeen,adb_database[entry].listCount);
    btutil_printBDaddress(adb_database[entry].result-&gt;remote_bd_addr);

    switch(method)
    {
    
    case ADB_PRINT_METHOD_BYTES:
        printf(" Data: ");
        btutil_adv_printPacketBytes(adv_data-&gt;data);
    break;

    case ADB_PRINT_METHOD_DECODE:
        printf("\n");
        btutil_adv_printPacketDecode(adv_data-&gt;data);
    break;
    } 
    printf("\n");

}
</pre>
<p>With the new function in place I now need to update the print function to call the new entry function.  Printing the history is just a matter of iterating through the linked list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_print(adb_print_method_t method,bool history,int entry)
{
    int start,end;
 
    if(entry &lt; 0)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry+1;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;end;i++)
    {
        if(history) // then iterate through the linked list print all of the packets
        {
            for(adb_adv_data_t *list = adb_database[i].list;list;list = (adb_adv_data_t *)list-&gt;next)
            {
                adb_db_printEntry(method,i,list);    
            }
        }
        else // Just print the first packet in the list
            adb_db_printEntry(method,i,adb_database[i].list);
    }
}</pre>
<p>Now, I need to update all of the calls to adb_db_print to have the new history parameter.  First, I made the decision that when you &#8220;print&#8221; from the command line that you are interested in the history.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_PRINT_RAW:
                    adb_db_print(ADB_PRINT_METHOD_BYTES,true,(int)msg.data0);
                break;
                case ADB_PRINT_DECODE:
                    adb_db_print(ADB_PRINT_METHOD_DECODE,true,(int)msg.data0);
                break;</pre>
<p>But when you are printing out the packet for a new device don&#8217;t print out the history</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">            adb_db_print(ADB_PRINT_METHOD_BYTES,false,adb_db_count-1);
</pre>
<h1>Program and Test</h1>
<p>After I program my development kit, I start by typing &#8220;watch all&#8221;.  Very quickly, at my house, you can see that a bunch of devices are discovered.  You can see that all of these have a &#8220;W&#8221; (meaning that I am watching them) and an &#8220;F&#8221; meaning they are filtering out duplicates.  Then I type &#8220;record&#8221; to turn on recording. After a minute I turn off recording then do the print you can see below.</p>
<p>A couple of things to notice.</p>
<ol>
<li>Device #4 (which I highlighted) appears to be sending out a pattern of alternating packets.  See that I have heard 3335 packets yet there are only two in the buffer</li>
<li>You can see device 11 seems to be sending out 16 different packets.  Why?  I don&#8217;t know.</li>
</ol>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-12-33-06-pm/" rel="attachment wp-att-10236"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1024x624.png" alt="" class="alignnone size-large wp-image-10236" width="1024" height="624" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1024x624.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-300x183.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-768x468.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1536x936.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-600x366.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM.png 2032w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>But we can &#8220;decode 11&#8221; to try to figure it out.  You can see that it is advertising manufactures specific data with Apple&#8217;s UUID which I happen to know is 0x004C.  But why?  I don&#8217;t know.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-12-37-51-pm/" rel="attachment wp-att-10237"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1024x807.jpg" alt="" class="alignnone size-large wp-image-10237" width="1024" height="807" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1024x807.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-300x236.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-768x605.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1536x1210.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-600x473.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM.jpg 1554w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I really want to move onto a new series of articles&#8230; but there are two functions which I will add to the program.  Stay tuned for what they do.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 7)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 07 Dec 2020 13:00:38 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10218</guid>

					<description><![CDATA[Summary In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 7 I will add the ability to record BLE ADV packets. Story If you have been reading along, at this point we have built a BLE scanner [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 7 I will add the ability to record BLE ADV packets.</p>
<h1>Story</h1>
<p>If you have been reading along, at this point we have built a BLE scanner that can see Bluetooth devices that are advertising.  My scanner has a command line and you can print out the most recent data.  Even better, we built a decoder that allows you to better understand the data.</p>
<p>Now I want to add the ability to record more than one advertising packet per device.  To that end I will add three commands:</p>
<ul>
<li>watch &#8211; Mark a device as one that needs to have the advertising data recorded.  You can type &#8220;watch 12&#8221; or you can say &#8220;watch all&#8221; or you can say &#8220;watch clear&#8221;</li>
<li>record &#8211; Turn on recording of &#8220;watched&#8221; devices.  When you type record it will toggle the recording state between On and Off.</li>
<li>erase &#8211; clear the record buffer of all but the most recent packet.</li>
</ul>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Update the advDatabase Interface</h1>
<p>The first thing I realized as I went to add a new command was that I was typing the exact same code over and over for the public interface.  The code looked like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_watch(int entry)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_WATCH;
    msg.data0 = (void *)entry;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If the queue is full... oh well

}</pre>
<p>So I created this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_queueCmd(adb_cmd_t cmd,void *data0, void *data1)
{
    adb_cmdMsg_t msg;
    msg.cmd = cmd;
    msg.data0 = data0;
    msg.data1 = data1;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If you loose an adv packet it is OK...
}</pre>
<p>Then did this to eliminate the duplication.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">inline void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data) { adb_queueCmd(ADB_ADD,(void *)scan_result,(void *)data);}
inline void adb_print(int entry) { adb_queueCmd(ADB_PRINT_RAW,(void *)entry,(void *)0); }
inline void adb_decode(int entry) { adb_queueCmd(ADB_PRINT_DECODE,(void*)entry,(void *)0); }
</pre>
<h1>Redo the Database</h1>
<p>If you recall from previous posts, my advertising database was just</p>
<ol>
<li>An Array of structures</li>
<li>Each structure contained the mac address and&#8230;</li>
<li>A pointer to a malloc&#8217;d copy of the advertising data</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    wiced_bt_ble_scan_results_t *result;
    uint8_t *data;
} adb_adv_t ;

#define ADB_MAX_SIZE (40)
adb_adv_t adb_database[ADB_MAX_SIZE];</pre>
<p>Here is a picture of the datastructure</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/db1/" rel="attachment wp-att-10226"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/db1.png" alt="" width="550" height="976" class="alignnone size-full wp-image-10226" srcset="https://iotexpert.com/wp-content/uploads/2020/11/db1.png 550w, https://iotexpert.com/wp-content/uploads/2020/11/db1-169x300.png 169w" sizes="auto, (max-width: 550px) 100vw, 550px" /></a></p>
<p>&nbsp;</p>
<p>Now what I want to do is make the &#8220;data&#8221; pointer to be a pointer to a linked list of data.  Here is the new definition.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    uint8_t *data;
    struct adb_adv_data_t *next;
} adb_adv_data_t;

typedef struct {
    wiced_bt_ble_scan_results_t *result;
    int listCount;
    bool record;
    int numSeen;
    adb_adv_data_t *list;
} adb_adv_t ;</pre>
<p>The new data structure looks like this</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/newdb/" rel="attachment wp-att-10227"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/newdb-1024x863.png" alt="" width="1024" height="863" class="alignnone size-large wp-image-10227" srcset="https://iotexpert.com/wp-content/uploads/2020/11/newdb-1024x863.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-300x253.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-768x647.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-600x506.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/newdb.png 1158w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I wanted to limit the number advertising packets that can be stored so I don&#8217;t run out of memory.  I am not actually sure how many can be stored, but I suppose a bunch as the chip has 1MB of RAM.  But, I pick 100 which seems like enough to start out with.  I create two variables</p>
<ol>
<li>A counter for the number of advertising packets that are currently saved</li>
<li>A recording state (are you saving or not)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_RECORD_MAX (100)
static int adb_recording_count = 0;
static bool adb_recording = false;
</pre>
<h1>Update the Printing</h1>
<p>You probably noticed that I declared two new members of the adb_adv_t structure, specifically numSeen and listCount, which I would like to print out.   I also wanted a visual indication that I am &#8220;watching&#8221; a device.  The columns are now:</p>
<ol>
<li>A &#8220;*&#8221; to indicate that a device is being watched</li>
<li>The device #</li>
<li>The number of packets that I have seen in total from that device</li>
<li>The number of recorded packets for that device</li>
<li>The MAC address</li>
<li>The raw bytes</li>
</ol>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/screen-shot-2020-11-13-at-9-11-45-am/" rel="attachment wp-att-10228"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1024x355.png" alt="" width="1024" height="355" class="alignnone size-large wp-image-10228" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1024x355.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-300x104.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-768x266.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1536x533.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-600x208.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM.png 1984w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To do implement this a simple change is made to the print function:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    for(int i=start;i&lt;end;i++)
    {
    
        printf("%s%02d %05d %03d MAC: ",adb_database[i].record?"*":" ",i,adb_database[i].numSeen,adb_database[i].listCount);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {
        
        case ADB_PRINT_METHOD_BYTES:
            printf(" Data: ");
            btutil_adv_printPacketBytes(adb_database[i].list-&gt;data);
        break;

        case ADB_PRINT_METHOD_DECODE:
            printf("\n");
            btutil_adv_printPacketDecode(adb_database[i].list-&gt;data);
        break;
        } 
        printf("\n");
    }</pre>
<h1>Update the Add</h1>
<p>Now that we have all of the infrastructure in place we need to update the function that saves advertising data.  When an advertising packet comes in you have three situations to consider:</p>
<ol>
<li>You have never seen the device before</li>
<li>You have seen the device before and you are &#8220;watching&#8221; it</li>
<li>You have see the device but you are not watching it</li>
</ol>
<p>In the case where you have never seen the device you need to</p>
<ol>
<li>Save the scan result</li>
<li>Set the listCount to 1 (you only have one datapoint)</li>
<li>Turn off recording (start with the recording off)</li>
<li>Set the total numSeen to 1 as this is the first packet you have seen</li>
<li>Allocate some memory for the advertising linked list structure</li>
<li>Terminate the linked list</li>
<li>Save the advertising data</li>
<li>Increment the database count (up to the max)</li>
<li>Print out the packet you just saw</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    if(entry == -1)
    {
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].listCount = 1;
        adb_database[adb_db_count].record = false;
        adb_database[adb_db_count].numSeen = 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;

        adb_database[adb_db_count].list = current;

        adb_db_count = adb_db_count + 1;
        if(adb_db_count == ADB_MAX_SIZE)
        {
            printf("ADV Table Max Size\n");
            adb_db_count = adb_db_count - 1;
        }
        else
        {    
            adb_db_print(ADB_PRINT_METHOD_BYTES,adb_db_count-1);
        }
    }</pre>
<p>In the case where you have</p>
<ol>
<li>Seen the device before</li>
<li>You are recording that device</li>
<li>There is room left in the recording buffer</li>
</ol>
<p>Then you will</p>
<ol>
<li>Increment number seen</li>
<li>Create memory for the new entry in the linked list</li>
<li>Attach the tail of the linked list to your new entry (you will insert at the front of the list)</li>
<li>Save the data</li>
<li>Increment the number of saved entries</li>
<li>Insert your new packet at the head of the list</li>
<li>Printout the packet</li>
<li>Increment the record count (the total number of packets in the recording buffer)</li>
<li>Then potentially stop recording if you have gotten to the max size.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else if(adb_database[entry].record &amp;&amp; adb_recording_count&lt;ADB_RECORD_MAX &amp;&amp; adb_recording)
    {
        adb_database[entry].numSeen += 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = (struct adb_adv_data_t *)adb_database[entry].list;
        current-&gt;data = data;
        adb_database[entry].listCount += 1;
        adb_database[entry].list = current;

        adb_db_print(ADB_PRINT_METHOD_BYTES,entry);

        adb_recording_count += 1;
        if(adb_recording_count == ADB_RECORD_MAX)
        {
            adb_recording = false;
            printf("Recording buffer full\n");
        }
    }</pre>
<p>In the case where you have seen the device before, but you are not recoding then you will</p>
<ol>
<li>Update the numSeen</li>
<li>Erase the old packet data</li>
<li>Save the new packet</li>
<li>Erase the &#8220;result&#8221; (you already have it saved)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else
    {
        adb_database[entry].numSeen += 1;
        free(adb_database[entry].list-&gt;data);
        adb_database[entry].list-&gt;data = data;
        free(scan_result);
    }</pre>
<h1>Add a Watch Command</h1>
<p>The watch function is pretty simple.  It just needs to either mark the &#8220;record&#8221; boolean as true or false.  When I decided to implement this function I decided to make positive numbers be the entry in the table.  But, I also wanted to be able to &#8220;watch all&#8221; and &#8220;watch clear&#8221;.  So, I used negative numbers for those two special meanings.  I used a #define in advDatabase.h to define those values.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_WATCH_ALL -1
#define ADB_WATCH_CLEAR -2</pre>
<p>The function is then pretty simple</p>
<ol>
<li>If it is watch all&#8230; then iterate through the database and turn them on</li>
<li>If it is watch clear &#8230; then iterate through the database and turn them off</li>
<li>Otherwise make sure that it is a legal number and toggle it.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_watch(int entry)
{
    if(entry == ADB_WATCH_ALL)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].record = true;
        }
        return;
    }

    if(entry == ADB_WATCH_CLEAR)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].record = false;
        }
        return;
    }

    if(entry &gt; adb_db_count-1 || entry &lt; ADB_WATCH_CLEAR)
    {
        printf("Record doesnt exist: %d\n",entry);
        return;      
    }
    adb_database[entry].record = !adb_database[entry].record; 

}</pre>
<p>Once I have the infrastructure in place, I then add the watch command to usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_watch(int argc, char **argv)
{

    if(argc == 2 &amp;&amp; !strcmp(argv[1],"all"))
    {
        adb_watch(ADB_WATCH_ALL); // all
        return 0;
    }


    if(argc == 2 &amp;&amp; !strcmp(argv[1],"clear"))
    {
        adb_watch(ADB_WATCH_CLEAR);
        return 0;
    }

    if(argc == 2)
    {
        int i;
        sscanf(argv[1],"%d",&amp;i);
        adb_watch(i);
        return 0;
    }

    return 0;
}</pre>
<h1>Add a Record Command</h1>
<p>The record command simply turns on the global bool to either true or false and prints out the number of spaces free in the record &#8220;buffer&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">                case ADB_RECORD:
                    adb_recording = !adb_recording;
                    printf("Record %s Buffer Entries Free=%d\n",adb_recording?"ON":"OFF",
                        ADB_RECORD_MAX-adb_recording_count);
                break;</pre>
<p>And the change to usrcmd.c is also simple.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">// record = toggles
static int usrcmd_record(int argc, char **argv)
{
    if(argc == 1)
    {
        adb_record(-1);
        return 0;
    }
    return 0;
}</pre>
<h1>Add an Erase Command</h1>
<p>The erase function is like &#8220;watch&#8221;, as I overload the &#8220;entry&#8221; to have an ALL which is setup in advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_ERASE_ALL -1</pre>
<p>The erase is a bit more complicated than the watch.  When you receive a erase command you will either erase them all by iterating over the whole dates, or just erase one.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">                case ADB_ERASE:
                    if((int)msg.data0 == ADB_ERASE_ALL)
                    {
                        for(int i=0;i&lt;adb_db_count;i++)
                        {
                            adb_eraseEntry(i);
                        }
                    }
                    else
                        adb_eraseEntry((int)msg.data0);

                    printf("Record Buffer Free %d\n",ADB_RECORD_MAX-adb_recording_count);
                break;</pre>
<p>The individual eraseEntry function checks to make sure that you have a legal &#8220;entry&#8221;.  Then it follows the linked list &#8220;freeing&#8221; the data structures.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static void adb_eraseEntry(int entry)
{
    if(entry &gt; adb_db_count-1 || entry&lt;0)
    {
        printf("Erase Entry Not Found %d\n",entry);
        return;
    }

    adb_adv_data_t *ptr;
    ptr = (adb_adv_data_t *)adb_database[entry].list-&gt;next;
    adb_database[entry].list-&gt;next = 0;
    while(ptr)
    {
        adb_adv_data_t *next;
        next = (adb_adv_data_t *)ptr-&gt;next;
        free(ptr-&gt;data);
        free(ptr);
        adb_database[entry].listCount -= 1;
        adb_recording_count -= 1;
        ptr = next;
    }
}
</pre>
<p>And, of course, you need to add the command to usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">// erase
// erase #
static int usrcmd_erase(int argc, char **argv)
{
    if(argc &gt; 2)
    {
        return 0;
    }

    if(argc == 1)
    {
        adb_erase(ADB_ERASE_ALL);
        return 0;
    }

    int i;
    sscanf(argv[1],"%d",&amp;i);
    adb_erase(i);
    return 0;    

}</pre>
<p>Now when you build and program the kit you can turn on/off recording and erase and&#8230;.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/screen-shot-2020-11-14-at-7-30-37-am/" rel="attachment wp-att-10233"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1024x741.jpg" alt="" width="1024" height="741" class="alignnone size-large wp-image-10233" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1024x741.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-300x217.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-768x556.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1536x1112.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-600x434.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM.jpg 1976w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next post I will add</p>
<ol>
<li>Smarter printing</li>
<li>A &#8220;filter&#8221; to eliminate duplicate advertising packets</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 6)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 30 Nov 2020 13:00:38 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10206</guid>

					<description><![CDATA[Summary In part 6 of this series I will update the AnyCloud BLE Advertising Scanner to decode advertising packets into a more human readable textual output Story We are now 6 (or maybe 7 depending on how you count) articles into this series and we are still looking at raw bytes.  I have gotten to [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In part 6 of this series I will update the AnyCloud BLE Advertising Scanner to decode advertising packets into a more human readable textual output</p>
<h1>Story</h1>
<p>We are now 6 (or maybe 7 depending on how you count) articles into this series and we are still looking at raw bytes.  I have gotten to where I am pretty good at understanding those bytes, but that is now way to roll.  You might remember from the <a href="https://iotexpert.com/anycloud-bluetooth-utilities-library/">article</a> on the IoT Expert Bluetooth Utility library that there were a some interesting functions defined in the header.  Here it is:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">wiced_bool_t btutil_isEddystone(uint8_t *data);
wiced_bool_t btutil_is_iBeacon(uint8_t *data);
wiced_bool_t btutil_isCypress(uint8_t *data);

int btutil_adv_len(uint8_t *packet);
void btutil_adv_printPacketDecode(uint8_t *packet);
void btutil_adv_printPacketBytes(uint8_t *packet);</pre>
<p>Lets transform our  project from part 6 to use these functions.  In this article I will</p>
<ul>
<li>Redo the print bytes (to be smarter) functionality and to use the built in function</li>
<li>Rework the logic for the &#8220;print&#8221; command implementation</li>
<li>Add a new command &#8220;decode&#8221; which will run the decode function</li>
</ul>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Replace two code blocks with function calls</h1>
<p>Do you remember this block of code?  It print&#8217;s out the 6-bytes of the Bluetooth Address.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    for(int i=0;i&lt;BD_ADDR_LEN;i++)
    {
        printf("%02X:",adb_database[entry].result-&gt;remote_bd_addr[i]);
    }
</pre>
<p>You might have noticed that this function already exists in the BT Utility Library.  Use it.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    btutil_printBDaddress(adb_database[entry].result-&gt;remote_bd_addr);</pre>
<p>Then you remember this block of code which iterates through and advertising packet and prints out the raw bytes?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(adb_database[entry].data[i])
    {
        for(int j=0;j&lt;adb_database[entry].data[i];j++)
        {
            printf("%02X ",adb_database[entry].data[i+1+j]);
        }
        i = i + adb_database[entry].data[i]+1;
    }
</pre>
<p>Well, it exists in the library as well.  Use it.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">btutil_adv_printPacketBytes(adb_database[entry].data);</pre>
<h1>Fix the &#8220;print&#8221; Command</h1>
<p>In the previous implementation I had two functions for &#8220;print&#8221;.  The first one printed one entry and the second one printed the whole table.  I decided that I didnt really like this logic, so I compressed those two functions into one function.  Specifically, it take a number &#8220;entry&#8221;.  If that number is -1 then it will print the whole table.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printRawPacket(int entry)
{
    int start,end;
 
    if(entry &lt;= -1)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {
    
        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        printf(" Data: ");
        btutil_adv_printPacketBytes(adb_database[i].data);

        printf("\n");
    }
}
</pre>
<h1>Add a new &#8220;decode&#8221; Command</h1>
<p>The next thing to do is to add a function to print out decoded packets (or the whole table).  So I wrote this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_printDecodePacket(int entry)
{
    int start,end;
 
    if(entry == -1)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {

        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        printf("\n");
        btutil_adv_printPacketDecode(adb_database[i].data);
        printf("\n");
    }
}</pre>
<p>After finishing that block of code, I realized I had implemented almost exactly the same functionality which two different functions.  So, I decided to redo this by doing this.  Notice that it take in a adb_print_method, in other words raw bytes or decoded packet.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_PRINT_METHOD_BYTES,
    ADB_PRINT_METHOD_DECODE,
} adb_print_method_t;

static void adb_db_print(adb_print_method_t method,int entry)
{
    int start,end;
 
    if(entry &lt; 0)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {
    
        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {
        
        case ADB_PRINT_METHOD_BYTES:
            printf(" Data: ");
            btutil_adv_printPacketBytes(adb_database[i].data);
        break;

        case ADB_PRINT_METHOD_DECODE:
            printf("\n");
            btutil_adv_printPacketDecode(adb_database[i].data);
        break;
        } 
        printf("\n");
    }
}
</pre>
<p>I don&#8217;t show it here, but after changing this I had to fix up the function calls in several places in the advDatabase.</p>
<h1>Add a new command to print decode packets</h1>
<p>Now that I have a new method to print packets, I add a command to the database to allow the user to call it:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT_RAW,
    ADB_PRINT_DECODE,
} adb_cmd_t;
</pre>
<p>Then in the queue loop:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">switch(msg.cmd)
            {
                case ADB_ADD:
                    scan_result = (wiced_bt_ble_scan_results_t *)msg.data0;
                    data = (uint8_t *)msg.data1;
                    adb_db_add(scan_result,data);
                break;
                case ADB_PRINT_RAW:
                    adb_db_print(ADB_PRINT_METHOD_BYTES,(int)msg.data0);
                break;
                case ADB_PRINT_DECODE:
                    adb_db_print(ADB_PRINT_METHOD_DECODE,(int)msg.data0);
                break;
            }</pre>
<p>Then the actual function</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_printDecode(int entry)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_PRINT_DECODE;
    msg.data0 = (void *)entry;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If the queue is full... oh well
}</pre>
<p>Then add it to advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_printDecode(int entry);
</pre>
<p>Finally to the usercmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_printDecode(int argc, char **argv)
{
    if(argc == 1)
    {
        adb_printDecode(-1);
    }

    if(argc == 2)
    {
        int val;
        sscanf(argv[1],"%d",&amp;val);
        adb_printDecode(val);
    }
    return 0;
}</pre>
<h1>Program and Test</h1>
<p>When I actually program the scanner you can see that I can print out 1 item.  OR I can decode one item.  Notice that one contains 3 fields</p>
<ul>
<li>flags</li>
<li>Tx Power Level</li>
<li>Manufacturers data.  Apparently an Apple something or the other</li>
</ul>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-53-43-am/" rel="attachment wp-att-10211"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-1024x219.png" alt="" class="alignnone size-large wp-image-10211" width="1024" height="219" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-1024x219.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-300x64.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-768x164.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-600x128.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM.png 1358w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And I can print the whole table</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-51-10-am/" rel="attachment wp-att-10213"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1024x629.jpg" alt="" class="alignnone size-large wp-image-10213" width="1024" height="629" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1024x629.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-300x184.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-768x472.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1536x944.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-2048x1259.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-600x369.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Or decode the whole table.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-51-33-am/" rel="attachment wp-att-10212"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1024x633.jpg" alt="" class="alignnone size-large wp-image-10212" width="1024" height="633" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1024x633.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-300x185.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-768x475.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1536x949.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-2048x1266.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-600x371.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 5)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 23 Nov 2020 18:03:57 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10196</guid>

					<description><![CDATA[Summary In this article I will add a new task to the AnyCloud BLE Advertising Scanning application which will save the advertising data into a database. Story There is still a boatload of mostly unintelligible advertising data coming ripping onto our screen.  It is FINALLY time to start fixing that.  In this article I will [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will add a new task to the AnyCloud BLE Advertising Scanning application which will save the advertising data into a database.</p>
<h1>Story</h1>
<p>There is still a boatload of mostly unintelligible advertising data coming ripping onto our screen.  It is FINALLY time to start fixing that.  In this article I will create a new task called the advertising database task which will hold the history of advertising packets that I have seen.  I will update the Bluetooth Manager task to submit the advertising packets to a queue running in the advertising database task.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Create an Advertising Data Database Task</h1>
<p>We need to create the file advertisingDatabase.h which will hold the task prototype (so that main can get going).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

void adb_task(void *arg);
</pre>
<p>Then create the advertisingDatabase.c to hold the actual database code.  It will start with the definition of messages which can be sent to the task.  For now just &#8220;ADB_ADD&#8221;.  To make things a little bit simpler these command can have two data elements (which I call data0 and data1).  Then the main part of the task just</p>
<ol>
<li>Creates the queue to manage the messages</li>
<li>Process the message until the end of time</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "FreeRTOS.h"
#include "queue.h"

static QueueHandle_t adb_cmdQueue;
typedef enum {
    ADB_ADD,
} adb_cmd_t;

typedef struct
{
    adb_cmd_t cmd;
    void *data0;
    void *data1;
} adb_cmdMsg_t;

void adb_task(void *arg)
{
    // setup the queue
    adb_cmdMsg_t msg;

    adb_cmdQueue = xQueueCreate(10,sizeof(adb_cmdMsg_t));
    
    while(1)
    {
        BaseType_t status = xQueueReceive(adb_cmdQueue,&amp;msg,portMAX_DELAY);
        if(status == pdTRUE) 
        {
            switch(msg.cmd)
            {
                case ADB_ADD:
                break;
            }

        }
    }
}
</pre>
<p>To start the task, you need to add it to main.c.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    xTaskCreate(adb_task,"adv database",configMINIMAL_STACK_SIZE*4,0,1,0);
</pre>
<p>When I build and program this, you can now see the new task.  Good that working.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">AnyCloud&gt; Unhandled Bluetooth Management Event: BTM_LOCAL_IDENTITY_KEYS_REQUEST_EVT
Started BT Stack Succesfully

AnyCloud&gt; tasks
Name          State Priority   Stack  Num
------------------------------------------
usrcmd_ta       X       0       228     5
IDLE            R       0       115     7
Tmr Svc         B       0       223     8
CYBT_HCI_       B       5       950     3
sleep_tas       B       6       221     1
CYBT_BT_T       B       4       1371    2
blinkTask       B       0       98      4
adv datab       B       1       479     6
‘B’ – Blocked
‘R’ – Ready
‘D’ – Deleted (waiting clean up)
‘S’ – Suspended, or Blocked without a timeout
Stack = bytes free at highwater
AnyCloud&gt;</pre>
<h1>Update the Advertising Database to Accept Submitted ADV Packets</h1>
<p>If you recall our original setup was to take advertising packets in the Bluetooth Manager thread and print out the data.  The first thing that we want to fix up is the ability of the advertising database task to accept advertising packets which are pushed to its command queue.   To prepare for this I create two local variables to hold the data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_task(void *arg)
{
    // setup the queue
    adb_cmdMsg_t msg;
    wiced_bt_ble_scan_results_t *scan_result;
    uint8_t *data;</pre>
<p>Then I update the ADB_ADD command.  My first, and really simple fix, is to grab the printing code from the Bluetooth Manager task.  Obviously this won&#8217;t be an improvement from the original program as far as the users goes, but it will verify that the tasks are working properly together.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_ADD:
                    // Print the MAC Address
                    scan_result = (wiced_bt_ble_scan_results_t *)msg.data0;
                    data = (uint8_t *)msg.data1;

                    printf("MAC: ");
                    for(int i=0;i&lt;BD_ADDR_LEN;i++)
                    {
                        printf("%02X:",scan_result-&gt;remote_bd_addr[i]);
                    }
                    // Print the RAW Data of the ADV Packet
                    printf(" Data: ");
                    int i=0;
                    while(data[i])
                    {
                        for(int j=0;j&lt;data[i];j++)
                        {
                            printf("%02X ",data[i+1+j]);
                        }
                        i = i + data[i]+1;
                    }
                    printf("\n");
    
                    free(msg.data0);
                    free(msg.data1);
                break;
</pre>
<p>Then I add a command to the advertisingDatabase.h which the Bluetooth Manager task can call to submit advertising packets</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data);</pre>
<p>The actual command in advertisingDatabase.c just takes the advertising information, puts it in a command message, then submits it to the command queue.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_ADD;
    msg.data0 = (void *)scan_result;
    msg.data1 = (void *)data;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If you loose an adv packet it is OK...
}
</pre>
<h1>Update the Bluetooth Manager to Submit Adv Packets</h1>
<p>Now I go and edit the bluetoothManager. c to submit packets rather than print them.  To do this I greatly simplify the callback.  There is one VERY important issue to deal with, which is one of those potential religious war issues.  Memory.</p>
<p>When you get the callback from the stack, it gives you POINTERS to data for the advertising packet that reside inside of buffers inside of the stack.  As soon as this callback returns this memory is purged.  To prevent this data from getting cleaned up by the stack I</p>
<ol>
<li>Malloc some memory for the wiced_bt_ble_scan_results</li>
<li>Malloc some memory for the advertising data</li>
<li>Make a copy of the data</li>
<li>Submit it to the Advertising Database</li>
</ol>
<p>I KNOW from the spec that the largest data packet is 31-bytes (actually it is 31-bytes + one more field with length 0).  So I know the maximum length is 32-bytes  This means that in many situations I will be copying GARBAGE into my buffer if the packet is less than 32 bytes long.  I think that this is simpler than calculating the length and then only copying that much data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void btm_advCallback(wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data)
{
    wiced_bt_ble_scan_results_t *scan_result = malloc(sizeof(wiced_bt_ble_scan_results_t));
    uint8_t *data = malloc(32);
   
    memcpy(data,p_adv_data,32);
    memcpy(scan_result,p_scan_result-&gt;remote_bd_addr,BD_ADDR_LEN);
    adb_addAdv(scan_result,data);
}
</pre>
<p>When I run this updated program I should get the same stream of data coming out on the serial port.  Sure enough the new thread is working.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/screen-shot-2020-11-07-at-10-23-16-am/" rel="attachment wp-att-10198"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1024x577.png" alt="" width="1024" height="577" class="alignnone size-large wp-image-10198" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1024x577.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-300x169.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-768x433.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1536x865.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-600x338.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM.png 1868w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Create an Advertising Data Database</h1>
<p>Now, lets create an actual database.  To simplify things my database is just an array of structures.  One structure per bluetooth device.  The structure will contain a pointer to the information about the device it just saw and the actual raw data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    wiced_bt_ble_scan_results_t *result;
    uint8_t *data;
} adb_adv_t ;

#define ADB_MAX_SIZE (40)
adb_adv_t adb_database[ADB_MAX_SIZE];
int adb_db_count=0;
</pre>
<p>Then I will create several helper functions to work with the database</p>
<ol>
<li>Find devices in the database given a mac address</li>
<li>Print an entry in the database</li>
<li>Add entries to the database</li>
</ol>
<p>First, find an entry in the database.  This function will search through the database and compare the mac address against the mac address in the database.  When the memcmp ==0 meaning it found a match, it will return that entry.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int adb_db_find(wiced_bt_device_address_t *add)
{
    int rval=-1;
    for(int i=0;i&lt;adb_db_count;i++)
    {
        if(memcmp(add,&amp;adb_database[i].result-&gt;remote_bd_addr,BD_ADDR_LEN)==0)
        {
            rval = i;
            break;
        }
    }
    return rval;
}</pre>
<p>The print function will make sure that you asked for a legal entry (much must be greater than 0&#8230; and less than the max).  Then it will print out the mac address and the raw data.  In a future post I will add a smarter print out.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printEntry(int entry)
{
    if(!(entry&gt;= 0 &amp;&amp; entry &lt;= adb_db_count))
    {
        printf("Illegal entry\n");
        return;
    }
    printf("%02d MAC: ",entry);

    for(int i=0;i&lt;BD_ADDR_LEN;i++)
    {
        printf("%02X:",adb_database[entry].result-&gt;remote_bd_addr[i]);
    }

    // Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(adb_database[entry].data[i])
    {
        for(int j=0;j&lt;adb_database[entry].data[i];j++)
        {
            printf("%02X ",adb_database[entry].data[i+1+j]);
        }
        i = i + adb_database[entry].data[i]+1;
    }
    printf("\n");
}</pre>
<p>To add an entry to the database, first make sure that it isn&#8217;t already in the database.  Then when you are sure that it isn&#8217;t the database, you just add the pointers to your table.  You need to make sure and not go beyond the end of the table, and if you did, you will have effectively blown away the last entry in the table.  Oh well.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_add(wiced_bt_ble_scan_results_t *scan_result,uint8_t *data)
{
 
    int entry = adb_db_find(&amp;scan_result-&gt;remote_bd_addr);
    if(entry == -1)
    {
        
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].data = data;
        adb_db_printEntry(adb_db_count);
        adb_db_count = adb_db_count + 1;
        if(adb_db_count == ADB_MAX_SIZE)
        {
            printf("ADV Table Max Size\n");
            adb_db_count = adb_db_count - 1;
        }
    }
    else
    {
        free(scan_result);
        free(data);
    }
}
</pre>
<h1>Add a Command to Print the Database</h1>
<p>Now we want to add the ability to print from the command line.  So add a new command message to the list of legal commands.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT,
} adb_cmd_t;
</pre>
<p>Then create a new function to print.  If you send in a &#8220;-1&#8221; it will print the whole table.  Otherwise just print the individual entry.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static void adb_printTable(int entry)
{
    if(entry == -1)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_db_printEntry(i);
        }

    }
    else
    {
        adb_db_printEntry(entry);
    }
    

}</pre>
<p>Now edit usercmd.c to have the new command line.  Notice that I use &#8220;sscanf&#8221; which obviously has some issues.  Too bad.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_print(int argc, char **argv)
{

    if(argc == 1)
    {
        adb_print(-1); // Print whole table
    }

    if(argc == 2)
    {
        int val;
        sscanf(argv[1],"%d",&amp;val);
        adb_print(val);
    }

    return 0;
}</pre>
<p>When I program the project it immediately prints out a bunch of devices that are at my house.  Then you can see I run the &#8220;print&#8221; command which prints the table.  Finally P do a print 0 to just print the first entry.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/screen-shot-2020-11-08-at-9-34-13-am/" rel="attachment wp-att-10201"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1024x782.jpg" alt="" width="1024" height="782" class="alignnone size-large wp-image-10201" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1024x782.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-300x229.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-768x587.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1536x1173.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-600x458.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM.jpg 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article I will add smarter diagnostics to the advertising packets.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Utilities Library</title>
		<link>https://iotexpert.com/anycloud-bluetooth-utilities-library/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-utilities-library/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 09 Nov 2020 13:18:17 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-BLE]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10175</guid>

					<description><![CDATA[Summary This article is a discussion of a library of utilities functions that support AnyCloud Bluetooth development.  It includes settings to configure the hardware, functions to decode stack events, functions to decode advertising packets etc. Story The Cypress, now Infineon, Modus Toolbox team has been working to bring the WICED Bluetooth devices to be closer [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This article is a discussion of a library of utilities functions that support AnyCloud Bluetooth development.  It includes settings to configure the hardware, functions to decode stack events, functions to decode advertising packets etc.</p>
<h1>Story</h1>
<p>The Cypress, now Infineon, Modus Toolbox team has been working to bring the WICED Bluetooth devices to be closer and more compatible with the PSoC 6 tools.  One of the important enablement things we have done is turn on the WICED Bluetooth Host stack on the PSoC 6 so that it can effectively talk to the CYW43XXX Bluetooth / WiFi combo chips.</p>
<p>As I have been using all of the new stuff I found myself adding my own custom functionality&#8230;. and after a while I realized (finally) that I should put all of those little helper things into a library, specifically an IoT Expert library.  For now this library contains:</p>
<ul>
<li>The Bluetooth Platform Configuration Settings</li>
<li>Functions to decode stack events</li>
<li>Functions to decode advertising packets</li>
</ul>
<p>but imagine with time I will add more functions and templates.</p>
<h1><span>bt_platform_cfg_settings</span></h1>
<p>As I discussed in the article <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener noreferrer">AnyCloud Bluetooth Advertising Scanner (Part 1)</a>, every single AnyCloud BLE Stack project will require a structure of type wiced_bt_cfg_settings_t.  This structure is used to setup the hardware before getting the stack going.  Remember you need to make a call like this to initialize the Bluetooth hardware.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    cybt_platform_config_init(&amp;bt_platform_cfg_settings);
</pre>
<p>At some point this file will be included automatically for you by the Modus Toolbox team, but for now I have added this to my library.  This file look like this.  Basically a bunch of pin definitions which are set for you automatically by the BSP.  Obviously you can make your own, but this should work on all of the Cypress development kits (I think)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cybt_platform_config.h"
#include "cybsp.h"
#include "wiced_bt_stack.h"

const cybt_platform_config_t bt_platform_cfg_settings =
{
    .hci_config =
    {
        .hci_transport = CYBT_HCI_UART,

        .hci =
        {
            .hci_uart =
            {
                .uart_tx_pin = CYBSP_BT_UART_TX,
                .uart_rx_pin = CYBSP_BT_UART_RX,
                .uart_rts_pin = CYBSP_BT_UART_RTS,
                .uart_cts_pin = CYBSP_BT_UART_CTS,

                .baud_rate_for_fw_download = 115200,
                .baud_rate_for_feature     = 115200,

                .data_bits = 8,
                .stop_bits = 1,
                .parity = CYHAL_UART_PARITY_NONE,
                .flow_control = WICED_TRUE
            }
        }
    },

    .controller_config =
    {
        .bt_power_pin      = CYBSP_BT_POWER,
        .sleep_mode =
        {
            #if (bt_0_power_0_ENABLED == 1) /* BT Power control is enabled in the LPA */
            #if (CYCFG_BT_LP_ENABLED == 1) /* Low power is enabled in the LPA, use the LPA configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYCFG_BT_DEV_WAKE_GPIO,
            .host_wakeup_pin = CYCFG_BT_HOST_WAKE_GPIO,
            .device_wake_polarity = CYCFG_BT_DEV_WAKE_POLARITY,
            .host_wake_polarity = CYCFG_BT_HOST_WAKE_IRQ_EVENT
            #else /* Low power is disabled in the LPA, disable low power */
            .sleep_mode_enabled = false
            #endif
            #else /* BT Power control is disabled in the LPA – default to BSP low power configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYBSP_BT_DEVICE_WAKE,
            .host_wakeup_pin = CYBSP_BT_HOST_WAKE,
            .device_wake_polarity = CYBT_WAKE_ACTIVE_LOW,
            .host_wake_polarity = CYBT_WAKE_ACTIVE_LOW
            #endif
        }
    },

    .task_mem_pool_size    = 2048
};</pre>
<h1><span>btutil_stack</span></h1>
<p>When you startup the Bluetooth Host stack you are responsible for providing a &#8220;management callback&#8221; which has the function prototype</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef wiced_result_t (wiced_bt_management_cback_t) (wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data);
</pre>
<p>The first parameter is an &#8220;event&#8221; which is  just an enumerated list of possible events by the Bluetooth Host Stack.  Here is the actual list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">enum wiced_bt_management_evt_e {
    /* Bluetooth status events */
    BTM_ENABLED_EVT,                                /**&lt; Bluetooth controller and host stack enabled. Event data: wiced_bt_dev_enabled_t */
    BTM_DISABLED_EVT,                               /**&lt; Bluetooth controller and host stack disabled. Event data: NULL */
    BTM_POWER_MANAGEMENT_STATUS_EVT,                /**&lt; Power management status change. Event data: wiced_bt_power_mgmt_notification_t */
    BTM_RE_START_EVT,                               /**&lt; Bluetooth controller and host stack re-enabled. Event data: tBTM_ENABLED_EVT */
    /* Security events */
    BTM_PIN_REQUEST_EVT,                            /**&lt; PIN request (used only with legacy devices). Event data: #wiced_bt_dev_name_and_class_t */
    BTM_USER_CONFIRMATION_REQUEST_EVT,              /**&lt; received USER_CONFIRMATION_REQUEST event (respond using #wiced_bt_dev_confirm_req_reply). Event data: #wiced_bt_dev_user_cfm_req_t */
    BTM_PASSKEY_NOTIFICATION_EVT,                   /**&lt; received USER_PASSKEY_NOTIFY event. Event data: #wiced_bt_dev_user_key_notif_t */
    BTM_PASSKEY_REQUEST_EVT,                        /**&lt; received USER_PASSKEY_REQUEST event @cond DUAL_MODE (respond using #wiced_bt_dev_pass_key_req_reply). Event data: #wiced_bt_dev_user_key_req_t @endcond
                                                     @note  BR/EDR Only */
    BTM_KEYPRESS_NOTIFICATION_EVT,                  /**&lt; received KEYPRESS_NOTIFY event. Event data: #wiced_bt_dev_user_keypress_t */
    BTM_PAIRING_IO_CAPABILITIES_BR_EDR_REQUEST_EVT, /**&lt; Requesting IO capabilities for BR/EDR pairing. Event data: #wiced_bt_dev_bredr_io_caps_req_t 
                                                        @note  BR/EDR Only */
    BTM_PAIRING_IO_CAPABILITIES_BR_EDR_RESPONSE_EVT,/**&lt; Received IO capabilities response for BR/EDR pairing. Event data: @cond DUAL_MODE #wiced_bt_dev_bredr_io_caps_rsp_t @endcond
                                                        @note  BR/EDR Only*/
    BTM_PAIRING_IO_CAPABILITIES_BLE_REQUEST_EVT,    /**&lt; Requesting IO capabilities for BLE pairing. Slave can check peer io capabilities in event data before updating with local io capabilities. Event data: #wiced_bt_dev_ble_io_caps_req_t */
    BTM_PAIRING_COMPLETE_EVT,                       /**&lt; received SIMPLE_PAIRING_COMPLETE event. Event data: #wiced_bt_dev_pairing_cplt_t */
    BTM_ENCRYPTION_STATUS_EVT,                      /**&lt; Encryption status change. Event data: #wiced_bt_dev_encryption_status_t */
    BTM_SECURITY_REQUEST_EVT,                       /**&lt; Security request (respond using #wiced_bt_ble_security_grant). Event data: #wiced_bt_dev_security_request_t */
    BTM_SECURITY_FAILED_EVT,                        /**&lt; Security procedure/authentication failed. Event data: #wiced_bt_dev_security_failed_t */
    BTM_SECURITY_ABORTED_EVT,                       /**&lt; Security procedure aborted locally, or unexpected link drop. Event data: #wiced_bt_dev_name_and_class_t */

    BTM_READ_LOCAL_OOB_DATA_COMPLETE_EVT,           /**&lt; Result of reading local OOB data @cond DUAL_MODE (#wiced_bt_dev_read_local_oob_data). Event data: #wiced_bt_dev_local_oob_t @endcond 
                                                        @note  BR/EDR Only */

    BTM_REMOTE_OOB_DATA_REQUEST_EVT,                /**&lt; OOB data from remote device @cond DUAL_MODE (respond using #wiced_bt_dev_remote_oob_data_reply). Event data: #wiced_bt_dev_remote_oob_t @endcond 
                                                        @note  BR/EDR Only */

    BTM_PAIRED_DEVICE_LINK_KEYS_UPDATE_EVT,         /**&lt; Updated remote device link keys (store device_link_keys to  NV memory). This is the place to
verify that the correct link key has been generated. Event data: #wiced_bt_device_link_keys_t */
    BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT,        /**&lt; Request for stored remote device link keys (restore device_link_keys from NV memory). If successful, return WICED_BT_SUCCESS. Event data: #wiced_bt_device_link_keys_t */

    BTM_LOCAL_IDENTITY_KEYS_UPDATE_EVT,             /**&lt; Update local identity key (stored local_identity_keys NV memory). Event data: #wiced_bt_local_identity_keys_t */
    BTM_LOCAL_IDENTITY_KEYS_REQUEST_EVT,            /**&lt; Request local identity key (get local_identity_keys from NV memory). If successful, return WICED_BT_SUCCESS. Event data: #wiced_bt_local_identity_keys_t */

    BTM_BLE_SCAN_STATE_CHANGED_EVT,                 /**&lt; BLE scan state change. Event data: #wiced_bt_ble_scan_type_t */
    BTM_BLE_ADVERT_STATE_CHANGED_EVT,               /**&lt; BLE advertisement state change. Event data: #wiced_bt_ble_advert_mode_t */

    /* BLE Secure Connection events */
    BTM_SMP_REMOTE_OOB_DATA_REQUEST_EVT,            /**&lt; SMP remote oob data request. Reply using wiced_bt_smp_oob_data_reply. Event data: #wiced_bt_smp_remote_oob_req_t  */
    BTM_SMP_SC_REMOTE_OOB_DATA_REQUEST_EVT,         /**&lt; LE secure connection remote oob data request. Reply using wiced_bt_smp_sc_oob_reply. Event data: #wiced_bt_smp_sc_remote_oob_req_t 
                                                        @note  BR/EDR Only */
    BTM_SMP_SC_LOCAL_OOB_DATA_NOTIFICATION_EVT,     /**&lt; LE secure connection local OOB data (wiced_bt_smp_create_local_sc_oob_data). Event data: #wiced_bt_smp_sc_local_oob_t */

    BTM_SCO_CONNECTED_EVT,                          /**&lt; SCO connected event. Event data: @cond DUAL_MODE #wiced_bt_sco_connected_t @endcond
                                                        @note  BR/EDR Only */
    BTM_SCO_DISCONNECTED_EVT,                       /**&lt; SCO disconnected event. Event data: @cond #wiced_bt_sco_disconnected_t @endcond
                                                        @note  BR/EDR Only */
    BTM_SCO_CONNECTION_REQUEST_EVT,                 /**&lt; SCO connection request event. Event data: @cond #wiced_bt_sco_connection_request_t @endcond
                                                        @note  BR/EDR Only */
    BTM_SCO_CONNECTION_CHANGE_EVT,                  /**&lt; SCO connection change event. Event data: @cond #wiced_bt_sco_connection_change_t @endcond
                                                        @note  BR/EDR Only */
    BTM_BLE_CONNECTION_PARAM_UPDATE,                /**&lt; BLE connection parameter update. Event data: #wiced_bt_ble_connection_param_update_t */
    BTM_BLE_PHY_UPDATE_EVT,                         /**&lt; BLE Physical link update. Event data: wiced_bt_ble_phy_update_t */
    BTM_LPM_STATE_LOW_POWER,                        /**&lt; BT device wake has been deasserted. Used for Host Stack Use Case. */
    BTM_MULTI_ADVERT_RESP_EVENT,                    /**&lt; Multi adv command status event Used for the status of the command sent */
#if SMP_CATB_CONFORMANCE_TESTER == TRUE
    BTM_SMP_SC_PEER_INFO_EVT                        /** The Secure Connections support information of the peer device */
#endif

};</pre>
<p>While you are trying to figure out what is going on during the development, it is very useful to be able to print out the name of the events (instead of the numbers).  In other words instead of doing</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">printf("Event = %02X\n",event);</pre>
<p>it is way better to do</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">printf("Event Name=%s\n",btutil_getBTEventName(event));</pre>
<p>While I was looking at an example project I found this function which I thought was awesome.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">const char *btutil_getBTEventName(wiced_bt_management_evt_t event)
{
    switch ( (int)event )
    {
    CASE_RETURN_STR(BTM_ENABLED_EVT)
    CASE_RETURN_STR(BTM_DISABLED_EVT)
    CASE_RETURN_STR(BTM_POWER_MANAGEMENT_STATUS_EVT)
    CASE_RETURN_STR(BTM_PIN_REQUEST_EVT)
    CASE_RETURN_STR(BTM_USER_CONFIRMATION_REQUEST_EVT)
    CASE_RETURN_STR(BTM_PASSKEY_NOTIFICATION_EVT)
    CASE_RETURN_STR(BTM_PASSKEY_REQUEST_EVT)
    CASE_RETURN_STR(BTM_KEYPRESS_NOTIFICATION_EVT)
    CASE_RETURN_STR(BTM_PAIRING_IO_CAPABILITIES_BR_EDR_REQUEST_EVT)
    CASE_RETURN_STR(BTM_PAIRING_IO_CAPABILITIES_BR_EDR_RESPONSE_EVT)
    CASE_RETURN_STR(BTM_PAIRING_IO_CAPABILITIES_BLE_REQUEST_EVT)
    CASE_RETURN_STR(BTM_PAIRING_COMPLETE_EVT)
    CASE_RETURN_STR(BTM_ENCRYPTION_STATUS_EVT)
    CASE_RETURN_STR(BTM_SECURITY_REQUEST_EVT)
    CASE_RETURN_STR(BTM_SECURITY_FAILED_EVT)
    CASE_RETURN_STR(BTM_SECURITY_ABORTED_EVT)
    CASE_RETURN_STR(BTM_READ_LOCAL_OOB_DATA_COMPLETE_EVT)
    CASE_RETURN_STR(BTM_REMOTE_OOB_DATA_REQUEST_EVT)
    CASE_RETURN_STR(BTM_PAIRED_DEVICE_LINK_KEYS_UPDATE_EVT)
    CASE_RETURN_STR(BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT)
    CASE_RETURN_STR(BTM_LOCAL_IDENTITY_KEYS_UPDATE_EVT)
    CASE_RETURN_STR(BTM_LOCAL_IDENTITY_KEYS_REQUEST_EVT)
    CASE_RETURN_STR(BTM_BLE_SCAN_STATE_CHANGED_EVT)
    CASE_RETURN_STR(BTM_BLE_ADVERT_STATE_CHANGED_EVT)
    CASE_RETURN_STR(BTM_SMP_REMOTE_OOB_DATA_REQUEST_EVT)
    CASE_RETURN_STR(BTM_SMP_SC_REMOTE_OOB_DATA_REQUEST_EVT)
    CASE_RETURN_STR(BTM_SMP_SC_LOCAL_OOB_DATA_NOTIFICATION_EVT)
    CASE_RETURN_STR(BTM_SCO_CONNECTED_EVT)
    CASE_RETURN_STR(BTM_SCO_DISCONNECTED_EVT)
    CASE_RETURN_STR(BTM_SCO_CONNECTION_REQUEST_EVT)
    CASE_RETURN_STR(BTM_SCO_CONNECTION_CHANGE_EVT)
    CASE_RETURN_STR(BTM_BLE_CONNECTION_PARAM_UPDATE)
#ifdef CYW20819A1
    CASE_RETURN_STR(BTM_BLE_PHY_UPDATE_EVT)
#endif
    }

    return NULL;
}</pre>
<p>And then I learned something new when I looked at the &#8220;function&#8221; CASE_RETURN_STR which used compiler trick to turn an enumerated value into a string.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define CASE_RETURN_STR(enum_val)          case enum_val: return #enum_val;</pre>
<p>This allows you to do this in your management callback (notice line 16 where the string is printed out)</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:
            if (WICED_BT_SUCCESS == p_event_data-&gt;enabled.status)
            {
                printf("Started BT Stack Succesfully\n");
                wiced_bt_ble_observe(WICED_TRUE,0,obv_callback);
            }
            break;

        default:
            printf("Unhandled Bluetooth Management Event: %s\n", btutil_getBTEventName(event));
            break;
    }

    return result;
}</pre>
<p>It turns out that there are several other places where the stack gives you an event-ish thing.  So these functions were created as well</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

const char *btutil_getBTEventName(wiced_bt_management_evt_t event);
const char *btutil_getBLEAdvertModeName(wiced_bt_ble_advert_mode_t mode);
const char *btutil_getBLEGattDisconnReasonName(wiced_bt_gatt_disconn_reason_t reason);
const char *btutil_getBLEGattStatusName(wiced_bt_gatt_status_t status);</pre>
<h1><span>btutil_adv_decode</span></h1>
<p>In <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener noreferrer">AnyCloud Bluetooth Advertising Scanner (Part 3)</a> I discussed the format of the advertising packet.  So I created functions which will decode the data in the advertising packets.  More on the future article AnyCloud Bluetooth Advertising Scanner (Part 4 or maybe 5 or maybe 6).  Here are the functions:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

wiced_bool_t btutil_isEddystone(uint8_t *data);
wiced_bool_t btutil_is_iBeacon(uint8_t *data);
wiced_bool_t btutil_isCypress(uint8_t *data);

int btutil_adv_len(uint8_t *packet);
void btutil_adv_printPacketDecode(uint8_t *packet);
void btutil_adv_printPacketBytes(uint8_t *packet);</pre>
<h1>btutil</h1>
<p>And because I like to have just one include to get access to all of the function I created &#8220;btutil.h&#8221; which just includes all of the headers in one place.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

#include "btutil_adv_decode.h"
#include "btutil_stack.h"
#include "btutil_general.h"
#include "bt_platform_cfg_settings.h"
</pre>
<h1>Add to the IoT Expert Manifest</h1>
<p>In order to set it up for my library to live in the library manager I updated the IoT Expert Manifest file to have a link to the GitHub repository</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">&lt;middleware&gt;
  
    &lt;name&gt;Bluetooth Utilities&lt;/name&gt;
    &lt;id&gt;btutil&lt;/id&gt;
    &lt;uri&gt;https://github.com/iotexpert/btutil&lt;/uri&gt;
    &lt;desc&gt;A library of Bluetooth Debugging Utilties for Cypress PSoC6 Anycloud&lt;/desc&gt;
    &lt;category&gt;IoT Expert&lt;/category&gt;
    &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
    &lt;versions&gt;
      &lt;version flow_version="1.0,2.0"&gt;
        &lt;num&gt;master&lt;/num&gt;
        &lt;commit&gt;master&lt;/commit&gt;
        &lt;desc&gt;master&lt;/desc&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/middleware&gt;
</pre>
<p>And now the library manager has the IoT Expert Bluetooth Utilities.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-utilities-library/screen-shot-2020-11-01-at-10-43-31-am/" rel="attachment wp-att-10180"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM-1024x815.png" alt="" class="alignnone size-large wp-image-10180" width="1024" height="815" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM-1024x815.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM-300x239.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM-768x611.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM-600x477.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-01-at-10.43.31-AM.png 1116w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1></h1>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-utilities-library/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 1)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 19 Oct 2020 12:40:29 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[ModusToolbox]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10102</guid>

					<description><![CDATA[Summary The first of several articles discussing the use of the AnyCloud BLE Stack to build advertising scanner/observers. Story A few summers ago while I was writing the WICED Bluetooth Academy book, I created a WICED based BLE advertising scanner.  Actually, I created a framework for the scanner and the remarkable summer intern I had [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>The first of several articles discussing the use of the AnyCloud BLE Stack to build advertising scanner/observers.</p>
<h1>Story</h1>
<p>A few summers ago while I was writing the WICED Bluetooth Academy book, I created a WICED based BLE advertising scanner.  Actually, I created a framework for the scanner and the remarkable summer intern I had finished the work.  That project has been sitting in the source code repository for the Bluetooth class, mostly only shown to face-to-face students.  This scanner is built using some of the original code combined with the new AnyCloud Bluetooth SDK.  It will act sort-of-like <a href="https://punchthrough.com/lightblue/" target="_blank" rel="noopener noreferrer">LightBlue</a> or one of the other Bluetooth advertising scanners you might run on your phone, but with a serial console.</p>
<p>Sometime in the last few months we released the Bluetooth SDK for AnyCloud (things have been crazy and I have lost track of time)  This SDK has all of the stuff needed to add Bluetooth to your AnyCloud project using one of the Cypress Bluetooth/WiFi combo chips.  I had not had a chance to try it out, so I decided to build a Bluetooth project and then port the scanning code.</p>
<p><span><p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p></span></p>
<h1>Bluetooth Application Architecture</h1>
<p>Bluetooth applications are divided into these four pieces</p>
<ol>
<li>You user application which responds to events and sends messages from/to the Bluetooth host stack</li>
<li>A Bluetooth Host Stack</li>
<li>A Bluetooth Controller Stack</li>
<li>The Bluetooth Radio</li>
</ol>
<p>These four pieces can be divided into multiple chips, as few as one or as many as four.  However, for this article, the project will be built to run on a PSoC 6 + CYW43012 WiFi/Bluetooth Combo chip.  Specifically:</p>
<ol>
<li>My scanner application running on the PSoC 6</li>
<li>The Bluetooth Host Stack running on the PSoC 6</li>
<li>The BlueTooth Controller Firmware running on the CYW43012</li>
<li>A Bluetooth Radio on the CYW43012</li>
</ol>
<p>But how do they talk?  Simple, there is:</p>
<ol>
<li>A UART Host Controller Interface (HCI) between the two chips</li>
<li>A GPIO to serve as a deep sleep wakeup from the 43012 &#8211;&gt; PSoC 6</li>
<li>A GPIO to serve as the bluetooth controller wakeup from the PSoC 6 &#8211;&gt; 43012</li>
<li>A GPIO to turn on the Bluetooth regulator from the PSoC 6 &#8211;&gt; 43012</li>
</ol>
<p>Here is the block diagram from the CY8CKIT-062S2-43012 Kit Guide.  Notice that signals labeled UART and Control going between the PSoC 6 and the CYW43012.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-18-at-9-34-51-am/" rel="attachment wp-att-10129"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-1024x486.png" alt="" width="1024" height="486" class="alignnone size-large wp-image-10129" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-1024x486.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-300x142.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-768x364.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-1536x729.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-2048x972.png 2048w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.51-AM-600x285.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And when you read more deeply into the schematic you can see the signals labeled</p>
<ul>
<li>BT_UART_TXD/RXD/CTS/RTS</li>
<li>BT_HOST_WAKE</li>
<li>BT_DEV_WAKE</li>
<li>BT_REG_ON</li>
</ul>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-18-at-9-34-25-am/" rel="attachment wp-att-10128"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM-1024x875.jpg" alt="" width="1024" height="875" class="alignnone size-large wp-image-10128" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM-1024x875.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM-300x256.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM-768x656.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM-600x512.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-18-at-9.34.25-AM.jpg 1192w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>How to Start the AnyCloud Bluetooth Stack</h1>
<p>To actually start the AnyCloud Bluetooth stack you will call two functions</p>
<ol>
<li><strong>cybt_platform_config_init</strong> &#8211; that will setup the hardware interface to the CYW43012</li>
<li><strong>wiced_bt_stack_init</strong> that will:
<ol>
<li>Start a task to manage the Host Controller Interface</li>
<li>Download the controller firmware to the CYW43012</li>
<li>Start a task to manage the host stack</li>
<li>Initialize both the host and the controller</li>
<li>Call you back when that is all done</li>
</ol>
</li>
</ol>
<p>Here is an example from main.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    cybt_platform_config_init(&amp;bt_platform_cfg_settings);
    wiced_bt_stack_init (app_bt_management_callback, &amp;wiced_bt_cfg_settings);</pre>
<p>When you look at these two function calls, you will find that you need to provide three things:</p>
<ol>
<li>A platform hardware configuration structure called bt_platform_cfg_settings</li>
<li>The Bluetooth stack configuration settings structure called wiced_bt_cfg_settings</li>
<li>A management callback called app_bt_management_callback</li>
</ol>
<h1>bt_platform_cfg_settings</h1>
<p>The purpose of the hardware configuration structure is to define the UART + parameters and the wakeup GPIOs.  Specifically, the hardware configuration structure defines the configuration of the host controller interface (hci)</p>
<ol>
<li>The HCI transport scheme (in this case UART)</li>
<li>The pins of the UART</li>
<li>Baud Rate</li>
<li>Data Bits</li>
<li>Stop Bits</li>
<li>Parity</li>
<li>Flow Control</li>
</ol>
<p>And the controller low power behavior (in the .controller_config member)</p>
<p>This is a fairly standard configuration and I think that we should help you by providing this structure somewhere in the BSP.  But for now, you need to provide it (in an upcoming article I&#8217;ll update the IoT Expert Bluetooth Library to provide it).  Here is the specific structure that I will be using.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">const cybt_platform_config_t bt_platform_cfg_settings =
{
    .hci_config =
    {
        .hci_transport = CYBT_HCI_UART,

        .hci =
        {
            .hci_uart =
            {
                .uart_tx_pin = CYBSP_BT_UART_TX,
                .uart_rx_pin = CYBSP_BT_UART_RX,
                .uart_rts_pin = CYBSP_BT_UART_RTS,
                .uart_cts_pin = CYBSP_BT_UART_CTS,

                .baud_rate_for_fw_download = 115200,
                .baud_rate_for_feature     = 115200,

                .data_bits = 8,
                .stop_bits = 1,
                .parity = CYHAL_UART_PARITY_NONE,
                .flow_control = WICED_TRUE
            }
        }
    },

    .controller_config =
    {
        .bt_power_pin      = CYBSP_BT_POWER,
        .sleep_mode =
        {
            #if (bt_0_power_0_ENABLED == 1) /* BT Power control is enabled in the LPA */
            #if (CYCFG_BT_LP_ENABLED == 1) /* Low power is enabled in the LPA, use the LPA configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYCFG_BT_DEV_WAKE_GPIO,
            .host_wakeup_pin = CYCFG_BT_HOST_WAKE_GPIO,
            .device_wake_polarity = CYCFG_BT_DEV_WAKE_POLARITY,
            .host_wake_polarity = CYCFG_BT_HOST_WAKE_IRQ_EVENT
            #else /* Low power is disabled in the LPA, disable low power */
            .sleep_mode_enabled = false
            #endif
            #else /* BT Power control is disabled in the LPA – default to BSP low power configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYBSP_BT_DEVICE_WAKE,
            .host_wakeup_pin = CYBSP_BT_HOST_WAKE,
            .device_wake_polarity = CYBT_WAKE_ACTIVE_LOW,
            .host_wake_polarity = CYBT_WAKE_ACTIVE_LOW
            #endif
        }
    },

    .task_mem_pool_size    = 2048
};
</pre>
<h1>wiced_bt_cfg_settings</h1>
<p>The Cypress WICED Bluetooth Stack has a boatload of configuration settings.  When you call the stack start function you need to provide all of those settings in a structure of type &#8220;wiced_bt_cfg_settings_t&#8221; which is actually a structure of structures.  There are several basic ways to set these settings</p>
<ul>
<li>Start from scratch and build you own settings</li>
<li>Copy from an example project</li>
<li>Use the Bluetooth Configurator to generate the structure</li>
</ul>
<p>For the purposes of THIS project I started by copying the structure from on of the example projects and then modifying the three numbers that were relevant to me.  Specifically</p>
<ul>
<li>max_simultanous_link &#8211; which I changed to 0 because this is simply a Bluetooth Observer</li>
<li>low_duty_scan_interval &#8211; how long in the window to listen for advertising packets</li>
<li>low_duty_scan_window &#8211; how wide the window of listening should be</li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="c">const wiced_bt_cfg_settings_t wiced_bt_cfg_settings =
{
    .device_name                         = (uint8_t *)BT_LOCAL_NAME,                                   /**&lt; Local device name (NULL terminated) */
    .device_class                        = {0x00, 0x00, 0x00},                                         /**&lt; Local device class */
    .security_requirement_mask           = BTM_SEC_NONE,                                               /**&lt; Security requirements mask (BTM_SEC_NONE, or combinination of BTM_SEC_IN_AUTHENTICATE, BTM_SEC_OUT_AUTHENTICATE, BTM_SEC_ENCRYPT (see #wiced_bt_sec_level_e)) */

    .max_simultaneous_links              = 0,                                                          /**&lt; Maximum number simultaneous links to different devices */

    .ble_scan_cfg =                                                 /* BLE scan settings  */
    {
        .scan_mode                       = BTM_BLE_SCAN_MODE_PASSIVE,                                  /**&lt; BLE scan mode (BTM_BLE_SCAN_MODE_PASSIVE, BTM_BLE_SCAN_MODE_ACTIVE, or BTM_BLE_SCAN_MODE_NONE) */

        /* Advertisement scan configuration */
        .high_duty_scan_interval         = WICED_BT_CFG_DEFAULT_HIGH_DUTY_SCAN_INTERVAL,               /**&lt; High duty scan interval */
        .high_duty_scan_window           = WICED_BT_CFG_DEFAULT_HIGH_DUTY_SCAN_WINDOW,                 /**&lt; High duty scan window */
        .high_duty_scan_duration         = 0,                                                          /**&lt; High duty scan duration in seconds (0 for infinite) */

        .low_duty_scan_interval          = 96,                                                         /**&lt; Low duty scan interval  */
        .low_duty_scan_window            = 96,                                                         /**&lt; Low duty scan window */
        .low_duty_scan_duration          = 0,                                                          /**&lt; Low duty scan duration in seconds (0 for infinite) */

        /* Connection scan configuration */
        .high_duty_conn_scan_interval    = WICED_BT_CFG_DEFAULT_HIGH_DUTY_CONN_SCAN_INTERVAL,          /**&lt; High duty cycle connection scan interval */
        .high_duty_conn_scan_window      = WICED_BT_CFG_DEFAULT_HIGH_DUTY_CONN_SCAN_WINDOW,            /**&lt; High duty cycle connection scan window */
        .high_duty_conn_duration         = 0,                                                         /**&lt; High duty cycle connection duration in seconds (0 for infinite) */

        .low_duty_conn_scan_interval     = WICED_BT_CFG_DEFAULT_LOW_DUTY_CONN_SCAN_INTERVAL,           /**&lt; Low duty cycle connection scan interval */
        .low_duty_conn_scan_window       = WICED_BT_CFG_DEFAULT_LOW_DUTY_CONN_SCAN_WINDOW,             /**&lt; Low duty cycle connection scan window */
        .low_duty_conn_duration          = 0,                                                         /**&lt; Low duty cycle connection duration in seconds (0 for infinite) */

        /* Connection configuration */
        .conn_min_interval               = WICED_BT_CFG_DEFAULT_CONN_MIN_INTERVAL,                     /**&lt; Minimum connection interval */
        .conn_max_interval               = WICED_BT_CFG_DEFAULT_CONN_MAX_INTERVAL,                     /**&lt; Maximum connection interval */
        .conn_latency                    = WICED_BT_CFG_DEFAULT_CONN_LATENCY,                          /**&lt; Connection latency */
        .conn_supervision_timeout        = WICED_BT_CFG_DEFAULT_CONN_SUPERVISION_TIMEOUT,              /**&lt; Connection link supervision timeout */
    },

    .default_ble_power_level            = 12                                                           /**&lt; Default LE power level, Refer lm_TxPwrTable table for the power range */
};
</pre>
<h1>app_bt_management_callback</h1>
<p>The last thing that you need to provide is a management callback.  This function is called by the Bluetooth Stack when a &#8220;management event&#8221; occurs.  There is a big-long-list of enumerated events of type wiced_bt_management_event_t.  The events include things like the the stack started &#8220;BTM_ENABLED_EVENT&#8221;.  Each event may have data associated with the event which is passed to you in a pointer to wiced_bt_management_event_data_t.</p>
<p>You typically deal with these events with a giant switch statement like this:</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:

            if (WICED_BT_SUCCESS == p_event_data-&gt;enabled.status)
            {
               printf("Stack Started Successfully\n");
            }

            break;


        default:
            printf("Unhandled Bluetooth Management Event: 0x%x %s\n", event, btutil_getBTEventName(event));
            break;
    }

    return result;
}
</pre>
<h1>Tasks</h1>
<p>The Bluetooth stack on the PSoC6 is operated with two tasks.  Specifically, when you call the wiced_bt_stack_init it will startup:</p>
<ol>
<li>CYBT_HCI_Task &#8211; a task that sends and receives HCI packets going to the Radio chip</li>
<li>CY_BT_Task &#8211; a task that manages the Bluetooth Host Stack</li>
</ol>
<p>Here is print of the task list from my project:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">AnyCloud&gt; tasks
Name          State Priority   Stack  Num
------------------------------------------
nt shell        X       0       236     5
IDLE            R       0       115     6
blink           B       0       98      4
CYBT_BT_Task    B       4       1371    2
sleep_task      B       6       217     1
CYBT_HCI_Task   B       5       950     3
Tmr Svc         B       6       76      7
‘B’ – Blocked
‘R’ – Ready
‘D’ – Deleted (waiting clean up)
‘S’ – Suspended, or Blocked without a timeout
Stack = bytes free at highwater</pre>
<p>&nbsp;</p>
<p>Now with the background in place, in the next article I will discuss Bluetooth advertising and how to build the observer project.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ModusToolbox 2.2 Template Project &#8211; FreeRTOS + NTShell</title>
		<link>https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/</link>
					<comments>https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 05 Oct 2020 12:00:59 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[ModusToolbox]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9875</guid>

					<description><![CDATA[Summary This article discusses the new library structure that was released with ModusToolbox 2.2.  I explain it by showing the creation of a template project that use FreeRTOS and NT Shell. Story I have often started projects from the IoT Expert FreeRTOS template project.   I realized the other day that almost always the first [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This article discusses the new library structure that was released with ModusToolbox 2.2.  I explain it by showing the creation of a template project that use FreeRTOS and NT Shell.</p>
<h1>Story</h1>
<p>I have often started projects from the IoT Expert <a href="https://iotexpert.com/2017/08/31/freertos-psoc-template-project/">FreeRTOS template project</a>.   I realized the other day that almost always the first thing I do after creating the project is add the <a href="https://iotexpert.com/2019/10/14/ntshell-for-mbed-os/">NT Shell library</a>.  My friend Hassane has a personal mantra that if he is going to do the same job more than once he will always automate it.  I should have listened to him on this one because I have done it a bunch of times.</p>
<p>In Modus Toolbox 2.2 we have created a new library scheme which allows sharing of libraries between projects.  So this will also be a good example of how that works.</p>
<p>This will also give you another example of adding template projects to your own manifest.</p>
<p>Here is what I am going to do:</p>
<ol>
<li>Create a project from the IoT Expert FreeRTOS Template</li>
<li>Add the NTShell Library &amp; Examine New Library Structure</li>
<li>Update the Project and Program</li>
<li>Add the Task List functionality (a nice feature of FreeRTOS)</li>
<li>Put the new template on GitHub</li>
<li>Update the IoT Expert App Manifest</li>
<li>Test the new Template</li>
</ol>
<h1>Create &amp; Test a project from the IoT Expert FreeRTOS Template</h1>
<p>I will start the whole process by creating  new project using my existing base template.  The kit that I happen to have on my desk right now is the CY8CKIT-062S2-43012.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-14-46-am/" rel="attachment wp-att-10715"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-1024x714.jpg" alt="" class="alignnone size-large wp-image-10715" width="1024" height="714" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-1024x714.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-300x209.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-768x536.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-1536x1071.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.14.46-AM-2048x1428.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Select the IoT Expert FreeRTOS Template and give it a name.  Notice that I add &#8220;NTShell&#8221; to the name (because that is what Im gonna add)</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-21-22-am/" rel="attachment wp-att-10716"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM-1024x959.jpg" alt="" class="alignnone size-large wp-image-10716" width="1024" height="959" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM-1024x959.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM-300x281.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM-768x719.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM-1536x1438.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.21.22-AM.jpg 1754w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you click create, Modus will do its magic and build you a complete project.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-23-18-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM-1024x783.png" alt="" class="alignnone wp-image-10717 size-large" width="1024" height="783" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM-1024x783.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM-300x229.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM-768x587.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM-1536x1175.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.23.18-AM.png 1624w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Today Im going to edit using Visual Studio Code.  Actually almost always I edit using Visual Studio Code.  You can do all of these tasks using Eclipse as well.  To turn my created project into a VSCODE project run &#8220;make vscode&#8221;</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-26-04-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM-834x1024.jpg" alt="" class="alignnone wp-image-10718 size-large" width="834" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM-834x1024.jpg 834w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM-244x300.jpg 244w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM-768x942.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM-1252x1536.jpg 1252w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.26.04-AM.jpg 1506w" sizes="auto, (max-width: 834px) 100vw, 834px" /></a></p>
<p>Before getting to far down the road I like to run a build to make sure everything is OK.  So &#8220;make -j build&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) IoT_Expert_FreeRTOS_NTShell_Template $ make -j build
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 195 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 491 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 183 file(s)
    Compiling app file lowPower.c
    Compiling app file main.c
    Compiling ext file startup_psoc6_02_cm4.S
    Compiling ext file cy_syslib_gcc.S
    Compiling ext file cycfg.c
    Compiling ext file cycfg_capsense.c
    Compiling ext file cycfg_clocks.c

....a bunch of stuff deleted

    Compiling ext file psoc6_04_cm0p_sleep.c
    Compiling ext file cy_retarget_io.c
    Linking output file MTBShellTemplate.elf
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  30280      | 
  | .ARM.exidx           |  0x10009648   |  8          | 
  | .copy.table          |  0x10009650   |  24         | 
  | .zero.table          |  0x10009668   |  8          | 
  | .data                |  0x080022e0   |  1320       | 
  | .cy_sharedmem        |  0x08002808   |  8          | 
  | .noinit              |  0x08002810   |  148        | 
  | .bss                 |  0x080028a4   |  1324       | 
  | .heap                |  0x08002dd0   |  1030704    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           39848      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033504    

  
arh (master) IoT_Expert_FreeRTOS_NTShell_Template $</pre>
<p>Then program it, just to make sure.  &#8220;make program&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) IoT_Expert_FreeRTOS_NTShell_Template $ make program
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 195 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 491 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 183 file(s)
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  30280      | 
  | .ARM.exidx           |  0x10009648   |  8          | 
  | .copy.table          |  0x10009650   |  24         | 
  | .zero.table          |  0x10009668   |  8          | 
  | .data                |  0x080022e0   |  1320       | 
  | .cy_sharedmem        |  0x08002808   |  8          | 
  | .noinit              |  0x08002810   |  148        | 
  | .bss                 |  0x080028a4   |  1324       | 
  | .heap                |  0x08002dd0   |  1030704    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           39848      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033504    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-4.1.0.1058 (2020-08-11-03:45)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
adapter srst delay: 25
adapter srst pulse_width: 25
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 14672 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.14.514
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Info : VTarget = 3.221 V
Info : kitprog3: acquiring the device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
***************************************
** Silicon: 0xE453, Family: 0x102, Rev.: 0x12 (A1)
** Detected Device: CY8C624ABZI-S2D44
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.378
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for psoc6.cpu.cm0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for psoc6.cpu.cm4 on 3334
Info : Listening on port 3334 for gdb connections
Info : SWD DPIDR 0x6ba02477
Info : kitprog3: acquiring the device...
psoc6.cpu.cm0 halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
psoc6.cpu.cm4 halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x1000179c, next section at 0x10002000
Info : Padding image section 0 at 0x1000179c with 100 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x10009ba0 with 96 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 37888 bytes from file /Users/arh/mtb22/IoT_Expert_FreeRTOS_NTShell_Template/build/CY8CKIT-062S2-43012/Debug/MTBShellTemplate.hex in 1.402638s (26.379 KiB/s)
** Programming Finished **
** Verify Started **
verified 37692 bytes in 0.080973s (454.579 KiB/s)
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x6ba02477
shutdown command invoked
Info : psoc6.dap: powering down debug domain...
Warn : Failed to power down Debug Domains
  
arh (master) IoT_Expert_FreeRTOS_NTShell_Template $</pre>
<h1>Add the NTShell Library &amp; Examine New Library Structure</h1>
<p>Everything is working and my basic project has FreeRTOS and a blinking LED.  Now let&#8217;s add the NT Shell Library.  To do this run the library manager by running &#8220;make modlibs&#8221; (or click on the button in Eclipse).  Select Libraries &#8211;&gt; IoT Expert &#8211;&gt; ntshell<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-29-44-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM-773x1024.jpg" alt="" class="alignnone wp-image-10719 size-large" width="773" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM-773x1024.jpg 773w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM-226x300.jpg 226w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM-768x1017.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM-1160x1536.jpg 1160w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.29.44-AM.jpg 1516w" sizes="auto, (max-width: 773px) 100vw, 773px" /></a></p>
<p>When you press update, the library manager will do its thing again.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-30-07-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.30.07-AM-1024x756.png" alt="" class="alignnone wp-image-10720 size-large" width="1024" height="756" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.30.07-AM-1024x756.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.30.07-AM-300x221.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.30.07-AM-768x567.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.30.07-AM.png 1398w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I look in the &#8220;deps&#8221; directory, I see some new file types called &#8220;.mtb&#8221;.  These files tell your project where to find each of the libraries.  Notice that the middleware-ntshell.mtb points to &#8220;$$ASSET_REPO$$&#8221;.  Where is that?</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-32-07-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM-1024x237.png" alt="" class="alignnone wp-image-10721 size-large" width="1024" height="237" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM-1024x237.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM-300x69.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM-768x178.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM-1536x355.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.32.07-AM.png 1540w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>If you have a aook at the Makefile it tell you that it is &#8220;../&#8221; and &#8220;mtb_shared&#8221;.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c"># Relative path to the shared repo location.
#
# All .mtb files have the format, &lt;URI&gt;&lt;COMMIT&gt;&lt;LOCATION&gt;. If the &lt;LOCATION&gt; field 
# begins with $$ASSET_REPO$$, then the repo is deposited in the path specified by 
# the CY_GETLIBS_SHARED_PATH variable. The default location is one directory level 
# above the current app directory.
# This is used with CY_GETLIBS_SHARED_NAME variable, which specifies the directory name.
CY_GETLIBS_SHARED_PATH=../

# Directory name of the shared repo location.
#
CY_GETLIBS_SHARED_NAME=mtb_shared</pre>
<p>To start editing I will run Visual Studio Code by typing &#8220;code .&#8221;.  The first thing that happens is that it notices that this is a workspace instead of just a directory.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-36-19-am/" rel="attachment wp-att-10723"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.36.19-AM.png" alt="" class="alignnone size-full wp-image-10723" width="922" height="278" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.36.19-AM.png 922w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.36.19-AM-300x90.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.36.19-AM-768x232.png 768w" sizes="auto, (max-width: 922px) 100vw, 922px" /></a></p>
<p>And when you look at the workspace you can see that it knows about both the example project as well as &#8220;mtb_shared&#8221;.  That is sweet.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-10-38-58-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.38.58-AM-417x1024.png" alt="" class="alignnone wp-image-10714 size-large" width="417" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.38.58-AM-417x1024.png 417w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.38.58-AM-122x300.png 122w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.38.58-AM.png 486w" sizes="auto, (max-width: 417px) 100vw, 417px" /></a></p>
<h1>Update the Project and Program</h1>
<p>Now follow the instructions from the middlware-ntshell readme by copying &#8220;usrcmd.*&#8221; into my project.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) IoT_Expert_FreeRTOS_NTShell_Template $ cp ../mtb_shared/middleware-ntshell/latest-v2.X/template/psoc6sdk/usrcmd.* .</pre>
<p>Then I edit main.c to</p>
<ol>
<li>#include &#8220;usrcmd.h&#8221; on line 8</li>
<li>Start the shell task which is called &#8220;usrcmd_task&#8221; on line 39</li>
</ol>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-42-45-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM-1024x936.jpg" alt="" class="alignnone wp-image-10725 size-large" width="1024" height="936" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM-1024x936.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM-300x274.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM-768x702.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM-1536x1405.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.42.45-AM.jpg 1824w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now buid/project by running &#8220;make -j program&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master *) IoT_Expert_FreeRTOS_NTShell_Template $ make -j program
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 205 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 503 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 193 file(s)
    Compiling app file main.c
    Linking output file MTBShellTemplate.elf
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  52780      | 
  | .ARM.exidx           |  0x1000ee2c   |  8          | 
  | .copy.table          |  0x1000ee34   |  24         | 
  | .zero.table          |  0x1000ee4c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  2136       | 
  | .heap                |  0x08003270   |  1029520    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           62716      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033500    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-4.1.0.1058 (2020-08-11-03:45)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
adapter srst delay: 25
adapter srst pulse_width: 25
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 14672 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.14.514
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Info : VTarget = 3.225 V
Info : kitprog3: acquiring the device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
***************************************
** Silicon: 0xE453, Family: 0x102, Rev.: 0x12 (A1)
** Detected Device: CY8C624ABZI-S2D44
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.378
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for psoc6.cpu.cm0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for psoc6.cpu.cm4 on 3334
Info : Listening on port 3334 for gdb connections
Info : SWD DPIDR 0x6ba02477
Info : kitprog3: acquiring the device...
psoc6.cpu.cm0 halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
psoc6.cpu.cm4 halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x1000179c, next section at 0x10002000
Info : Padding image section 0 at 0x1000179c with 100 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x1000f4f4 with 268 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 60928 bytes from file /Users/arh/mtb22/IoT_Expert_FreeRTOS_NTShell_Template/build/CY8CKIT-062S2-43012/Debug/MTBShellTemplate.hex in 2.017097s (29.498 KiB/s)
** Programming Finished **
** Verify Started **
verified 60560 bytes in 0.119193s (496.175 KiB/s)
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x6ba02477
shutdown command invoked
Info : psoc6.dap: powering down debug domain...
  
arh (master *) IoT_Expert_FreeRTOS_NTShell_Template $</pre>
<p>Now I have a functional shell.  Here is the serial console.</p>
<p><a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-44-30-am-1/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.44.30-AM-1-1024x274.png" alt="" class="alignnone wp-image-10726 size-large" width="1024" height="274" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.44.30-AM-1-1024x274.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.44.30-AM-1-300x80.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.44.30-AM-1-768x206.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.44.30-AM-1.png 1516w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Add the Task List functionality</h1>
<p>In the main.c above I started up the usrcmd_task with a stack size of config_MINIMAL_STACK_SIZE * 4.  Where did I get that?  Well the first couple of times I did this it crashed by running out of stack so I tried bigger and bigger numbers until it stopped crashing.  This is a kind of a pain in the ass.   If you know FreeRTOS there is a function called &#8220;vTaskList&#8221; which will give you stats about the tasks.</p>
<p>In order to use that function you need to turn it on.  Notice that I #ifdef and #if to see if it is turned on inside of usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#ifdef configUSE_TRACE_FACILITY
#if configUSE_STATS_FORMATTING_FUNCTIONS ==1
static int usrcmd_list(int argc, char **argv);
#endif
#endif
</pre>
<p>So let&#8217;s turn it on by editing &#8220;FreeRTOSConfig.h&#8221; and enabling the two required defines.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define configUSE_TRACE_FACILITY					1
#define configUSE_STATS_FORMATTING_FUNCTIONS        1</pre>
<p>Now build/program.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master *) IoT_Expert_FreeRTOS_NTShell_Template $ make -j program
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 205 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 503 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 193 file(s)
    Compiling app file lowPower.c
    Compiling app file main.c
    Compiling app file usrcmd.c
    Compiling ext file croutine.c
    Compiling ext file event_groups.c
    Compiling ext file list.c
    Compiling ext file heap_1.c
    Compiling ext file heap_2.c
    Compiling ext file heap_3.c
    Compiling ext file heap_4.c
    Compiling ext file heap_5.c
    Compiling ext file port.c
    Compiling ext file queue.c
    Compiling ext file stream_buffer.c
    Compiling ext file tasks.c
    Compiling ext file timers.c
    Compiling ext file psoc6_ntshell_port.c
    Linking output file MTBShellTemplate.elf
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  54876      | 
  | .ARM.exidx           |  0x1000f65c   |  8          | 
  | .copy.table          |  0x1000f664   |  24         | 
  | .zero.table          |  0x1000f67c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  2136       | 
  | .heap                |  0x08003270   |  1029520    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           64812      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033500    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-4.1.0.1058 (2020-08-11-03:45)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
adapter srst delay: 25
adapter srst pulse_width: 25
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 14672 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.14.514
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Info : VTarget = 3.220 V
Info : kitprog3: acquiring the device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
***************************************
** Silicon: 0xE453, Family: 0x102, Rev.: 0x12 (A1)
** Detected Device: CY8C624ABZI-S2D44
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.378
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for psoc6.cpu.cm0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for psoc6.cpu.cm4 on 3334
Info : Listening on port 3334 for gdb connections
Info : SWD DPIDR 0x6ba02477
Info : kitprog3: acquiring the device...
psoc6.cpu.cm0 halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
psoc6.cpu.cm4 halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x1000179c, next section at 0x10002000
Info : Padding image section 0 at 0x1000179c with 100 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x1000fd24 with 220 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 62976 bytes from file /Users/arh/mtb22/IoT_Expert_FreeRTOS_NTShell_Template/build/CY8CKIT-062S2-43012/Debug/MTBShellTemplate.hex in 2.092903s (29.385 KiB/s)
** Programming Finished **
** Verify Started **
verified 62656 bytes in 0.123619s (494.968 KiB/s)
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x6ba02477
shutdown command invoked
Info : psoc6.dap: powering down debug domain...</pre>
<p>When I run help you can see I have a new command called &#8220;tasks&#8221; which lists all of the tasks and their stack high water marks.<br />
<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-48-14-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.48.14-AM-1024x418.png" alt="" class="alignnone wp-image-10728 size-large" width="1024" height="418" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.48.14-AM-1024x418.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.48.14-AM-300x123.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.48.14-AM-768x314.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.48.14-AM.png 1522w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Put the Template on GitHub</h1>
<p>I am happy with my new template.  So, I go to GitHub and create a new repository.<br />
<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-9-50-46-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM-1024x749.png" alt="" class="alignnone wp-image-10729 size-large" width="1024" height="749" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM-1024x749.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM-300x219.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM-768x562.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM-1536x1123.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-9.50.46-AM.png 1704w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then on my current project:</p>
<ol>
<li>I blow away the git history (didnt really have to do that).</li>
<li>Create a new git repo &#8220;git init .&#8221;</li>
<li>Add a pointer to GitHub &#8220;git remote add&#8230;.&#8221;</li>
<li>Add all of the files &#8220;git add *&#8221;</li>
<li>Add the .gitignore &#8220;git add .gitignore&#8221;</li>
<li>Commit the changes &#8220;git commit&#8230;&#8221;</li>
<li>Push it to GitHub &#8220;git push &#8230;&#8221;</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master *) IoT_Expert_FreeRTOS_NTShell_Template $ rm -rf .git
arh IoT_Expert_FreeRTOS_NTShell_Template $ git init .
Initialized empty Git repository in /Users/arh/mtb22/IoT_Expert_FreeRTOS_NTShell_Template/.git/
arh (master #) IoT_Expert_FreeRTOS_NTShell_Template $ git remote add origin git@iotexpert.github.com:iotexpert/mtb2-freertos-ntshell-template.git
arh (master #) IoT_Expert_FreeRTOS_NTShell_Template $ git add * 
The following paths are ignored by one of your .gitignore files:
build
Use -f if you really want to add them.
arh (master #) IoT_Expert_FreeRTOS_NTShell_Template $ git add .gitignore
arh (master #) IoT_Expert_FreeRTOS_NTShell_Template $ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached &lt;file&gt;..." to unstage)
	new file:   .gitignore
	new file:   FreeRTOSConfig.h
	new file:   LICENSE
	new file:   MTBShellTemplate.code-workspace
	new file:   Makefile
	new file:   README.md
	new file:   deps/TARGET_CY8CKIT-062S2-43012.mtb
	new file:   deps/freertos.mtb
	new file:   deps/middleware-ntshell.mtb
	new file:   deps/retarget-io.mtb
	new file:   global.h
	new file:   lowPower.c
	new file:   main.c
	new file:   openocd.tcl
	new file:   usrcmd.c
	new file:   usrcmd.h

Untracked files:
  (use "git add &lt;file&gt;..." to include in what will be committed)
	.vscode/

arh (master #) IoT_Expert_FreeRTOS_NTShell_Template $ git commit -m "Initial commit"
[master (root-commit) 26b5d3c] Initial commit
 16 files changed, 994 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 FreeRTOSConfig.h
 create mode 100644 LICENSE
 create mode 100644 MTBShellTemplate.code-workspace
 create mode 100644 Makefile
 create mode 100644 README.md
 create mode 100644 deps/TARGET_CY8CKIT-062S2-43012.mtb
 create mode 100644 deps/freertos.mtb
 create mode 100644 deps/middleware-ntshell.mtb
 create mode 100644 deps/retarget-io.mtb
 create mode 100644 global.h
 create mode 100644 lowPower.c
 create mode 100644 main.c
 create mode 100644 openocd.tcl
 create mode 100644 usrcmd.c
 create mode 100644 usrcmd.h
arh (master) IoT_Expert_FreeRTOS_NTShell_Template $ git push -u origin master
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 12 threads
Compressing objects: 100% (19/19), done.
Writing objects: 100% (19/19), 16.21 KiB | 5.40 MiB/s, done.
Total 19 (delta 0), reused 0 (delta 0)
To iotexpert.github.com:iotexpert/mtb2-freertos-ntshell-template.git
 * [new branch]      master -&gt; master
Branch 'master' set up to track remote branch 'master' from 'origin'.
arh (master) IoT_Expert_FreeRTOS_NTShell_Template $</pre>
<h1>Update the Manifests</h1>
<p>To get access to the new template I need to add it to the IoT Expert App Manifest.  I edit the xml file to have the new app</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">&lt;apps&gt;
  &lt;app&gt;
    &lt;name&gt;IoT Expert FreeRTOS Template&lt;/name&gt;
    &lt;id&gt;mtb2-freertos-template&lt;/id&gt;
    &lt;uri&gt;https://github.com/iotexpert/mtb2-freertos-template&lt;/uri&gt;
    &lt;description&gt;This template provide a starting point for FreeRTOS projects.  Including a starting blinking LED task&lt;/description&gt;
    &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
    &lt;versions&gt;
      &lt;version&gt;
        &lt;num&gt;Latest 1.X release&lt;/num&gt;
        &lt;commit&gt;master&lt;/commit&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/app&gt;
    &lt;app&gt;
    &lt;name&gt;IoT Expert FreeRTOS NTShell Template&lt;/name&gt;
    &lt;id&gt;mtb2-freertos-ntshell-template&lt;/id&gt;
    &lt;uri&gt;https://github.com/iotexpert/mtb2-freertos-ntshell-template&lt;/uri&gt;
    &lt;description&gt;This template provide a starting point for FreeRTOS projects.  Including a starting blinking LED task and shell&lt;/description&gt;
    &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
    &lt;versions&gt;
      &lt;version&gt;
        &lt;num&gt;Latest 1.X release&lt;/num&gt;
        &lt;commit&gt;master&lt;/commit&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/app&gt;
&lt;/apps&gt;</pre>
<p>Now I need to git add, git commit and git push it to GitHub.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) mtb2-iotexpert-manifests $ code .
arh (master) mtb2-iotexpert-manifests $ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add &lt;file&gt;..." to update what will be committed)
  (use "git restore &lt;file&gt;..." to discard changes in working directory)
	modified:   iotexpert-app-manifest.xml

no changes added to commit (use "git add" and/or "git commit -a")
arh (master *) mtb2-iotexpert-manifests $ git add iotexpert-app-manifest.xml
arh (master +) mtb2-iotexpert-manifests $ git commit -m "Updated with ntshell example"
[master 47a7bb1] Updated with ntshell example
 1 file changed, 13 insertions(+)
arh (master) mtb2-iotexpert-manifests $ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 554 bytes | 554.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To iotexpert.github.com:iotexpert/mtb2-iotexpert-manifests.git
   28ed2d0..47a7bb1  master -&gt; master
</pre>
<h1>Test the new Template</h1>
<p>Everything should be working so make a new project.<br />
<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-10-00-29-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-1024x701.jpg" alt="" class="alignnone wp-image-10711 size-large" width="1024" height="701" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-1024x701.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-300x205.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-768x526.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-1536x1052.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.00.29-AM-2048x1402.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Cool.  There is the new template.<br />
<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-10-08-12-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-1024x700.jpg" alt="" class="alignnone wp-image-10712 size-large" width="1024" height="700" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-1024x700.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-300x205.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-768x525.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-1536x1050.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.08.12-AM-2048x1401.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I program it&#8230; everything is cool.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) TestNTS $ make -j program
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 205 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 503 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 193 file(s)
    Compiling app file lowPower.c
    Compiling app file main.c
    Compiling app file usrcmd.c
    Compiling ext file startup_psoc6_02_cm4.S
    Compiling ext file cy_syslib_gcc.S
    Compiling ext file cycfg.c
    Compiling ext file cycfg_capsense.c
    Compiling ext file cycfg_clocks.c
    Compiling ext file cycfg_peripherals.c
    Compiling ext file cycfg_pins.c
    Compiling ext file cycfg_qspi_memslot.c
    Compiling ext file cycfg_routing.c
    Compiling ext file cycfg_system.c
    Compiling ext file system_psoc6_cm4.c
    Compiling ext file cybsp.c
    Compiling ext file cy_capsense_centroid.c
    Compiling ext file cy_capsense_control.c
    Compiling ext file cy_capsense_csd.c
    Compiling ext file cy_capsense_csx.c
    Compiling ext file cy_capsense_filter.c
    Compiling ext file cy_capsense_processing.c
    Compiling ext file cy_capsense_selftest.c
    Compiling ext file cy_capsense_sensing.c
    Compiling ext file cy_capsense_structure.c
    Compiling ext file cy_capsense_tuner.c
    Compiling ext file croutine.c
    Compiling ext file event_groups.c
    Compiling ext file list.c
    Compiling ext file heap_1.c
    Compiling ext file heap_2.c
    Compiling ext file heap_3.c
    Compiling ext file heap_4.c
    Compiling ext file heap_5.c
    Compiling ext file port.c
    Compiling ext file queue.c
    Compiling ext file stream_buffer.c
    Compiling ext file tasks.c
    Compiling ext file timers.c
    Compiling ext file ntlibc.c
    Compiling ext file ntshell.c
    Compiling ext file text_editor.c
    Compiling ext file text_history.c
    Compiling ext file vtrecv.c
    Compiling ext file vtsend.c
    Compiling ext file psoc6_ntshell_port.c
    Compiling ext file ntopt.c
    Compiling ext file ntstdio.c
    Compiling ext file cyhal_adc.c
    Compiling ext file cyhal_analog_common.c
    Compiling ext file cyhal_clock.c
    Compiling ext file cyhal_comp.c
    Compiling ext file cyhal_comp_ctb.c
    Compiling ext file cyhal_comp_lp.c
    Compiling ext file cyhal_crc.c
    Compiling ext file cyhal_crypto_common.c
    Compiling ext file cyhal_dac.c
    Compiling ext file cyhal_deprecated.c
    Compiling ext file cyhal_dma.c
    Compiling ext file cyhal_dma_dmac.c
    Compiling ext file cyhal_dma_dw.c
    Compiling ext file cyhal_ezi2c.c
    Compiling ext file cyhal_flash.c
    Compiling ext file cyhal_gpio.c
    Compiling ext file cyhal_hwmgr.c
    Compiling ext file cyhal_i2c.c
    Compiling ext file cyhal_i2s.c
    Compiling ext file cyhal_interconnect.c
    Compiling ext file cyhal_lptimer.c
    Compiling ext file cyhal_not_implemented.c
    Compiling ext file cyhal_opamp.c
    Compiling ext file cyhal_pdmpcm.c
    Compiling ext file cyhal_pwm.c
    Compiling ext file cyhal_qspi.c
    Compiling ext file cyhal_rtc.c
    Compiling ext file cyhal_scb_common.c
    Compiling ext file cyhal_sdhc.c
    Compiling ext file cyhal_spi.c
    Compiling ext file cyhal_syspm.c
    Compiling ext file cyhal_system.c
    Compiling ext file cyhal_tcpwm_common.c
    Compiling ext file cyhal_timer.c
    Compiling ext file cyhal_trng.c
    Compiling ext file cyhal_uart.c
    Compiling ext file cyhal_udb_sdio.c
    Compiling ext file cyhal_usb_dev.c
    Compiling ext file cyhal_utils.c
    Compiling ext file cyhal_wdt.c
    Compiling ext file cyhal_psoc6_01_104_m_csp_ble.c
    Compiling ext file cyhal_psoc6_01_104_m_csp_ble_usb.c
    Compiling ext file cyhal_psoc6_01_116_bga_ble.c
    Compiling ext file cyhal_psoc6_01_116_bga_usb.c
    Compiling ext file cyhal_psoc6_01_124_bga.c
    Compiling ext file cyhal_psoc6_01_124_bga_sip.c
    Compiling ext file cyhal_psoc6_01_43_smt.c
    Compiling ext file cyhal_psoc6_01_68_qfn_ble.c
    Compiling ext file cyhal_psoc6_01_80_wlcsp.c
    Compiling ext file cyhal_psoc6_02_100_wlcsp.c
    Compiling ext file cyhal_psoc6_02_124_bga.c
    Compiling ext file cyhal_psoc6_02_128_tqfp.c
    Compiling ext file cyhal_psoc6_02_68_qfn.c
    Compiling ext file cyhal_psoc6_03_100_tqfp.c
    Compiling ext file cyhal_psoc6_03_49_wlcsp.c
    Compiling ext file cyhal_psoc6_03_68_qfn.c
    Compiling ext file cyhal_psoc6_04_64_tqfp.c
    Compiling ext file cyhal_psoc6_04_68_qfn.c
    Compiling ext file cyhal_psoc6_04_80_tqfp.c
    Compiling ext file cyhal_triggers_psoc6_01.c
    Compiling ext file cyhal_triggers_psoc6_02.c
    Compiling ext file cyhal_triggers_psoc6_03.c
    Compiling ext file cyhal_triggers_psoc6_04.c
    Compiling ext file cy_ble_clk.c
    Compiling ext file cy_canfd.c
    Compiling ext file cy_crypto.c
    Compiling ext file cy_crypto_core_aes_v1.c
    Compiling ext file cy_crypto_core_aes_v2.c
    Compiling ext file cy_crypto_core_cmac_v1.c
    Compiling ext file cy_crypto_core_cmac_v2.c
    Compiling ext file cy_crypto_core_crc_v1.c
    Compiling ext file cy_crypto_core_crc_v2.c
    Compiling ext file cy_crypto_core_des_v1.c
    Compiling ext file cy_crypto_core_des_v2.c
    Compiling ext file cy_crypto_core_ecc_domain_params.c
    Compiling ext file cy_crypto_core_ecc_ecdsa.c
    Compiling ext file cy_crypto_core_ecc_key_gen.c
    Compiling ext file cy_crypto_core_ecc_nist_p.c
    Compiling ext file cy_crypto_core_hmac_v1.c
    Compiling ext file cy_crypto_core_hmac_v2.c
    Compiling ext file cy_crypto_core_hw.c
    Compiling ext file cy_crypto_core_hw_v1.c
    Compiling ext file cy_crypto_core_mem_v1.c
    Compiling ext file cy_crypto_core_mem_v2.c
    Compiling ext file cy_crypto_core_prng_v1.c
    Compiling ext file cy_crypto_core_prng_v2.c
    Compiling ext file cy_crypto_core_rsa.c
    Compiling ext file cy_crypto_core_sha_v1.c
    Compiling ext file cy_crypto_core_sha_v2.c
    Compiling ext file cy_crypto_core_trng_v1.c
    Compiling ext file cy_crypto_core_trng_v2.c
    Compiling ext file cy_crypto_core_vu.c
    Compiling ext file cy_crypto_server.c
    Compiling ext file cy_csd.c
    Compiling ext file cy_ctb.c
    Compiling ext file cy_ctdac.c
    Compiling ext file cy_device.c
    Compiling ext file cy_dma.c
    Compiling ext file cy_dmac.c
    Compiling ext file cy_efuse.c
    Compiling ext file cy_flash.c
    Compiling ext file cy_gpio.c
    Compiling ext file cy_i2s.c
    Compiling ext file cy_ipc_drv.c
    Compiling ext file cy_ipc_pipe.c
    Compiling ext file cy_ipc_sema.c
    Compiling ext file cy_lpcomp.c
    Compiling ext file cy_lvd.c
    Compiling ext file cy_mcwdt.c
    Compiling ext file cy_pdm_pcm.c
    Compiling ext file cy_pra.c
    Compiling ext file cy_pra_cfg.c
    Compiling ext file cy_profile.c
    Compiling ext file cy_prot.c
    Compiling ext file cy_rtc.c
    Compiling ext file cy_sar.c
    Compiling ext file cy_scb_common.c
    Compiling ext file cy_scb_ezi2c.c
    Compiling ext file cy_scb_i2c.c
    Compiling ext file cy_scb_spi.c
    Compiling ext file cy_scb_uart.c
    Compiling ext file cy_sd_host.c
    Compiling ext file cy_seglcd.c
    Compiling ext file cy_smartio.c
    Compiling ext file cy_smif.c
    Compiling ext file cy_smif_memslot.c
    Compiling ext file cy_sysanalog.c
    Compiling ext file cy_sysclk.c
    Compiling ext file cy_sysint.c
    Compiling ext file cy_syslib.c
    Compiling ext file cy_syspm.c
    Compiling ext file cy_systick.c
    Compiling ext file cy_tcpwm_counter.c
    Compiling ext file cy_tcpwm_pwm.c
    Compiling ext file cy_tcpwm_quaddec.c
    Compiling ext file cy_tcpwm_shiftreg.c
    Compiling ext file cy_trigmux.c
    Compiling ext file cy_usbfs_dev_drv.c
    Compiling ext file cy_usbfs_dev_drv_io.c
    Compiling ext file cy_usbfs_dev_drv_io_dma.c
    Compiling ext file cy_wdt.c
    Compiling ext file psoc6_01_cm0p_sleep.c
    Compiling ext file psoc6_02_cm0p_sleep.c
    Compiling ext file psoc6_03_cm0p_sleep.c
    Compiling ext file psoc6_04_cm0p_sleep.c
    Compiling ext file cy_retarget_io.c
    Linking output file MTBShellTemplate.elf
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  54876      | 
  | .ARM.exidx           |  0x1000f65c   |  8          | 
  | .copy.table          |  0x1000f664   |  24         | 
  | .zero.table          |  0x1000f67c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  2136       | 
  | .heap                |  0x08003270   |  1029520    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           64812      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033500    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-4.1.0.1058 (2020-08-11-03:45)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
adapter srst delay: 25
adapter srst pulse_width: 25
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 14672 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.14.514
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Info : VTarget = 3.221 V
Info : kitprog3: acquiring the device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
***************************************
** Silicon: 0xE453, Family: 0x102, Rev.: 0x12 (A1)
** Detected Device: CY8C624ABZI-S2D44
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.378
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for psoc6.cpu.cm0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for psoc6.cpu.cm4 on 3334
Info : Listening on port 3334 for gdb connections
Info : SWD DPIDR 0x6ba02477
Info : kitprog3: acquiring the device...
psoc6.cpu.cm0 halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
psoc6.cpu.cm4 halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x1000179c, next section at 0x10002000
Info : Padding image section 0 at 0x1000179c with 100 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x1000fd24 with 220 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 62976 bytes from file /Users/arh/mtb22/TestNTS/build/CY8CKIT-062S2-43012/Debug/MTBShellTemplate.hex in 2.082329s (29.534 KiB/s)
** Programming Finished **
** Verify Started **
verified 62656 bytes in 0.122516s (499.425 KiB/s)
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x6ba02477
shutdown command invoked
Info : psoc6.dap: powering down debug domain...
  
arh (master) TestNTS $</pre>
<p>And the project seems to be doing the needful.<br />
<a href="https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/screen-shot-2020-10-04-at-10-09-31-am/"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.09.31-AM-1024x475.png" alt="" class="alignnone wp-image-10713 size-large" width="1024" height="475" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.09.31-AM-1024x475.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.09.31-AM-300x139.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.09.31-AM-768x356.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-04-at-10.09.31-AM.png 1478w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/modustoolbox-2-2-template-project-freertos-ntshell/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB driver</title>
		<link>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/</link>
					<comments>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 07 Sep 2020 11:42:09 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9326</guid>

					<description><![CDATA[Summary This article shows the completion of the PSoC 6 SDK One Wire Bus library.  It shows the test apparatus for evaluating DS18B20 sensors. Story If you remember from the previous articles, I created the one wire bus library by looking at the function calls in the DS18B20 library and reverse engineering the function prototypes. [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This article shows the completion of the PSoC 6 SDK One Wire Bus library.  It shows the test apparatus for evaluating DS18B20 sensors.</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &amp; Write</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/29/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait &amp; Debug</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/?p=9329" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature?</a></td>
</tr>

<tr><td >PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver</td>
</tr>
</tbody></table></div></p>
<h1>Story</h1>
<p>If you remember from the previous articles, I created the one wire bus library by looking at the function calls in the DS18B20 library and reverse engineering the function prototypes.  And, as I said in the earlier article, it would have been way better to just look at the David Antliff &#8220;OWB&#8221; library.  But that is not how it went down.  I wonder how much time in the world is wasted by programmer re-implementing code that already exists?</p>
<p>After the first four articles, I had three functions which the DS18B20 library defined, but I had not yet implemented.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_write_rom_code(OneWireBus *bus, OneWireBus_ROMCode romcode);

owb_ret_t owb_crc8_bytes(uint32_t val, uint8_t *buffer, uint32_t length);

void   owb_set_strong_pullup( OneWireBus *bus, bool val);</pre>
<p>I had not implemented them because I was not totally sure how they worked.  So, I decided to go back to GitHub and see what David had done originally.  When I got to the GitHub site, <a href="https://github.com/DavidAntliff/esp32-owb/blob/master/include/owb.h" target="_blank" rel="noopener noreferrer">https://github.com/DavidAntliff/esp32-owb/blob/master/include/owb.h</a>, there were actually quite a few functions in his owb library that I had not implemented.</p>
<p>Here is the list:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_use_crc(OneWireBus * bus, bool use_crc);
owb_ret_t owb_use_parasitic_power(OneWireBus * bus, bool use_parasitic_power);
owb_ret_t owb_use_strong_pullup_gpio(OneWireBus * bus, cyhal_gpio_t gpio);
owb_ret_t owb_read_rom(OneWireBus * bus, OneWireBus_ROMCode * rom_code);
owb_ret_t owb_verify_rom(OneWireBus * bus, OneWireBus_ROMCode *rom_code, bool * is_present);
owb_ret_t owb_write_rom_code(OneWireBus * bus, OneWireBus_ROMCode *rom_code);
uint8_t owb_crc8_byte(uint8_t crc, uint8_t data);
uint8_t owb_crc8_bytes(uint8_t crc, const uint8_t * data, size_t len);
owb_ret_t owb_search_first(OneWireBus * bus, OneWireBus_SearchState * state, bool *found_device);
owb_ret_t owb_search_next(OneWireBus * bus, OneWireBus_SearchState * state, bool *found_device);
char * owb_string_from_rom_code(OneWireBus_ROMCode *rom_code, char * buffer, size_t len);
owb_ret_t owb_set_strong_pullup(OneWireBus * bus, bool enable);</pre>
<p>In this article I will create and/or <strong>copy</strong> the missing functions.  As I look through his implementation I also notice that we have some style differences that I will discuss.  In general I will say that his implementation is very good and any place that I did something different was just a matter of programming taste.</p>
<p>I was originally planning on this article taking you linearly through how I did the changes, but in reality I jumped around while I was doing the changes, that approach won&#8217;t work.  Here is the list of what I did:</p>
<ol>
<li>Add Doxygen Function Headers</li>
<li>Move Logging Function to Library</li>
<li>Change Commands to Enumerated Type</li>
<li>Change Const Bus Pointer</li>
<li>Pack the Structures</li>
<li>Pass Structures as Pointers</li>
<li>Driver Functions</li>
<li>Test the Search</li>
<li>Test the Parastitic Power</li>
</ol>
<h1>Doxygen Headers</h1>
<p>I like using documentation that has been generated with Doxygen.  Specifically I like that the documentation is written &#8220;at the point of attack&#8221;.  But I have never actually used or generated it using Doxygen.  To make the documentation you need to put comments into your c-header files in the right format.  Here is an example from owb.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">/**
 * @brief Represents a set of the legal one wire bus commands
 */
typedef enum {
    OWB_ROM_SEARCH        =0xF0,  ///&lt; Perform Search ROM cycle to identify devices on the bus
    OWB_ROM_READ          =0x33,  ///&lt; Read device ROM (single device on bus only)
    OWB_ROM_MATCH         =0x55,  ///&lt; Address a specific device on the bus by ROM
    OWB_ROM_SKIP          =0xCC,  ///&lt; Address all devices on the bus simultaneously
    OWB_ROM_SEARCH_ALARM  =0xEC,  ///&lt; Address all devices on the bus with a set alarm flag
} owb_commands_t;</pre>
<p>In this case, David had done most of the work already and all I needed to do was copy/modify his headers in the few places where we had differences in the public interface to the library.  After that, I ran doxygen.  When I first did this I got an absolute boatload of warnings about places where I had not documented with comments.  If Hassane is reading he will say &#8230; &#8220;Really Alan didn&#8217;t write comments, imagine that&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master *) p6sdk-onewire $ doxygen
Doxygen version used: 1.8.18
Searching for include files...
Searching for example files...
Searching for images...
Searching for dot files...
Searching for msc files...
Searching for dia files...
Searching for files to exclude
Searching INPUT for files to process...
Searching for files in directory /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire
Reading and parsing tag files
Parsing files
Reading /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire/README.md...
Preprocessing /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire/owb.c...
Parsing file /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire/owb.c...
Preprocessing /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire/owb.h...
Parsing file /Users/arh/proj/owb-ds18b20/DS18B20Test/p6sdk-onewire/owb.h...
Building group list...
Building directory list...
Building namespace list...
Building file list...
Building class list...
Computing nesting relations for classes...
Associating documentation with classes...
Building example list...
Searching for enumerations...
Searching for documented typedefs...
Searching for members imported via using declarations...
Searching for included using directives...
Searching for documented variables...
Building interface member list...
Building member list...
Searching for friends...
Searching for documented defines...
Computing class inheritance relations...
Computing class usage relations...
Flushing cached template relations that have become invalid...
Computing class relations...
Add enum values to enums...
Searching for member function documentation...
Creating members for template instances...
Building page list...
Search for main page...
Computing page relations...
Determining the scope of groups...
Sorting lists...
Determining which enums are documented
Computing member relations...
Building full member lists recursively...
Adding members to member groups.
Computing member references...
Inheriting documentation...
Generating disk names...
Adding source references...
Adding xrefitems...
Sorting member lists...
Setting anonymous enum type...
Computing dependencies between directories...
Generating citations page...
Counting members...
Counting data structures...
Resolving user defined references...
Finding anchors and sections in the documentation...
Transferring function references...
Combining using relations...
Adding members to index pages...
Correcting members for VHDL...
Generating style sheet...
Generating search indices...
Generating example documentation...
Generating file sources...
Generating code for file owb.h...
Generating file documentation...
Generating docs for file owb.h...
Generating page documentation...
Generating docs for page md_README...
Generating group documentation...
Generating class documentation...
Generating docs for compound OneWireBus...
Generating docs for compound OneWireBus_ROMCode...
Generating docs for nested compound OneWireBus_ROMCode::fields...
Generating docs for compound OneWireBus_SearchState...
Generating namespace index...
Generating graph info page...
Generating directory documentation...
Generating index page...
Generating page index...
Generating module index...
Generating namespace index...
Generating namespace member index...
Generating annotated compound index...
Generating alphabetical compound index...
Generating hierarchical class index...
Generating member index...
Generating file index...
Generating file member index...
Generating example index...
finalizing index lists...
writing tag file...
Running plantuml with JAVA...
lookup cache used 45/65536 hits=385 misses=48
finished...
arh (master *) p6sdk-onewire $</pre>
<p>Now I have some documentation</p>
<p><a href="https://iotexpert.com/2020/09/07/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/screen-shot-2020-09-07-at-6-29-12-am/" rel="attachment wp-att-9794"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/09/Screen-Shot-2020-09-07-at-6.29.12-AM-1024x566.jpg" alt="" width="1024" height="566" class="alignnone size-large wp-image-9794" /></a></p>
<p>I will say that I wish I had a few days to really learn Doxygen as there are many many many options which I have no idea what they do.  Oh well.</p>
<h1>Fix the Logging Function</h1>
<p>David built the library on top of the ESP32 libraries.  This included calls to the ESP32 logging library &#8220;<a href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html" target="_blank" rel="noopener noreferrer">log.h/.c</a>&#8220;.  All through his library he calls &#8220;ESP_LOG&#8221; like this.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">ESP_LOGE(TAG, "bus is NULL");</pre>
<p>When I first looked at this I decided to just do this to make the error messages go away.  This is just a trick that will use the c-preprocessor to replace the function call to &#8220;ESP32_LOGE&#8221; with NOTHING</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ESP_LOGE(...)</pre>
<p>After I sorted everything else out I went back to decide what to do.  My choices were</p>
<ol>
<li>Clone the Espressif library and &#8220;fix it&#8221;</li>
<li>Implement the functions that David used in the OWB library</li>
<li>Find another library</li>
</ol>
<p>I decided to use option 3 &#8211; a logging library that I found on GitHub called &#8220;<a href="https://github.com/rxi/log.c" target="_blank" rel="noopener noreferrer">log.c</a>&#8221; (which is a very unfortunate name when you clone it).  It is really simple and works well.  Since the Tour de France is going as I write this article I will say &#8220;chappeau rxi&#8221;.  This library is written in C99 (just normal C) and has functions which can easily replace the ESP_LOG functions.  I add it to my project with &#8220;git clone git@github.com:rxi/log.c.git&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">log_trace(const char *fmt, ...);
log_debug(const char *fmt, ...);
log_info(const char *fmt, ...);
log_warn(const char *fmt, ...);
log_error(const char *fmt, ...);
log_fatal(const char *fmt, ...);</pre>
<p>This means that I just replace &#8220;ESP_LOGE&#8221; with &#8220;log_error&#8221;.  In reality rxi did something very nice by using a feature of the compiler to insert the file/line numbers.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)</pre>
<p>This only left me with the function</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">ESP_LOG_BUFFER_HEX_LEVEL(TAG, scratchpad, count, ESP_LOG_DEBUG);</pre>
<p>Which I decided to do something cheap to solve.  The original code was:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">              //ESP_LOG_BUFFER_HEX_LEVEL(TAG, &amp;scratchpad-&gt;trigger_high, 3, ESP_LOG_DEBUG);</pre>
<p>And I replaced the two uses with:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">log_debug( "scratchpad write 3 bytes:%02X%02X%02X",scratchpad[0],scratchpad[1],scratchpad[2]);</pre>
<p>and</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">                //ESP_LOG_BUFFER_HEX_LEVEL(TAG, scratchpad, count, ESP_LOG_DEBUG);
                log_debug( "%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                    scratchpad[0],scratchpad[1],scratchpad[2],
                    scratchpad[3],scratchpad[4],scratchpad[5],
                    scratchpad[6],scratchpad[7],scratchpad[8]);</pre>
<p>I know it isn&#8217;t beautiful what I did, but it works.</p>
<h1>Enumerated Command Type</h1>
<p>When I examined the original source code, the one-wire commands were defined using #defines.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// ROM commands
#define OWB_ROM_SEARCH        0xF0  ///&lt; Perform Search ROM cycle to identify devices on the bus
#define OWB_ROM_READ          0x33  ///&lt; Read device ROM (single device on bus only)
#define OWB_ROM_MATCH         0x55  ///&lt; Address a specific device on the bus by ROM
#define OWB_ROM_SKIP          0xCC  ///&lt; Address all devices on the bus simultaneously
#define OWB_ROM_SEARCH_ALARM  0xEC  ///&lt; Address all devices on the bus with a set alarm flag</pre>
<p>When I did the implementation originally I chose to make the #defines into an enumerated list.  I suppose that it doesn&#8217;t really matter.  But, by enumerating the values it lets the compiler help you in situations like a switch or a function call.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    OWB_ROM_SEARCH        =0xF0,  ///&lt; Perform Search ROM cycle to identify devices on the bus
    OWB_ROM_READ          =0x33,  ///&lt; Read device ROM (single device on bus only)
    OWB_ROM_MATCH         =0x55,  ///&lt; Address a specific device on the bus by ROM
    OWB_ROM_SKIP          =0xCC,  ///&lt; Address all devices on the bus simultaneously
    OWB_ROM_SEARCH_ALARM  =0xEC,  ///&lt; Address all devices on the bus with a set alarm flag
} owb_commands_t;</pre>
<h1>Const Bus pointer</h1>
<p>Through out the original one wire bus library, the bus pointer is defined as const.  Like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_status owb_read_rom(const OneWireBus * bus, OneWireBus_ROMCode * rom_code)</pre>
<p>But, I wanted to use the OneWireBus structure to also store some context.  By context I mean variables (which can change) but hold state for the bus.  This included the semaphore that I used to fix the delay functions.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">/**
 * @brief Structure containing 1-Wire bus information relevant to a single instance.
 */
typedef struct  
{
    cyhal_gpio_t  pin;                   ///&lt;Pin that the bus is attached to
    cyhal_gpio_t strong_pullup_gpio;     ///&lt;Pin that the pullup gpio is attached to
    bool use_parasitic_power;            ///&lt;Driver is using parastic power mode
    bool use_crc;                        ///&lt;Enable the use of crc checks on the ROM
    // Internal use only
    bool is_init;                        ///&lt;Private
    bool detect;                         ///&lt;Private
    SemaphoreHandle_t signalSemaphore;   ///&lt;Private
    cyhal_timer_t bitTimer;              ///&lt;Private
    SemaphoreHandle_t owb_num_active;    ///&lt;Private
    uint8_t scratchBitValue;             ///&lt;Private
} OneWireBus;</pre>
<h1>ROM Code Structure Packed</h1>
<p>In the original library the ROMCode is a union that allows access to individual bytes, or the actual data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">typedef union
{
    /// Provides access via field names
    struct fields
    {
        uint8_t family[1];         ///&lt; family identifier (1 byte, LSB - read/write first)
        uint8_t serial_number[6];  ///&lt; serial number (6 bytes)
        uint8_t crc[1];            ///&lt; CRC check byte (1 byte, MSB - read/write last)
    } __PACKED fields;             ///&lt; Provides access via field names

    uint8_t bytes[8];              ///&lt; Provides raw byte access

} OneWireBus_ROMCode;</pre>
<p>The problem is there is no guarantee that the compiler will pack the family, serial number and crc.  You should tell it to with the __PACKED macro.  I would say that I think that David got luck that there was not a bug.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/**
 * @brief Represents a 1-Wire ROM Code. This is a sequence of eight bytes, where
 *        the first byte is the family number, then the following 6 bytes form the
 *        serial number. The final byte is the CRC8 check byte.
 */
typedef union
{
    /// Provides access via field names
    struct fields
    {
        uint8_t family[1];         ///&lt; family identifier (1 byte, LSB - read/write first)
        uint8_t serial_number[6];  ///&lt; serial number (6 bytes)
        uint8_t crc[1];            ///&lt; CRC check byte (1 byte, MSB - read/write last)
    } __PACKED fields;             ///&lt; Provides access via field names

    uint8_t bytes[8];              ///&lt; Provides raw byte access

} OneWireBus_ROMCode;</pre>
<h1>C-Programming: Passing Structures as Function Arguments</h1>
<p>In the original library David passed the rom_code structure as an argument on the stack.  But, because I started programming in the days before it was legal to pass a structure as a function argument when I did the implementation I passed a pointer.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_status owb_verify_rom(const OneWireBus * bus, OneWireBus_ROMCode rom_code, bool * is_present);</pre>
<p>I wrote</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_verify_rom(OneWireBus * bus, OneWireBus_ROMCode *rom_code, bool * is_present);</pre>
<p>Which meant that he could write</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">        OneWireBus_SearchState state = {
            .rom_code = rom_code,
            .last_discrepancy = 64,
            .last_device_flag = false,
        };</pre>
<p>but I had to write</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">        OneWireBus_SearchState state = {
            //.rom_code = rom_code,
            .last_discrepancy = 64,
            .last_device_flag = false,
        };

        memcpy(&amp;state.rom_code,rom_code,sizeof(OneWireBus_ROMCode));</pre>
<p>In this case it doesn&#8217;t really matter as the structure is small.</p>
<h1>Driver Functions</h1>
<p>If you look at the original implementation the author has a &#8220;driver&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">typedef struct
{
    const struct _OneWireBus_Timing * timing;   ///&lt; Pointer to timing information
    bool use_crc;                               ///&lt; True if CRC checks are to be used when retrieving information from a device on the bus
    bool use_parasitic_power;                   ///&lt; True if parasitic-powered devices are expected on the bus
    gpio_num_t strong_pullup_gpio;              ///&lt; Set if an external strong pull-up circuit is required
    const struct owb_driver * driver;           ///&lt; Pointer to hardware driver instance
} OneWireBus;</pre>
<p>Which is a structure with function pointers to talk to bus.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">/** NOTE: Driver assumes that (*init) was called prior to any other methods */
struct owb_driver
{
    /** Driver identification **/
    const char* name;

    /** Pointer to driver uninitialization function **/
    owb_status (*uninitialize)(const OneWireBus * bus);

    /** Pointer to driver reset functio **/
    owb_status (*reset)(const OneWireBus * bus, bool *is_present);

    /** NOTE: The data is shifted out of the low bits, eg. it is written in the order of lsb to msb */
    owb_status (*write_bits)(const OneWireBus *bus, uint8_t out, int number_of_bits_to_write);

    /** NOTE: Data is read into the high bits, eg. each bit read is shifted down before the next bit is read */
    owb_status (*read_bits)(const OneWireBus *bus, uint8_t *in, int number_of_bits_to_read);
};</pre>
<p>Which meant that he did this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">bus-&gt;driver-&gt;read_bits(bus, &amp;id_bit, 1);
bus-&gt;driver-&gt;read_bits(bus, &amp;cmp_id_bit, 1);
</pre>
<p>In my implementation I wrote functions for those things.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_read_bit(bus,&amp;id_bit);
owb_read_bit(bus,&amp;cmp_id_bit);</pre>
<p>I don&#8217;t really think that it helped abstract the hardware because he also did this.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">            gpio_set_level(bus-&gt;strong_pullup_gpio, enable ? 1 : 0);</pre>
<p>Perhaps a driver with function pointers would have made the original port easier if I had started there?  But if so, it would have required more adherence to the original  architecture.</p>
<h1>Test Search</h1>
<p>A nice thing that came with his library was an implementation of the search feature which allows multiple devices to be attached to the bus.  To test this I added two sensors.</p>
<p><a href="https://iotexpert.com/2020/09/07/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/img_1950/" rel="attachment wp-att-9377"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-1024x763.jpg" alt="" width="1024" height="763" class="alignnone size-large wp-image-9377" srcset="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-1024x763.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-scaled-600x447.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-300x223.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-768x572.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-1536x1144.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1950-2048x1526.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then made a command in my console to run the test.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_search(int argc, char **argv)
{
    printf("Search\n");
    OneWireBus_SearchState state;
    bool found_device;

    owb_search_first(&amp;bus, &amp;state, &amp;found_device);

    do {
        if(found_device)
        {
            printf("Found Device = ");
            for(int i=0;i&lt;8;i++)
            {
                printf("%02X ",state.rom_code.bytes[i]);
            }
            printf("\n");
        }

        owb_search_next(&amp;bus, &amp;state, &amp;found_device);

    } while(found_device);

    printf("Search done\n");
    return 0;
}</pre>
<p>Which worked perfectly.</p>
<p><a href="https://iotexpert.com/2020/09/07/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/screen-shot-2020-06-14-at-4-48-30-pm/" rel="attachment wp-att-9371"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM-1024x357.png" alt="" width="1024" height="357" class="alignnone size-large wp-image-9371" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM-1024x357.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM-600x209.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM-300x105.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM-768x268.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-14-at-4.48.30-PM.png 1176w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Parasitic Power</h1>
<p>I would like to test the functionality of the parasitic power.  Here is a schematic from the data sheet of how it work.  But I don&#8217;t have that transistor so that will be left for another day.</p>
<p><a href="https://iotexpert.com/2020/09/07/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/screen-shot-2020-06-11-at-5-07-12-pm/" rel="attachment wp-att-9327"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM-1024x596.png" alt="" width="1024" height="596" class="alignnone size-large wp-image-9327" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM-1024x596.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM-600x349.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM-300x175.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM-768x447.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.07.12-PM.png 1178w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>What is Next?</h1>
<p>There are several things that I should do.</p>
<ol>
<li>Fix up the libraries to use the manifest files so they are available all of the time</li>
<li>Fix up the libraries to use the dependency scheme</li>
<li>Test the parasitic power</li>
<li>Test the actual DS18B20 library (the original point of this whole thing)</li>
</ol>
<p>I have found myself in the middle of a bunch of other problems, so these things will need to happen another day.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-5-round-out-the-owb-driver/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 Pins &#038; the SPI Port</title>
		<link>https://iotexpert.com/psoc-6-pins-the-spi-port/</link>
					<comments>https://iotexpert.com/psoc-6-pins-the-spi-port/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 10 Aug 2020 12:32:19 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=7927</guid>

					<description><![CDATA[Summary Recently, I have been helping a reader sort out some code that makes strings of WS2812 LEDs work.  Specifically, this code takes data from a frame buffer inside of the PSoC 6 and drives it out a SPI port via the MOSI pin. I have written about this a couple of times, but,  the [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Recently, I have been helping a <a href="https://www.cypress.com/blog/ceo-corner/who-am-i" target="_blank" rel="noopener noreferrer">reader</a> sort out some code that makes strings of WS2812 LEDs work.  Specifically, this code takes data from a frame buffer inside of the PSoC 6 and drives it out a SPI port via the MOSI pin. I have <a href="https://iotexpert.com/?s=ws2812" target="_blank" rel="noopener noreferrer">written</a> about this a couple of times, but,  the new wrinkle in our code is that it allows you to use any combination of SPI port/pins on the chip.  Instead of using the configurators to setup the SPI to GPIO connection, I setup the connection using PDL to talk directly to the PSoC 6 configuration the registers.</p>
<p>Perhaps it is obvious to everyone how a connection from a peripheral to a GPIO works, but I thought that I would write about it anyway.  In this article I am going to show you a bunch of the documentation for PSoC as well as the PDL source code which implements the documentation.  Specifically, I will show you the PSoC 6</p>
<ol>
<li><a href="https://www.cypress.com/file/399201/download" target="_blank" rel="noopener noreferrer">Architecture TRM</a></li>
<li><a href="https://www.cypress.com/file/421411/download" target="_blank" rel="noopener noreferrer">Register TRM</a></li>
<li><a href="https://www.cypress.com/file/460816/download" target="_blank" rel="noopener noreferrer">Datasheet</a></li>
<li>PDL</li>
</ol>
<h1>Architecture TRM</h1>
<p>In the picture below, which I copied from the <a href="https://www.cypress.com/file/399201/download" target="_blank" rel="noopener noreferrer">PSoC 6 Architecture TRM</a>, you can see how an individual GPIO works.  Starting  at the Pin of the chip you can see that there are three connections from/to the pin (look at the green box).</p>
<ul>
<li>A set of switches to/from the Analog Mux Bus which enable CapSense or Analog peripherals to talk to the Pin</li>
<li>A connection from the pin to the Analog peripherals (some Analog peripherals can attach directly to a pin and not though the Analog Mux Bus</li>
<li>A connection to the High Speed I/O Matrix (HSIOM) &#8211; for the digital peripherals</li>
</ul>
<p>Notice that all of the signals coming into the green box from the top are DIGITAL.  All of the signals coming into the box from the bottom are Analog and the line coming into the middle of the box controls the behavior of the I/O.</p>
<p>For my case the SPI is one of the &#8220;Fixed Function Digital Peripherals&#8221;.  In order to get it to connect to the pin I will beed to pick out the right signal in the multiplexer that is in the HSIOM Matrix box.</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-11-55-54-am/" rel="attachment wp-att-7928"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM-1024x953.png" alt="" width="1024" height="953" class="alignnone size-large wp-image-7928" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM-1024x953.png 1024w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM-600x559.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM-300x279.png 300w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM-768x715.png 768w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.55.54-AM.png 1510w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you scroll down a little bit further in the Architecture TRM, the next diagram is a more detailed description of the GPIO.  Notice that there are a bunch of configuration register bits which setup different parts of the I/O like slew rate, interrupts, drive mode etc.  Notice that the multiplexer that is connected to &#8220;out&#8221;<br />
and &#8220;out_en&#8221; has a bunch of different possible signals.  Including &#8220;GPIO_PRTx_OUT[OUTy]&#8221; which is a register bit which is can be used for &#8220;digital write&#8221;.  For instance GPIO_PRT0_OUT[2] would be P0_2.  The other interesting thing going on here is you can see that there are really three classes of signals attached to the mutiplexer</p>
<ul>
<li>The digital output pin</li>
<li>Active signals &#8211; which work while the chip is not in deep sleep</li>
<li>Deep Sleep signals &#8211; which work while the chip is in deep sleep.</li>
</ul>
<p>On the output side you can see the two pullup and pulldown resistors, as well as the two transistors which pullup and pull down.  All of these can be configured to be connected&#8230; or not.</p>
<p>And finally at the bottom of the I/O you can see the analog signals.</p>
<p>&nbsp;</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-16-56-pm/" rel="attachment wp-att-7931"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM-744x1024.png" alt="" width="744" height="1024" class="alignnone size-large wp-image-7931" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM-744x1024.png 744w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM-600x826.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM-218x300.png 218w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM-768x1057.png 768w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.16.56-PM.png 1402w" sizes="auto, (max-width: 744px) 100vw, 744px" /></a></p>
<p>If you look a little bit further down in the Architecture TRM you will find this table which describes how each of the actual pins on the multiplexer work.</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-20-52-pm/" rel="attachment wp-att-7932"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM-934x1024.png" alt="" width="934" height="1024" class="alignnone size-large wp-image-7932" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM-934x1024.png 934w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM-600x658.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM-274x300.png 274w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM-768x842.png 768w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.20.52-PM.png 2036w" sizes="auto, (max-width: 934px) 100vw, 934px" /></a></p>
<h1>PSoC 6 Register TRM</h1>
<p>If you want to start to make specific configurations for specific pins you will need to look into the PSoC 6 Register TRM.  In that document you will find that the</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-22-56-pm/" rel="attachment wp-att-7933"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.22.56-PM-1024x218.png" alt="" width="1024" height="218" class="alignnone size-large wp-image-7933" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.22.56-PM-1024x218.png 1024w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.22.56-PM-600x128.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.22.56-PM-300x64.png 300w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.22.56-PM-768x164.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a> <a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-23-15-pm/" rel="attachment wp-att-7934"></a></p>
<p>Register TRM</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-23-15-pm/" rel="attachment wp-att-7934"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.15-PM-1024x725.png" alt="" width="1024" height="725" class="alignnone size-large wp-image-7934" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.15-PM-1024x725.png 1024w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.15-PM-600x425.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.15-PM-300x212.png 300w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.15-PM-768x544.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Register TRM</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-4-23-24-pm/" rel="attachment wp-att-7935"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.24-PM-1024x585.png" alt="" width="1024" height="585" class="alignnone size-large wp-image-7935" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.24-PM-1024x585.png 1024w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.24-PM-600x343.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.24-PM-300x171.png 300w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-4.23.24-PM-768x439.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>PSoC 6 Datasheet</h1>
<p>But what are all of the active and deep sleep signals?  Well if you look in the <a href="https://www.cypress.com/file/460816/download" target="_blank" rel="noopener noreferrer">PSoC 6 data sheet</a> you can find all of those connections.  For instance on P0.1 active signal 8 is the SCB 0 SPI Select signal 2.</p>
<p><a href="https://iotexpert.com/2020/08/10/psoc-6-pins-the-spi-port/screen-shot-2019-09-21-at-11-58-41-am/" rel="attachment wp-att-7930"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.58.41-AM-1024x368.png" alt="" width="1024" height="368" class="alignnone size-large wp-image-7930" srcset="https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.58.41-AM-1024x368.png 1024w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.58.41-AM-600x216.png 600w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.58.41-AM-300x108.png 300w, https://iotexpert.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-21-at-11.58.41-AM-768x276.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>PSoC 6 PDL</h1>
<p>But really all of these register reads and writes are not really that fun.  So, Cypress provides other, less painful ways of getting things going.  Specifically,</p>
<ul>
<li>void Cy_GPIO_SetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum, en_hsiom_sel_t value)</li>
</ul>
<p>or</p>
<ul>
<li>Cy_GPIO_Pin_Init(GPIO_PRT_Type *base, uint32_t pinNum, const cy_stc_gpio_pin_config_t *config)</li>
</ul>
<p>When you call both of these function you need to provide the value for the multipler either directly in the Cy_GPIO_SetHSIOM or indirectly in the Cy_GPIO_Pin_Init case where you provide it as a member of the cy_stc_gpio_pin_config_t *config structure called &#8220;hsiom&#8221;</p>
<p>Depending on which package you have selected you will have a file like gpio_psoc6_01_124_bga.h which will have both the generic definitions for the HSIOM multiplexer select (like this)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="&quot;c”">/* HSIOM Connections */
typedef enum
{
    /* Generic HSIOM connections */
    HSIOM_SEL_GPIO                  =  0,       /* GPIO controls 'out' */
    HSIOM_SEL_GPIO_DSI              =  1,       /* GPIO controls 'out', DSI controls 'output enable' */
    HSIOM_SEL_DSI_DSI               =  2,       /* DSI controls 'out' and 'output enable' */
    HSIOM_SEL_DSI_GPIO              =  3,       /* DSI controls 'out', GPIO controls 'output enable' */
    HSIOM_SEL_AMUXA                 =  4,       /* Analog mux bus A */
    HSIOM_SEL_AMUXB                 =  5,       /* Analog mux bus B */
    HSIOM_SEL_AMUXA_DSI             =  6,       /* Analog mux bus A, DSI control */
    HSIOM_SEL_AMUXB_DSI             =  7,       /* Analog mux bus B, DSI control */
    HSIOM_SEL_ACT_0                 =  8,       /* Active functionality 0 */
    HSIOM_SEL_ACT_1                 =  9,       /* Active functionality 1 */
    HSIOM_SEL_ACT_2                 = 10,       /* Active functionality 2 */
    HSIOM_SEL_ACT_3                 = 11,       /* Active functionality 3 */
    HSIOM_SEL_DS_0                  = 12,       /* DeepSleep functionality 0 */
    HSIOM_SEL_DS_1                  = 13,       /* DeepSleep functionality 1 */
    HSIOM_SEL_DS_2                  = 14,       /* DeepSleep functionality 2 */
    HSIOM_SEL_DS_3                  = 15,       /* DeepSleep functionality 3 */
    HSIOM_SEL_ACT_4                 = 16,       /* Active functionality 4 */
    HSIOM_SEL_ACT_5                 = 17,       /* Active functionality 5 */
    HSIOM_SEL_ACT_6                 = 18,       /* Active functionality 6 */
    HSIOM_SEL_ACT_7                 = 19,       /* Active functionality 7 */
    HSIOM_SEL_ACT_8                 = 20,       /* Active functionality 8 */
    HSIOM_SEL_ACT_9                 = 21,       /* Active functionality 9 */
    HSIOM_SEL_ACT_10                = 22,       /* Active functionality 10 */
    HSIOM_SEL_ACT_11                = 23,       /* Active functionality 11 */
    HSIOM_SEL_ACT_12                = 24,       /* Active functionality 12 */
    HSIOM_SEL_ACT_13                = 25,       /* Active functionality 13 */
    HSIOM_SEL_ACT_14                = 26,       /* Active functionality 14 */
    HSIOM_SEL_ACT_15                = 27,       /* Active functionality 15 */
    HSIOM_SEL_DS_4                  = 28,       /* DeepSleep functionality 4 */
    HSIOM_SEL_DS_5                  = 29,       /* DeepSleep functionality 5 */
    HSIOM_SEL_DS_6                  = 30,       /* DeepSleep functionality 6 */
    HSIOM_SEL_DS_7                  = 31,       /* DeepSleep functionality 7 */</pre>
<p>As well as the pin by pin definitions&#8230; like this for P0_2</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c” ">    /* P0.2 */
    P0_2_GPIO                       =  0,       /* GPIO controls 'out' */
    P0_2_AMUXA                      =  4,       /* Analog mux bus A */
    P0_2_AMUXB                      =  5,       /* Analog mux bus B */
    P0_2_AMUXA_DSI                  =  6,       /* Analog mux bus A, DSI control */
    P0_2_AMUXB_DSI                  =  7,       /* Analog mux bus B, DSI control */
    P0_2_TCPWM0_LINE1               =  8,       /* Digital Active - tcpwm[0].line[1]:0 */
    P0_2_TCPWM1_LINE1               =  9,       /* Digital Active - tcpwm[1].line[1]:0 */
    P0_2_CSD_CSD_TX                 = 10,       /* Digital Active - csd.csd_tx:2 */
    P0_2_CSD_CSD_TX_N               = 11,       /* Digital Active - csd.csd_tx_n:2 */
    P0_2_LCD_COM2                   = 12,       /* Digital Deep Sleep - lcd.com[2]:0 */
    P0_2_LCD_SEG2                   = 13,       /* Digital Deep Sleep - lcd.seg[2]:0 */
    P0_2_SCB0_UART_RX               = 18,       /* Digital Active - scb[0].uart_rx:0 */
    P0_2_SCB0_I2C_SCL               = 19,       /* Digital Active - scb[0].i2c_scl:0 */
    P0_2_SCB0_SPI_MOSI              = 20,       /* Digital Active - scb[0].spi_mosi:0 */</pre>
<p>If you look at the Cy_GPIO_Pin_Init function you will see that on line 96 it sets the register which picks the correct pin mux.</p>
<pre class="start-line:70 EnlighterJSRAW" data-enlighter-language="c”">cy_en_gpio_status_t Cy_GPIO_Pin_Init(GPIO_PRT_Type *base, uint32_t pinNum, const cy_stc_gpio_pin_config_t *config)
{
    cy_en_gpio_status_t status = CY_GPIO_BAD_PARAM;

    if ((NULL != base) &amp;&amp; (NULL != config))
    {
        uint32_t maskCfgOut;
        uint32_t tempReg;
        
        CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;outVal));
        CY_ASSERT_L2(CY_GPIO_IS_DM_VALID(config-&gt;driveMode));
        CY_ASSERT_L2(CY_GPIO_IS_HSIOM_VALID(config-&gt;hsiom));  
        CY_ASSERT_L2(CY_GPIO_IS_INT_EDGE_VALID(config-&gt;intEdge)); 
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;intMask));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;vtrip));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;slewRate));
        CY_ASSERT_L2(CY_GPIO_IS_DRIVE_SEL_VALID(config-&gt;driveSel));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;vregEn));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;ibufMode));
        CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config-&gt;vtripSel));
        CY_ASSERT_L2(CY_GPIO_IS_VREF_SEL_VALID(config-&gt;vrefSel));
        CY_ASSERT_L2(CY_GPIO_IS_VOH_SEL_VALID(config-&gt;vohSel));
    
        Cy_GPIO_Write(base, pinNum, config-&gt;outVal);
        Cy_GPIO_SetDrivemode(base, pinNum, config-&gt;driveMode);
        Cy_GPIO_SetHSIOM(base, pinNum, config-&gt;hsiom);

        Cy_GPIO_SetInterruptEdge(base, pinNum, config-&gt;intEdge);
        Cy_GPIO_SetInterruptMask(base, pinNum, config-&gt;intMask);
        Cy_GPIO_SetVtrip(base, pinNum, config-&gt;vtrip);

        /* Slew rate and Driver strength */
        maskCfgOut = (CY_GPIO_CFG_OUT_SLOW_MASK &lt;&lt; pinNum) 
                     | (CY_GPIO_CFG_OUT_DRIVE_SEL_MASK &lt;&lt; ((uint32_t)(pinNum &lt;&lt; 1U) + CY_GPIO_CFG_OUT_DRIVE_OFFSET));
        tempReg = GPIO_PRT_CFG_OUT(base) &amp; ~(maskCfgOut);
        
        GPIO_PRT_CFG_OUT(base) = tempReg | ((config-&gt;slewRate &amp; CY_GPIO_CFG_OUT_SLOW_MASK) &lt;&lt; pinNum)
                            | ((config-&gt;driveSel &amp; CY_GPIO_CFG_OUT_DRIVE_SEL_MASK) &lt;&lt; ((uint32_t)(pinNum &lt;&lt; 1U) + CY_GPIO_CFG_OUT_DRIVE_OFFSET));

        /* SIO specific configuration */
        tempReg = GPIO_PRT_CFG_SIO(base) &amp; ~(CY_GPIO_SIO_PIN_MASK);
        GPIO_PRT_CFG_SIO(base) = tempReg | (((config-&gt;vregEn &amp; CY_GPIO_VREG_EN_MASK)
                                         | ((config-&gt;ibufMode &amp; CY_GPIO_IBUF_MASK) &lt;&lt; CY_GPIO_IBUF_SHIFT)
                                         | ((config-&gt;vtripSel &amp; CY_GPIO_VTRIP_SEL_MASK) &lt;&lt; CY_GPIO_VTRIP_SEL_SHIFT)
                                         | ((config-&gt;vrefSel &amp; CY_GPIO_VREF_SEL_MASK)  &lt;&lt; CY_GPIO_VREF_SEL_SHIFT)
                                         | ((config-&gt;vohSel &amp; CY_GPIO_VOH_SEL_MASK) &lt;&lt; CY_GPIO_VOH_SEL_SHIFT))
                                           &lt;&lt; ((pinNum &amp; CY_GPIO_SIO_ODD_PIN_MASK) &lt;&lt; CY_GPIO_CFG_SIO_OFFSET));

        status = CY_GPIO_SUCCESS;
    }

    return(status);
}
</pre>
<p>And finally the Cy_GPIO_SetHSIOM actually writes to the register.</p>
<pre class="start-line:652 EnlighterJSRAW" data-enlighter-language="c”">__STATIC_INLINE void Cy_GPIO_SetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum, en_hsiom_sel_t value)
{
    uint32_t portNum;
    uint32_t tempReg;
    HSIOM_PRT_V1_Type* portAddrHSIOM;

    CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum));
    CY_ASSERT_L2(CY_GPIO_IS_HSIOM_VALID(value));

    portNum = ((uint32_t)(base) - CY_GPIO_BASE) / GPIO_PRT_SECTION_SIZE;
    portAddrHSIOM = (HSIOM_PRT_V1_Type*)(CY_HSIOM_BASE + (HSIOM_PRT_SECTION_SIZE * portNum));

    if(pinNum &lt; CY_GPIO_PRT_HALF)
    {
        tempReg = HSIOM_PRT_PORT_SEL0(portAddrHSIOM) &amp; ~(CY_GPIO_HSIOM_MASK &lt;&lt; (pinNum &lt;&lt; CY_GPIO_HSIOM_OFFSET));
        HSIOM_PRT_PORT_SEL0(portAddrHSIOM) = tempReg | ((value &amp; CY_GPIO_HSIOM_MASK) &lt;&lt; (pinNum &lt;&lt; CY_GPIO_HSIOM_OFFSET));
    }
    else
    {
        pinNum -= CY_GPIO_PRT_HALF;
        tempReg = HSIOM_PRT_PORT_SEL1(portAddrHSIOM) &amp; ~(CY_GPIO_HSIOM_MASK &lt;&lt; (pinNum &lt;&lt; CY_GPIO_HSIOM_OFFSET));
        HSIOM_PRT_PORT_SEL1(portAddrHSIOM) = tempReg | ((value &amp; CY_GPIO_HSIOM_MASK) &lt;&lt; (pinNum &lt;&lt; CY_GPIO_HSIOM_OFFSET));
    }
}
</pre>
<h1>PSoC 6 SPI</h1>
<p>Finally, it may seem obvious, but there is a limited set of connections to each GPIO in PSoC 6.  This means that any given SCB can only connect its SPI pins to a specific set of pins on the chip.  But, what are they?  You can either look at the data sheet, or you can search the file which you will find the pin definitions which will all be in the form of Px_y_SCBz_SPI_MOSI and this will give you a complete map.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-pins-the-spi-port/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 SDK OneWire Bus (Part 4): But, Can It Read the Temperature?</title>
		<link>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-4-but-can-it-read-the-temperature/</link>
					<comments>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-4-but-can-it-read-the-temperature/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 06 Jul 2020 10:29:20 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9329</guid>

					<description><![CDATA[Summary In this series of articles I have been implementing a one-wire sensor library to work with PSoC 6.  In this article I will test the library by reading the temperature from the DS18B20 sensor. Story After three articles crawling through one-wire documents and firmware we are down to the real question.  Will it actually [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I have been implementing a one-wire sensor library to work with PSoC 6.  In this article I will test the library by reading the temperature from the DS18B20 sensor.</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &amp; Write</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/29/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait &amp; Debug</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/?p=9329" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature?</a></td>
</tr>

<tr><td >PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver</td>
</tr>
</tbody></table></div></p>
<h1>Story</h1>
<p>After three articles crawling through one-wire documents and firmware we are down to the real question.  Will it actually read the temperature?  Each device on a one-wire bus is addressed by a unique 64-bit value which is programmed at the factory.  Before you can talk to a device you need to read the rom value.  The question is how do you find the ROM value when you have multiple devices connected on the bus?  There are two ways</p>
<ol>
<li>Follow a rather complicated discovery process (next article)</li>
<li>If there is only 1 device on the bus you can follow a short cut.</li>
</ol>
<p>Well, lets start with the simple method.</p>
<h1>Read ROM</h1>
<p>The data sheet is pretty clear about how to read the ROM code when you only have one device.  Basically, you send a 0x33, then you read 8 bytes.  Here is a clip from the data sheet.</p>
<p><a href="https://iotexpert.com/?attachment_id=9332" rel="attachment wp-att-9332"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM-1024x371.png" alt="" width="1024" height="371" class="alignnone size-large wp-image-9332" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM-1024x371.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM-600x217.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM-300x109.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM-768x278.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.25-AM.png 1160w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I will add a command to my ntshell command line.  The command is &#8220;readrom&#8221; it will</p>
<ol>
<li>Send the reset</li>
<li>Wait 1MS (I don&#8217;t think you have to do this, but this was a bug work around)</li>
<li>Send the 0x33</li>
<li>Then read 8 bytes.</li>
<li>And print out the result (lines</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">OneWireBus_ROMCode rom;

static int usrcmd_readrom(int argc, char **argv)
{
    owb_ret_t rval;

    printf("Sending reset\n");
    bool result;
    rval = owb_reset(&amp;bus,&amp;result);
    if(rval != OWB_STATUS_OK)
    {
        printf("Reset failed\n");
        return 0;
    }

    CyDelay(1);

    printf("Sending 0x33\n");

    rval = owb_write_byte(&amp;bus,0x33);
    if(rval != OWB_STATUS_OK)
    {
        printf("Write 0x33 failed\n");
        return 0;
    }


    // read 64-bit rom
    printf("Reading 8 bytes\n");

    rval = owb_read_bytes(&amp;bus,rom.romAddr,8);

   if(rval != OWB_STATUS_OK)
    {
        printf("read 8 bytes failed\n");
        return 0;
    }
    // 
    printf("Rom = ");
    for(int i=0;i&lt;8;i++)
    {
        printf("%02X ",rom.romAddr[i]);
    }
    printf("\n");
    return 0;
}</pre>
<p>When I test it, things seem to be working.</p>
<p><a href="https://iotexpert.com/?attachment_id=9336" rel="attachment wp-att-9336"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM-1024x612.png" alt="" width="1024" height="612" class="alignnone size-large wp-image-9336" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM-1024x612.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM-600x359.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM-300x179.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM-768x459.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.16.21-AM.png 1218w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Read Temperature</h1>
<p>Now that we know the ROM Code, which is used as the address, how do we get the temperature.  To do this you should follow this procedure.</p>
<ol>
<li>Do a Match ROM</li>
<li>Send the ROM address</li>
<li>Send a Convert Temperature</li>
<li>Wait for the right amount of time</li>
<li>Send a Read Scratch Pad</li>
<li>Read 9 Bytes</li>
<li>Convert the values</li>
</ol>
<p>The Match ROM command 0x55 + the ROM code selects your device to be acted on.</p>
<p><a href="https://iotexpert.com/?attachment_id=9333" rel="attachment wp-att-9333"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM-1024x395.png" alt="" width="1024" height="395" class="alignnone size-large wp-image-9333" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM-1024x395.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM-600x232.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM-300x116.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM-768x296.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.08.51-AM.png 1166w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you send a convert T 0x44 your device will start the internal process of reading the temperature and storing it in the scratch pad.  The amount of time this take depends on what resolution you have configured.</p>
<p><a href="https://iotexpert.com/?attachment_id=9334" rel="attachment wp-att-9334"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM-1024x796.png" alt="" width="1024" height="796" class="alignnone size-large wp-image-9334" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM-1024x796.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM-600x467.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM-300x233.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM-768x597.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.14-AM.png 1196w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The scratchpad is a 9-byte register inside of the chip which contains the most recently read temperature plus some settings.</p>
<p><a href="https://iotexpert.com/?attachment_id=9337" rel="attachment wp-att-9337"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-1024x389.png" alt="" width="1024" height="389" class="alignnone size-large wp-image-9337" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-1024x389.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-600x228.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-300x114.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-768x292.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-1536x583.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.19.04-AM-2048x777.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To read the scratchpad you need to send a 0xBE, then read 9-bytes.  Notice that the 9th byte is a CRC for the first 8 bytes,  if you are concerned you can follow the CRC procedure documented in the datasheet to calculate a CRC to verify a match.  For this example, lets skip that.</p>
<p><a href="https://iotexpert.com/?attachment_id=9335" rel="attachment wp-att-9335"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM-1024x412.png" alt="" width="1024" height="412" class="alignnone size-large wp-image-9335" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM-1024x412.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM-600x242.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM-300x121.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM-768x309.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.09.22-AM.png 1182w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In order to convert the temperature you need to know the resolution.  Bit-6 and Bit-5 of the configuration register tells you this.  This is a writable register so you can change the resolution which you might do to speed up the reading time.</p>
<p><a href="https://iotexpert.com/?attachment_id=9338" rel="attachment wp-att-9338"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-1024x365.png" alt="" width="1024" height="365" class="alignnone size-large wp-image-9338" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-1024x365.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-600x214.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-300x107.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-768x273.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-1536x547.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.20.06-AM-2048x729.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is the whole code together as a new command.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_readtemp(int argc, char **argv)
{
    uint8_t scratchpad[9];
    bool result;

    // send reset
    // send match rom 0x55
    // send rom address
    // send trigger 0x44
    // delay 1 second
    // send reset
    // send match rom 0x55
    // send read scratchpad BEh
    // read 9 bytes of scratch pad

    owb_reset(&amp;bus,&amp;result);
    owb_write_byte(&amp;bus,0x55);
    owb_write_bytes(&amp;bus,rom.romAddr,8);
    owb_write_byte(&amp;bus,0x44);
    vTaskDelay(1000);
    owb_reset(&amp;bus,&amp;result);

    owb_write_byte(&amp;bus,0x55);
    owb_write_bytes(&amp;bus,rom.romAddr,8);
    owb_write_byte(&amp;bus,0xbe);
    owb_read_bytes(&amp;bus,scratchpad,9);
    printf("Scratchpad =");
    for(int i=0;i&lt;9;i++)
    {
        printf("%02X ",scratchpad[i]);
    }
    printf("\n");
 
    int16_t tempbits = scratchpad[0] | (scratchpad[1] &lt;&lt; 8);
    uint32_t resolution=2^12;
    float temperature=0.0;
    switch(scratchpad[5] &gt;&gt;5 &amp; 0x03)
    {
        case 0:
            resolution = 2^9;
            break;
        case 1:
            resolution = 2^10;
            break;
        case 2:
            resolution = 2^11;
            break;
        case 3:
            resolution = 2^12;
        break;
    }

    temperature = (float)tempbits / (float)resolution;

    printf("Temperature = %f\n",temperature);
    return 0;  

}</pre>
<p>Now I build and program the development kit to setup the test.  The first step is to read the ROM with the command line &#8220;readrom&#8221;.  Then I tell it to try to read the temperature.  You can see the values in the scratch pad, plus my conversion to celsius.  Since I am in Kentucky I probably should have done Fahrenheit &#8230; oh well. 28.35C is 83.3F my office is pretty hot today.</p>
<p><a href="https://iotexpert.com/?attachment_id=9339" rel="attachment wp-att-9339"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM-1024x609.png" alt="" width="1024" height="609" class="alignnone size-large wp-image-9339" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM-1024x609.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM-600x357.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM-300x178.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM-768x457.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-10.24.10-AM.png 1228w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-4-but-can-it-read-the-temperature/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 SDK OneWire Bus (Part 3): Remove Busy Wait &#038; Debug</title>
		<link>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/</link>
					<comments>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 29 Jun 2020 12:00:50 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9246</guid>

					<description><![CDATA[Summary In this article I will replace the stupid busy wait implementation of OneWire write and read bit with an interrupt based implementation. Story In the previous article, I implemented a OneWire bus library for PSoC 6.  Specifically, to read temperatures from the DS18B20 1-wire temperature sensor.  This implementation used the CyDelay to handle bit timing. Here [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will replace the stupid busy wait implementation of OneWire write and read bit with an interrupt based implementation.</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &amp; Write</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/29/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait &amp; Debug</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/?p=9329" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature?</a></td>
</tr>

<tr><td >PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver</td>
</tr>
</tbody></table></div></p>
<h1>Story</h1>
<p>In the previous article, I implemented a OneWire bus library for PSoC 6.  Specifically, to read temperatures from the DS18B20 1-wire temperature sensor.  This implementation used the CyDelay to handle bit timing. Here is the write bit function.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_write_bit(OneWireBus *bus,uint8_t val)
{
    owb_ret_t rval = OWB_STATUS_OK;

    cyhal_gpio_write(bus-&gt;pin,0);
    if(val == 0)
    {
        CyDelayUs(60);
        cyhal_gpio_write(bus-&gt;pin,1);
        CyDelayUs(2);
    }
    else
    {
        CyDelayUs(1);
        cyhal_gpio_write(bus-&gt;pin,1);
        CyDelayUs(60);
    }
    return rval;
}</pre>
<p>And the read bit function.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_read_bit( OneWireBus *bus, uint8_t *bit)
{
    owb_ret_t rval = OWB_STATUS_OK;

    cyhal_gpio_write(bus-&gt;pin,0);
    CyDelayUs(1);
    cyhal_gpio_write(bus-&gt;pin,1);
    CyDelayUs(5);

    *bit = cyhal_gpio_read(bus-&gt;pin);
    CyDelayUs(60);
    return rval;
}</pre>
<p>Both of these functions APPEAR to work perfectly.  Here is a write of 0xFF</p>
<p><a href="https://iotexpert.com/?attachment_id=9249" rel="attachment wp-att-9249"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00004.png" alt="" class="alignnone size-full wp-image-9249" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00004.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00004-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>However, both of these implementations are subject to fail if an interrupt from the RTOS occurs during the delay period.  You could easily end up with a delay that is too long by enough that the sensor attached to the bus won&#8217;t work.  Moreover, I have always hated busy wait loops as the processor could be doing something useful.  So let&#8217;s replace this with something better.</p>
<p>This is a late edit to the article, but as I read the documentation for the &#8220;owb&#8221; library I found this note in Dave Antliff&#8217;s documentation</p>
<p><a href="https://iotexpert.com/?attachment_id=9324" rel="attachment wp-att-9324"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-1024x71.png" alt="" class="alignnone size-large wp-image-9324" width="1024" height="71" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-1024x71.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-600x42.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-300x21.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-768x54.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-1536x107.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-5.02.43-PM-2048x143.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Im not exactly sure what a &#8220;RMT&#8221; is in the world of ESP32, but I gotta imagine that it is a hardware timer.</p>
<h1>Implement an HW Timer and Interrupt Scheme</h1>
<p>Both the read and write operation require that the master</p>
<ul>
<li>Write a 0</li>
<li>Wait for some time</li>
<li>Write a 1</li>
<li>Wait for some time (then optionally read)</li>
<li>Wait for some time end</li>
</ul>
<p>The PSoC 6 TCPWM can be used to generate accurate interrupts at specific times in the future.   This hardware is abstracted using the Cypress HAL which will let you configure</p>
<ul>
<li>The input frequency to the timer</li>
<li>The counter in the timer</li>
<li>A &#8220;compare&#8221; value to trigger an interrupt with event type CYHAL_TIMER_IRQ_CAPTURE_COMPARE</li>
<li>A &#8220;period&#8221; value to trigger an interrupt with the event type CYHAL_TIMER_IRQ_TERMINAL_COUNT</li>
</ul>
<p>If you are confused about the TCPWM hardware you are not alone, it can do a mind blowing amount of different things.  However in this simple case we have it set to</p>
<ol>
<li>Input frequency 1 Mhz (aka 1uS per count)</li>
<li>Start at 0</li>
<li>Trigger an event CYHAL_TIMER_IRQ_CAPTURE_COMPARE at the compare value</li>
<li>Tigger an event CYHAL_TIMER_IRQ_TERMINAL_COUNT at the period</li>
<li>Stop counting</li>
<li>Reset back to 0</li>
</ol>
<p>If you look the code below on lines 23-30 the configuration of the timer is set.  Remember from the data sheet that a &#8220;1&#8221; is a 1uS 0 followed by a 60uS 1 and a 0 is a 60uS 0 followed by a 1uS 1.  I use the &#8220;compare&#8221; to be the trigger from 0&#8211;&gt;1.  Notice lines 5-9 in the code below.</p>
<p>On lines 40-41 I tell the HAL that I am interested in getting an event interrupt.</p>
<p>Line 43 initiates the write with a write of 0.  Then line 45 starts the timer going.</p>
<p>To &#8220;end&#8221; the operation I use a semaphore to wait until the interrupt is triggered by the Terminal Count (aka Period).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void write_bit_event_callback(void *callback_arg, cyhal_timer_event_t event)
{
    OneWireBus *bus = (OneWireBus *)callback_arg;

    if(event &amp; CYHAL_TIMER_IRQ_CAPTURE_COMPARE)
    {
        cyhal_gpio_write(bus-&gt;pin,1);
    }
    if(event &amp; CYHAL_TIMER_IRQ_TERMINAL_COUNT)
    {
        BaseType_t xHigherPriorityTaskWoken;
        xHigherPriorityTaskWoken = pdFALSE;
        xSemaphoreGiveFromISR(bus-&gt;signalSemaphore,&amp;xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }

}

owb_ret_t owb_write_bit(OneWireBus *bus,uint8_t val)
{
    owb_ret_t rval;

    cyhal_timer_cfg_t cfgBit = {
        .is_continuous = false,
        .direction = CYHAL_TIMER_DIR_UP,
        .is_compare = true,
        .compare_value = 1,
        .period = 70,
        .value = 0,
    };

    if(val == 0)
        cfgBit.compare_value = 65;
    else
        cfgBit.compare_value = 1;
    
    cyhal_timer_configure(&amp;bus-&gt;bitTimer,&amp;cfgBit);
    cyhal_timer_reset(&amp;bus-&gt;bitTimer);

    cyhal_timer_register_callback(&amp;bus-&gt;bitTimer,write_bit_event_callback,bus);
    cyhal_timer_enable_event(&amp;bus-&gt;bitTimer,CYHAL_TIMER_IRQ_TERMINAL_COUNT|CYHAL_TIMER_IRQ_CAPTURE_COMPARE,5,true);

    cyhal_gpio_write(bus-&gt;pin,0);

    cyhal_timer_start(&amp;bus-&gt;bitTimer);
    
    BaseType_t rsem = xSemaphoreTake(bus-&gt;signalSemaphore,1); 

    if(rsem == pdTRUE)
        rval = OWB_STATUS_OK;
    else
        rval = OWB_STATUS_ERROR;

    return rval;
}</pre>
<h1>Fixing the Write Bug</h1>
<p>When I programmed this code I got some weird stuff.  Suck.  So to debug it, I put in a command line to let me &#8220;wbyte ff&#8221; (or whatever byte value).  At the top of usrcmd.c you need to declare the usrcmd_wbyte function and add it to the command table (notice that I chopped out everything around it)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_wbyte(int argc, char **argv);

static const cmd_table_t cmdlist[] = {

    { "wbyte","write byte", usrcmd_wbyte},

};</pre>
<p>Then make a function will will take an argument (the value you want to write).  Notice that the input is a 2 digit hex number.  Yes I known sscanf is dangerous (but in this case I use it only as a debugging tool.)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_wbyte(int argc, char **argv)
{
    if(argc != 2)
    {
        printf("Invalid argument write  %d\n",argc);
        return 0;
    }

    owb_ret_t ret=OWB_STATUS_OK;

    int val;
    sscanf(argv[1],"%02x",&amp;val);

    printf("Write Byte Val = %02X\n",val);

    ret = owb_write_byte(&amp;bus,(uint8_t)val);

    if(ret == OWB_STATUS_OK)
        printf("Write byte succeeded\n");
    else
        printf("Write byte failed\n");


    return 0;
}</pre>
<p>When I run the code I seem to get the write byte function working sometimes and failing sometimes.  What the hell?</p>
<p><a href="https://iotexpert.com/?attachment_id=9251" rel="attachment wp-att-9251"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM-1024x709.png" alt="" class="alignnone size-large wp-image-9251" width="1024" height="709" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM-1024x709.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM-600x415.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM-300x208.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM-768x532.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-08-at-10.43.41-AM.png 1196w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now, the pain starts.  To debug, I get out the oscilloscope and have a look.  Here is a write of 0xFF which should be 8 short 0 pulses.  But notice that only three get written.  OK, that must mean that the semaphore is timing out. How can that be?</p>
<p><a href="https://iotexpert.com/?attachment_id=9252" rel="attachment wp-att-9252"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00006.png" alt="" class="alignnone size-full wp-image-9252" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00006.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00006-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>To try to debug that I update a pin to toggle with the semaphore (and git rid of the exit case).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    cyhal_gpio_write(CYBSP_D5,1);
    BaseType_t rsem = xSemaphoreTake(bus-&gt;signalSemaphore,1); 
    cyhal_gpio_write(CYBSP_D5,0);</pre>
<p>Now I get this (on the debug pin)&#8230; notice a very short timeout&#8230; then longer ones followed by another partially shorter timeout.</p>
<p><a href="https://iotexpert.com/?attachment_id=9258" rel="attachment wp-att-9258"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00009.png" alt="" class="alignnone size-full wp-image-9258" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00009.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00009-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>The problem is the semaphore timeout is set to 1.  Should be at least 1 ms right?  Why is that a problem as 1ms is way more than the 60-ish uS you need to wait?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">BaseType_t rsem = xSemaphoreTake(bus-&gt;signalSemaphore,1);</pre>
<p>Classic off by 1 error.  The 1 means expire at the NEXT SysTick, which will happen NO MORE than 1ms from now. Change it to 2.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    BaseType_t rsem = xSemaphoreTake(bus-&gt;signalSemaphore,2); 
</pre>
<p>Now, all the bits come out at a steady rate.</p>
<p><a href="https://iotexpert.com/?attachment_id=9259" rel="attachment wp-att-9259"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00010.png" alt="" class="alignnone size-full wp-image-9259" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00010.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00010-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>And it works&#8230; sometimes&#8230;</p>
<h1>Deep Sleep</h1>
<p>Other times I end up with this picture.  Notice that the space between the start of one bit and the start of the next bit (from a-b on the scope) is 361.6 uS (don&#8217;t forget the 0.6 uS).</p>
<p><a href="https://iotexpert.com/?attachment_id=9247" rel="attachment wp-att-9247"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00003.png" alt="" class="alignnone size-full wp-image-9247" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00003.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00003-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>Why are the interrupts getting delayed?  The answer is the chip is in deep sleep (or going to deep sleep) when the interrupt from the timer happens.  And when the deep sleep is happening, it takes a bit of time to go to deep sleep, then to wake up.  To fix this go into the system configurator and change the Deep Sleep Latency.</p>
<p><a href="https://iotexpert.com/?attachment_id=9262" rel="attachment wp-att-9262"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM-1024x109.png" alt="" class="alignnone size-large wp-image-9262" width="1024" height="109" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM-1024x109.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM-600x64.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM-300x32.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM-768x82.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.25-AM.png 1348w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Change the timeout to 3</p>
<p><a href="https://iotexpert.com/?attachment_id=9261" rel="attachment wp-att-9261"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.50-AM.png" alt="" class="alignnone size-full wp-image-9261" width="996" height="152" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.50-AM.png 996w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.50-AM-600x92.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.50-AM-300x46.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-10-at-10.30.50-AM-768x117.png 768w" sizes="auto, (max-width: 996px) 100vw, 996px" /></a></p>
<p>Now it works.. here is a write of 0xFE</p>
<p><a href="https://iotexpert.com/?attachment_id=9255" rel="attachment wp-att-9255"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00008.png" alt="" class="alignnone size-full wp-image-9255" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00008.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00008-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<h1>Implement the Read Bit</h1>
<p>Now that the write bit is working, move the read bit function to the same scheme.  Notice that I use the compare to trigger the read of the pin.  In the read code I probably should have done a critical section from the start of the 0 to the start of the timer so that an interrupt doesn&#8217;t occur before the timer gets started.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">void read_bit_event_callback(void *callback_arg, cyhal_timer_event_t event)
{
    OneWireBus *bus = (OneWireBus *)callback_arg;

    if(event &amp; CYHAL_TIMER_IRQ_CAPTURE_COMPARE)
    {
        bus-&gt;scratchBitValue = cyhal_gpio_read(bus-&gt;pin);
    }
    if(event &amp; CYHAL_TIMER_IRQ_TERMINAL_COUNT)
    {
        BaseType_t xHigherPriorityTaskWoken;
        xHigherPriorityTaskWoken = pdFALSE;
        xSemaphoreGiveFromISR(bus-&gt;signalSemaphore,&amp;xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }

}


owb_ret_t owb_read_bit( OneWireBus *bus, uint8_t *bit)
{
    owb_ret_t rval;

    cyhal_timer_cfg_t cfgBit = {
        .is_continuous = false,
        .direction = CYHAL_TIMER_DIR_UP,
        .is_compare = true,
        .compare_value = 10,
        .period = 61,
        .value = 0
    };

    cyhal_timer_configure(&amp;bus-&gt;bitTimer,&amp;cfgBit);

    cyhal_timer_register_callback(&amp;bus-&gt;bitTimer,read_bit_event_callback,bus);
    cyhal_timer_enable_event(&amp;bus-&gt;bitTimer,CYHAL_TIMER_IRQ_TERMINAL_COUNT|CYHAL_TIMER_IRQ_CAPTURE_COMPARE,5,true);

    // Pull a 0
    cyhal_gpio_write(bus-&gt;pin,0);
    CyDelayUs(1);
    cyhal_gpio_write(bus-&gt;pin,1);

    cyhal_timer_reset(&amp;bus-&gt;bitTimer);
    cyhal_timer_start(&amp;bus-&gt;bitTimer);

    BaseType_t rsem = xSemaphoreTake(bus-&gt;signalSemaphore,2); // Then entire write cycle is 61uS so 2ms would be a major failure
    *bit = bus-&gt;scratchBitValue;

    if(rsem == pdTRUE)
        rval = OWB_STATUS_OK;
    else
        rval = OWB_STATUS_ERROR;

    return rval;
}</pre>
<p>In fact as I look at this code, I decide that I had better to fix the critical section.  Here is the updated read code.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    void taskENTER_CRITICAL();

    cyhal_gpio_write(bus-&gt;pin,0);     // Pull a 0
    CyDelayUs(1);
    cyhal_gpio_write(bus-&gt;pin,1);

    cyhal_timer_start(&amp;bus-&gt;bitTimer);
    void taskEXIT_CRITICAL( );</pre>
<p>And the updated write code</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    taskENTER_CRITICAL();
    cyhal_gpio_write(bus-&gt;pin,0);

    cyhal_timer_start(&amp;bus-&gt;bitTimer);
    taskEXIT_CRITICAL();</pre>
<p>In the next article I&#8217;ll show you code to actually read the temperature.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &#038; Write</title>
		<link>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-2-implement-read-write/</link>
					<comments>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-2-implement-read-write/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 22 Jun 2020 09:42:35 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9300</guid>

					<description><![CDATA[Summary In this article I will explain how to implement (badly) the one wire bus read &#38; write functions using the PSoC 6 SDK.  This is one of many articles that are part of a series discussing the implementation: Story In the previous article, I built a test framework inside of a PSoC 6 FreeRTOS [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will explain how to implement (badly) the one wire bus read &amp; write functions using the PSoC 6 SDK.  This is one of many articles that are part of a series discussing the implementation:</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &amp; Write</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/29/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait &amp; Debug</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/?p=9329" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature?</a></td>
</tr>

<tr><td >PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver</td>
</tr>
</tbody></table></div></p>
<h1>Story</h1>
<p>In the <a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener noreferrer">previous article</a>, I built a test framework inside of a PSoC 6 FreeRTOS project.  This includes a command line shell which will enable me to execute functions based on typed commands.  This means I can use the CLI shell to debug my interface.  To get going testing, I bought a DS18B20 temperature sensor from Mouser.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/img_1944/" rel="attachment wp-att-9353"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-1024x907.jpg" alt="" class="alignnone size-large wp-image-9353" width="1024" height="907" srcset="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-1024x907.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-scaled-600x531.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-300x266.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-768x680.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-1536x1360.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1944-2048x1814.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then wired it like this:</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-53-00-pm/" rel="attachment wp-att-9318"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM-1024x540.png" alt="" class="alignnone size-large wp-image-9318" width="1024" height="540" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM-1024x540.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM-600x316.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM-300x158.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM-768x405.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.53.00-PM.png 1526w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is a picture of the test jig.  It looks like I used 4200 ohms instead of 4400 ohms, oh well it seems to work.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/img_1942/" rel="attachment wp-att-9302"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-916x1024.jpg" alt="" class="alignnone size-large wp-image-9302" width="916" height="1024" srcset="https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-916x1024.jpg 916w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-scaled-600x670.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-268x300.jpg 268w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-768x858.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-1375x1536.jpg 1375w, https://iotexpert.com/wp-content/uploads/2020/06/IMG_1942-1833x2048.jpg 1833w" sizes="auto, (max-width: 916px) 100vw, 916px" /></a></p>
<h1>Init</h1>
<p>Init seems like a good place to start.  To have a one wire bus you need to have a GPIO to read/drive.  So, that will be the only argument to the initialization function.  In the implementation I will use a common semaphore to handle blocking functions (line 13).  On lines 15-17 I initialize a timer to handle the requirements of reset, read and writes (more on this later).  At the end on line 20 I initialize the GPIO.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "owb.h"
#include &lt;stdint.h&gt;
#include "cyhal.h"
#include "cybsp.h"
#include "task.h"
#include &lt;stdbool.h&gt;
#include &lt;stdio.h&gt;

owb_ret_t owb_init(OneWireBus *bus)
{
    cy_rslt_t rslt;

    bus-&gt;signalSemaphore = xSemaphoreCreateBinary();

    rslt = cyhal_timer_init(&amp;bus-&gt;bitTimer,NC,0);
    CY_ASSERT(rslt == CY_RSLT_SUCCESS);
    rslt = cyhal_timer_set_frequency(&amp;bus-&gt;bitTimer,1000000);
    
    CY_ASSERT(rslt == CY_RSLT_SUCCESS);
    rslt = cyhal_gpio_init(bus-&gt;pin,CYHAL_GPIO_DIR_BIDIRECTIONAL,CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW,true);
    CY_ASSERT(rslt == CY_RSLT_SUCCESS);
    return OWB_STATUS_OK;    
}</pre>
<p>In the usrcmd.c I need to add includes for the new stuff.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#include "cybsp.h"
#include "owb.h"</pre>
<p>The next step is to add the &#8220;init&#8221; command to usrcmd.c  This is accomplished by adding a function header for usrcmd_init and adding it to the table of legal commands.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_init(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 },
    { "printargs","print the list of arguments", usrcmd_printargs},
    { "init","Initialize the 1-wire bus", usrcmd_init},

};</pre>
<p>Then you need to add the usrcmd_init function to call the owb init.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static OneWireBus bus;
static int usrcmd_init(int argc, char **argv)
{
    bus.pin = CYBSP_D4;
    owb_init(&amp;bus);
    printf("Initialized D4\n");

    return 0;
}
</pre>
<p>Now test it.  All good.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-14-07-pm/" rel="attachment wp-att-9309"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM-1024x729.png" alt="" class="alignnone size-large wp-image-9309" width="1024" height="729" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM-1024x729.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM-600x427.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM-300x214.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM-768x547.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.14.07-PM.png 1432w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Reset</h1>
<p>In order to reset the bus you follow this process</p>
<ol>
<li>Pull down the bus for trstl=480uS</li>
<li>Let the bus go back to 1 (remember that it is restive pull-up)</li>
<li>Wait another trsth=480uS</li>
<li>If there is a slave device on the bus it will pull down the bus at some point to indicate a &#8220;presence detect&#8221;</li>
</ol>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-12-20-55-pm/" rel="attachment wp-att-9303"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-1024x408.png" alt="" class="alignnone size-large wp-image-9303" width="1024" height="408" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-1024x408.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-600x239.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-300x120.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-768x306.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-1536x612.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.20.55-PM-2048x816.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>From the data sheet you can see that the low&amp; high times = 480uS.  At some point during the high period the slave will pull the bus down for 15-&gt;60uS</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-12-22-03-pm/" rel="attachment wp-att-9304"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-1024x154.png" alt="" class="alignnone size-large wp-image-9304" width="1024" height="154" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-1024x154.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-600x90.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-300x45.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-768x116.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-1536x231.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.22.03-PM-2048x309.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In order to implement the reset I will modify the owb.c file.  To meet the timing requirements I will use a cyhal_timer.  The cyhal_timer is implemented in the Cypress PDL at a Cy_TCPWM_Timer which is then implemented in the hardware as a timer counter.  In this configuration the timer has:</p>
<ul>
<li>A Counter (an up or down counter)</li>
<li>A Compare (a register which can be compared with the counter to trigger events)</li>
<li>A Period (a register which is compared to the counter to reset the counter back to 0).   This event is also called the &#8220;terminal count&#8221;</li>
</ul>
<p>For this implementation I will setup a timer with</p>
<ol>
<li>Input clock 1Mz (aka 1uS per count)</li>
<li>An up counter</li>
<li>Starts at 0</li>
<li>Compare value = 480 (means trigger an interrupt at 480uS)</li>
<li>Period = 960 (means trigger an interrupt at 480uS)</li>
<li>One shot (stop counting when you get to period (aka Terminal Count))</li>
</ol>
<p>The code will</p>
<ol>
<li>Configure the timer (line 41-52)</li>
<li>Pull a 0 onto the bus (line 54)</li>
<li>Start the timer (line 56)</li>
<li>At the compare value 480uS reset the bus to 1 using the event handler (line 20) and setup the GPIO trigger a fall event interrupt (line 21-22)</li>
<li>At the period release the semaphore (27-30)</li>
<li>After the compare value if the GPIO pulls down, use the GPIO interrupt to record the presence of a device (line 10)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reset
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void reset_gpio_event_callback(void *callback_arg, cyhal_gpio_event_t event)
{
    OneWireBus *bus = (OneWireBus *)callback_arg;

    if(event &amp; CYHAL_GPIO_IRQ_FALL)
    {
        bus-&gt;detect = true;
    }
}

static void reset_timer_event_callback(void *callback_arg, cyhal_timer_event_t event)
{
    OneWireBus *bus = (OneWireBus *)callback_arg;

    if(event &amp; CYHAL_TIMER_IRQ_CAPTURE_COMPARE)
    {
        cyhal_gpio_write(bus-&gt;pin,1);
        cyhal_gpio_register_callback(bus-&gt;pin, reset_gpio_event_callback,(void *)bus);
        cyhal_gpio_enable_event(bus-&gt;pin,CYHAL_GPIO_IRQ_FALL,5,true);
    }
    if(event &amp; CYHAL_TIMER_IRQ_TERMINAL_COUNT)
    {

        BaseType_t xHigherPriorityTaskWoken;
        xHigherPriorityTaskWoken = pdFALSE;
        xSemaphoreGiveFromISR(bus-&gt;signalSemaphore,&amp;xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }
 
}

owb_ret_t owb_reset(OneWireBus *bus, bool *result)
{
    owb_ret_t rval = OWB_STATUS_OK;

    bus-&gt;detect = false;

    cyhal_timer_cfg_t cfgBit = {
        .is_continuous = false,
        .direction = CYHAL_TIMER_DIR_UP,
        .is_compare = true,
        .compare_value = 480,
        .period = 960,
        .value = 0
    };
    cyhal_timer_configure(&amp;bus-&gt;bitTimer,&amp;cfgBit);
    cyhal_timer_reset(&amp;bus-&gt;bitTimer);
    cyhal_timer_register_callback(&amp;bus-&gt;bitTimer,reset_timer_event_callback,bus); 
    cyhal_timer_enable_event(&amp;bus-&gt;bitTimer,CYHAL_TIMER_IRQ_ALL,5,true);

    cyhal_gpio_write(bus-&gt;pin,0);

    cyhal_timer_start(&amp;bus-&gt;bitTimer);

    xSemaphoreTake(bus-&gt;signalSemaphore,2); // worst case is really 960uS
    cyhal_gpio_enable_event(bus-&gt;pin,CYHAL_GPIO_IRQ_FALL,5,true);
    return rval;
}</pre>
<p>Once I have the owb_init code I add the init command to usrcmd.c.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_reset(int argc, char **argv)
{
    bool result;
    owb_reset(&amp;bus,&amp;result);
    if(bus.detect)
    {
        printf("Reset Succeeded\n");

    }
    else

        printf("Reset Failed\n");

    return 0;
}</pre>
<p>When I run it, I get this nice picture from the oscilliscope.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/tek00012/" rel="attachment wp-att-9308"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00012.png" alt="" class="alignnone size-full wp-image-9308" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00012.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00012-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<h1>Write</h1>
<p>In the ds18b20.c file I see that the author has three functions of interest.  In the implementation owb_write_bytes will call owb_write byte and owb_write_byte will call owb_write bit.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_write_bit( OneWireBus *bus, uint8_t val);
owb_ret_t owb_write_byte( OneWireBus *bus, uint8_t val);
owb_ret_t owb_write_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t length);
</pre>
<p>The one wire protocol has the following steps.</p>
<p>In order to write a &#8220;0&#8221; you need to</p>
<ol>
<li>Pull down the bus (write a 0)</li>
<li>Wait 60uS</li>
<li>Write a 1</li>
<li>Wait 1uS (to allow the next &#8220;slot&#8221; to start</li>
</ol>
<p>In order to write a &#8220;1&#8221; you need to</p>
<ol>
<li>Pull down the bus (write a 0)</li>
<li>Wait 1 uS</li>
<li>Write a 1</li>
<li>Wait 60uS (to allow the next &#8220;slot&#8221; to start)</li>
</ol>
<p>Notice that the minimum write slot is 60uS and the maximum is 120uS.  Here is a picture from the data sheet.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-20-16-pm/" rel="attachment wp-att-9310"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-1024x349.png" alt="" class="alignnone size-large wp-image-9310" width="1024" height="349" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-1024x349.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-600x204.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-300x102.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-768x261.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-1536x523.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.20.16-PM-2048x697.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>For the first implementation of owb_write_bit I will use a simple &#8220;CyDelayUs&#8221;  to implement the delays (this is a bad idea, but is a &#8216;cheap&#8217; way to get going).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_write_bit(OneWireBus *bus,uint8_t val)
{
    owb_ret_t rval = OWB_STATUS_OK;
    cyhal_gpio_write(bus-&gt;pin,0);
    if(val == 0)
    {
        CyDelayUs(60);
        cyhal_gpio_write(bus-&gt;pin,1);
        CyDelayUs(2);

    }
    else
    {
        CyDelayUs(1);
        cyhal_gpio_write(bus-&gt;pin,1);
        CyDelayUs(60);
    }
    return rval;
}</pre>
<p>The write byte function just loops through the 8-bit and uses the owb_write_bit function.  Notice that it is least significant bit first.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_write_byte( OneWireBus *bus, uint8_t val)
{
    owb_ret_t ret = OWB_STATUS_OK;
    for(int i=0;i&lt;8;i++)
    {
        ret = owb_write_bit(bus,(val&gt;&gt;i) &amp; 0x01);
        if(ret != OWB_STATUS_OK)
            return ret;        
    }
    return OWB_STATUS_OK;
}</pre>
<p>And write_bytes (multiple) just loops through the buffer calling the write_byte function.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_write_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t length)
{
    owb_ret_t ret = OWB_STATUS_OK;
    for(int i=0;i&lt;length;i++)
    {
        ret = owb_write_byte(bus,buffer[i]);
        if(ret != OWB_STATUS_OK)
            return ret;
    }
    return OWB_STATUS_OK;
}</pre>
<p>Now that I have the three write functions I will add a new command to usrcmd.c  This function lets the user type a command like &#8220;wbyte a1&#8221; where he/she can input a 2-character hex command.  Yes, I use the sscanf function which is unsafe&#8230; but cheap for a test rig.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_wbyte(int argc, char **argv)
{
    if(argc != 2)
    {
        printf("Invalid argument write  %d\n",argc);
        return 0;
    }

    owb_ret_t ret=OWB_STATUS_OK;

    int val;
    sscanf(argv[1],"%02x",&amp;val);

    printf("Write Byte Val = %02X\n",val);

    ret = owb_write_byte(&amp;bus,(uint8_t)val);

    if(ret == OWB_STATUS_OK)
        printf("Write byte succeeded\n");
    else
        printf("Write byte failed\n");


    return 0;
}</pre>
<p>When I program and launch the project I end up here.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-32-57-pm/" rel="attachment wp-att-9311"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-1024x665.png" alt="" class="alignnone size-large wp-image-9311" width="1024" height="665" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-1024x665.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-600x390.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-300x195.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-768x499.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-1536x997.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.32.57-PM-2048x1330.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>OK that is easy enough to fix, I just ran out of stack in the ntshell thread.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    xTaskCreate(ntShellTask, "nt shell task", configMINIMAL_STACK_SIZE*3,0 /* args */ ,0 /* priority */, 0);</pre>
<p>Now when I run it I am off to the races.</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-33-51-pm/" rel="attachment wp-att-9313"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM-1024x432.png" alt="" class="alignnone size-large wp-image-9313" width="1024" height="432" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM-1024x432.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM-600x253.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM-300x127.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM-768x324.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.33.51-PM.png 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Here is an example of &#8220;wbyte ff&#8221;</p>
<p><a href="https://iotexpert.com/?attachment_id=9249" rel="attachment wp-att-9249"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00004.png" alt="" class="alignnone size-full wp-image-9249" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00004.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00004-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>What about &#8220;owb_write_rom_code&#8221;?  I don&#8217;t know what it does, but Ill figure it out as I integrate the rest of the library.</p>
<h1>Read</h1>
<p>When I examine the ds18b20.c file I find these three read functions, which mirror the write functions.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_read_bit( OneWireBus *bus, uint8_t *bit);
owb_ret_t owb_read_byte( OneWireBus *bus, uint8_t *byte);
owb_ret_t owb_read_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t length);</pre>
<p>To read a bit you follow a a very similar process to the write.</p>
<ol>
<li>Write a 0 on the bus</li>
<li>Wait 1uS</li>
<li>Write a 1 on the bus (release the bus)</li>
<li>Wait 5uS</li>
<li>Read (the slave will pull a 0 or a 1 onto the bus)</li>
<li>Wait 55uS to the end of the slot</li>
</ol>
<p>Here is a picture</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-12-at-3-15-01-pm/" rel="attachment wp-att-9360"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-1024x390.png" alt="" class="alignnone size-large wp-image-9360" width="1024" height="390" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-1024x390.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-600x228.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-300x114.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-768x292.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-1536x585.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-12-at-3.15.01-PM-2048x780.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The code uses a really bad busy-wait delay (but it is a good starting place to figure out what is happening)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_read_bit( OneWireBus *bus, uint8_t *bit)
{
    owb_ret_t rval = OWB_STATUS_OK;

    cyhal_gpio_write(bus-&gt;pin,0);
    CyDelayUs(1);
    cyhal_gpio_write(bus-&gt;pin,1);
    CyDelayUs(5);

    *bit = cyhal_gpio_read(bus-&gt;pin);
    CyDelayUs(55);
    return rval;
}</pre>
<p>To read a byte, just read 8 bits using the owb_read_bit function</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">owb_ret_t owb_read_byte( OneWireBus *bus, uint8_t *byte)
{
    uint8_t bit;
    owb_ret_t ret = OWB_STATUS_OK;

    *byte = 0;
    for(int i=0;i&lt;8;i++)
    {
        ret = owb_read_bit(bus,&amp;bit);
        if(ret != OWB_STATUS_OK)
            return ret;
        *byte = *byte | (bit&lt;&lt;i);
    }
    return OWB_STATUS_OK;
}
</pre>
<p>To read an array of bytes, use a loop of read_byte</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">owb_ret_t owb_read_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t count)
{
    owb_ret_t ret = OWB_STATUS_OK;
    for(int i=0;i&lt;count;i++)
    {
        ret = owb_read_byte(bus,&amp;buffer[i]);
        if(ret != OWB_STATUS_OK)
            return ret;       
    }
    return ret;
}</pre>
<p>Now that you have a read and a write, update the usrcmd.c to add a &#8220;rbyte&#8221; command to the CLI</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_rbyte(int argc, char **argv)
{

    owb_ret_t ret=OWB_STATUS_OK;

    uint8_t val;
 
    ret = owb_read_byte(&amp;bus,&amp;val);

    if(ret == OWB_STATUS_OK)
        printf("Read byte succeeded %02x\n",val);
    else
        printf("Read byte failed\n");


    return 0;
}</pre>
<p>When I program the kit I can send a 0x33 (which will make the sensor respond more on this later), then read the first byte of the ROM</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/screen-shot-2020-06-11-at-4-47-45-pm/" rel="attachment wp-att-9315"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM-1024x520.png" alt="" class="alignnone size-large wp-image-9315" width="1024" height="520" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM-1024x520.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM-600x305.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM-300x152.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM-768x390.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-4.47.45-PM.png 1430w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When you look at the scope picture (from right to left) you can see 10110110 which sure enough is B6.  The thin gaps are 1&#8217;s and the wide gaps are 0&#8217;s</p>
<p><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/tek00013/" rel="attachment wp-att-9316"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/TEK00013.png" alt="" class="alignnone size-full wp-image-9316" width="480" height="234" srcset="https://iotexpert.com/wp-content/uploads/2020/06/TEK00013.png 480w, https://iotexpert.com/wp-content/uploads/2020/06/TEK00013-300x146.png 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a></p>
<p>In the next article Ill deal with the stupid CyDelay&#8217;s</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-2-implement-read-write/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</title>
		<link>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-1-build-basic-project/</link>
					<comments>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-1-build-basic-project/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 15 Jun 2020 12:00:28 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=9269</guid>

					<description><![CDATA[Summary This is the first article in a series about my journey implementing PSoC 6 SDK libraries for the Maxxim One Wire Bus and the DS18B20 temperature sensor. As you can see there will be many parts to this story: Story I recently got a twitter message from a gentleman named &#8220;Neeraj Dhekale&#8221;.  He asked [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This is the first article in a series about my journey implementing PSoC 6 SDK libraries for the Maxxim One Wire Bus and the DS18B20 temperature sensor.</p>
<p>As you can see there will be many parts to this story:</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/2020/06/15/psoc-6-sdk-onewire-bus-part-1-build-basic-project/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/22/psoc-6-sdk-onewire-bus-part-2-implement-read-write/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 2) : Implement Read &amp; Write</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/2020/06/29/psoc-6-sdk-onewire-bus-part-3-remove-busy-wait-debug/" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait &amp; Debug</a></td>
</tr>

<tr><td ><a href="https://iotexpert.com/?p=9329" target="_blank" rel="noopener">PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature?</a></td>
</tr>

<tr><td >PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver</td>
</tr>
</tbody></table></div></p>
<h1>Story</h1>
<p>I recently got a twitter message from a gentleman named &#8220;Neeraj Dhekale&#8221;.  He asked about a library for a one wire sensor for PSoC, actually to be specific he asked about a component for a PSoC 4.</p>
<p><a href="https://iotexpert.com/?attachment_id=9272" rel="attachment wp-att-9272"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM-1024x255.png" alt="" width="1024" height="255" class="alignnone size-large wp-image-9272" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM-1024x255.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM-600x149.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM-300x75.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM-768x191.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.17.25-AM.png 1230w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then I asked him what sensor and responded that he wanted to use the <a href="https://www.mouser.com/datasheet/2/256/DS18B20-370043.pdf" target="_blank" rel="noopener noreferrer">Maxxim DS18B20</a> temperature sensor.</p>
<p><a href="https://iotexpert.com/?attachment_id=9274" rel="attachment wp-att-9274"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM-1024x193.png" alt="" width="1024" height="193" class="alignnone size-large wp-image-9274" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM-1024x193.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM-600x113.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM-300x57.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM-768x145.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.24.33-AM.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This sensor is a one wire temperature sensor, here is a bit of snapshot from the data sheet.</p>
<p><a href="https://iotexpert.com/?attachment_id=9275" rel="attachment wp-att-9275"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-1024x632.png" alt="" width="1024" height="632" class="alignnone size-large wp-image-9275" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-1024x632.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-600x370.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-300x185.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-768x474.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-1536x948.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.47.17-AM-2048x1264.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After reading the data sheet I decided that I really didn&#8217;t want to implement a complete library for this sensor.  So, I started looking around for a driver library.  After googling around a little bit I found a library on GitHub (https://github.com/DavidAntliff/esp32-ds18b20) which looked promising, even though it is ESP32 specific.</p>
<p><a href="https://iotexpert.com/?attachment_id=9273" rel="attachment wp-att-9273"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-1010x1024.png" alt="" width="1010" height="1024" class="alignnone size-large wp-image-9273" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-1010x1024.png 1010w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-100x100.png 100w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-600x608.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-296x300.png 296w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-768x779.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM-1515x1536.png 1515w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-10.39.50-AM.png 1716w" sizes="auto, (max-width: 1010px) 100vw, 1010px" /></a></p>
<p>But, after looking at this GitHub library a bit, I decide to start from there.</p>
<p>Before I get started two comments.</p>
<ol>
<li>He asked for PSoC 4 &#8230; but I am going to do PSoC 6 (because I can use Modus Toolbox).  There is no reason why this wouldn&#8217;t work on PSoC 4 &#8211; but it would take a bit of work</li>
<li>I can&#8217;t think of a good reason to use 1-wire, it sure seems like I2C would be simpler</li>
</ol>
<h1>Build a Base Project</h1>
<p>I start this whole effort by creating a new project for the CY8CKIT-062S2-43012 (because that happens to be the kit on my desk at the moment)</p>
<p><a href="https://iotexpert.com/?attachment_id=9279" rel="attachment wp-att-9279"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-1024x773.png" alt="" width="1024" height="773" class="alignnone size-large wp-image-9279" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-1024x773.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-600x453.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-300x226.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-768x580.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM-1536x1160.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.06-AM.png 1820w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I will use the IoT Expert FreeRTOS Template project</p>
<p><a href="https://iotexpert.com/?attachment_id=9280" rel="attachment wp-att-9280"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-1024x772.png" alt="" width="1024" height="772" class="alignnone size-large wp-image-9280" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-1024x772.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-600x452.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-300x226.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-768x579.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM-1536x1157.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.24.38-AM.png 1826w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>For debugging this whole thing I will use a command line shell.  To get this into the project I add the ntshell library. Run &#8220;make modlibs&#8221; to start the library manager.</p>
<p><a href="https://iotexpert.com/?attachment_id=9282" rel="attachment wp-att-9282"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM-1024x645.png" alt="" width="1024" height="645" class="alignnone size-large wp-image-9282" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM-1024x645.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM-600x378.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM-300x189.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM-768x483.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.27.43-AM.png 1166w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the library manager pick the &#8220;ntshell&#8221; library</p>
<p><a href="https://iotexpert.com/?attachment_id=9281" rel="attachment wp-att-9281"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-1024x789.png" alt="" width="1024" height="789" class="alignnone size-large wp-image-9281" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-1024x789.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-600x462.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-300x231.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-768x592.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-1536x1183.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.26.37-AM-2048x1578.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To develop this project I want to use Visual Studio code.  So, I run &#8220;make vscode&#8221; (to create the configuration files) and start vscode by running &#8220;code .&#8221;</p>
<p><a href="https://iotexpert.com/?attachment_id=9283" rel="attachment wp-att-9283"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM-882x1024.png" alt="" width="882" height="1024" class="alignnone size-large wp-image-9283" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM-882x1024.png 882w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM-600x697.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM-258x300.png 258w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM-768x892.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.29.46-AM.png 1164w" sizes="auto, (max-width: 882px) 100vw, 882px" /></a></p>
<p>When VSCODE starts up it looks like this:</p>
<p><a href="https://iotexpert.com/?attachment_id=9284" rel="attachment wp-att-9284"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-1024x769.png" alt="" width="1024" height="769" class="alignnone size-large wp-image-9284" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-1024x769.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-600x450.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-300x225.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-768x577.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM-1536x1153.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.30.58-AM.png 2046w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In order to use the ntshell library you need to shuffle the files around a little bit.  Move the ntshell.h/.c into the main project by doing a drag/drop in the explorer window.</p>
<p><a href="https://iotexpert.com/?attachment_id=9285" rel="attachment wp-att-9285"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM-574x1024.png" alt="" width="574" height="1024" class="alignnone size-large wp-image-9285" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM-574x1024.png 574w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM-600x1071.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM-168x300.png 168w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM-768x1370.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.11-AM.png 834w" sizes="auto, (max-width: 574px) 100vw, 574px" /></a></p>
<p>It will ask you really want to move the files</p>
<p><a href="https://iotexpert.com/?attachment_id=9286" rel="attachment wp-att-9286"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM-1001x1024.png" alt="" width="1001" height="1024" class="alignnone size-large wp-image-9286" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM-1001x1024.png 1001w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM-600x614.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM-293x300.png 293w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM-768x785.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.33-AM.png 1498w" sizes="auto, (max-width: 1001px) 100vw, 1001px" /></a></p>
<p>Once it is done, the ntshell functions which you need to customize will be part of the project.</p>
<p><a href="https://iotexpert.com/?attachment_id=9287" rel="attachment wp-att-9287"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-567x1024.png" alt="" width="567" height="1024" class="alignnone size-large wp-image-9287" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-567x1024.png 567w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-600x1083.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-166x300.png 166w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-768x1386.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM-851x1536.png 851w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.37.51-AM.png 852w" sizes="auto, (max-width: 567px) 100vw, 567px" /></a></p>
<p>To use the ntshell, you need to add the task to main.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cy_pdl.h"
#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include &lt;stdio.h&gt;
#include "FreeRTOS.h"
#include "task.h"

#include "ntshell.h"
#include "ntlibc.h"
#include "psoc6_ntshell_port.h"

// Global variable with a handle to the shell
ntshell_t ntshell;

void ntShellTask()
{

  printf("Started ntshell\n");
  setvbuf(stdin, NULL, _IONBF, 0);
  ntshell_init(
	       &amp;ntshell,
	       ntshell_read,
	       ntshell_write,
	       ntshell_callback,
	       (void *)&amp;ntshell);
  ntshell_set_prompt(&amp;ntshell, "DS18B20&gt; ");
  vtsend_erase_display(&amp;ntshell.vtsend);
  ntshell_execute(&amp;ntshell);
}
</pre>
<p>And start the task</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    xTaskCreate(ntShellTask, "nt shell task", configMINIMAL_STACK_SIZE*2,0 /* args */ ,0 /* priority */, 0);</pre>
<p>Build and compile</p>
<p><a href="https://iotexpert.com/?attachment_id=9288" rel="attachment wp-att-9288"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM-1024x344.png" alt="" width="1024" height="344" class="alignnone size-large wp-image-9288" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM-1024x344.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM-600x201.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM-300x101.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM-768x258.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.44-AM.png 1240w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And you should have a working project.</p>
<p><a href="https://iotexpert.com/?attachment_id=9289" rel="attachment wp-att-9289"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM-1024x585.png" alt="" width="1024" height="585" class="alignnone size-large wp-image-9289" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM-1024x585.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM-600x343.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM-300x171.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM-768x438.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.44.52-AM.png 1198w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Run &#8220;make program&#8221; to get the board going</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">arh (master *) OWB_DS18B20 $ make program
Tools Directory: /Applications/ModusToolbox/tools_2.1

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.1

Initializing build: mtb-example-psoc6-empty-app Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 202 .c file(s)
-&gt; Found 50 .S file(s)
-&gt; Found 27 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 4 .a file(s)
-&gt; Found 450 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Building 181 file(s)
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  5972       | 
  | .text                |  0x10002000   |  49532      | 
  | .ARM.exidx           |  0x1000e17c   |  8          | 
  | .copy.table          |  0x1000e184   |  24         | 
  | .zero.table          |  0x1000e19c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  985176     | 
  | .heap                |  0x080f3270   |  46480      | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           59468      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized)            1033500    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-3.0.0.665 (2020-03-20-17:12)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 6485 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.11.159
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Warn : *******************************************************************************************
Warn : * KitProg firmware is out of date, please update to the latest version using fw-loader at *
Warn : * ModusToolbox/tools/fw-loader                                                            *
Warn : *******************************************************************************************
Info : VTarget = 3.263 V
Info : kitprog3: acquiring PSoC device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
Info : psoc6.cpu.cm0: external reset detected
***************************************
** Silicon: 0xE402, Family: 0x102, Rev.: 0x11 (A0)
** Detected Device: CY8C624ABZI-S2D44A0
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.45
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : psoc6.cpu.cm4: external reset detected
Info : Listening on port 3333 for gdb connections
Info : Listening on port 3334 for gdb connections
Info : kitprog3: acquiring PSoC device...
target halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x10001754, next section at 0x10002000
Info : Padding image section 0 at 0x10001754 with 172 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x1000e844 with 444 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 57856 bytes from file /Users/arh/proj/xxx/OWB_DS18B20/build/CY8CKIT-062S2-43012/Debug/mtb-example-psoc6-empty-app.hex in 2.294771s (24.621 KiB/s)
** Programming Finished **
** Verify Started **
verified 57240 bytes in 0.155447s (359.598 KiB/s)
** Verified OK **
** Resetting Target **
shutdown command invoked

arh (master *) OWB_DS18B20 $</pre>
<p>And you should have a working project (with a blinking led and a command line)</p>
<p><a href="https://iotexpert.com/?attachment_id=9291" rel="attachment wp-att-9291"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM-1024x494.png" alt="" width="1024" height="494" class="alignnone size-large wp-image-9291" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM-1024x494.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM-600x289.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM-300x145.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM-768x370.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.47.30-AM.png 1112w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Add the DS18B20 Library</h1>
<p>Now that I have a working project the next step is to clone the DS18B20 library into my project.  This is done using</p>
<ul>
<li>git clone https://github.com/DavidAntliff/esp32-ds18b20</li>
</ul>
<p><a href="https://iotexpert.com/?attachment_id=9293" rel="attachment wp-att-9293"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM-1024x216.png" alt="" width="1024" height="216" class="alignnone size-large wp-image-9293" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM-1024x216.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM-600x126.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM-300x63.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM-768x162.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.53.38-AM.png 1434w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next step is to establish how bad things are with the new library.  So run the compiler.</p>
<p><a href="https://iotexpert.com/?attachment_id=9294" rel="attachment wp-att-9294"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM-1024x480.png" alt="" width="1024" height="480" class="alignnone size-large wp-image-9294" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM-1024x480.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM-600x281.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM-300x141.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM-768x360.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-11.55.48-AM.png 1170w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I look at the ds18b20.c file I can see that there are some obvious problems</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_log.h"

#include "ds18b20.h"
#include "owb.h"</pre>
<p>Fix those:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "FreeRTOS.h"
#include "task.h"
//#include "driver/gpio.h"
//#include "esp_system.h"
//#include "esp_log.h"

#include "ds18b20.h"
//#include "owb.h"</pre>
<p>Run the compiler again.  Now I am missing owb.h which is the public header file for the one wire bus.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">In file included from esp32-ds18b20/ds18b20.c:47:0:
./esp32-ds18b20/include/ds18b20.h:37:10: fatal error: owb.h: No such file or directory
 #include "owb.h"</pre>
<p>I now make a directory to hold the new owb files called &#8220;p6sdk-onewire&#8221;.  Then I add a file &#8220;owb.h&#8221; (as a blank file)</p>
<p><a href="https://iotexpert.com/?attachment_id=9296" rel="attachment wp-att-9296"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.00.49-PM-530x1024.png" alt="" width="530" height="1024" class="alignnone size-large wp-image-9296" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.00.49-PM-530x1024.png 530w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.00.49-PM-600x1159.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.00.49-PM-155x300.png 155w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.00.49-PM.png 736w" sizes="auto, (max-width: 530px) 100vw, 530px" /></a></p>
<p>When I run the compiler again, there are now two classes or error &#8230; owb and esp32 logging function. Here is an example of the ESP_ problems.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">esp32-ds18b20/ds18b20.c:249:17: warning: implicit declaration of function 'ESP_LOG_BUFFER_HEX_LEVEL' [-Wimplicit-function-declaration]
                 ESP_LOG_BUFFER_HEX_LEVEL(TAG, scratchpad, count, ESP_LOG_DEBUG);
                 ^~~~~~~~~~~~~~~~~~~~~~~~
esp32-ds18b20/ds18b20.c:249:66: error: 'ESP_LOG_DEBUG' undeclared (first use in this function)
                 ESP_LOG_BUFFER_HEX_LEVEL(TAG, scratchpad, count, ESP_LOG_DEBUG);</pre>
<p>And here is an example of the owb problems.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">esp32-ds18b20/ds18b20.c: In function 'ds18b20_wait_for_conversion':
esp32-ds18b20/ds18b20.c:504:30: error: request for member 'use_parasitic_power' in something not a structure or union
         if (ds18b20_info-&gt;bus-&gt;use_parasitic_power)
                              ^~
esp32-ds18b20/ds18b20.c: At top level:
esp32-ds18b20/ds18b20.c:568:54: error: unknown type name 'OneWireBus'
 DS18B20_ERROR ds18b20_check_for_parasite_power(const OneWireBus * bus, bool * present)
                                                      ^~~~~~~~~~
esp32-ds18b20/ds18b20.c: In function 'ds18b20_check_for_parasite_power':
esp32-ds18b20/ds18b20.c:577:44: error: 'OWB_ROM_SKIP' undeclared (first use in this function); did you mean 'CY_ROM_SIZE'?
             if ((err = owb_write_byte(bus, OWB_ROM_SKIP)) == DS18B20_OK)
                                            ^~~~~~~~~~~~
                                            CY_ROM_SIZE
make[1]: *** [/Users/arh/proj/xxx/OWB_DS18B20/build/CY8CKIT-062S2-4301</pre>
<p>To make this thing go, I edit ds18b20.c file and add logging templates (just stub functions that don&#8217;t do anything)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">void ESP_LOGD(const char * code, char *val,...)
{

}

void ESP_LOGE(const char * code, ...)
{

}

void ESP_LOGW(const char *code,...)
{

}

#define ESP_LOG_DEBUG 0
void ESP_LOG_BUFFER_HEX_LEVEL(const char *code,...)
{

}

uint64_t esp_timer_get_time()
{
    return 0;
}</pre>
<h1>Create owb.h</h1>
<p>If I was smart, I would have started with David Antliff &#8220;owb&#8221; library.  But I don&#8217;t.  What I do is search through &#8220;ds18b20.c&#8221; and find every function call to owb_ and then copy those function calls into owb.h (my new file).  Then I fix the function calls to have correct prototypes based on what I see in the ds18b20 library.  Here is what my owb.h file looks like after that process.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#ifndef OWB_H
#define OWB_H

#ifdef __cplusplus
extern "C" {
#endif

#define OWB_ROM_MATCH 0
#define OWB_ROM_SKIP 0

#include &lt;stdint.h&gt;
#include "cyhal.h"
#include "FreeRTOS.h"
#include "semphr.h"

typedef struct  
{
    cyhal_gpio_t  pin;
    bool use_parasitic_power;
    SemaphoreHandle_t signalSemaphore;
    cyhal_timer_t bitTimer;
    bool detect;
    SemaphoreHandle_t owb_num_active;
} OneWireBus;        

typedef struct {
    uint8_t romAddr[8];

} OneWireBus_ROMCode;

typedef enum {
    OWB_STATUS_OK,
    OWB_STATUS_ERROR,
} owb_ret_t ;

owb_ret_t owb_init(OneWireBus *bus);
    
owb_ret_t owb_reset(OneWireBus *bus, bool *result);

owb_ret_t owb_write_bit( OneWireBus *bus, uint8_t val);
owb_ret_t owb_write_byte( OneWireBus *bus, uint8_t val);
owb_ret_t owb_write_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t length);

owb_ret_t owb_write_rom_code(OneWireBus *bus, OneWireBus_ROMCode romcode);

owb_ret_t owb_read_bit( OneWireBus *bus, uint8_t *bit);
owb_ret_t owb_read_byte( OneWireBus *bus, uint8_t *byte);
owb_ret_t owb_read_bytes( OneWireBus *bus, uint8_t *buffer, uint32_t length);

owb_ret_t owb_crc8_bytes(uint32_t val, uint8_t *buffer, uint32_t length);

void   owb_set_strong_pullup( OneWireBus *bus, bool val);

#endif

#ifdef __cplusplus
}
#endif</pre>
<p>When I run the compiler again things look way better (just some complaining about const datatypes) and a complaint about the include path.  The include path thing is visual studio code not knowing that I added a new directory called p6sdk-onewire.</p>
<p><a href="https://iotexpert.com/?attachment_id=9297" rel="attachment wp-att-9297"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-1024x417.png" alt="" width="1024" height="417" class="alignnone size-large wp-image-9297" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-1024x417.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-600x244.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-300x122.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-768x313.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-1536x625.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.06.30-PM-2048x833.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To fix the include path I run &#8220;make vscode&#8221; which tells VSCODE about the new directory.</p>
<p><a href="https://iotexpert.com/?attachment_id=9298" rel="attachment wp-att-9298"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-1024x148.png" alt="" width="1024" height="148" class="alignnone size-large wp-image-9298" srcset="https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-1024x148.png 1024w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-600x87.png 600w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-300x43.png 300w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-768x111.png 768w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM-1536x222.png 1536w, https://iotexpert.com/wp-content/uploads/2020/06/Screen-Shot-2020-06-11-at-12.07.59-PM.png 1830w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>That is a good place to split this article.  In the next article I will add functions to read and write the bus.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-sdk-onewire-bus-part-1-build-basic-project/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PSoC 6 TCPWM Pulse Width Measurement</title>
		<link>https://iotexpert.com/psoc-6-tcpwm-pulse-width-measurement/</link>
					<comments>https://iotexpert.com/psoc-6-tcpwm-pulse-width-measurement/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 18 May 2020 12:37:44 +0000</pubDate>
				<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=8897</guid>

					<description><![CDATA[Summary This article walks you through a PSoC 6 SDK example of measuring a pulse width using the TCPWM block&#8217;s counter function. The Story Recently I have been working with a Cypress guy and frequent collaborator Hassane.  He is working on a project that includes some kind of sonic distance sensor (I am actually not [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>This article walks you through a PSoC 6 SDK example of measuring a pulse width using the TCPWM block&#8217;s counter function.</p>
<h1>The Story</h1>
<p>Recently I have been working with a Cypress guy and frequent collaborator Hassane.  He is working on a project that includes some kind of sonic distance sensor (I am actually not sure which one).  In order to &#8220;read&#8221; the sensor you need to be able to measure the width of a pulse which is easy enough to do using the TCPWM.  I originally wanted to use the Cypress HAL to setup the PSoC 6 to do this function, but it is not yet enabled.  So, I need to use PDL and the PSoC 6 Configurator.</p>
<h1>Configure The TCPWM</h1>
<p>Start with a new PSoC 6 project.  In my case I am using the CY8CKIT-062-WiFi-BT development kit because I had one where I had already soldered a wire onto the user switch.  My plan is to create a &#8220;pulse&#8221; with the user switch, starting from the press, ending with the user letting go.  This will be an active low pulse.  I will configure the TCPWM to have start, reload setup as Falling edges.  In other words the counter will reset and start counting when the button is pressed.  Then I will setup Stop and Reload on Rising edges, in other words the timer will STOP and give an interrupt on the rising edge.  All of these pins are connected to P9[0] on the PSoC.</p>
<p><a href="https://iotexpert.com/?attachment_id=8898" rel="attachment wp-att-8898"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-930x1024.png" alt="" width="930" height="1024" class="alignnone size-large wp-image-8898" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-930x1024.png 930w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-600x660.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-273x300.png 273w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-768x845.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM-1395x1536.png 1395w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.10-PM.png 1468w" sizes="auto, (max-width: 930px) 100vw, 930px" /></a></p>
<p>You might ask yourself, why P9[0]?  That development kit has a switch connected to P0[4] seems like you should have connected the TCPWM to that pin.  That was done because the TCPWM is only attached to a limited set of signals.  Here is a screenshot from the configurator.</p>
<p><a href="https://iotexpert.com/?attachment_id=8902" rel="attachment wp-att-8902"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM-926x1024.png" alt="" width="926" height="1024" class="alignnone size-large wp-image-8902" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM-926x1024.png 926w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM-600x663.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM-271x300.png 271w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM-768x849.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.38.44-AM.png 1134w" sizes="auto, (max-width: 926px) 100vw, 926px" /></a></p>
<p>I want this setup to be interrupt based, specifically I want an interrupt when the Capture signal is active.  It is also interesting when the counter rolls over (overflow).  So I setup the interrupt source to be &#8220;Overflow &amp; Underflow or Compare &amp; Capture&#8221;.</p>
<p>The last thing you need is a clock.   you now need a clock.  To do this clock on the Clock Signal.  For this example I decided to use a 16-bit clock.</p>
<p><a href="https://iotexpert.com/?attachment_id=8903" rel="attachment wp-att-8903"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM-1024x307.png" alt="" width="1024" height="307" class="alignnone size-large wp-image-8903" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM-1024x307.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM-600x180.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM-300x90.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM-768x230.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.45.03-AM.png 1376w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>But what frequency is the input clock?  To set this go to the &#8220;Peripheral-Clocks&#8221;  The click on the divider you choose from above.  Then pick a divide value.  I choose 10000 which will give me 100MHz/10K=10KHz.</p>
<p><a href="https://iotexpert.com/?attachment_id=8904" rel="attachment wp-att-8904"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-1024x608.png" alt="" width="1024" height="608" class="alignnone size-large wp-image-8904" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-1024x608.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-600x356.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-300x178.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-768x456.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM-1536x912.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.46.29-AM.png 1550w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>But where did the 100MHz come from?  Click on the &#8220;System&#8221; and look at the clock diagram.  All of the &#8220;Peripheral Clocks&#8221; use the signal &#8220;CLK_PERI&#8221; as their source.  This is attached to CLK_HF0 (which is 100Mhz) in this case.</p>
<p><a href="https://iotexpert.com/?attachment_id=8905" rel="attachment wp-att-8905"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-1024x487.png" alt="" width="1024" height="487" class="alignnone size-large wp-image-8905" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-1024x487.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-600x285.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-300x143.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-768x365.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-1536x730.png 1536w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-21-at-6.48.54-AM-2048x974.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>The Program</h1>
<p>Once is everything is configured you need to write a bit of code.</p>
<p>9-14: First I create an ISR which will set a flag and clear the interrupt source in the TCPWM</p>
<p>Then I write a main function</p>
<p>20: Turn on the printf functionality using the cy_retarget_io library</p>
<p>25: Initialize the counter using the structure created by the configurator.</p>
<p>26: Then I enable the counter to run.  Be careful with this function because counter numbers are NOT the same thing as counter masks.  Counter 3 is counter mask 1&lt;&lt;3=8</p>
<p>28-30: Turn on the interrupts and register my ISR called counterDone</p>
<p>34: In the loop I wait around until the flag gets set by the ISR</p>
<p>36: Read the value from the counter and convert it to seconds</p>
<p>37: Print the value</p>
<p>38: Reset the flag</p>
<p>And do it all over again</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cy_pdl.h"
#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include &lt;stdio.h&gt;

volatile int flag=0;

void counterDone()
{
    uint32 intCause = Cy_TCPWM_GetInterruptStatusMasked(MYC_HW,MYC_NUM);
    flag = 1;
    Cy_TCPWM_ClearInterrupt(MYC_HW,MYC_NUM,intCause);
}

int main(void)
{
    cybsp_init() ;
    
    cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);
    __enable_irq();

    printf("Started\n");

    Cy_TCPWM_Counter_Init(MYC_HW,MYC_NUM,&amp;MYC_config);
    Cy_TCPWM_Enable_Multiple(MYC_HW,MYC_MASK);

    cy_stc_sysint_t mycounter= {.intrSrc = MYC_IRQ, .intrPriority=7};
    Cy_SysInt_Init(&amp;mycounter,counterDone);
    NVIC_EnableIRQ(MYC_IRQ);

    for(;;)
    {
        if(flag == 1)
        {
            float val = (float)Cy_TCPWM_Counter_GetCounter(MYC_HW,MYC_NUM) / 10000.0;
            printf("%.2fs\n",val);
            flag = 0;
        }
    }
}
</pre>
<h1>Test</h1>
<p>For an earlier article I had to solder a wire onto the switch.  This let me attach it to an oscilliscope.  It turns out that was an easy way to attach the switch to P9[0]</p>
<p><a href="https://iotexpert.com/?attachment_id=8900" rel="attachment wp-att-8900"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-1024x796.jpg" alt="" width="1024" height="796" class="alignnone size-large wp-image-8900" srcset="https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-1024x796.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-scaled-600x467.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-300x233.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-768x597.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-1536x1195.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/03/IMG_1658-2048x1593.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I run the project I get a bunch of different pulse.  Looks good.</p>
<p><a href="https://iotexpert.com/?attachment_id=8899" rel="attachment wp-att-8899"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM-1024x710.png" alt="" width="1024" height="710" class="alignnone size-large wp-image-8899" srcset="https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM-1024x710.png 1024w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM-600x416.png 600w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM-300x208.png 300w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM-768x532.png 768w, https://iotexpert.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-20-at-6.05.57-PM.png 1192w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/psoc-6-tcpwm-pulse-width-measurement/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
