소스 검색

changed uint8 to uchar (it looks nicer) and cleaned up postMessage/sendMessage

Pat Beirne 1 개월 전
부모
커밋
f3ad6ca5d3
4개의 변경된 파일78개의 추가작업 그리고 74개의 파일을 삭제
  1. 77 74
      CooperativeMultitasking.md
  2. 1 0
      c.xml
  3. BIN
      postMessage.png
  4. BIN
      sendMessage.png

+ 77 - 74
CooperativeMultitasking.md

@@ -5,7 +5,7 @@ email: <patb@pbeirne.com>
 date: 2025/01/15
 date: 2025/01/15
 license: MIT
 license: MIT
 ---
 ---
-
+<style> h2 { border-top: solid thin #899;}   </style>
 # Part 1: Cooperative Multitasking
 # Part 1: Cooperative Multitasking
 
 
 <!-- ## Introduction -->
 <!-- ## Introduction -->
@@ -22,7 +22,7 @@ The core of *this* technique is covered in
 [Part 1](#part-1-cooperative-multitasking)
 [Part 1](#part-1-cooperative-multitasking)
 of this paper. 
 of this paper. 
 If you just want to see how it all comes together, 
 If you just want to see how it all comes together, 
-jump to [Final Implementaion](#final-implementation). 
+jump to [Final Implementation](#final-implementation). 
 
 
 [Part 2](#part-2) contains enhancements and variations, 
 [Part 2](#part-2) contains enhancements and variations, 
 probably useful reading if you decide to adopt
 probably useful reading if you decide to adopt
@@ -86,7 +86,7 @@ to make this happen?
 
 
 ## First Page
 ## First Page
 
 
-Let's look an a pseudocode overview of what we want to do:
+Let's look at the pseudocode overview of what we want to do:
 
 
 ```C
 ```C
 void initialize(void) {
 void initialize(void) {
@@ -137,12 +137,12 @@ In order to have a responsive system, it would make sense to use the
 
 
 In the task described, we need to respond to a button press. 
 In the task described, we need to respond to a button press. 
 So let's connect the button to 
 So let's connect the button to 
-an input pin and enable it to repsond to a button press with interrupt code.
+an input pin and enable it to respond to a button press with interrupt code.
 
 
 We also need to keep track of time.....so let's hook up a system timer to another interrupt.
 We also need to keep track of time.....so let's hook up a system timer to another interrupt.
 
 
 Each interrupt causes the execution of *interrupt handler* code. For this project, it might look
 Each interrupt causes the execution of *interrupt handler* code. For this project, it might look
-somthing like this:
+something like this:
 
 
 ```C
 ```C
 enum {EVT_NONE, EVT_TICK, EVT_BUTTON};
 enum {EVT_NONE, EVT_TICK, EVT_BUTTON};
@@ -198,7 +198,7 @@ Implemented, it can be a *byte*, or an *int* or an even larger structure.
 But in these small microcontrollers, let's use a *byte*.
 But in these small microcontrollers, let's use a *byte*.
 
 
 ```C
 ```C
-volatile uint8 event;
+volatile uchar event;
 ```
 ```
 
 
 These *events* will be created in interrupt level of the code, 
 These *events* will be created in interrupt level of the code, 
@@ -218,7 +218,7 @@ and *non-zero* to represent
 an event/message.
 an event/message.
 
 
 ```C
 ```C
-volatile uint8 event;
+volatile uchar event;
 enum {EVT_NONE, EVT_TICK, EVT_BUTTON}; // 0,1,2
 enum {EVT_NONE, EVT_TICK, EVT_BUTTON}; // 0,1,2
 ```
 ```
 
 
@@ -244,13 +244,13 @@ How do we send the information (events/messages) from the interrupt
 service routine to the 
 service routine to the 
 `main()` code? We used shared memory.
 `main()` code? We used shared memory.
 
 
-One way would be to have a global `volatile uint8` location into which 
+One way would be to have a global `volatile uchar` location into which 
 we drop the *event* information. But
 we drop the *event* information. But
 having only one socket for that would be a bit naive; 
 having only one socket for that would be a bit naive; 
 what happens if a timer tick and a button press
 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?
 happen very close in time? What happens if the timer tick events start to stack up?
 
 
-It makes more sense to have an array: `volatile uint8 events[NUM_EVENTS]` 
+It makes more sense to have an array: `volatile uchar events[NUM_EVENTS]` 
 where NUM_EVENTS is on the order of 5..10. 
 where NUM_EVENTS is on the order of 5..10. 
 That would give us 50-100msec to catch up in case there's a 
 That would give us 50-100msec to catch up in case there's a 
 pileup of events/messages.
 pileup of events/messages.
@@ -263,8 +263,8 @@ The `newEvent(evt)` routine simply adds the `evt` to the array `events[]`.
 Something like this might work:
 Something like this might work:
 
 
 ```C
 ```C
-void newEvent(uint8 evt) {
-  static uint8 nextEvent;
+void newEvent(uchar evt) {
+  static uchar nextEvent;
   events[nextEvent++] = evt;
   events[nextEvent++] = evt;
   if (nextEvent == NUM_EVENTS)
   if (nextEvent == NUM_EVENTS)
     nextEvent = 0;
     nextEvent = 0;
@@ -283,7 +283,7 @@ Here's a more realistic version:
 
 
 ```C
 ```C
 void newEvent(char evt) {
 void newEvent(char evt) {
-  static uint8 nextEvent;   // keep track of where we are in queue
+  static uchar nextEvent;   // keep track of where we are in queue
   disable_irq();                    // critical section
   disable_irq();                    // critical section
   events[nextEvent++] = evt;        // insert event into queue
   events[nextEvent++] = evt;        // insert event into queue
   if (nextEvent == NUM_EVENTS)      // loop back to the start of queue
   if (nextEvent == NUM_EVENTS)      // loop back to the start of queue
@@ -312,7 +312,7 @@ To see the real code for the dispatcher, [jump ahead](#dispatcher-details).
 The `main()` code illustrated here calls the tasks 
 The `main()` code illustrated here calls the tasks 
 as subroutines, sending each one a copy of the event number. 
 as subroutines, sending each one a copy of the event number. 
 
 
-As I mentioned earlier, *events* can also be refered to as *messages*. 
+As I mentioned earlier, *events* can also be referred to as *messages*. 
 We can also refer to this process "sending
 We can also refer to this process "sending
 a message to the task"
 a message to the task"
 
 
@@ -345,11 +345,11 @@ the event, speeding up the whole system.
 
 
 ## Tasks
 ## Tasks
 
 
-In this environment, the code that impliments a *task* is simply a 
+In this environment, the code that implements a *task* is simply a 
 subroutine that accepts an *event/message*.
 subroutine that accepts an *event/message*.
 
 
 ```C
 ```C
-void taskCode(uint8 event) {
+void taskCode(uchar event) {
   ... process the event information ...
   ... process the event information ...
 }
 }
 ```
 ```
@@ -382,11 +382,11 @@ The above diagram can be implemented in this code:
 
 
 ```C
 ```C
 enum {RTB_IDLE, RTB_ON};          // RTB_IDLE=0, RTB_ON=1
 enum {RTB_IDLE, RTB_ON};          // RTB_IDLE=0, RTB_ON=1
-static uint8  rtbState      = RTB_IDLE;
+static uchar  rtbState      = RTB_IDLE;
 static uint16 rtbTimerCount = 0;
 static uint16 rtbTimerCount = 0;
 const  uint16 TIMER_LIMIT   = 150;
 const  uint16 TIMER_LIMIT   = 150;
 
 
-void respondToButtonTask(uint8 evt) {
+void respondToButtonTask(uchar evt) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (evt == EVT_BUTTON) {
       if (evt == EVT_BUTTON) {
@@ -440,12 +440,12 @@ The code for this might be:
 
 
 ```C
 ```C
 enum {LED_ON, LED_OFF};
 enum {LED_ON, LED_OFF};
-static uint8 ledState       = LED_OFF;
+static uchar ledState       = LED_OFF;
 static uint16 ledTimerCount = 0;
 static uint16 ledTimerCount = 0;
 const  uint16 LED_ON_TIME   = 100;
 const  uint16 LED_ON_TIME   = 100;
 const  uint16 LED_OFF_TIME  = 100;
 const  uint16 LED_OFF_TIME  = 100;
 
 
-void ledTask(uint8 evt) {
+void ledTask(uchar evt) {
   switch(ledState) {
   switch(ledState) {
     case LED_OFF:
     case LED_OFF:
       if (evt == EVT_TICK) {
       if (evt == EVT_TICK) {
@@ -569,11 +569,11 @@ Let's put all of the above together, for an SMT32F Cortex M0, in *C* code.
 ```C
 ```C
 /***** declarations ****/
 /***** declarations ****/
 #define NUM_EVENTS 10
 #define NUM_EVENTS 10
-volatile uint8 events[NUM_EVENTS];
+volatile uchar events[NUM_EVENTS];
 
 
-void newEvent(uint8 e);
-void ledTask(uint8 evt);
-void respondToButtonTask(uint8 evt);
+void newEvent(uchar e);
+void ledTask(uchar evt);
+void respondToButtonTask(uchar evt);
 
 
 /********** interrupts **************/
 /********** interrupts **************/
 
 
@@ -593,8 +593,8 @@ void button_isr(void) {
  * 
  * 
  * @param the event
  * @param the event
  */
  */
-void newEvent(uint8 e) {
-  static uint8 nextEvent;
+void newEvent(uchar e) {
+  static uchar nextEvent;
   dint(); // critical section
   dint(); // critical section
   events[nextEvent++] = e;
   events[nextEvent++] = e;
   if (nextEvent==NUM_EVENTS)
   if (nextEvent==NUM_EVENTS)
@@ -623,11 +623,11 @@ void main(void) {
 /*********** task code, with states ************/
 /*********** task code, with states ************/
 enum {LED_ON, LED_OFF};
 enum {LED_ON, LED_OFF};
 enum {RTB_IDLE, RTB_ON};    // states
 enum {RTB_IDLE, RTB_ON};    // states
-static uint8  rtbState      = RTB_IDLE;
+static uchar  rtbState      = RTB_IDLE;
 static uint16 rtbTimerCount = 0;
 static uint16 rtbTimerCount = 0;
 const  uint16 LED_ON_TIME   = 150;
 const  uint16 LED_ON_TIME   = 150;
 
 
-void respondToButtonTask(uint8 evt) {
+void respondToButtonTask(uchar evt) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (evt == EVT_BUTTON) {
       if (evt == EVT_BUTTON) {
@@ -649,10 +649,10 @@ void respondToButtonTask(uint8 evt) {
 
 
 const  uint16 LED_ON_TIME   = 150;
 const  uint16 LED_ON_TIME   = 150;
 const  uint16 LED_OFF_TIME  = 50;
 const  uint16 LED_OFF_TIME  = 50;
-static uint8 ledState       = LED_OFF;
+static uchar ledState       = LED_OFF;
 static uint16 ledTimerCount = 0;
 static uint16 ledTimerCount = 0;
 
 
-void ledTask(uint8 evt) {
+void ledTask(uchar evt) {
   switch(ledState) {
   switch(ledState) {
     case LED_OFF:
     case LED_OFF:
       if (evt == EVT_TICK) {
       if (evt == EVT_TICK) {
@@ -714,7 +714,7 @@ LED timer on each key press:
 <div style="display: flex;">
 <div style="display: flex;">
 ![RTB (respond to button) state machine, with restart](rtb_state_2.png)\ 
 ![RTB (respond to button) state machine, with restart](rtb_state_2.png)\ 
 ```C
 ```C
-void rtbTask(uint8 event) {
+void rtbTask(uchar event) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (event == EVT_BUTTON) {
       if (event == EVT_BUTTON) {
@@ -746,7 +746,7 @@ Or have a 2nd press of the button cause the LED to extinguish early:
 <div style="display: flex;">
 <div style="display: flex;">
 ![RTB state machine, with early-off](rtb_state_3.png)\ 
 ![RTB state machine, with early-off](rtb_state_3.png)\ 
 ```C
 ```C
-void rtbTask(uint8 event) {
+void rtbTask(uchar event) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (event == EVT_BUTTON) {
       if (event == EVT_BUTTON) {
@@ -783,7 +783,7 @@ it: (see also [substates](#substates))
 ![RTB state machine, push to stop](rtb_state_4.png)\ 
 ![RTB state machine, push to stop](rtb_state_4.png)\ 
 
 
 ```C
 ```C
-void rtbTask(uint8 event) {
+void rtbTask(uchar event) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (event == EVT_BUTTON) {
       if (event == EVT_BUTTON) {
@@ -888,7 +888,7 @@ If a task occasionally runs into the 10's of msec, the event queue will
 handle buffering the events until they can be processed.
 handle buffering the events until they can be processed.
 
 
 Under no circumstances should a task take more than 100msec. Use a new state,
 Under no circumstances should a task take more than 100msec. Use a new state,
-and return from the tast. Process the new state later.
+and return from the task. Process the new state later.
 <hr>
 <hr>
 </details>
 </details>
 
 
@@ -915,9 +915,9 @@ and the code: arrows leaving a state correspond to an `if()` phrase.
 
 
 ```C
 ```C
 enum {WINDOW_IDLE, WINDOW_UP, WINDOW_DOWN};
 enum {WINDOW_IDLE, WINDOW_UP, WINDOW_DOWN};
-static uint8 windowState = WINDOW_IDLE;
+static uchar windowState = WINDOW_IDLE;
 
 
-void windowTask(uint8 evt) {
+void windowTask(uchar evt) {
   switch(windowState) {
   switch(windowState) {
     case WINDOW_IDLE:
     case WINDOW_IDLE:
       if (evt == EVT_BUTTON_UP) {
       if (evt == EVT_BUTTON_UP) {
@@ -962,7 +962,7 @@ code from the previous version.
 <details><summary>Reality Check</summary>
 <details><summary>Reality Check</summary>
 This is such a simple task, with only a few I/O pins involved. In theory, a
 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
 cheap microcontroller could control a dozen windows, each appearing to operate
-independantly. 
+independently. 
 
 
 In the code, one wouldn't need to create a dozen tasks......just create an index
 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 
 into the same code and invoke it in a way that makes it appear as an 
@@ -1020,7 +1020,7 @@ And here is the corresponding code.
 
 
 ```C
 ```C
 enum {FRIDGE_CLOSED, FRIDGE_OPEN, FRIDGE_BEEPING};
 enum {FRIDGE_CLOSED, FRIDGE_OPEN, FRIDGE_BEEPING};
-uint8  fridgeState;
+uchar  fridgeState;
 uint16 fridgeTimer;
 uint16 fridgeTimer;
 const uint16 FRIDGE_OPEN_LIMIT = 9000; // 90 seconds at 10msec tick
 const uint16 FRIDGE_OPEN_LIMIT = 9000; // 90 seconds at 10msec tick
 void fridgeTask(char event) {
 void fridgeTask(char event) {
@@ -1135,18 +1135,18 @@ Here's the state diagram:
 
 
 ![RFID operated door lock](door.png)
 ![RFID operated door lock](door.png)
 
 
-I use `EVT_` type events to indicate that they originate in hardware, probably
-at the interrupt level; and `MSG_` type events to indicate they come from a
-software source, perhaps a sibling task.
-
 Suppose now that the serial number needs to be verified by a central service.
 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 
 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
 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.
 for 4 seconds. The rest of the problem is as stated above.
 
 
+I use `EVT_` type events to indicate that they originate in hardware, probably
+at the interrupt level; and `MSG_` type events to indicate they come from a
+software source, perhaps a sibling task.
+
 Here's the modified state diagram:
 Here's the modified state diagram:
 
 
-![RFID operated door, with remove key verify](door2.png)
+![RFID operated door, with remote key verify](door2.png)
 
 
 ### Beer Vat
 ### Beer Vat
 
 
@@ -1198,16 +1198,17 @@ Event e = {MSG_KEYPRESS, KEY_A};
 ```
 ```
 
 
 In the old Windows system, *events/messages* were realized as a 16 bit number,
 In the old Windows system, *events/messages* were realized as a 16 bit number,
-with an extra 32 bit number glued to it for extra information. 
+with extra 16 and 32 bit numbers glued to it for extra information. 
 
 
 ```C
 ```C
 typedef struct MSG {
 typedef struct MSG {
   UINT   message;
   UINT   message;
+  WPARAM wParam;
   LPARAM lParam;
   LPARAM lParam;
 };    // some extra detail removed
 };    // some extra detail removed
 ```
 ```
 For example, 
 For example, 
-`WM_CHAR=0x0102` indicates that a key was pressed, with the extra 32bit `lParam`
+`message == WM_CHAR == 0x0102` indicates that a key was pressed, with the `wParam`
 carrying the information about *which* key. 
 carrying the information about *which* key. 
 <hr>
 <hr>
 
 
@@ -1253,8 +1254,8 @@ and increment until it hits the desired limit (100 in this case).
 In a moderate sized project, timers like this will proliferate throughout the code,
 In a moderate sized project, timers like this will proliferate throughout the code,
 making it awkward to read. One solution to this is to centralize the timers.
 making it awkward to read. One solution to this is to centralize the timers.
 
 
-In all the above examples, the `timer_irq()` code is trivial, just `newEvent(EVT_TICK)`.
-Suppose we add code to the `timer_irq()` so that it can process timer counting on
+In all the above examples, the `timer_isr()` code is trivial, just `newEvent(EVT_TICK)`.
+Suppose we add code to the `timer_isr()` so that it can process timer counting on
 behalf of the tasks......
 behalf of the tasks......
 
 
 ### Timers as a Resource
 ### Timers as a Resource
@@ -1262,9 +1263,9 @@ behalf of the tasks......
 Let's create a centralized service called `setTimer(timer_index, timer_count)`. 
 Let's create a centralized service called `setTimer(timer_index, timer_count)`. 
 
 
 A task can call this service with a unique `timer_index` and a requested count. The
 A task can call this service with a unique `timer_index` and a requested count. The
-`timer_irq()` uses a pool of timer registers, and will count out the ticks 
+`timer_isr()` uses a pool of timer registers, and will count out the ticks 
 on behalf of the task, and when the tick
 on behalf of the task, and when the tick
-count is finished, the `timer_irq()` code can generate a unique event, perhaps
+count is finished, the `timer_isr()` code can generate a unique event, perhaps
 `EVT_TIMER_n`. 
 `EVT_TIMER_n`. 
 
 
 So the state code can then look something like this:
 So the state code can then look something like this:
@@ -1294,7 +1295,7 @@ void stateCode(char event) {
 This makes the state code simpler to read, 
 This makes the state code simpler to read, 
 hiding all the increments/decrements and limit testing.
 hiding all the increments/decrements and limit testing.
 
 
-The overhead for this ends up in the `timer_irq()` code, 
+The overhead for this ends up in the `timer_isr()` code, 
 and might look something like this:
 and might look something like this:
 
 
 ```C
 ```C
@@ -1303,7 +1304,7 @@ static uint16 timers[NUM_TIMERS];
 enum {EVENT_TIMER_1=EVT_TIMER_OFFSET, EVENT_TIMER_2, EVENT_TIMER_3}; // 100, 101...
 enum {EVENT_TIMER_1=EVT_TIMER_OFFSET, EVENT_TIMER_2, EVENT_TIMER_3}; // 100, 101...
 enum {TIMER_1, TIMER_2, TIMER_3};   // 0,1,2,....
 enum {TIMER_1, TIMER_2, TIMER_3};   // 0,1,2,....
 
 
-void timer_irq() {
+void timer_isr() {
   newEvent(EVT_TICK);           // the main tick, fires every time
   newEvent(EVT_TICK);           // the main tick, fires every time
   for (i=0; i<NUM_TIMERS) {     // the system timers, fires on completion
   for (i=0; i<NUM_TIMERS) {     // the system timers, fires on completion
     if (timers[i]>0) {
     if (timers[i]>0) {
@@ -1321,7 +1322,7 @@ void setTimer(int timerIndex, unsigned int timerCount) {
 
 
 <details><summary>Reality Check</summary>
 <details><summary>Reality Check</summary>
 On a typical microcontroller running at 24MHz, with 5 timers, this adds about
 On a typical microcontroller running at 24MHz, with 5 timers, this adds about
-2 microseconds of extra time to the `timer_irq()` code, which typically runs every 
+2 microseconds of extra time to the `timer_isr()` code, which typically runs every 
 10 or 100msec. It simplifies the task code, makes it more legible
 10 or 100msec. It simplifies the task code, makes it more legible
 and probably reduces bugs that may appear by duplication of code.
 and probably reduces bugs that may appear by duplication of code.
 
 
@@ -1339,7 +1340,7 @@ INTERRUPT timer_isr(void) {
 
 
 // .... state code ...
 // .... state code ...
 static int targetTime;
 static int targetTime;
-void stateCode(uint8 event) {
+void stateCode(uchar event) {
   switch(state) {
   switch(state) {
     case STATE1:
     case STATE1:
       //..... set a target
       //..... set a target
@@ -1399,15 +1400,15 @@ void gpio_set(uint32 bitPosition, bool value) {
 ```C
 ```C
 /***** events ****/
 /***** events ****/
 #define NUM_EVENTS 10
 #define NUM_EVENTS 10
-volatile uint8 events[NUM_EVENTS];
+volatile uchar events[NUM_EVENTS];
 enum { EVT_NONE,
 enum { EVT_NONE,
       EVT_TICK,
       EVT_TICK,
       EVT_BUTTON};
       EVT_BUTTON};
-void newEvent(uint8 e);
+void newEvent(uchar e);
 
 
 /********** tasks ***********/
 /********** tasks ***********/
-void ledTask(uint8 evt);
-void respondToButtonTask(uint8 evt);
+void ledTask(uchar evt);
+void respondToButtonTask(uchar evt);
 
 
 /********** interrupts **************/
 /********** interrupts **************/
 volatile uint32 tick;   // increasing at 100 ticks/sec
 volatile uint32 tick;   // increasing at 100 ticks/sec
@@ -1503,11 +1504,11 @@ void main(void) {
 /*********** task code, with states ************/
 /*********** task code, with states ************/
 enum {LED_ON, LED_OFF};
 enum {LED_ON, LED_OFF};
 enum {RTB_IDLE, RTB_ON};    // states
 enum {RTB_IDLE, RTB_ON};    // states
-static uint8 rtbState            = RTB_IDLE;
+static uchar rtbState            = RTB_IDLE;
 static uint16 rtbTimerCount      = 0;
 static uint16 rtbTimerCount      = 0;
 const  uint16 BUTTON_LED_ON_TIME = 150;
 const  uint16 BUTTON_LED_ON_TIME = 150;
 
 
-void respondToButtonTask(uint8 evt) {
+void respondToButtonTask(uchar evt) {
   switch(rtbState) {
   switch(rtbState) {
     case RTB_IDLE:
     case RTB_IDLE:
       if (evt == EVT_BUTTON) {
       if (evt == EVT_BUTTON) {
@@ -1529,10 +1530,10 @@ void respondToButtonTask(uint8 evt) {
 
 
 const int LED_ON_TIME  = 150;
 const int LED_ON_TIME  = 150;
 const int LED_OFF_TIME = 50;
 const int LED_OFF_TIME = 50;
-static uint8  ledState      = LED_OFF;
+static uchar  ledState      = LED_OFF;
 static uint16 ledTimerCount = 0;
 static uint16 ledTimerCount = 0;
 
 
-void ledTask(uint8 evt) {
+void ledTask(uchar evt) {
   switch(ledState) {
   switch(ledState) {
     case LED_OFF:
     case LED_OFF:
       if (evt == EVT_TICK) {
       if (evt == EVT_TICK) {
@@ -1606,8 +1607,8 @@ simplifies:
 
 
 
 
 ```C
 ```C
-uint8 rtbState = RTB_IDLE;              // major state, RTB_IDLE/RTB_FLASHING
-uint8 rtbSubState = RTB_FLASH_OFF;      // minor state, toggles LED on/off
+uchar rtbState = RTB_IDLE;              // major state, RTB_IDLE/RTB_FLASHING
+uchar rtbSubState = RTB_FLASH_OFF;      // minor state, toggles LED on/off
 ```
 ```
 
 
 Alternatively, you could use the *timer counter*
 Alternatively, you could use the *timer counter*
@@ -1620,7 +1621,7 @@ variable, and make changes at the half-way point through the count.
 ```C
 ```C
 const uint16 FLASH_CYCLE_TIME 150;
 const uint16 FLASH_CYCLE_TIME 150;
 const uint16 FLASH_ON_TIME 40;
 const uint16 FLASH_ON_TIME 40;
-uint8 rtbState = STATE_IDLE;
+uchar rtbState = STATE_IDLE;
 void rtbTaskCode(char event) {
 void rtbTaskCode(char event) {
   static uint16 flashCount=0;
   static uint16 flashCount=0;
 
 
@@ -1677,8 +1678,8 @@ Then, in the state code, you can catch that event and set up whatever might
 be required
 be required
 
 
 ```C
 ```C
-uint8 myState;
-void stateCode(uint8 event) {
+uchar myState;
+void stateCode(uchar event) {
   if (event==EVT_INIT) {
   if (event==EVT_INIT) {
     // ... do setup code
     // ... do setup code
     myState = FIRST_STATE;
     myState = FIRST_STATE;
@@ -1707,7 +1708,7 @@ only be called from interrupts.
 ![cd-eject task uses postMessage() to broadcast a message](postMessage.png)
 ![cd-eject task uses postMessage() to broadcast a message](postMessage.png)
 
 
 ```C
 ```C
-void postMessage(uint8 message);
+void postMessage(uchar message);
 ```
 ```
 
 
 Notice that `postMessage` can't return any information, because it's not 
 Notice that `postMessage` can't return any information, because it's not 
@@ -1726,7 +1727,8 @@ In some cases we may want the sibling task to process the information immediatel
 This means:
 This means:
 
 
 - we can be assured that the sibling task has fully processed the information
 - we can be assured that the sibling task has fully processed the information
-- does not involve the dispatcher; but does require extra room on the stack
+- does not involve the dispatcher
+- requires extra room on the stack, since we're calling within a call
 - we *could* get a return value from the sibling task; since it's implemented as
 - we *could* get a return value from the sibling task; since it's implemented as
 a subroutine, it's allowed to return a value
 a subroutine, it's allowed to return a value
 
 
@@ -1735,15 +1737,15 @@ a subroutine, it's allowed to return a value
 To return a value means that the prototype for task functions would change from 
 To return a value means that the prototype for task functions would change from 
 
 
 ```C
 ```C
-void taskCode(uint8 event);
+void taskCode(uchar event);
 to
 to
-uint8 taskCode(uint8 event);
+uchar taskCode(uchar event);
 ```
 ```
 
 
 The service routine to send a message like this would look like:
 The service routine to send a message like this would look like:
 
 
 ```C
 ```C
-uint8 SendMessage(int8 taskPointer(uint8), uint8 message) {
+uchar SendMessage(int8 taskPointer(uchar), uchar message) {
   return taskPointer(message);
   return taskPointer(message);
 }
 }
 ```
 ```
@@ -1752,7 +1754,8 @@ uint8 SendMessage(int8 taskPointer(uint8), uint8 message) {
 
 
 Why might one want to *send a message* between tasks?
 Why might one want to *send a message* between tasks?
 
 
-Suppose you have a rotary encoder, which sends quadrant signals, which need
+**PostMessage()** Suppose you have a rotary encoder, which sends 
+quadrant signals, which need
 to be interpreted as *clockwise* and *counter clockwise*. You could have one
 to be interpreted as *clockwise* and *counter clockwise*. You could have one
 task devoted to determining the direction of the knob 
 task devoted to determining the direction of the knob 
 (and [debouncing](#debouncing)), and have it *send* (or *post*) clean 
 (and [debouncing](#debouncing)), and have it *send* (or *post*) clean 
@@ -1763,7 +1766,7 @@ For example, a device which has
 a temperature set by "up/down" buttons on a front panel could receive the same
 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).
 controls from an infra-red remote, or even a serial port (perhaps for testing).
 
 
-And why `sendMessage()`? Perhaps you need to have a sibling task change
+**SendMessage()** Perhaps you need to have a sibling task change
 states, or process information *before* you continue in your task. Imagine
 states, or process information *before* you continue in your task. Imagine
 there is a slave WiFi chip that needs to be powered up *before* you send it
 there is a slave WiFi chip that needs to be powered up *before* you send it
 a request....you could use `sendMessage()` to activate the power, and then
 a request....you could use `sendMessage()` to activate the power, and then
@@ -1819,8 +1822,8 @@ uint16 radioTimer = 0;
 const uint16 radioTimeout = 5;  // 0.5 seconds
 const uint16 radioTimeout = 5;  // 0.5 seconds
 
 
 enum {IDLE, FREQ_UP, FREQ_UP_FAST, FREQ_DN, FREQ_DN_FAST};
 enum {IDLE, FREQ_UP, FREQ_UP_FAST, FREQ_DN, FREQ_DN_FAST};
-uint8 state = IDLE;
-void radioTask(uint8 event) {
+uchar state = IDLE;
+void radioTask(uchar event) {
   switch(state) {
   switch(state) {
     case IDLE:
     case IDLE:
       if (event == EVT_UP_PRESS) {
       if (event == EVT_UP_PRESS) {

+ 1 - 0
c.xml

@@ -86,6 +86,7 @@
       <item>char</item>
       <item>char</item>
       <item>char16_t</item>
       <item>char16_t</item>
       <item>char32_t</item>
       <item>char32_t</item>
+      <item>uchar</item>
       <item>double</item>
       <item>double</item>
       <item>float</item>
       <item>float</item>
       <item>int</item>
       <item>int</item>

BIN
postMessage.png


BIN
sendMessage.png