Browse Source

change link to .html

Pat Beirne 2 weeks ago
parent
commit
e13dec91e4
2 changed files with 1776 additions and 1 deletions
  1. 1775 0
      CooperativeMultitasking.html
  2. 1 1
      README.md

+ 1775 - 0
CooperativeMultitasking.html

@@ -0,0 +1,1775 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
+<head>
+  <meta charset="utf-8" />
+  <meta name="generator" content="pandoc" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
+  <meta name="author" content="Pat Beirne" />
+  <title>Cooperative Multitasking</title>
+  <style>
+    code{white-space: pre-wrap;}
+    span.smallcaps{font-variant: small-caps;}
+    div.columns{display: flex; gap: min(4vw, 1.5em);}
+    div.column{flex: auto; overflow-x: auto;}
+    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
+    /* The extra [class] is a hack that increases specificity enough to
+       override a similar rule in reveal.js */
+    ul.task-list[class]{list-style: none;}
+    ul.task-list li input[type="checkbox"] {
+      font-size: inherit;
+      width: 0.8em;
+      margin: 0 0.8em 0.2em -1.6em;
+      vertical-align: middle;
+    }
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
+    /* CSS for syntax highlighting */
+    pre > code.sourceCode { white-space: pre; position: relative; }
+    pre > code.sourceCode > span { line-height: 1.25; }
+    pre > code.sourceCode > span:empty { height: 1.2em; }
+    .sourceCode { overflow: visible; }
+    code.sourceCode > span { color: inherit; text-decoration: inherit; }
+    div.sourceCode { margin: 1em 0; }
+    pre.sourceCode { margin: 0; }
+    @media screen {
+    div.sourceCode { overflow: auto; }
+    }
+    @media print {
+    pre > code.sourceCode { white-space: pre-wrap; }
+    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
+    }
+    pre.numberSource code
+      { counter-reset: source-line 0; }
+    pre.numberSource code > span
+      { position: relative; left: -4em; counter-increment: source-line; }
+    pre.numberSource code > span > a:first-child::before
+      { content: counter(source-line);
+        position: relative; left: -1em; text-align: right; vertical-align: baseline;
+        border: none; display: inline-block;
+        -webkit-touch-callout: none; -webkit-user-select: none;
+        -khtml-user-select: none; -moz-user-select: none;
+        -ms-user-select: none; user-select: none;
+        padding: 0 4px; width: 4em;
+        color: #aaaaaa;
+      }
+    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
+    div.sourceCode
+      {   }
+    @media screen {
+    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
+    }
+    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
+    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
+    code span.at { color: #7d9029; } /* Attribute */
+    code span.bn { color: #40a070; } /* BaseN */
+    code span.bu { color: #008000; } /* BuiltIn */
+    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
+    code span.ch { color: #4070a0; } /* Char */
+    code span.cn { color: #880000; } /* Constant */
+    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
+    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
+    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
+    code span.dt { color: #902000; } /* DataType */
+    code span.dv { color: #40a070; } /* DecVal */
+    code span.er { color: #ff0000; font-weight: bold; } /* Error */
+    code span.ex { } /* Extension */
+    code span.fl { color: #40a070; } /* Float */
+    code span.fu { color: #06287e; } /* Function */
+    code span.im { color: #008000; font-weight: bold; } /* Import */
+    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
+    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
+    code span.op { color: #666666; } /* Operator */
+    code span.ot { color: #007020; } /* Other */
+    code span.pp { color: #bc7a00; } /* Preprocessor */
+    code span.sc { color: #4070a0; } /* SpecialChar */
+    code span.ss { color: #bb6688; } /* SpecialString */
+    code span.st { color: #4070a0; } /* String */
+    code span.va { color: #19177c; } /* Variable */
+    code span.vs { color: #4070a0; } /* VerbatimString */
+    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
+  </style>
+  <link rel="stylesheet" href="pandoc.css" />
+</head>
+<body>
+<header id="title-block-header">
+<h1 class="title">Cooperative Multitasking</h1>
+<p class="author">Pat Beirne</p>
+<p class="date">2025/01/15</p>
+</header>
+<nav id="TOC" role="doc-toc">
+<ul>
+<li><a href="#part-1-cooperative-multitasking"
+id="toc-part-1-cooperative-multitasking">Part 1: Cooperative
+Multitasking</a>
+<ul>
+<li><a href="#intro" id="toc-intro">Intro</a>
+<ul>
+<li><a href="#abstract" id="toc-abstract">Abstract</a></li>
+<li><a href="#audience" id="toc-audience">Audience</a></li>
+</ul></li>
+<li><a href="#the-problem" id="toc-the-problem">The Problem</a></li>
+<li><a href="#first-page" id="toc-first-page">First Page</a></li>
+<li><a href="#interrupts" id="toc-interrupts">Interrupts</a></li>
+<li><a href="#events" id="toc-events">Events</a></li>
+<li><a href="#newevent" id="toc-newevent">newEvent()</a></li>
+<li><a href="#dispatch" id="toc-dispatch">Dispatch</a></li>
+<li><a href="#tasks" id="toc-tasks">Tasks</a></li>
+<li><a href="#state-machine" id="toc-state-machine">State
+Machine</a></li>
+<li><a href="#another-state-machine"
+id="toc-another-state-machine">Another State Machine</a></li>
+<li><a href="#dispatcher-details" id="toc-dispatcher-details">Dispatcher
+Details</a></li>
+<li><a href="#final-implementation" id="toc-final-implementation">Final
+Implementation</a></li>
+</ul></li>
+<li><a href="#part-2" id="toc-part-2">Part 2</a>
+<ul>
+<li><a href="#variations" id="toc-variations">Variations</a></li>
+<li><a href="#working-with-arduino"
+id="toc-working-with-arduino">Working with Arduino</a></li>
+<li><a href="#tasks-1" id="toc-tasks-1">Tasks</a></li>
+<li><a href="#state-machine-examples"
+id="toc-state-machine-examples">State Machine Examples</a>
+<ul>
+<li><a href="#car-window" id="toc-car-window">Car Window</a></li>
+<li><a href="#fridge-door" id="toc-fridge-door">Fridge Door</a></li>
+<li><a href="#door-opener" id="toc-door-opener">Door Opener</a></li>
+<li><a href="#beer-vat" id="toc-beer-vat">Beer Vat</a></li>
+<li><a href="#vending-machine" id="toc-vending-machine">Vending
+Machine</a></li>
+</ul></li>
+<li><a href="#events-1" id="toc-events-1">Events</a></li>
+<li><a href="#timers" id="toc-timers">Timers</a></li>
+<li><a href="#real-code" id="toc-real-code">Real Code</a></li>
+<li><a href="#substates" id="toc-substates">Substates</a></li>
+<li><a href="#state-machine-initialization"
+id="toc-state-machine-initialization">State Machine
+Initialization</a></li>
+<li><a href="#messages" id="toc-messages">Messages</a>
+<ul>
+<li><a href="#postmessage" id="toc-postmessage">PostMessage</a></li>
+<li><a href="#sendmessage" id="toc-sendmessage">SendMessage</a></li>
+<li><a href="#usage" id="toc-usage">Usage</a></li>
+</ul></li>
+<li><a href="#ideas-for-tasks" id="toc-ideas-for-tasks">Ideas for
+Tasks</a></li>
+<li><a href="#more-state-machines" id="toc-more-state-machines">More
+State Machines</a>
+<ul>
+<li><a href="#radio-tuner" id="toc-radio-tuner">Radio Tuner</a></li>
+</ul></li>
+</ul></li>
+</ul>
+</nav>
+<h1 id="part-1-cooperative-multitasking">Part 1: Cooperative
+Multitasking</h1>
+<!-- ## Introduction -->
+<p>Small microcontrollers are often required to handle several tasks,
+sometimes with overlapping phases. This paper will lead you through the
+creation of a small <strong><em>operating system</em></strong> which can
+be implemented on a tiny microcontroller, without the fancy time-slicing
+that is offered by sophisticated operating systems like <a
+href="https://linux.org">Linux</a> and <a
+href="https://freertos.org">FreeRTos</a>.</p>
+<p>The core of <em>this</em> technique is covered in <a
+href="#part-1-cooperative-multitasking">Part 1</a> of this paper. If you
+just want to see how it all comes together, jump to <a
+href="#final-implementation">Final Implementaion</a>.</p>
+<p><a href="#part-2">Part 2</a> contains enhancements and variations,
+probably useful reading if you decide to adopt this programming
+technique in your projects.</p>
+<h2 id="intro">Intro</h2>
+<h3 id="abstract">Abstract</h3>
+<p>This paper will take you through the creation of a tiny <em>operating
+system</em> that can be implemented on a small microcontroller.</p>
+<h3 id="audience">Audience</h3>
+<p>These techniques can be applied by anyone with experience in
+<strong><em>C</em></strong>, <strong><em>Python</em></strong> or any
+modern computer language. It helps to have a passing knowledge of how to
+connect a transducer (button, LED, buzzer, etc) to a
+microcontroller.</p>
+<blockquote>
+<p>The <strong><em>Reality Check</em></strong> dropdowns in this article
+provide extra, often practical supplementary reading.</p>
+</blockquote>
+<details>
+<summary>
+Reality Check
+</summary>
+<p>The technique described here is also called <strong><em>event driven
+programming</em></strong>.</p>
+<p>This technique was used in the original Window (1995), including some
+of the system calls:
+<code>sendMessage(), postMessage() and setTimer()</code>.</p>
+<p>This event-driven technique is applicable to a whole host of small
+microcontrollers, including</p>
+<ul>
+<li>MSP430</li>
+<li>Cortex M0, M0+ (SAM, STM32, PY32, Cypress, Kinetis, HT32, XMC,
+LPC81x)</li>
+<li>AtMega, AtTiny</li>
+<li>8051 (SiliconLabs, Nuvoton, HT85)</li>
+<li>RL78 (Renesas)</li>
+<li>Pic 12/14/16</li>
+<li>Risc (ch32v)</li>
+<li>STM8</li>
+</ul>
+<p><em>Some of the really tiny ones don’t have enough stack space to
+implement these techniques (Puolop PB150, Padauk PxS15x, Bojuxing BJ8P,
+Yspring MDT1x, EastSoft HR7P, Holtek Ht68.)</em></p>
+<img src="blb.jpg" alt="Here" /> is a typical board hosting 12 buttons,
+12 RGB LEDs, all hosted by an STM32. Every light and button can be
+controlled separately and simultaneously, using the technique described
+in this paper.
+</details>
+<h2 id="the-problem">The Problem</h2>
+<p>Let’s suppose we want to flash an LED at 1 flash/2 sec, and
+independently, respond to a push button by operating a different LED for
+1.5 seconds. Both operations must operate separately. How do we
+structure the code for the microcontroller to make this happen?</p>
+<h2 id="first-page">First Page</h2>
+<p>Let’s look an a pseudocode overview of what we want to do:</p>
+<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> initialize<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  setup_hardware<span class="op">();</span></span>
+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  setup_interrupts<span class="op">();</span></span>
+<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>INTERRUPT <span class="dt">void</span> irq<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  create_event<span class="op">();</span></span>
+<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  acknowledge_interrupt<span class="op">();</span></span>
+<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  initialize<span class="op">();</span></span>
+<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span> <span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>      flashLedTask<span class="op">(</span>event<span class="op">);</span></span>
+<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>      respondToButtonTask<span class="op">(</span>event<span class="op">);</span></span>
+<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>That’s about it.</p>
+<p>Of course, we will need to write the code for
+<code>setup_hardware()</code> and <code>setup_interrupts()</code>. And
+<code>flashLedTask()</code> and <code>respondToButtonTask()</code>. And
+create the <em>magic</em> that allows <code>event</code> information to
+flow. Don’t worry, it will all be laid out in the following pages.</p>
+<p>If you’re concerned with complexity, feel free to jump ahead to the
+<a href="#final-implementation">final implementation</a> page to see
+real, tested, code.</p>
+<p>Between here and there, I’ll walk you step-by-step through building
+the structure and implementation.</p>
+<p>This paper continues after that though, to show you how to expand
+upon a build as the project-definition changes. There are also several
+examples of state machines, and some discussion of practical matters,
+refactoring and project structure.</p>
+<h2 id="interrupts">Interrupts</h2>
+<p>In order to have a responsive system, it would make sense to use the
+<em>interrupt</em> capabilities of these small micrcontrollers.</p>
+<p>In the task described, we need to respond to a button press. So let’s
+connect the button to an input pin and enable it to repsond to a button
+press with interrupt code.</p>
+<p>We also need to keep track of time…..so let’s hook up a system timer
+to another interrupt.</p>
+<p>Each interrupt causes the execution of <em>interrupt handler</em>
+code. For this project, it might look somthing like this:</p>
+<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>EVT_NONE<span class="op">,</span> EVT_TICK<span class="op">,</span> EVT_BUTTON<span class="op">};</span></span>
+<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>INTERRUPT timer_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_TICK<span class="op">);</span></span>
+<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>INTERRUPT button_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_BUTTON<span class="op">);</span>  <span class="co">// see notes about button bounce and acknowledgement</span></span>
+<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>The interrupt handlers are both very simple. They just create a
+unique <em>event</em> and let the system know about it. Next, let’s talk
+about <em>events</em>.</p>
+<details>
+<summary>
+Reality check
+</summary>
+<p>In some microcontrollers, interrupts must be <em>acknowledged</em>.
+Sometimes that means setting a hardware flag to indicate to the device
+that you’re ready for another interrupt of the same type. And in some
+cases, there’s no need to ack. Specifically, the SYS_TICK interrupt in
+the ARM Cortex processors does <em>not</em> need an ack, so the above
+code example for <code>timer_isr()</code> is complete.</p>
+<p>When a pushbutton or switch is connected to a microcontroller, the
+first bit of activity will cause the interrupt and execute the
+<code>button_isr()</code> code. However, real buttons produce about
+5msec of <em>bounce</em> and this will cause subsequent interrupts
+unless they are somehow filtered out. There are lots of ways to handle
+<em>bounce</em>, and I’ll let you read about that
+[elsewhere]](#debouncing). Most techniques boil down to either ignoring
+subsequent interrupts (from the same button) for about 5 msec, or
+disabling that specific interrupt until the 5msec has passed.</p>
+<p>As a general rule, <em>input</em> pins should be observed either by
+interrupt service routine (ISR), or scanned periodically by the timer
+ISR. <em>Outputs</em> should be controlled in the task code, which we’ll
+see below.</p>
+</details>
+<h2 id="events">Events</h2>
+<p>An <em>event</em> in this context is a small bit of information that
+appears asynchronously in the system. Implemented, it can be a
+<em>byte</em>, or an <em>int</em> or an even larger structure. But in
+these small microcontrollers, let’s use a <em>byte</em>.</p>
+<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> uint8 event<span class="op">;</span></span></code></pre></div>
+<p>These <em>events</em> will be created in interrupt level of the code,
+and processed at the main level. We use the <code>event</code> object to
+send information between these levels, so we have to mark it <a
+href="https://en.wikipedia.org/wiki/Volatile_(computer_programming)"><code>volatile</code></a>.</p>
+<p>In this paper, the word <em>message</em> and <em>event</em> are
+equivalent. <em>Message</em> has the sense of “a bit of communication
+from another part of the program” and <em>event</em> has the sense of
+“something external just happened”. At this point in the design, they
+both mean the same thing.</p>
+<p>By convention, let’s use <em>zero</em> to indicate the absence of an
+event/message, and <em>non-zero</em> to represent an event/message.</p>
+<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> uint8 event<span class="op">;</span></span>
+<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>EVT_NONE<span class="op">,</span> EVT_TICK<span class="op">,</span> EVT_BUTTON<span class="op">};</span> <span class="co">// 0,1,2</span></span></code></pre></div>
+<details>
+<summary>
+Reality check
+</summary>
+<hr>
+For this project, let’s suppose the timer ticks happen every 10ms (100
+per second).
+<hr>
+</details>
+<p>So now we start to get an idea of what kind of information the
+<em>interrupt handler</em> code generates. Now let’s look at how that
+information gets sent to the rest of the code:
+<code>newEvent()</code>.</p>
+<h2 id="newevent">newEvent()</h2>
+<p>Here’s a block diagram of the message flow <img
+src="dispatch1.jpg" /></p>
+<p>How do we send the information (events/messages) from the interrupt
+service routine to the <code>main()</code> code? We used shared
+memory.</p>
+<p>One way would be to have a global <code>volatile uint8</code>
+location into which we drop the <em>event</em> information. But having
+only one socket for that would be a bit naive; what happens if a timer
+tick and a button press happen very close in time? What happens if the
+timer tick events start to stack up?</p>
+<p>It makes more sense to have an array:
+<code>volatile uint8 events[NUM_EVENTS]</code> where NUM_EVENTS is on
+the order of 5..10. That would give us 50-100msec to catch up in case
+there’s a pileup of events/messages.</p>
+<p>At the beginning, before anything happens, we need to make sure the
+<code>events[]</code> is full of zeros (EVT_NONE), indicating that it’s
+empty.</p>
+<p>The <code>newEvent(evt)</code> routine simply adds the
+<code>evt</code> to the array <code>events[]</code>.</p>
+<p>Something like this might work:</p>
+<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span>uint8r evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> <span class="dt">unsigned</span> uint8 nextEvent<span class="op">;</span></span>
+<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  events<span class="op">[</span>nextEvent<span class="op">++]</span> <span class="op">=</span> evt<span class="op">;</span></span>
+<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>nextEvent <span class="op">==</span> NUM_EVENTS<span class="op">)</span></span>
+<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    nextEvent <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<details>
+<summary>
+Reality check
+</summary>
+<p>There is a problem with the above code. What happens if a
+<code>key_isr()</code> is running, and is halfway through its call to
+<code>newEvent()</code> when a <code>timer_isr()</code> happens, and
+reenters the <code>newEvent()</code> routine. This will get really
+messed up. So we need to wrap <em>this particular</em> code in a
+critical section.</p>
+<p>Here’s a more realistic version:</p>
+<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span><span class="dt">char</span> evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> <span class="dt">unsigned</span> <span class="dt">char</span> nextEvent<span class="op">;</span>   <span class="co">// keep track of where we are in queue</span></span>
+<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  disable_irq<span class="op">();</span>                    <span class="co">// critical section</span></span>
+<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  events<span class="op">[</span>nextEvent<span class="op">++]</span> <span class="op">=</span> evt<span class="op">;</span>        <span class="co">// insert event into queue</span></span>
+<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>nextEvent <span class="op">==</span> NUM_EVENTS<span class="op">)</span>      <span class="co">// loop back to the start of queue</span></span>
+<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    nextEvent <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  enable_irq<span class="op">();</span>           <span class="co">// end critical section, probably &lt;100us of blockage</span></span>
+<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+</details>
+<p>In the next section, we’ll show how the <code>main()</code> code
+pulls the events out of the array, and leaves an EVT_NONE in its
+place.</p>
+<h2 id="dispatch">Dispatch</h2>
+<p>The <code>main()</code> code can simply watch the
+<code>events[]</code> to see when an entry goes non-zero (!=EVT_NONE).
+When that happens, <code>main()</code> will pull out the
+<em>event/message</em> from the array, and call the task subroutines. In
+this case, <code>flashLedTask()</code> and
+<code>respondToButtonTask()</code>.</p>
+<p>To see the real code for the dispatcher, <a
+href="#dispatcher-details">jump ahead</a>.</p>
+<details>
+<summary>
+Terminology
+</summary>
+<p>The <code>main()</code> code illustrated here calls the tasks as
+subroutines, sending each one a copy of the event number.</p>
+<p>As I mentioned earlier, <em>events</em> can also be refered to as
+<em>messages</em>. We can also refer to this process “sending a message
+to the task”</p>
+<p>So, for this paper, these are equivalent</p>
+<ul>
+<li>calling a task subroutine with the event information</li>
+<li>sending a message to a task</li>
+</ul>
+</details>
+<figure>
+<img src="dispatch2.jpg" alt="Call task routines with event" />
+<figcaption aria-hidden="true">Call task routines with
+event</figcaption>
+</figure>
+<details>
+<summary>
+Reality check
+</summary>
+<p>It may seem wasteful to send <em>all</em> events to <em>all</em>
+tasks. Probably some tasks don’t care about certain classes of events.
+But classifying, sorting and filtering the events takes real time, and
+code space, and probably isn’t worth it for these small
+microcontrollers.</p>
+<p>More sophisticated event systems do, in fact, filter and sort events.
+For example, Windows only sends <code>MOUSE_MOVE</code> events to the
+code belonging to the window over which the mouse is travelling. All the
+other windows don’t get the event, speeding up the whole system.</p>
+</details>
+<h2 id="tasks">Tasks</h2>
+<p>In this environment, the code that impliments a <em>task</em> is
+simply a subroutine that accepts an <em>event/message</em>.</p>
+<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> taskCode<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span> process the event information <span class="op">...</span></span>
+<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>The subroutine should be designed to flow-through as quickly as
+possible, without any pauses/waits/delays.</p>
+<p>If the problem that you’re trying to solve involves the passage of
+time, or any delay, then you must break down the actions into individual
+items, and build a <a href="#state-machine">state machine</a>.</p>
+<h2 id="state-machine">State Machine</h2>
+<p>A <em>state machine</em> in this environment is a subroutine which
+can be called many times, and it remembers in which <em>state</em> it
+was left from the previous call. Some invocations of this subroutine may
+cause it to change state, which can be represented in a net diagram.</p>
+<p>Here’s a state diagram for the task which reacts to a button press by
+flashing an LED.</p>
+<figure>
+<img src="rtb_state.png" alt="simple state diagram" />
+<figcaption aria-hidden="true">simple state diagram</figcaption>
+</figure>
+<p>How does the <em>state code</em> remember what state it’s in between
+invocations? We can use a <code>static</code> variable. A
+<code>static</code> is stored in main memory (<em>not on the
+stack</em>), persists between calls and is initialized to zero.</p>
+<p>The above diagram can be implemented in this code:</p>
+<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>RTB_IDLE<span class="op">,</span> RTB_ON<span class="op">};</span>          <span class="co">// RTB_IDLE=0, RTB_ON=1</span></span>
+<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8  rtbState      <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 rtbTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 TIMER_LIMIT   <span class="op">=</span> <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> respondToButtonTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>        rtbTimerCount <span class="op">=</span> TIMER_LIMIT<span class="op">;</span></span>
+<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>rtbTimerCount <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>Each time this routine is called, it checks the <em>event</em> that
+it was given, and sometimes processes it. And sometimes it changes
+state.</p>
+<p>Here’s a few things to notice:</p>
+<ul>
+<li>The code <em>flows through</em>. It does not stop or wait for
+anything.</li>
+<li>Each arrow in the net diagram corresponds to a phrase in the code.
+The <em>tail</em> of the arrow corresponds to an <code>if</code>
+statement</li>
+<li>The code ignores <em>events</em> that are not relevant.</li>
+</ul>
+<details>
+<summary>
+Reality check
+</summary>
+<p>The <em>state</em> variable must be <code>static</code> or in the
+global memory space. <em>NEVER put a state variable on the stack!</em>
+i.e. as a local variable.</p>
+The tick counter could equally well count up from zero to threshold. See
+the discussion about <a href="#timers-as-a-resource">shared timers</a>
+</details>
+<h2 id="another-state-machine">Another State Machine</h2>
+<p>The other task of this project simply flashes the LED on and off.</p>
+<p><img src="led_state_simple.png" /></p>
+<p>The code for this might be:</p>
+<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>LED_ON<span class="op">,</span> LED_OFF<span class="op">};</span></span>
+<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8 ledState       <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 LED_ON_TIME   <span class="op">=</span> <span class="dv">100</span><span class="op">;</span></span>
+<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 LED_OFF_TIME  <span class="op">=</span> <span class="dv">100</span><span class="op">;</span></span>
+<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> ledTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>ledState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_OFF<span class="op">:</span></span>
+<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>ledTimerCount <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> LED_ON_TIME<span class="op">;</span></span>
+<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>          ledState <span class="op">=</span> LED_ON<span class="op">;</span></span>
+<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_ON<span class="op">:</span></span>
+<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>ledTimerCount <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> LED_OFF_TIME<span class="op">;</span></span>
+<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>          ledState <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<details>
+<summary>
+Discussion
+</summary>
+<p>Perhaps a more accurate state diagram might be:</p>
+<p><img src="led_state.png" /></p>
+<p>As you build the code from the diagram, I <em>strongly</em> suggest
+that you use a <code>switch(currentState) ....case STATE_1</code>
+approach to the task routine. If you try and code it with multiple
+<code>if(currentState==STATE_1)</code>, you will find yourself in a
+tangle of spaghetti; and if you forget a critical <code>else</code>,
+nothing will work as you expect.</p>
+<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>state<span class="op">==</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVT_1<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    P3OUT <span class="op">=</span> <span class="dv">27</span><span class="op">;</span> <span class="co">// turn on some hardware</span></span>
+<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    state <span class="op">=</span> <span class="dv">2</span><span class="op">;</span>  <span class="co">// and change state</span></span>
+<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> </span>
+<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>state<span class="op">==</span><span class="dv">2</span><span class="op">)</span> <span class="op">{</span> <span class="co">// &lt;&lt;&lt;----- BAD BAD</span></span>
+<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  P3OUT <span class="op">=</span> <span class="dv">14</span><span class="op">;</span></span>
+<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>  state <span class="op">=</span> <span class="dv">3</span><span class="op">;</span>    <span class="co">// &lt;&lt;&lt;--- dont&#39; change state twice in the same event</span></span>
+<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span></code></pre></div>
+<p>rather</p>
+<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="cf">switch</span><span class="op">(</span>state<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">1</span><span class="op">:</span></span>
+<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVT_1<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>      P3OUT <span class="op">=</span> <span class="dv">27</span><span class="op">;</span>   <span class="co">// turn on some hardware</span></span>
+<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>      state <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
+<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">2</span><span class="op">:</span></span>
+<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>    P3OUT <span class="op">=</span> <span class="dv">14</span><span class="op">;</span></span>
+<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>    state <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
+<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
+<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>As a general rule, try to avoid changing states more than once per
+event; this kind of discipline will help with debugging a complex
+project.</p>
+</details>
+<h2 id="dispatcher-details">Dispatcher Details</h2>
+<p>The last piece of the puzzle is the <code>main()</code> code which
+observes the <code>events[]</code> array and calls the tasks.</p>
+<p>The <code>events[]</code> array is designed so that a 0 means ‘no
+event’, and the non-zero events are dropped into the array in order…so
+pulling them out is pretty straight forward.</p>
+<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main<span class="op">()</span> <span class="op">{</span></span>
+<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  initialize<span class="op">();</span></span>
+<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span><span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i<span class="op">;</span></span>
+<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>i<span class="op">=</span><span class="dv">0</span><span class="op">;</span> i<span class="op">&lt;</span>NUM_EVENTS<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
+<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">while</span> <span class="op">(</span>events<span class="op">[</span>i<span class="op">]==</span>EVT_NONE<span class="op">)</span></span>
+<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">{}</span></span>
+<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>      ledTask<span class="op">(</span>events<span class="op">[</span>i<span class="op">]);</span></span>
+<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>      respondToButtonTask<span class="op">(</span>events<span class="op">[</span>i<span class="op">]);</span></span>
+<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>      events<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> EVT_NONE<span class="op">;</span></span>
+<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>Each non-zero event is “sent” to each task…..by means of a subroutine
+call. Once all the tasks have been invoked, the <code>event</code> is
+thrown away and its slot in the array is set to zero.</p>
+<details>
+<summary>
+Reality check
+</summary>
+<p>The <code>main()</code> code above needs to run with interrupts
+enabled.</p>
+<p>There’s lots of ways to structure the ‘wait for event’ loop. For
+example, when you detect that the <code>events[]</code> array is empty,
+you could power-down the microcontroller. In most microprocessors, an
+interrupt will wake the CPU again, and deliver a non-zero event into the
+array, so you might as well power-down while you’re waiting.</p>
+</details>
+<h2 id="final-implementation">Final Implementation</h2>
+<p>Let’s put all of the above together, for an SMT32F Cortex M0, in
+<em>C</em> code.</p>
+<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">/***** declarations ****/</span></span>
+<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define NUM_EVENTS </span><span class="dv">10</span></span>
+<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> uint8 events<span class="op">[</span>NUM_EVENTS<span class="op">];</span></span>
+<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span>uint8 e<span class="op">);</span></span>
+<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> ledTask<span class="op">(</span>uint8 evt<span class="op">);</span></span>
+<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> respondToButtonTask<span class="op">(</span>uint8 evt<span class="op">);</span></span>
+<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="co">/********** interrupts **************/</span></span>
+<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> timer_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_TICK<span class="op">);</span></span>
+<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// this interrupt is auto-ack&#39;d</span></span>
+<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> button_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_BUTTON<span class="op">);</span></span>
+<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>  EXTI<span class="op">-&gt;</span>PR <span class="op">|=</span> KEY_IRQ_ACK_MASK<span class="op">;</span>    <span class="co">// the hardware requires that we acknowledge </span></span>
+<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a><span class="co">/** newEvent</span></span>
+<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="co"> * add the event to the event queue</span></span>
+<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a><span class="co"> * wrapped in critical section</span></span>
+<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span></span>
+<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">the</span><span class="co"> event</span></span>
+<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
+<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span>uint8 e<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> uint8 nextEvent<span class="op">;</span></span>
+<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>  dint<span class="op">();</span> <span class="co">// critical section</span></span>
+<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>  events<span class="op">[</span>nextEvent<span class="op">++]</span> <span class="op">=</span> e<span class="op">;</span></span>
+<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>nextEvent<span class="op">==</span>NUM_EVENTS<span class="op">)</span></span>
+<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>    nextEvent <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>  eint<span class="op">();</span></span>
+<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a><span class="co">/****** main() and dispatcher *********/</span></span>
+<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>  eint<span class="op">();</span></span>
+<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a>  <span class="co">// dispatcher loop</span></span>
+<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span><span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> j<span class="op">;</span></span>
+<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>j<span class="op">=</span><span class="dv">0</span><span class="op">;</span> j<span class="op">&lt;</span>NUM_EVENTS<span class="op">;</span> j<span class="op">++)</span> <span class="op">{</span></span>
+<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a>       <span class="cf">while</span> <span class="op">(</span>events<span class="op">[</span>j<span class="op">]==</span>EVT_NONE<span class="op">)</span></span>
+<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a>         <span class="op">{}</span></span>
+<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a>       ledTask<span class="op">(</span>events<span class="op">[</span>j<span class="op">]);</span></span>
+<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a>       respondToButtonTask<span class="op">(</span>events<span class="op">[</span>j<span class="op">]);</span></span>
+<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a>       events<span class="op">[</span>j<span class="op">]</span> <span class="op">=</span> EVT_NONE<span class="op">;</span></span>
+<span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb13-51"><a href="#cb13-51" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb13-52"><a href="#cb13-52" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb13-53"><a href="#cb13-53" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-54"><a href="#cb13-54" aria-hidden="true" tabindex="-1"></a><span class="co">/*********** task code, with states ************/</span></span>
+<span id="cb13-55"><a href="#cb13-55" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>LED_ON<span class="op">,</span> LED_OFF<span class="op">};</span></span>
+<span id="cb13-56"><a href="#cb13-56" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>RTB_IDLE<span class="op">,</span> RTB_ON<span class="op">};</span>    <span class="co">// states</span></span>
+<span id="cb13-57"><a href="#cb13-57" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8  rtbState      <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb13-58"><a href="#cb13-58" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 rtbTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-59"><a href="#cb13-59" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 LED_ON_TIME   <span class="op">=</span> <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb13-60"><a href="#cb13-60" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-61"><a href="#cb13-61" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> respondToButtonTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-62"><a href="#cb13-62" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-63"><a href="#cb13-63" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb13-64"><a href="#cb13-64" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-65"><a href="#cb13-65" aria-hidden="true" tabindex="-1"></a>        rtbTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-66"><a href="#cb13-66" aria-hidden="true" tabindex="-1"></a>        rtbState      <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb13-67"><a href="#cb13-67" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb13-68"><a href="#cb13-68" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb13-69"><a href="#cb13-69" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb13-70"><a href="#cb13-70" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb13-71"><a href="#cb13-71" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-72"><a href="#cb13-72" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>rtbTimerCount <span class="op">&gt;</span> LED_ON_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-73"><a href="#cb13-73" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb13-74"><a href="#cb13-74" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb13-75"><a href="#cb13-75" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb13-76"><a href="#cb13-76" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb13-77"><a href="#cb13-77" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb13-78"><a href="#cb13-78" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb13-79"><a href="#cb13-79" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb13-80"><a href="#cb13-80" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-81"><a href="#cb13-81" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 LED_ON_TIME   <span class="op">=</span> <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb13-82"><a href="#cb13-82" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span>  uint16 LED_OFF_TIME  <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
+<span id="cb13-83"><a href="#cb13-83" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8 ledState       <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb13-84"><a href="#cb13-84" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-85"><a href="#cb13-85" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb13-86"><a href="#cb13-86" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> ledTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-87"><a href="#cb13-87" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>ledState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-88"><a href="#cb13-88" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_OFF<span class="op">:</span></span>
+<span id="cb13-89"><a href="#cb13-89" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-90"><a href="#cb13-90" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>ledTimerCount <span class="op">&gt;</span> LED_OFF_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-91"><a href="#cb13-91" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED2<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb13-92"><a href="#cb13-92" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-93"><a href="#cb13-93" aria-hidden="true" tabindex="-1"></a>          ledState      <span class="op">=</span> LED_ON<span class="op">;</span></span>
+<span id="cb13-94"><a href="#cb13-94" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb13-95"><a href="#cb13-95" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb13-96"><a href="#cb13-96" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb13-97"><a href="#cb13-97" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_ON<span class="op">:</span></span>
+<span id="cb13-98"><a href="#cb13-98" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-99"><a href="#cb13-99" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>ledTimerCount <span class="op">&gt;</span> LED_ON_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb13-100"><a href="#cb13-100" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED2<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb13-101"><a href="#cb13-101" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb13-102"><a href="#cb13-102" aria-hidden="true" tabindex="-1"></a>          ledState      <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb13-103"><a href="#cb13-103" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb13-104"><a href="#cb13-104" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb13-105"><a href="#cb13-105" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb13-106"><a href="#cb13-106" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb13-107"><a href="#cb13-107" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>This is the end of the main presentation. With the above techniques,
+you can make a tiny microprocessor appear to multitask.</p>
+<p>For further tips, read the next section. The interesting topics
+are:</p>
+<ul>
+<li><a href="#state-machine-examples">more state code examples</a>
+<ul>
+<li>with implementation</li>
+</ul></li>
+<li><a href="#state-machine-initialization">how to initialize a state
+machine</a></li>
+<li><a href="#messages">inter-task communication</a></li>
+<li><a href="#timers">unified timers</a></li>
+</ul>
+<details>
+<summary>
+Reality Check
+</summary>
+<p>What’s missing from this code sample is the initialization of the
+hardware……..some kind of <code>setup()</code> routine. I left it out
+because it’s going to vary so much between processors, and only
+distracts from the point of this paper. If you want a detailed, tested
+copy of this code, see <a href="build/demo.c">here</a></p>
+The above example only shows 2 tasks, so all the formal structure may
+seem a bit silly. But once you have the infrastructure in place, you can
+easily handle <em>dozens</em> of tasks, even on sub-$1 processors.
+</details>
+<h1 id="part-2">Part 2</h1>
+<h2 id="variations">Variations</h2>
+<style>
+.imageleft {float: left;}
+.imageright {float: right;}
+</style>
+<p>Now that the infrastructure is in place, it’s easy to expand or
+modify the code for changes in the project definition.</p>
+<p>For example, suppose we want the <code>respondToButtonTask()</code>
+to restart the LED timer on each key press:</p>
+<p><img src="rtb_state_2.png" class="imageleft" /></p>
+<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> rtbTask<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>        rtbTimer <span class="op">=</span> RTB_TIMEOUT<span class="op">;</span></span>
+<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span> </span>
+<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        rtbTimer <span class="op">=</span> RTB_TIMEOUT<span class="op">;</span></span>
+<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>rtbTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<hr>
+<p>Or have a 2nd press of the button cause the LED to extinguish
+early:</p>
+<p><img src="rtb_state_3.png" class="imageleft" /></p>
+<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> rtbTask<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>        rtbTimer <span class="op">=</span> RTB_TIMEOUT<span class="op">;</span></span>
+<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span> </span>
+<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>rtbTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<hr>
+<p>How about have the button start a flash sequence, and a 2nd press
+stops it: (see also <a href="#substates">substates</a>)</p>
+<p><img src="rtb_state_4.png" class="imageright" /></p>
+<div class="sourceCode" id="cb16"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> rtbTask<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        rtbTimer <span class="op">=</span> RTB_TIMEOUT<span class="op">;</span></span>
+<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span> </span>
+<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>rtbTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>          rtbTimer <span class="op">=</span> RTB_FLASH_TIME<span class="op">;</span></span>
+<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_OFF<span class="op">;</span></span>
+<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_OFF<span class="op">:</span></span>
+<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span> </span>
+<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>rtbTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>          rtbTimer <span class="op">=</span> RTB_FLASH_TIME<span class="op">;</span></span>
+<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<hr>
+<p>Each of these diagrams corresponds to trivial changes in the state
+code.</p>
+<h2 id="working-with-arduino">Working with Arduino</h2>
+<p>If you’re from the Arduino world, you have no doubt seen the
+similarity between this OS plan and the Arduino infrastructure.</p>
+<div class="sourceCode" id="cb17"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>setup<span class="op">()</span> </span>
+<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span>    <span class="co">// initialize and start up the devices and services</span></span>
+<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>loop<span class="op">()</span></span>
+<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span>    <span class="co">// code for continuous operation</span></span></code></pre></div>
+<p>You can certainly merge this paper’s operating system into the
+Arduino architecture:</p>
+<div class="sourceCode" id="cb18"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> events<span class="op">[];</span></span>
+<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>interrupt_service_routines<span class="op">()</span> <span class="op">{</span></span>
+<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>evt<span class="op">);</span> <span class="co">// insert events/messages into events[]</span></span>
+<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>   </span>
+<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> nextEvent<span class="op">;</span></span>
+<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span><span class="dt">char</span> evt<span class="op">)</span> </span>
+<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span> <span class="co">// same as above; put evt into the events[]</span></span>
+<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>setup<span class="op">()</span></span>
+<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span></span>
+<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>loop<span class="op">()</span> <span class="op">{</span></span>
+<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> <span class="dt">int</span> nextTaskEvent<span class="op">;</span></span>
+<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>events<span class="op">[</span>nextTaskEvent<span class="op">]!=</span>EVT_NONE<span class="op">)</span> <span class="op">{</span>        <span class="co">// check for non-zero events[],</span></span>
+<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>    task1<span class="op">(</span>events<span class="op">[</span>nextTaskEvent<span class="op">]);</span>     <span class="co">// and call the task routines</span></span>
+<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>    task2<span class="op">(</span>events<span class="op">[</span>nextTaskEvent<span class="op">]);</span></span>
+<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>    events<span class="op">[</span>nextTaskEvent<span class="op">)</span> <span class="op">=</span> EVT_NONE<span class="op">;</span> <span class="co">// free the slot, fill with 0</span></span>
+<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(++</span>nextTaskEvent <span class="op">&gt;</span> NUM_EVENTS<span class="op">)</span></span>
+<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>      nextTaskEvent <span class="op">=</span> <span class="dv">0</span><span class="op">;</span>              <span class="co">// and loop through the array</span></span>
+<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>  </span>
+<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> task1<span class="op">(</span><span class="dt">char</span> evt<span class="op">)</span> <span class="op">{}</span></span>
+<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> task2<span class="op">(</span><span class="dt">char</span> evt<span class="op">)</span> <span class="op">{}</span></span>
+<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>    </span></code></pre></div>
+<h2 id="tasks-1">Tasks</h2>
+<p>The fundamental guideline for tasks is that <em>they do not
+stop</em>. Control flows through and out the bottom, returning to the
+dispatcher quickly.</p>
+<details>
+<summary>
+Reality Check
+</summary>
+<p>In practical terms, if you have a timer tick that runs at every 10ms,
+and about 5 tasks, then if you can keep each task under 2ms, you won’t
+lose any events.</p>
+<p>If a task occasionally runs into the 10’s of msec, the event queue
+will handle buffering the events until they can be processed.</p>
+Under no circumstances should a task take more than 100msec. Use a new
+state, and return from the tast. Process the new state later.
+<hr>
+</details>
+<h2 id="state-machine-examples">State Machine Examples</h2>
+<h3 id="car-window">Car Window</h3>
+<p>Suppose we want to control the power window on a car? For this
+problem, we have an up/down button, a motor to drive the window up or
+down, and a motor-overload sensor to detect when the motor is straining.
+So the buttons &amp; overload sensor are inputs, and the motor drive is
+outputs.</p>
+<p>When the user presses the “up” button, we should start the motor
+moving upward. When the overload sensor detects a strain, then either
+the window is all the way up….or it has encountered a finger or hand; in
+either case, we need to turn the motor drive off.</p>
+<p>Here’s a possible state diagram. <img src="window_state.png"
+alt="window motor control" /></p>
+<p>And here’s the matching code. Note the correspondence between the
+diagram and the code: arrows leaving a state correspond to an
+<code>if()</code> phrase.</p>
+<div class="sourceCode" id="cb19"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>WINDOW_IDLE<span class="op">,</span> WINDOW_UP<span class="op">,</span> WINDOW_DOWN<span class="op">};</span></span>
+<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8 windowState <span class="op">=</span> WINDOW_IDLE<span class="op">;</span></span>
+<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> windowTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>windowState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> WINDOW_IDLE<span class="op">:</span></span>
+<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_BUTTON_UP<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>MOTOR<span class="op">,</span> UP<span class="op">);</span></span>
+<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        windowState <span class="op">=</span> WINDOW_UP<span class="op">;</span></span>
+<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_BUTTON_DOWN<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>MOTOR<span class="op">,</span> DOWN<span class="op">);</span></span>
+<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>        windowState <span class="op">=</span> WINDOW_DOWN<span class="op">;</span></span>
+<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> WINDOW_UP<span class="op">:</span></span>
+<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_MOTOR_SENSE <span class="op">||</span> </span>
+<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>          evt <span class="op">==</span> EVT_BUTTON_RELEASE<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>MOTOR<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>        windowState <span class="op">=</span> WINDOW_IDLE<span class="op">;</span></span>
+<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> WINDOW_DOWN<span class="op">:</span></span>
+<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_MOTOR_SENSE <span class="op">||</span> </span>
+<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>          evt <span class="op">==</span> EVT_BUTTON_RELEASE<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>MOTOR<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>        windowState <span class="op">=</span> WINDOW_IDLE<span class="op">;</span></span>
+<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>Now, suppose the problem definition is changed: if the user presses
+the “up” button, the motor should only operate while the button is
+pressed; stop on release. But if the user presses the “up” button a
+second time within 1 second of the first release, the motor should drive
+the window all the way up (auto-close).</p>
+<p>Here is a possible state diagram. Notice the significant re-use of
+code from the previous version.</p>
+<figure>
+<img src="window_complex.png"
+alt="window control with auto open/close, (_ma) motor activated (_ms) motor stopped" />
+<figcaption aria-hidden="true">window control with auto open/close,
+(_ma) motor activated (_ms) motor stopped</figcaption>
+</figure>
+<details>
+<summary>
+Reality Check
+</summary>
+<p>This is such a simple task, with only a few I/O pins involved. In
+theory, a cheap microcontroller could control a dozen windows, each
+appearing to operate independantly.</p>
+<p>In the code, one wouldn’t need to create a dozen tasks……just create
+an index into the same code and invoke it in a way that makes it appear
+as an independent task:</p>
+<pre><code>void main(void) {
+  eint();
+  while(1) {
+    for (i=0; i&lt;NUM_EVENTS; i++) {
+      while (events[i]==EVT_NONE)
+        {}
+      taskWindow(events[i],0);
+      taskWindow(events[i],1);
+      // ...
+      taskWindow(events[i],NUM_WINDOWS-1);
+      events[i] = EVT_NONE;
+    }
+  }
+}
+
+// window management task
+int windowState[NUM_WINDOWS];
+void taskWindow(char event, int windowIndex) {
+  // find the state from the windowState[windowIndex] 
+  // run through the state machine
+  // any I/O will require an array of I/O addresses, use &#39;windowIndex&#39;
+
+  switch(windowState[windowIndex]) {
+    case WS_IDLE:
+      ...
+      ...
+  }
+}</code></pre>
+</details>
+<h3 id="fridge-door">Fridge Door</h3>
+<p>A simple state machine can control the interior light of a fridge.
+Here’s the use-case:</p>
+<p>The problem has one input (door open) and two outputs (light and
+audible alarm). If the door is open, turn on the light and start a timer
+for 90 seconds. If the door is still open at the end of the 90 seconds,
+start an audible alarm. If the door closes, stop the timer and turn off
+the light and alarm. And if the door closes during the 90 seconds, turn
+off the light.</p>
+<p>Here is the state diagram.</p>
+<p><img src="fridge_state.png" /></p>
+<p>And here is the corresponding code.</p>
+<div class="sourceCode" id="cb21"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>FRIDGE_CLOSED<span class="op">,</span> FRIDGE_OPEN<span class="op">,</span> FRIDGE_BEEPING<span class="op">};</span></span>
+<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>uint8  fridgeState<span class="op">;</span></span>
+<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>uint16 fridgeTimer<span class="op">;</span></span>
+<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 FRIDGE_OPEN_LIMIT <span class="op">=</span> <span class="dv">9000</span><span class="op">;</span> <span class="co">// 90 seconds at 10msec tick</span></span>
+<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fridgeTask<span class="op">(</span><span class="dt">char</span> event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>fridgeState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_CLOSED<span class="op">:</span></span>
+<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_OPEN<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>        set_io<span class="op">(</span>LIGHT<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>        fridgeTimer <span class="op">=</span> FRIDGE_OPEN_LIMIT<span class="op">;</span></span>
+<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>        fridgeState <span class="op">=</span> FRIDGE_OPEN<span class="op">;</span></span>
+<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_OPEN<span class="op">:</span></span>
+<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_CLOSE<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>        set_io<span class="op">(</span>LIGHT<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>        fridgeState <span class="op">=</span> FRIDGE_CLOSED<span class="op">;</span></span>
+<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>fridgeTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>          set_io<span class="op">(</span>ALARM<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>          fridgeState <span class="op">=</span> FRIDGE_BEEPING<span class="op">;</span></span>
+<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_BEEPING<span class="op">:</span></span>
+<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_CLOSE<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a>        set_io<span class="op">(</span>ALARM<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a>        set_io<span class="op">(</span>LIGHT<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb21-30"><a href="#cb21-30" aria-hidden="true" tabindex="-1"></a>        fridgeState <span class="op">=</span> FRIDGE_CLOSED<span class="op">;</span></span>
+<span id="cb21-31"><a href="#cb21-31" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb21-32"><a href="#cb21-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb21-33"><a href="#cb21-33" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb21-34"><a href="#cb21-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<h4 id="refactor-for-changestate">Refactor for
+<code>changeState()</code></h4>
+<p>Notice on the state diagram, the arrows heads and tails cluster, and
+similar actions happen for multiple arrows. Perhaps we should write a
+function that just deals with all the actions required when leaving or
+entering a state. Then the task code would only have to manage the
+<em>arrows</em> of the state diagram. Like this:</p>
+<div class="sourceCode" id="cb22"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co">// this outer code deals with the arrows on the state diagram</span></span>
+<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fridgeTask<span class="op">(</span><span class="dt">char</span> event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span> <span class="op">(</span>fridgeState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_CLOSED<span class="op">:</span></span>
+<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_OPEN<span class="op">)</span> changeFridgeState<span class="op">(</span>FRIDGE_OPEN<span class="op">);</span></span>
+<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_OPEN<span class="op">:</span></span>
+<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_CLOSE<span class="op">)</span> changeFridgeState<span class="op">(</span>FRIDGE_CLOSED<span class="op">);</span></span>
+<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_FRIDGE_TIMEOUT<span class="op">)</span> changeFridgeState<span class="op">(</span>FRIDGE_BEEPING<span class="op">);</span></span>
+<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_BEEPING<span class="op">:</span></span>
+<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_CLOSE<span class="op">)</span> changeFridgeState<span class="op">(</span>FRIDGE_CLOSED<span class="op">);</span></span>
+<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>while the inner code deals with the actions required for
+<em>entry</em> and <em>exit</em> from each state</p>
+<div class="sourceCode" id="cb23"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> changeFridgeState<span class="op">(</span><span class="dt">char</span> newState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> <span class="dt">char</span> oldState <span class="op">=</span> FRIDGE_CLOSED<span class="op">;</span></span>
+<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// do all the state-leaving actions</span></span>
+<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>oldState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_CLOSED<span class="op">:</span></span>
+<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>      set_io<span class="op">(</span>LIGHT<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>      setTimer<span class="op">(</span>FRIDGE_TIMER<span class="op">,</span> FRIDGE_OPEN_LIMIT<span class="op">);</span></span>
+<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_OPEN<span class="op">:</span></span>
+<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_BEEPING<span class="op">:</span></span>
+<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>      set_io<span class="op">(</span>ALARM<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// change state</span></span>
+<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>  fridgeState <span class="op">=</span> oldState <span class="op">=</span> newState<span class="op">;</span></span>
+<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">// and do the state-entry code</span></span>
+<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>newState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_CLOSED<span class="op">:</span></span>
+<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>      set_io<span class="op">(</span>LIGHT<span class="op">,</span> OFF<span class="op">);</span></span>
+<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a>      setTimer<span class="op">(</span>FRIDGE_TIMER<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
+<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-23"><a href="#cb23-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_OPEN<span class="op">:</span></span>
+<span id="cb23-24"><a href="#cb23-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-25"><a href="#cb23-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FRIDGE_BEEPING<span class="op">:</span></span>
+<span id="cb23-26"><a href="#cb23-26" aria-hidden="true" tabindex="-1"></a>      set_io<span class="op">(</span>ALARM<span class="op">,</span> ON<span class="op">);</span></span>
+<span id="cb23-27"><a href="#cb23-27" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb23-28"><a href="#cb23-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb23-29"><a href="#cb23-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<h3 id="door-opener">Door Opener</h3>
+<p>Suppose we have a power lock on a door, using a solenoid, and an RFID
+tag detector on the “outside” and a push button on the “inside”. There
+is also a WiFi connection to a server, by which we report door openings.
+When the RFID tag sends us a message, it will contain a serial number.
+If the number matches a known record, then operate the door-opener
+solenoid for 4 seconds. If the “inside” button is pushed, operate the
+door-opener for 4 seconds; if the “inside” button is pressed during the
+4 seconds, restart the 4 second timer.</p>
+<p>After the door is locked, send a report to the master control via the
+WiFi.</p>
+<p>Here’s the state diagram:</p>
+<figure>
+<img src="door.png" alt="RFID operated door lock" />
+<figcaption aria-hidden="true">RFID operated door lock</figcaption>
+</figure>
+<p>I use <code>EVT_</code> type events to indicate that they originate
+in hardware, probably at the interrupt level; and <code>MSG_</code> type
+events to indicate they come from a software source, perhaps a sibling
+task.</p>
+<p>Suppose now that the serial number needs to be verified by a central
+service. So when an RFID tag is detected, send a request to the master
+control and wait for an ACK or NAK response. In the case of an ACK, open
+the door solenoid for 4 seconds. The rest of the problem is as stated
+above.</p>
+<p>Here’s the modified state diagram:</p>
+<figure>
+<img src="door2.png" alt="RFID operated door, with remove key verify" />
+<figcaption aria-hidden="true">RFID operated door, with remove key
+verify</figcaption>
+</figure>
+<h3 id="beer-vat">Beer Vat</h3>
+<p>Suppose we have to move a servo motor to lift the lid from a brewing
+vat, to release excess pressure.</p>
+<p>Inputs: pressure valve, manual operation button Outputs: servo, LED,
+beeper</p>
+<p>If high pressure is detected, flash the LED for 10 seconds, then
+operate the beeper for 5 seconds, then operate servo; hold it open for 5
+seconds and return the servo, LED and beeper to idle.</p>
+<p>If the manual operation button is pressed, go directly to “operate
+servo” as above. <img src="beer_vat.png"
+alt="state machine for beer vat pressure release valve" /></p>
+<p>If the manual button is pressed while the lid is open, close
+immediately.</p>
+<h3 id="vending-machine">Vending Machine</h3>
+<p>When idle, wait for payment tap. If selection button is pressed
+before payment, display cost to inform the user for 3 seconds.</p>
+<p>After payment tap, request the user select item.</p>
+<p>Operate dispense motor.</p>
+<p>Wait for object to be removed from output bin.</p>
+<figure>
+<img src="vending.png" alt="states for vending machine" />
+<figcaption aria-hidden="true">states for vending machine</figcaption>
+</figure>
+<h2 id="events-1">Events</h2>
+<p>In all the above, events were implemented as a simple
+<code>unsigned char</code>, allowing 255 different event types.</p>
+<p>There’s no reason we couldn’t use an <code>unsigned short</code> or
+even an <code>int</code>. Further, a 16 bit event number could be
+designed to be 8 bits of event type, and 8 bits of supplementary event
+information:</p>
+<div class="sourceCode" id="cb24"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> Event <span class="op">{</span></span>
+<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">unsigned</span> <span class="dt">char</span> type<span class="op">;</span></span>
+<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">unsigned</span> <span class="dt">char</span> info<span class="op">;</span></span>
+<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> Event<span class="op">;</span></span>
+<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>Event e <span class="op">=</span> <span class="op">{</span>MSG_KEYPRESS<span class="op">,</span> KEY_A<span class="op">};</span></span></code></pre></div>
+<p>In the old Windows system, <em>events/messages</em> were realized as
+a 16 bit number, with an extra 32 bit number glued to it for extra
+information.</p>
+<div class="sourceCode" id="cb25"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> MSG <span class="op">{</span></span>
+<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>  UINT   message<span class="op">;</span></span>
+<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>  LPARAM lParam<span class="op">;</span></span>
+<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="op">};</span>    <span class="co">// some extra detail removed</span></span></code></pre></div>
+For example, <code>WM_CHAR=0x0102</code> indicates that a key was
+pressed, with the extra 32bit <code>lParam</code> carrying the
+information about <em>which</em> key.
+<hr>
+<h2 id="timers">Timers</h2>
+<p>The simplest state timer is made with a static variable associated
+with the state code.</p>
+<p>To start the timer, simply initialize the static variable. On timer
+ticks, decrement (or increment if you prefer) this variable until it
+hits a limit, and then make a state change.</p>
+<p>For instance, to create a timer that waits 100 timer ticks, you could
+use:</p>
+<div class="sourceCode" id="cb26"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> state<span class="op">;</span></span>
+<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> stateTimer<span class="op">;</span></span>
+<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> stateCode<span class="op">(</span><span class="dt">char</span> event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>state<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE_IDLE<span class="op">:</span></span>
+<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVENT_TRIGGER<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>        stateTimer <span class="op">=</span> <span class="dv">100</span><span class="op">;</span></span>
+<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> STATE_DELAY<span class="op">;</span></span>
+<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE_DELAY<span class="op">:</span></span>
+<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVENT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>stateTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>          <span class="co">// the timer is finished</span></span>
+<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>          state <span class="op">=</span> STATE_NEXT<span class="op">;</span></span>
+<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ....</span></span>
+<span id="cb26-20"><a href="#cb26-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb26-21"><a href="#cb26-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb26-22"><a href="#cb26-22" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-23"><a href="#cb26-23" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-24"><a href="#cb26-24" aria-hidden="true" tabindex="-1"></a>In the above example<span class="op">,</span> you could equally well have set the timer to start at zero</span>
+<span id="cb26-25"><a href="#cb26-25" aria-hidden="true" tabindex="-1"></a>and increment until it hits the desired limit <span class="op">(</span><span class="dv">100</span> in this <span class="cf">case</span><span class="op">).</span></span>
+<span id="cb26-26"><a href="#cb26-26" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-27"><a href="#cb26-27" aria-hidden="true" tabindex="-1"></a>In a moderate sized project<span class="op">,</span> timers like this will proliferate throughout the code<span class="op">,</span></span>
+<span id="cb26-28"><a href="#cb26-28" aria-hidden="true" tabindex="-1"></a>making it awkward to read<span class="op">.</span> One solution to this is to centralize the timers<span class="op">.</span></span>
+<span id="cb26-29"><a href="#cb26-29" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-30"><a href="#cb26-30" aria-hidden="true" tabindex="-1"></a>In all the above examples<span class="op">,</span> the `timer_irq<span class="op">()</span>` code is trivial<span class="op">,</span> just `newEvent<span class="op">(</span>EVT_TICK<span class="op">)</span>`<span class="op">.</span></span>
+<span id="cb26-31"><a href="#cb26-31" aria-hidden="true" tabindex="-1"></a>Suppose we add code to the `timer_irq<span class="op">()</span>` so that it can process timer counting on</span>
+<span id="cb26-32"><a href="#cb26-32" aria-hidden="true" tabindex="-1"></a>behalf of the tasks<span class="op">......</span></span>
+<span id="cb26-33"><a href="#cb26-33" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-34"><a href="#cb26-34" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">## Timers as a Resource</span></span>
+<span id="cb26-35"><a href="#cb26-35" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-36"><a href="#cb26-36" aria-hidden="true" tabindex="-1"></a>Let<span class="ch">&#39;s</span><span class="er"> create a centralized service called `setTimer(timer_index, timer_count)`. </span></span>
+<span id="cb26-37"><a href="#cb26-37" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-38"><a href="#cb26-38" aria-hidden="true" tabindex="-1"></a>A task can call this service with a unique `timer_index` and a requested count<span class="op">.</span> The</span>
+<span id="cb26-39"><a href="#cb26-39" aria-hidden="true" tabindex="-1"></a>`timer_irq<span class="op">()</span>` will then count out the ticks on behalf of the task<span class="op">,</span> and when the tick</span>
+<span id="cb26-40"><a href="#cb26-40" aria-hidden="true" tabindex="-1"></a>count is finished<span class="op">,</span> the `timer_irq<span class="op">()</span>` code can generate a unique event<span class="op">,</span> perhaps</span>
+<span id="cb26-41"><a href="#cb26-41" aria-hidden="true" tabindex="-1"></a>`EVT_TIMER_n`<span class="op">.</span> </span>
+<span id="cb26-42"><a href="#cb26-42" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-43"><a href="#cb26-43" aria-hidden="true" tabindex="-1"></a>So the state code can then look something like this<span class="op">:</span></span>
+<span id="cb26-44"><a href="#cb26-44" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb26-45"><a href="#cb26-45" aria-hidden="true" tabindex="-1"></a>```C</span>
+<span id="cb26-46"><a href="#cb26-46" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> state<span class="op">;</span></span>
+<span id="cb26-47"><a href="#cb26-47" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> stateCode<span class="op">(</span><span class="dt">char</span> event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-48"><a href="#cb26-48" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>state<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-49"><a href="#cb26-49" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE_IDLE<span class="op">:</span></span>
+<span id="cb26-50"><a href="#cb26-50" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVENT_TRIGGER<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-51"><a href="#cb26-51" aria-hidden="true" tabindex="-1"></a>        setTimer<span class="op">(</span>TIMER_1<span class="op">,</span><span class="dv">100</span><span class="op">);</span></span>
+<span id="cb26-52"><a href="#cb26-52" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> STATE_DELAY<span class="op">;</span></span>
+<span id="cb26-53"><a href="#cb26-53" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb26-54"><a href="#cb26-54" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb26-55"><a href="#cb26-55" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE_DELAY<span class="op">:</span></span>
+<span id="cb26-56"><a href="#cb26-56" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">=</span> EVENT_TIMER_1<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb26-57"><a href="#cb26-57" aria-hidden="true" tabindex="-1"></a>          <span class="co">// the timer is finished</span></span>
+<span id="cb26-58"><a href="#cb26-58" aria-hidden="true" tabindex="-1"></a>          state <span class="op">=</span> STATE_NEXT<span class="op">;</span></span>
+<span id="cb26-59"><a href="#cb26-59" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb26-60"><a href="#cb26-60" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb26-61"><a href="#cb26-61" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb26-62"><a href="#cb26-62" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ....</span></span>
+<span id="cb26-63"><a href="#cb26-63" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb26-64"><a href="#cb26-64" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>This makes the state code much simpler to read, hiding all the
+increments/decrements and limit testing.</p>
+<p>The overhead for this ends up in the <code>timer_irq()</code> code,
+and might look something like this:</p>
+<div class="sourceCode" id="cb27"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">unsigned</span> <span class="dt">int</span> timers<span class="op">[</span>NUM_TIMERS<span class="op">];</span></span>
+<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define EVT_TIMER_OFFSET </span><span class="dv">100</span></span>
+<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>EVENT_TIMER_1<span class="op">=</span>EVT_TIMER_OFFSET<span class="op">,</span> EVENT_TIMER_2<span class="op">,</span> EVENT_TIMER_3<span class="op">};</span> <span class="co">// 100, 101...</span></span>
+<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>TIMER_1<span class="op">,</span> TIMER_2<span class="op">,</span> TIMER_3<span class="op">};</span>   <span class="co">// 0,1,2,....</span></span>
+<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> timer_irq<span class="op">()</span> <span class="op">{</span></span>
+<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_TICK<span class="op">);</span>           <span class="co">// the main tick, fires every time</span></span>
+<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span>i<span class="op">=</span><span class="dv">0</span><span class="op">;</span> i<span class="op">&lt;</span>NUM_TIMERS<span class="op">)</span> <span class="op">{</span>     <span class="co">// the system timers, fires on completion</span></span>
+<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>timers<span class="op">[</span>i<span class="op">]&gt;</span><span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(--</span>timers<span class="op">[</span>i<span class="op">]==</span><span class="dv">0</span><span class="op">)</span></span>
+<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>        newEvent<span class="op">(</span>i <span class="op">+</span> EVT_TIMER_OFFSET<span class="op">);</span></span>
+<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a><span class="co">/* common service, available to all tasks */</span></span>
+<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> setTimer<span class="op">(</span><span class="dt">int</span> timerIndex<span class="op">,</span> <span class="dt">unsigned</span> <span class="dt">int</span> timerCount<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb27-18"><a href="#cb27-18" aria-hidden="true" tabindex="-1"></a>  timers<span class="op">[</span>timerIndex<span class="op">]</span> <span class="op">=</span> timerCount<span class="op">;</span></span>
+<span id="cb27-19"><a href="#cb27-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<details>
+<summary>
+Reality Check
+</summary>
+<p>On a typical microcontroller running at 24MHz, with 5 timers, this
+adds about 2 microseconds of extra time to the <code>timer_irq()</code>
+code, which typically runs every 10 or 100msec. It considerably
+simplifies the task code, makes it more legible and probably reduces
+bugs that may appear by duplication of code.</p>
+<p>Another possible design for timers is to have the main
+<code>timer_isr()</code> increment a global atomic
+<code>voloatile int timer</code> variable, and the tasks can observe
+this timer and set a target based on that.</p>
+<div class="sourceCode" id="cb28"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> <span class="dt">int</span> timer<span class="op">;</span>         <span class="co">// on most microcontrollers, access to an int</span></span>
+<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>                            <span class="co">// will be atomic</span></span>
+<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>INTERRUPT timer_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  timer<span class="op">++;</span></span>
+<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_TICK<span class="op">);</span></span>
+<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="co">// .... state code ...</span></span>
+<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> targetTime<span class="op">;</span></span>
+<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> stateCode<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>state<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE1<span class="op">:</span></span>
+<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>      <span class="co">//..... set a target</span></span>
+<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>      targetTimer <span class="op">=</span> time <span class="op">+</span> DELAY_TIME<span class="op">;</span></span>
+<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>      state <span class="op">=</span> state2<span class="op">;</span></span>
+<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>      <span class="co">//.....</span></span>
+<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE2<span class="op">:</span></span>
+<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>time <span class="op">==</span> targetTimer<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a>          <span class="co">//.... we&#39;ve waited long enough</span></span>
+<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">//...</span></span>
+<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+</details>
+<h2 id="real-code">Real Code</h2>
+<p>Here is an example of a complete and tested project on a small
+STM32F030 board. Open all the little arrows to see the complete
+code.</p>
+<details>
+<summary>
+board specific defines
+</summary>
+<div class="sourceCode" id="cb29"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&quot;stm32f030.h&quot;</span></span>
+<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="co">/****** project hardware ******/</span></span>
+<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="co">// on this demo board, there is a push button on PB13 and</span></span>
+<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="co">// an LED on PA4 and PF5</span></span>
+<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define LED  </span><span class="bn">0x10</span><span class="pp"> </span><span class="co">// port A bit 4  these LED are LOW=lit-up</span></span>
+<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define LED2 </span><span class="bn">0x50020</span><span class="pp"> </span><span class="co">// port F bit 5</span></span>
+<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>GPIO_TypeDef <span class="op">*</span> GROUP<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span>GPIOA<span class="op">,</span> GPIOB<span class="op">,</span> GPIOC<span class="op">,</span> GPIOD<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> GPIOF<span class="op">};</span>  <span class="co">// 0,0x10000,0x20000, etc</span></span>
+<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> gpio_set<span class="op">(</span>uint32 bitPosition<span class="op">,</span> <span class="dt">bool</span> value<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>  vu32<span class="op">*</span> group <span class="op">=</span> <span class="op">&amp;((</span>GROUP<span class="op">[</span>bitPosition <span class="op">&gt;&gt;</span> <span class="dv">16</span><span class="op">])-&gt;</span>ODR<span class="op">);</span></span>
+<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>  bitPosition <span class="op">&amp;=</span> <span class="bn">0xFFFF</span><span class="op">;</span></span>
+<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>value<span class="op">)</span></span>
+<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>group <span class="op">|=</span> bitPosition<span class="op">;</span></span>
+<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span></span>
+<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>group <span class="op">&amp;=</span> <span class="op">~</span>bitPosition<span class="op">;</span></span>
+<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+</details>
+<div class="sourceCode" id="cb30"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="co">/***** events ****/</span></span>
+<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define NUM_EVENTS </span><span class="dv">10</span></span>
+<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> uint8 events<span class="op">[</span>NUM_EVENTS<span class="op">];</span></span>
+<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span> EVT_NONE<span class="op">,</span></span>
+<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>      EVT_TICK<span class="op">,</span></span>
+<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>      EVT_BUTTON<span class="op">};</span></span>
+<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span>uint8 e<span class="op">);</span></span>
+<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="co">/********** tasks ***********/</span></span>
+<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> ledTask<span class="op">(</span>uint8 evt<span class="op">);</span></span>
+<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> respondToButtonTask<span class="op">(</span>uint8 evt<span class="op">);</span></span>
+<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a><span class="co">/********** interrupts **************/</span></span>
+<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a><span class="dt">volatile</span> uint32 tick<span class="op">;</span>   <span class="co">// increasing at 100 ticks/sec</span></span>
+<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>                        <span class="co">// takes a year to roll-over</span></span>
+<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> timer_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a>  tick<span class="op">++;</span></span>
+<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_TICK<span class="op">);</span></span>
+<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// this interrupt is auto-ack&#39;d</span></span>
+<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> button_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb30-24"><a href="#cb30-24" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_BUTTON<span class="op">);</span></span>
+<span id="cb30-25"><a href="#cb30-25" aria-hidden="true" tabindex="-1"></a>  EXTI<span class="op">-&gt;</span>PR <span class="op">|=</span> <span class="bn">0x3001</span><span class="op">;</span>    <span class="co">// ack it </span></span>
+<span id="cb30-26"><a href="#cb30-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb30-27"><a href="#cb30-27" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb30-28"><a href="#cb30-28" aria-hidden="true" tabindex="-1"></a><span class="co">/** newEvent</span></span>
+<span id="cb30-29"><a href="#cb30-29" aria-hidden="true" tabindex="-1"></a><span class="co"> * add the event to the event queue</span></span>
+<span id="cb30-30"><a href="#cb30-30" aria-hidden="true" tabindex="-1"></a><span class="co"> * wrapped in critical section</span></span>
+<span id="cb30-31"><a href="#cb30-31" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span></span>
+<span id="cb30-32"><a href="#cb30-32" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">the</span><span class="co"> event</span></span>
+<span id="cb30-33"><a href="#cb30-33" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
+<span id="cb30-34"><a href="#cb30-34" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> newEvent<span class="op">(</span><span class="dt">char</span> e<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb30-35"><a href="#cb30-35" aria-hidden="true" tabindex="-1"></a>        <span class="dt">static</span> uint nextEvent<span class="op">;</span></span>
+<span id="cb30-36"><a href="#cb30-36" aria-hidden="true" tabindex="-1"></a>        dint<span class="op">();</span> <span class="co">// critical section</span></span>
+<span id="cb30-37"><a href="#cb30-37" aria-hidden="true" tabindex="-1"></a>        events<span class="op">[</span>nextEvent<span class="op">++]</span> <span class="op">=</span> e<span class="op">;</span></span>
+<span id="cb30-38"><a href="#cb30-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>nextEvent<span class="op">==</span>NUM_EVENTS<span class="op">)</span></span>
+<span id="cb30-39"><a href="#cb30-39" aria-hidden="true" tabindex="-1"></a>                nextEvent <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb30-40"><a href="#cb30-40" aria-hidden="true" tabindex="-1"></a>        eint<span class="op">();</span></span>
+<span id="cb30-41"><a href="#cb30-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+</details>
+<details>
+<summary>
+hardware initialization
+</summary>
+<div class="sourceCode" id="cb31"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="co">/***** init ******/</span></span>
+<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="co">/* called by newlib startup */</span></span>
+<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> _init<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// startup code</span></span>
+<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// use default clocks</span></span>
+<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// turn on all the GPIO&#39;s</span></span>
+<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>  RCC<span class="op">-&gt;</span>AHBENR  <span class="op">=</span> <span class="bn">0x005e0014</span><span class="op">;</span></span>
+<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// enable SysCfg</span></span>
+<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>  RCC<span class="op">-&gt;</span>APB2ENR <span class="op">=</span> <span class="bn">0x00004801</span><span class="op">;</span></span>
+<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// enable the two LEDs as outputs</span></span>
+<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>  GPIOA<span class="op">-&gt;</span>MODER <span class="op">=</span> <span class="op">(</span>GPIOA<span class="op">-&gt;</span>MODER <span class="op">&amp;</span> <span class="bn">0xFFFFFCFF</span><span class="op">)</span> <span class="op">|</span> <span class="bn">0x00000100</span><span class="op">;</span> <span class="co">// port A bit 4</span></span>
+<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>  GPIOF<span class="op">-&gt;</span>MODER <span class="op">=</span> <span class="op">(</span>GPIOF<span class="op">-&gt;</span>MODER <span class="op">&amp;</span> <span class="bn">0xFFFFF3FF</span><span class="op">)</span> <span class="op">|</span> <span class="bn">0x00000400</span><span class="op">;</span> <span class="co">// port F bit 5</span></span>
+<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// and the push button as input + pulldown</span></span>
+<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a>  GPIOB<span class="op">-&gt;</span>PUPDR <span class="op">=</span> <span class="op">(</span>GPIOB<span class="op">-&gt;</span>PUPDR <span class="op">&amp;</span> <span class="bn">0xF3FFFFFF</span><span class="op">)</span> <span class="op">|</span> <span class="bn">0x08000000</span><span class="op">;</span> <span class="co">// pulldown on 13</span></span>
+<span id="cb31-18"><a href="#cb31-18" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// keep the clocking system simple: just use the 8MHz HSI everywhere</span></span>
+<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a>  SysTick<span class="op">-&gt;</span>LOAD <span class="op">=</span> <span class="dv">10000</span><span class="op">;</span>                <span class="co">// 10 msec</span></span>
+<span id="cb31-21"><a href="#cb31-21" aria-hidden="true" tabindex="-1"></a>  SysTick<span class="op">-&gt;</span>VAL  <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb31-22"><a href="#cb31-22" aria-hidden="true" tabindex="-1"></a>  SysTick<span class="op">-&gt;</span>CTRL <span class="op">=</span> <span class="dv">3</span><span class="op">;</span>                    <span class="co">// count at 1usec, use interrupts</span></span>
+<span id="cb31-23"><a href="#cb31-23" aria-hidden="true" tabindex="-1"></a> </span>
+<span id="cb31-24"><a href="#cb31-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* to configure an interrupt on the stm32f0xx,</span></span>
+<span id="cb31-25"><a href="#cb31-25" aria-hidden="true" tabindex="-1"></a><span class="co">    - enable the EXTI-&gt;IMR for the pin</span></span>
+<span id="cb31-26"><a href="#cb31-26" aria-hidden="true" tabindex="-1"></a><span class="co">    - set EXTI-&gt;RTSR for select rising edge</span></span>
+<span id="cb31-27"><a href="#cb31-27" aria-hidden="true" tabindex="-1"></a><span class="co">    - set the SYSCFG-&gt;EXTICRx pin to route it </span></span>
+<span id="cb31-28"><a href="#cb31-28" aria-hidden="true" tabindex="-1"></a><span class="co">    - enable the gating bit in the NVIC register </span></span>
+<span id="cb31-29"><a href="#cb31-29" aria-hidden="true" tabindex="-1"></a><span class="co">    - don&#39;t forget to ack each interrupt at EXTI-&gt;PR</span></span>
+<span id="cb31-30"><a href="#cb31-30" aria-hidden="true" tabindex="-1"></a><span class="co">  */</span></span>
+<span id="cb31-31"><a href="#cb31-31" aria-hidden="true" tabindex="-1"></a>  EXTI<span class="op">-&gt;</span>IMR         <span class="op">=</span> <span class="bn">0x2000</span><span class="op">;</span>        <span class="co">// enable interrupt from line 13</span></span>
+<span id="cb31-32"><a href="#cb31-32" aria-hidden="true" tabindex="-1"></a>  EXTI<span class="op">-&gt;</span>RTSR        <span class="op">=</span> <span class="bn">0x2000</span><span class="op">;</span>        <span class="co">// interrupt on rising edge</span></span>
+<span id="cb31-33"><a href="#cb31-33" aria-hidden="true" tabindex="-1"></a>  SYSCFG<span class="op">-&gt;</span>EXTICR<span class="op">[</span><span class="dv">3</span><span class="op">]</span> <span class="op">=</span> <span class="bn">0x0010</span><span class="op">;</span>   <span class="co">// select prot B for exti-13</span></span>
+<span id="cb31-34"><a href="#cb31-34" aria-hidden="true" tabindex="-1"></a>  NVIC<span class="op">-&gt;</span>ISER<span class="op">[</span><span class="dv">0</span><span class="op">]</span>     <span class="op">=</span> <span class="bn">0x00E1</span><span class="op">;</span>        <span class="co">// enable in NVIC: gpio &amp; watchdog</span></span>
+<span id="cb31-35"><a href="#cb31-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+</details>
+<div class="sourceCode" id="cb32"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  eint<span class="op">();</span></span>
+<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// dispatcher loop</span></span>
+<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span><span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> j<span class="op">;</span></span>
+<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>j<span class="op">=</span><span class="dv">0</span><span class="op">;</span> j<span class="op">&lt;</span>NUM_EVENTS<span class="op">;</span> j<span class="op">++)</span> <span class="op">{</span></span>
+<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>       <span class="cf">while</span> <span class="op">(</span>events<span class="op">[</span>j<span class="op">]==</span>EVT_NONE<span class="op">)</span></span>
+<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>         <span class="op">{}</span></span>
+<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>       ledTask<span class="op">(</span>events<span class="op">[</span>j<span class="op">]);</span></span>
+<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>       respondToButtonTask<span class="op">(</span>events<span class="op">[</span>j<span class="op">]);</span></span>
+<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>       events<span class="op">[</span>j<span class="op">]</span> <span class="op">=</span> EVT_NONE<span class="op">;</span></span>
+<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a><span class="co">/*********** task code, with states ************/</span></span>
+<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>LED_ON<span class="op">,</span> LED_OFF<span class="op">};</span></span>
+<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>RTB_IDLE<span class="op">,</span> RTB_ON<span class="op">};</span>    <span class="co">// states</span></span>
+<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8 rtbState           <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 rtbTimerCount     <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 BUTTON_LED_ON_TIME <span class="op">=</span> <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> respondToButtonTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>rtbState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a>        rtbState      <span class="op">=</span> RTB_ON<span class="op">;</span></span>
+<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a>        rtbTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a>        gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_ON<span class="op">:</span></span>
+<span id="cb32-35"><a href="#cb32-35" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-36"><a href="#cb32-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>rtbTimerCount <span class="op">&gt;</span> BUTTON_LED_ON_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-37"><a href="#cb32-37" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb32-38"><a href="#cb32-38" aria-hidden="true" tabindex="-1"></a>          rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb32-39"><a href="#cb32-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb32-40"><a href="#cb32-40" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb32-41"><a href="#cb32-41" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb32-42"><a href="#cb32-42" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb32-43"><a href="#cb32-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb32-44"><a href="#cb32-44" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-45"><a href="#cb32-45" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 LED_ON_TIME  <span class="op">=</span> <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb32-46"><a href="#cb32-46" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 LED_OFF_TIME <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
+<span id="cb32-47"><a href="#cb32-47" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint8 ledState       <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb32-48"><a href="#cb32-48" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> uint16 ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb32-49"><a href="#cb32-49" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb32-50"><a href="#cb32-50" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> ledTask<span class="op">(</span>uint8 evt<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-51"><a href="#cb32-51" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>ledState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-52"><a href="#cb32-52" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_OFF<span class="op">:</span></span>
+<span id="cb32-53"><a href="#cb32-53" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-54"><a href="#cb32-54" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>ledTimerCount <span class="op">&gt;</span> LED_OFF_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-55"><a href="#cb32-55" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED2<span class="op">,</span> LED_ON<span class="op">);</span></span>
+<span id="cb32-56"><a href="#cb32-56" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb32-57"><a href="#cb32-57" aria-hidden="true" tabindex="-1"></a>          ledState      <span class="op">=</span> LED_ON<span class="op">;</span></span>
+<span id="cb32-58"><a href="#cb32-58" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb32-59"><a href="#cb32-59" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb32-60"><a href="#cb32-60" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb32-61"><a href="#cb32-61" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> LED_ON<span class="op">:</span></span>
+<span id="cb32-62"><a href="#cb32-62" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>evt <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-63"><a href="#cb32-63" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(++</span>ledTimerCount <span class="op">&gt;</span> LED_ON_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb32-64"><a href="#cb32-64" aria-hidden="true" tabindex="-1"></a>          gpio_set<span class="op">(</span>LED2<span class="op">,</span> LED_OFF<span class="op">);</span></span>
+<span id="cb32-65"><a href="#cb32-65" aria-hidden="true" tabindex="-1"></a>          ledTimerCount <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb32-66"><a href="#cb32-66" aria-hidden="true" tabindex="-1"></a>          ledState      <span class="op">=</span> LED_OFF<span class="op">;</span></span>
+<span id="cb32-67"><a href="#cb32-67" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb32-68"><a href="#cb32-68" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb32-69"><a href="#cb32-69" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb32-70"><a href="#cb32-70" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb32-71"><a href="#cb32-71" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<details>
+<summary>
+vector table
+</summary>
+<div class="sourceCode" id="cb33"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="co">/* vector table */</span></span>
+<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define STACK_TOP </span><span class="bn">0x20002000</span></span>
+<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> default_isr<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{}</span></span>
+<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="kw">extern</span> <span class="dt">void</span> _start<span class="op">(</span><span class="dt">void</span><span class="op">);</span></span>
+<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="op">(*</span>myvectors<span class="op">[])(</span><span class="dt">void</span><span class="op">)</span> __attribute__ <span class="op">((</span>section<span class="op">(</span><span class="st">&quot;.vectors&quot;</span><span class="op">)))=</span> <span class="op">{</span></span>
+<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span><span class="dt">void</span><span class="op">(*)(</span><span class="dt">void</span><span class="op">))</span> STACK_TOP<span class="op">,</span>     <span class="co">// stack pointer</span></span>
+<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>    _start<span class="op">,</span>        <span class="co">// code entry point</span></span>
+<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>    default_isr<span class="op">,</span>   <span class="co">// handle non-maskable interrupts</span></span>
+<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>    default_isr<span class="op">,</span> <span class="co">// handle hard faults</span></span>
+<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 10...1f */</span></span>
+<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 20...2f */</span></span>
+<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>timer_isr<span class="op">,</span>        <span class="co">/* 30...3f */</span></span>
+<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span></span>
+<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span>button_isr<span class="op">,</span>button_isr<span class="op">,</span>button_isr<span class="op">,</span> <span class="co">/* 50...5f */</span></span>
+<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 60...6f */</span></span>
+<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 70...7f */</span></span>
+<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 80...8f */</span></span>
+<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 90...9f */</span></span>
+<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* a0...af */</span></span>
+<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* b0...bf */</span></span>
+<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* c0...cf */</span></span>
+<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* d0...df */</span></span>
+<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* e0...ef */</span></span>
+<span id="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* f0...ff */</span></span>
+<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span>                <span class="co">/* 100.10f */</span></span>
+<span id="cb33-27"><a href="#cb33-27" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span><span class="op">,</span><span class="dv">0</span>                 <span class="co">/* 110.11f */</span></span>
+<span id="cb33-28"><a href="#cb33-28" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
+</details>
+<h2 id="substates">Substates</h2>
+<p>For things like flashing LED’s, you could create two states, and
+toggle between them, like this:</p>
+<p><img src="rtb_state_4.png" /></p>
+<hr>
+<p>Or, you could simply have an internal (static, not-on-the-stack)
+variable which can keep track of the LED toggle. The state diagram then
+simplifies:</p>
+<div class="sourceCode" id="cb34"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>uint8 rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span>              <span class="co">// major state, RTB_IDLE/RTB_FLASHING</span></span>
+<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>uint8 rtbSubState <span class="op">=</span> RTB_FLASH_OFF<span class="op">;</span>      <span class="co">// minor state, toggles LED on/off</span></span></code></pre></div>
+<p>Alternatively, you could use the <em>timer counter</em> variable, and
+make changes at the half-way point through the count. This simplifies
+the substate design to this:</p>
+<p><img src="rtb_state_5.png" class="imageright" /></p>
+<div class="sourceCode" id="cb35"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 FLASH_CYCLE_TIME <span class="dv">150</span><span class="op">;</span></span>
+<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 FLASH_ON_TIME <span class="dv">40</span><span class="op">;</span></span>
+<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>uint8 rtbState <span class="op">=</span> STATE_IDLE<span class="op">;</span></span>
+<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> rtbTaskCode<span class="op">(</span><span class="dt">char</span> event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> uint16 flashCount<span class="op">=</span><span class="dv">0</span><span class="op">;</span></span>
+<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>taskState<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> RTB_IDLE<span class="op">:</span></span>
+<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> STATE_FLASHING<span class="op">;</span></span>
+<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>        flashCount <span class="op">=</span> FLASH_CYCLE_TIME<span class="op">;</span></span>
+<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> STATE_FLASHING<span class="op">:</span></span>
+<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>      <span class="co">// count down flashCount, toggle LED halfway through</span></span>
+<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>flashCount <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a>          setLED<span class="op">(</span>OFF<span class="op">);</span></span>
+<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a>          flashCount <span class="op">=</span> FLASH_CYCLE_TIME<span class="op">;</span></span>
+<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>flashCount <span class="op">==</span> FLASH_ON_TIME<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a>          setLED<span class="op">(</span>ON<span class="op">);</span></span>
+<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
+<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a>      <span class="co">// ... make sure to turn LED off when leaving this state</span></span>
+<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_BUTTON<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a>        setLED<span class="op">(</span>OFF<span class="op">);</span></span>
+<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a>        rtbState <span class="op">=</span> RTB_IDLE<span class="op">;</span></span>
+<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> </span>
+<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb35-29"><a href="#cb35-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
+<span id="cb35-30"><a href="#cb35-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb35-31"><a href="#cb35-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<h2 id="state-machine-initialization">State Machine Initialization</h2>
+<p>Notice that there’s no initialization of states in this code. It
+<em>would</em> be very handy if we knew when to initialize all the
+lights and buzzers and match up the various states. Perhaps the
+<code>main()</code> code could add a single event into the event queue
+at power-up, perhaps <code>EVT_INIT</code>. It might be added like
+this:</p>
+<div class="sourceCode" id="cb36"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>  newEvent<span class="op">(</span>EVT_INIT<span class="op">);</span>  <span class="co">// early, before interrupts, so we know it&#39;s first in line</span></span>
+<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  eint<span class="op">();</span></span>
+<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span><span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
+<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>      <span class="op">...</span> dispatcher code <span class="op">...</span></span>
+<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>Then, in the state code, you can catch that event and set up whatever
+might be required</p>
+<div class="sourceCode" id="cb37"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>uint8 myState<span class="op">;</span></span>
+<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> stateCode<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>event<span class="op">==</span>EVT_INIT<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ... do setup code</span></span>
+<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>    myState <span class="op">=</span> FIRST_STATE<span class="op">;</span></span>
+<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span><span class="op">;</span></span>
+<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... regular state machine code</span></span>
+<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<h2 id="messages">Messages</h2>
+<p>Now that we have an event/dispatcher system, we can also also use it
+to send information asychronously between tasks. For example, if a
+keyboard processing task needs to inform its siblings, it can create
+<em>messages</em> which can be injected into the event queue.</p>
+<p>Notice the change of terminology, where <em>message</em> indicates
+that the entry was created by code procesing, rather than an
+interrupt.</p>
+<h3 id="postmessage">PostMessage</h3>
+<p>We need a service routine to add messages to the event queue:
+<code>postMessage()</code>. This call is very smimilar
+<code>newEvent()</code> which should only be called from interrupts.</p>
+<figure>
+<img src="postMessage.png"
+alt="cd-eject task uses postMessage() to broadcast a message" />
+<figcaption aria-hidden="true">cd-eject task uses postMessage() to
+broadcast a message</figcaption>
+</figure>
+<div class="sourceCode" id="cb38"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> postMessage<span class="op">(</span>uint8 message<span class="op">);</span></span></code></pre></div>
+<p>Notice that <code>postMessage</code> can’t return any information,
+because it’s not processed immediately; the <em>message</em> is added to
+the <em>event queue</em> to be processed at a later time.</p>
+<details>
+<summary>
+Reality Check
+</summary>
+In this tiny system, <code>postMessage()</code> is exactly the same as
+<code>newEvent()</code>. The reason that I use different names is that
+some more sophisticated operating systems require that these two
+functions are <em>not</em> identical.
+</details>
+<h3 id="sendmessage">SendMessage</h3>
+<p>In some cases we may want the sibling task to process the information
+immediately. This means:</p>
+<ul>
+<li>we can be assured that the sibling task has fully processed the
+information</li>
+<li>does not involve the dispatcher; but does require extra room on the
+stack</li>
+<li>we <em>could</em> get a return value from the sibling task; since
+it’s implemented as a subroutine, it’s allowed to return a value</li>
+</ul>
+<figure>
+<img src="sendMessage.png"
+alt="cd-eject task uses sendMessage() to call a sibling task" />
+<figcaption aria-hidden="true">cd-eject task uses sendMessage() to call
+a sibling task</figcaption>
+</figure>
+<p>This of course means that the prototype for task functions would
+change from</p>
+<div class="sourceCode" id="cb39"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> taskCode<span class="op">(</span>uint8 event<span class="op">);</span></span>
+<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>to</span>
+<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>uint8 taskCode<span class="op">(</span>uint8 event<span class="op">);</span></span></code></pre></div>
+<p>The service routine to send a message like this would look like:</p>
+<div class="sourceCode" id="cb40"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>uint8 SendMessage<span class="op">(</span>int8 taskPointer<span class="op">(</span>uint8<span class="op">),</span> uint8 message<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> taskPointer<span class="op">(</span>message<span class="op">);</span></span>
+<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<h3 id="usage">Usage</h3>
+<p>Why might one want to send a <em>message</em> between tasks?</p>
+<p>Suppose you have a rotary encoder, which sends quadrant signals,
+which need to be interpreted as <em>clockwise</em> and <em>counter
+clockwise</em>. You could have one task devoted to determining the
+direction of the knob (and <a href="#debouncing">debouncing</a>), and
+have it send clean EVT_CW and EVT_CCW <em>messages</em> to its sibgling
+tasks.</p>
+<p>Another possible use of <em>messages</em> is to create alternate
+souces of input. For example, a device which has a temperature set by
+“up/down” buttons on a front panel could receive the same controls from
+an infra-red remote, or even a serial port (perhaps for testing).</p>
+<p>And why <code>sendMessage()</code>? Perhaps you need to have a
+sibling task change states, or process information <em>before</em> you
+continue in your task. Imagine there is a slave WiFi chip that needs to
+be powered up <em>before</em> you send it a request….you could use
+<code>sendMessage()</code> to activate the power, and then continue,
+knowing that your peripheral is available.</p>
+<h2 id="ideas-for-tasks">Ideas for Tasks</h2>
+<p>I taught this coding technique at the college level, and a typical
+end-of-term assignment was to code up a simulated automobile
+entertainment system, which included about 6-10 concurrent tasks:</p>
+<ul>
+<li>task blue light to show bluetooth connectivity</li>
+<li>volume up/down sense and display</li>
+<li>radio channel select buttons
+<ul>
+<li>step single freq, or high-speed scan</li>
+</ul></li>
+<li>power on/off management</li>
+<li>remote control of volume/radio-select from the steering wheel (uart
+link)</li>
+<li>backlight for night-time viewing (auto sense from a light
+sensor)</li>
+<li>service-required LED, flashing</li>
+<li>a beeper to confirm keypresses (30ms) and alarm (700ms/100ms)</li>
+<li>a clock up/down set button
+<ul>
+<li>3 buttons: “set min/hr” and “+” and “-”</li>
+</ul></li>
+</ul>
+<p>Each list item above corresponds to one task. My students were able
+to code this up with about 35k of source, which compiles to about 8k of
+code and 256B of RAM (on an STM32)</p>
+<h2 id="more-state-machines">More State Machines</h2>
+<h3 id="radio-tuner">Radio Tuner</h3>
+<p>Suppose we have a <code>+</code> and <code>-</code> button for tuning
+a radio. A press of either will move the radio frequency by one step. If
+the button is held for more than 0.5 seconds, the radio should change to
+a rapid scroll through all available frequencies.</p>
+<p>Suppose we have events coming at 100msec, and that the radio
+frequencies are 88.7 up to 107.9, with steps at 0.1. And finally,
+suppose there are 5 available events:</p>
+<div class="sourceCode" id="cb41"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>EVT_NONE<span class="op">,</span> EVT_TICK<span class="op">,</span> EVT_UP_PRESS<span class="op">,</span> EVT_UP_RELEASE<span class="op">,</span> EVT_DN_PRESS<span class="op">,</span> EVT_DN_RELEASE<span class="op">};</span></span></code></pre></div>
+<figure>
+<img src="radio_tuner.png" alt="state machine for radio tuner" />
+<figcaption aria-hidden="true">state machine for radio
+tuner</figcaption>
+</figure>
+<div class="sourceCode" id="cb42"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">float</span> MIN_FREQ<span class="op">=</span><span class="fl">88.7</span><span class="op">,</span> MAX_FREQ<span class="op">=</span><span class="fl">107.9</span><span class="op">,</span> INC_FREQ<span class="op">=</span><span class="dv">0</span><span class="er">.1</span><span class="op">;</span></span>
+<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a><span class="dt">float</span> radioFreq <span class="op">=</span> MIN_FREQ<span class="op">;</span></span>
+<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>uint16 radioTimer <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> uint16 radioTimeout <span class="op">=</span> <span class="dv">5</span><span class="op">;</span>  <span class="co">// 0.5 seconds</span></span>
+<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="op">{</span>IDLE<span class="op">,</span> FREQ_UP<span class="op">,</span> FREQ_UP_FAST<span class="op">,</span> FREQ_DN<span class="op">,</span> FREQ_DN_FAST<span class="op">};</span></span>
+<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>uint8 state <span class="op">=</span> IDLE<span class="op">;</span></span>
+<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> radioTask<span class="op">(</span>uint8 event<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span><span class="op">(</span>state<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> IDLE<span class="op">:</span></span>
+<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_UP_PRESS<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>        radioFreq <span class="op">+=</span> INC_FREQ<span class="op">;</span></span>
+<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>        checkRadioFreq<span class="op">();</span></span>
+<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a>        radioTimer <span class="op">=</span> radioTimeout<span class="op">;</span></span>
+<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> FREQ_UP<span class="op">;</span></span>
+<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_DN_PRESS<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>        radioFreq <span class="op">-=</span> INC_FREQ<span class="op">;</span></span>
+<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a>        checkRadioFreq<span class="op">();</span></span>
+<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>        radioTimer <span class="op">=</span> radioTimeout<span class="op">;</span></span>
+<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> FREQ_DN<span class="op">;</span></span>
+<span id="cb42-22"><a href="#cb42-22" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb42-23"><a href="#cb42-23" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb42-24"><a href="#cb42-24" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FREQ_UP<span class="op">:</span></span>
+<span id="cb42-25"><a href="#cb42-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_UP_RELEASE<span class="op">)</span> </span>
+<span id="cb42-26"><a href="#cb42-26" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> IDLE<span class="op">;</span></span>
+<span id="cb42-27"><a href="#cb42-27" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-28"><a href="#cb42-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>radioTimer <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> </span>
+<span id="cb42-29"><a href="#cb42-29" aria-hidden="true" tabindex="-1"></a>          state <span class="op">=</span> FREQ_UP_FAST<span class="op">;</span></span>
+<span id="cb42-30"><a href="#cb42-30" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb42-31"><a href="#cb42-31" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb42-32"><a href="#cb42-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> FREQ_UP_FAST<span class="op">:</span></span>
+<span id="cb42-33"><a href="#cb42-33" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_TICK<span class="op">)</span> <span class="op">{</span></span>
+<span id="cb42-34"><a href="#cb42-34" aria-hidden="true" tabindex="-1"></a>        radioFreq <span class="op">+=</span> INC_FREQ<span class="op">;</span></span>
+<span id="cb42-35"><a href="#cb42-35" aria-hidden="true" tabindex="-1"></a>        checkRadioFreq<span class="op">();</span></span>
+<span id="cb42-36"><a href="#cb42-36" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
+<span id="cb42-37"><a href="#cb42-37" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>event <span class="op">==</span> EVT_UP_RELEASE<span class="op">)</span> </span>
+<span id="cb42-38"><a href="#cb42-38" aria-hidden="true" tabindex="-1"></a>        state <span class="op">=</span> IDLE<span class="op">;</span></span>
+<span id="cb42-39"><a href="#cb42-39" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
+<span id="cb42-40"><a href="#cb42-40" aria-hidden="true" tabindex="-1"></a>    <span class="co">// and the same for FREQ_DN and FREQ_DN_FAST</span></span>
+<span id="cb42-41"><a href="#cb42-41" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
+<span id="cb42-42"><a href="#cb42-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
+<span id="cb42-43"><a href="#cb42-43" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb42-44"><a href="#cb42-44" aria-hidden="true" tabindex="-1"></a><span class="co">// manage rollover</span></span>
+<span id="cb42-45"><a href="#cb42-45" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> checkRadioFreq<span class="op">()</span> <span class="op">{</span></span>
+<span id="cb42-46"><a href="#cb42-46" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>radioFreq <span class="op">&gt;</span> MAX_FREQ<span class="op">)</span></span>
+<span id="cb42-47"><a href="#cb42-47" aria-hidden="true" tabindex="-1"></a>    radioFreq <span class="op">=</span> MIN_FREQ<span class="op">;</span></span>
+<span id="cb42-48"><a href="#cb42-48" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>radioFreq <span class="op">&lt;</span> MIN_FREQ<span class="op">)</span></span>
+<span id="cb42-49"><a href="#cb42-49" aria-hidden="true" tabindex="-1"></a>    radioFreq <span class="op">=</span> MAX_FREQ<span class="op">;</span></span>
+<span id="cb42-50"><a href="#cb42-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
+<p>This may seem like a lot of code, but it compiles to something quite
+small. It is non-blocking, and easily maintained and modified. And it
+works.</p>
+</body>
+</html>

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
-This is a [web-based article](CooperativeMultitasking.md) 
+This is a [web-based article](CooperativeMultitasking.html) 
 describing *cooperative multitasking*, also known as
 *event driven programming*. The method described here is small enough to fit on
 many sub-$1 microcontrollers, those without memory management units. Examples are