<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: Faster DigitalRead ?</title>
		<link>http://forums.leaflabs.com/topic.php?id=1107</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:17:10 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=1107" rel="self" type="application/rss+xml" />

		<item>
			<title>gbulmer on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-7068</link>
			<pubDate>Wed, 02 Nov 2011 13:14:22 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7068@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;newyorkbrass -&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;since counter is 32 bit - if you need to count up to 27 bits you can&#60;br /&#62;
alway wait with the shift operator until you need of even do away completely&#60;br /&#62;
and just use a constant that is shifted &#38;lt;&#38;lt;5&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;void interrupt_vector()
{
Counter += (GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5));
}&#60;/code&#62;&#60;/pre&#62;&#60;/blockquote&#62;
&#60;p&#62;Nifty thinking!&#60;/p&#62;
&#60;p&#62;If bit-band addressing is used, there is no need for the binary 'and' (&#60;code&#62;&#38;amp;&#60;/code&#62;).&#60;br /&#62;
Also a bit-band-address value is one bit, the bottom bit, even though it is read or written as a 32 bit word. It is always 0 or 1 so no need for binary 'right shift' (&#60;code&#62;&#38;gt;&#38;gt;&#60;/code&#62;). i.e.:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;loop() {
    Counter += IOBitBand(&#38;amp;(GPIOB_BASE-&#38;gt;IDR), 5);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In this case, implementing IOBitBand as a macro or inline function would make the bit band address a constant, which, once loaded into a register would be very quick. &#60;/p&#62;
&#60;p&#62;The overhead of &#60;code&#62;loop() { ... }&#60;/code&#62; is slower than the time to read the port register, extract the bit and shift it right.&#60;br /&#62;
So a faster solution would be:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;loop() {
    while (1) {
        Counter += IOBitBand(&#38;amp;(GPIOB_BASE-&#38;gt;IDR), 5);
    }
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;(Edit: bb_peri_get_bit() is already implemented.)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>newyorkbrass on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-7067</link>
			<pubDate>Wed, 02 Nov 2011 12:01:47 +0000</pubDate>
			<dc:creator>newyorkbrass</dc:creator>
			<guid isPermaLink="false">7067@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;
loop() {&#60;br /&#62;
    Counter +=  (GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5)) &#38;gt;&#38;gt; 5;&#60;br /&#62;
}
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;since counter is 32 bit - if you need to count up to  27 bits you can&#60;br /&#62;
alway wait with the shift operator until you need of even do away completely&#60;br /&#62;
and just use a constant that is shifted &#38;lt;&#38;lt;5&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;void interrupt_vector()&#60;br /&#62;
{&#60;br /&#62;
    Counter +=  (GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5));&#60;br /&#62;
}&#60;/p&#62;
&#60;p&#62;loop() {&#60;br /&#62;
    .&#60;br /&#62;
     .&#60;br /&#62;
    some_lengthly_operation();&#60;br /&#62;
    use_counter(Counter &#38;lt;&#38;lt; 5);&#60;br /&#62;
    .&#60;br /&#62;
   .&#60;br /&#62;
}
&#60;/p&#62;&#60;/blockquote&#62;</description>
		</item>
		<item>
			<title>TRC on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-6859</link>
			<pubDate>Thu, 13 Oct 2011 04:11:07 +0000</pubDate>
			<dc:creator>TRC</dc:creator>
			<guid isPermaLink="false">6859@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Great thanks for the info!
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-6830</link>
			<pubDate>Tue, 11 Oct 2011 20:00:36 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">6830@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Each  I/O pin is represented in a 16-bit 'port', a bunch of memory locations which:&#60;br /&#62;
- control the pin direction (whether pins are inputs or outputs),&#60;br /&#62;
- the value of the pins that are inputs, and&#60;br /&#62;
- the state of output pins&#60;br /&#62;
- a few other things ...&#60;br /&#62;
This is described in the ST Micro manual RM0008, in section 9 &#34;General-purpose and alternate-function I/Os (GPIOs and AFIOs)&#34;. e.g.&#60;br /&#62;
&#60;a href=&#34;http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf&#34; rel=&#34;nofollow&#34;&#62;http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;To figure out which port digital pin 4 is on, go look at the Maple pinmap, e.g.&#60;br /&#62;
&#60;a href=&#34;http://leaflabs.com/docs/hardware/maple.html#master-pin-map&#34; rel=&#34;nofollow&#34;&#62;http://leaflabs.com/docs/hardware/maple.html#master-pin-map&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;You can see that D4 (data pin 4) is &#34;PB5&#34;, that is port B, pin 5.&#60;br /&#62;
So Port B is GPIOB&#60;br /&#62;
hence the call is &#60;code&#62;gpio_read_bit(GPIOB, 5);&#60;/code&#62;&#60;/p&#62;
&#60;p&#62;Or, you can 'do it yourself' and just write&#60;br /&#62;
... GPIOB_BASE-&#38;gt;IDR &#38;amp; BIT(5) ...&#60;br /&#62;
which has a similar effect.&#60;br /&#62;
The part of the expression &#60;code&#62;&#38;amp; BIT(5)&#60;/code&#62; is extracting the specific pin value.&#60;br /&#62;
Then you might use a test for zero, e.g.&#60;br /&#62;
&#60;code&#62;if (GPIOB_BASE-&#38;gt;IDR &#38;amp; BIT(5)) { Counter ++; }&#60;/code&#62;&#60;/p&#62;
&#60;p&#62;if you actually want to use the bit value, the code would have to shift the bit.&#60;br /&#62;
As an example, the code could use the value as an integer value 0 or 1, either:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;loop() {
    Counter += GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5)? 1 : 0;
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;or&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;loop() {
    Counter +=  (GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5)) &#38;gt;&#38;gt; 5;
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The if test disappears, though the compiler might generate a better code sequence for an &#60;code&#62;if&#60;/code&#62; compared to the &#60;code&#62;...? 1 : 0;&#60;/code&#62; I'd have to go look.&#60;br /&#62;
I think the second one (&#60;code&#62;GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5)) &#38;gt;&#38;gt; 5&#60;/code&#62;) might be quickest because the Cortex-M3 has a fast shift or bit test which might do that in one cycle (the compiler will know what to do :-)&#60;/p&#62;
&#60;p&#62;Theoretically, that specific expression &#60;code&#62;GPIOB_BASE-&#38;gt;IDR&#38;amp; BIT(5)) &#38;gt;&#38;gt; 5&#60;/code&#62;, once set up, could run in 3 cycles (.e. 24MHz), but the address of GPIO_BASE-&#38;gt;IDR will have to be loaded so you'll not see that unless you have a long piece of code to keep testing the pin.&#60;/p&#62;
&#60;p&#62;There is an even quicker way using 'bit banding'.&#60;br /&#62;
Every I/O &#60;em&#62;pin&#60;/em&#62; has a second 'shadow address' where a whole memory word is used to set or test the pin value, so the &#60;code&#62;&#38;amp; BIT(5)&#60;/code&#62; becomes unnecessary.&#60;/p&#62;
&#60;p&#62;Pete Harrison has an article at:&#60;br /&#62;
&#60;a href=&#34;http://www.micromouseonline.com/2010/07/14/bit-banding-in-the-stm32/#axzz1aWWAbNQg&#34; rel=&#34;nofollow&#34;&#62;http://www.micromouseonline.com/2010/07/14/bit-banding-in-the-stm32/#axzz1aWWAbNQg&#60;/a&#62;&#60;br /&#62;
Instead of using the bit band region for memory:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;#define RAM_BASE 0x20000000
#define RAM_BB_BASE 0x22000000&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;You would be using the bit band region for I/O registers:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;#define IO_BASE 0×40000000
#define IO_BB_BASE 0×42000000&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;and change the macros to match.&#60;/p&#62;
&#60;p&#62;Essentially, the code Pete shows converts a memory address, and the bit within the memory address to a memory address for a bit.&#60;br /&#62;
You could modify the macros to convert the I/O port address and pin within that port to a bit-band memory address, and use that to test the pin (I've called that IOGetBit()).&#60;/p&#62;
&#60;p&#62;All of that can be calculated at compile time, so there is no need for the &#60;code&#62;&#38;amp; BIT(5)&#60;/code&#62;, &#60;em&#62;and&#60;/em&#62; the bit is always in bit position 0.&#60;br /&#62;
So, it is possible to test a bit in two cycles once the bit-band address is loaded into a register. That is 36MHz. Again, you'll never see it go that fast unless it is in a long piece of code with all the addresses loaded into CPU registers.&#60;/p&#62;
&#60;p&#62;So your code:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;void loop()
{
    if (digitalRead(4) == HIGH){
        Counter ++;
    }
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;would become&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;void loop()
{
    Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;which wouldn't do much useful (just count like crazy), but the overhead of calling &#60;code&#62;loop()&#60;/code&#62; would be humungous by comparison with the time needed to test a pin.&#60;/p&#62;
&#60;p&#62;The time spent doing:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;int start_time = millis();
for (int i=0; i&#38;lt;6000000; ++i) { // 6 million
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
}
int end_time = millis();&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;would be slightly more &#60;code&#62;for&#60;/code&#62; loop than the pin test.&#60;br /&#62;
I guess that is less than 1 second, but it's late and I'm sleepy.&#60;/p&#62;
&#60;p&#62;Hence 'unrolling` the for loop:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;int start_time = millis();
for (int i=0; i&#38;lt;1000000; ++i) { // 1 million
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
        Counter += IOGetBit(GPIO_BASE-&#38;gt;IDR, 5);
}
int end_time = millis();&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;should be noticeably faster.&#60;/p&#62;
&#60;p&#62;[WARNING: I have not compiled and tested the code]&#60;br /&#62;
(Note to self: I think Pete's macros and the gpio.h header don't declare GPIOB_BASE as the address of a &#60;code&#62;volatile&#60;/code&#62; so GPIOB-&#38;gt;regs-&#38;gt;IDR might be better because &#60;code&#62;regs&#60;/code&#62; is &#60;code&#62;volatile&#60;/code&#62;)&#60;/p&#62;
&#60;p&#62;(full disclosure: I am not a member of LeafLabs staff)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>poslathian on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-6827</link>
			<pubDate>Tue, 11 Oct 2011 17:34:40 +0000</pubDate>
			<dc:creator>poslathian</dc:creator>
			<guid isPermaLink="false">6827@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;digging into libmaple here: &#60;a href=&#34;https://github.com/leaflabs/libmaple/blob/master/libmaple/gpio.h&#34; rel=&#34;nofollow&#34;&#62;https://github.com/leaflabs/libmaple/blob/master/libmaple/gpio.h&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;you can see that the read-bit function gets inlined (for faster digitalRead downstream) and is defined here:&#60;/p&#62;
&#60;p&#62;static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) {&#60;br /&#62;
    return dev-&#38;gt;regs-&#38;gt;IDR &#38;amp; BIT(pin);&#60;br /&#62;
}&#60;/p&#62;
&#60;p&#62;you can figure out exactly what &#34;dev&#34; and &#34;regs&#34; are by looking up their type definitions in the same file. the long and short of it is that dev is a struct of type gpio_dev and regs is of type gpio_regmap which are also defined in that file. &#60;/p&#62;
&#60;p&#62;You could re-create what gpio.h does for you in your test, but since gpio_read_bit is inlined ANYWAY, calling that function inside a loop is about as fast as you are going to get without being very clever or dropping into asm.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>TRC on "Faster DigitalRead ?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1107#post-6814</link>
			<pubDate>Tue, 11 Oct 2011 09:09:51 +0000</pubDate>
			<dc:creator>TRC</dc:creator>
			<guid isPermaLink="false">6814@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hello all I was wondering if someone could tell me how to make the process of reading the High or Low state of a pin 'faster'? The DigitalRead command probably has 'a lot' of overhead and I am sure there must be some low level direct excess code to read the High or Low state of a pin directly and bypass the speed limitations of the DigitalRead command.&#60;/p&#62;
&#60;p&#62;So far example, using this simple code:&#60;/p&#62;
&#60;p&#62;/////////////////////////////////////////////&#60;br /&#62;
int Counter = 0;&#60;/p&#62;
&#60;p&#62;void setup()&#60;br /&#62;
{&#60;br /&#62;
}&#60;/p&#62;
&#60;p&#62;void loop()&#60;br /&#62;
{&#60;br /&#62;
  if (digitalRead(4) == HIGH){&#60;br /&#62;
    Counter ++;&#60;br /&#62;
  }&#60;br /&#62;
}&#60;br /&#62;
/////////////////////////////////////////////&#60;/p&#62;
&#60;p&#62;Only then with direct pin readout, bypassing the DigitalRead commands overhead.&#60;br /&#62;
So that it responds as fast as possible when pin 4 goes high.&#60;/p&#62;
&#60;p&#62;Now I have done some speed measurements of the DigitalRead command on the:&#60;br /&#62;
- Arduino&#60;br /&#62;
- Maple&#60;br /&#62;
- Uno32&#60;br /&#62;
And although the Uno32 has the most mhz of them all, Maple's DigitalRead overhead was the lowest. But hey, we always want more speed.&#60;/p&#62;
&#60;p&#62;Thanks for the help in advance!&#60;br /&#62;
Regards,&#60;br /&#62;
TRC
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
