Merge branch 'master' of ssh://git.gag.com/scm/git/web/altusmetrum
[web/altusmetrum] / AltOS / doc / altos.html
1 <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>AltOS</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"><div class="titlepage"><div><div><h1 class="title"><a name="idm6237104"></a>AltOS</h1></div><div><h2 class="subtitle">Altos Metrum Operating System</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Keith</span> <span class="surname">Packard</span></h3></div></div><div><p class="copyright">Copyright © 2010 Keith Packard</p></div><div><div class="legalnotice"><a name="idp47806768"></a><p>
2         This document is released under the terms of the
3         <a class="ulink" href="http://creativecommons.org/licenses/by-sa/3.0/" target="_top">
4           Creative Commons ShareAlike 3.0
5         </a>
6         license.
7       </p></div></div><div><div class="revhistory"><table style="border-style:solid; width:100%;" summary="Revision History"><tr><th align="left" valign="top" colspan="2"><b>Revision History</b></th></tr><tr><td align="left">Revision 1.1</td><td align="left">05 November 2012</td></tr><tr><td align="left" colspan="2">Portable version</td></tr><tr><td align="left">Revision 0.1</td><td align="left">22 November 2010</td></tr><tr><td align="left" colspan="2">Initial content</td></tr></table></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="chapter"><a href="#idp47731744">1. Overview</a></span></dt><dt><span class="chapter"><a href="#idp48618208">2. AltOS Porting Layer</a></span></dt><dd><dl><dt><span class="section"><a href="#idp48619712">1. Low-level CPU operations</a></span></dt><dd><dl><dt><span class="section"><a href="#idp48620944">1.1. ao_arch_block_interrupts/ao_arch_release_interrupts</a></span></dt><dt><span class="section"><a href="#idp48622992">1.2. ao_arch_save_regs, ao_arch_save_stack,
8         ao_arch_restore_stack</a></span></dt><dt><span class="section"><a href="#idp52661280">1.3. ao_arch_wait_interupt</a></span></dt></dl></dd><dt><span class="section"><a href="#idp52663824">2. GPIO operations</a></span></dt><dd><dl><dt><span class="section"><a href="#idp52664992">2.1. GPIO setup</a></span></dt><dt><span class="section"><a href="#idp52674048">2.2. Reading and writing GPIO pins</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#idp47738336">3. Programming the 8051 with SDCC</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47740384">1. 8051 memory spaces</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47742320">1.1. __data</a></span></dt><dt><span class="section"><a href="#idp47744496">1.2. __idata</a></span></dt><dt><span class="section"><a href="#idp47745936">1.3. __xdata</a></span></dt><dt><span class="section"><a href="#idp47747344">1.4. __pdata</a></span></dt><dt><span class="section"><a href="#idp47748848">1.5. __code</a></span></dt><dt><span class="section"><a href="#idp47750288">1.6. __bit</a></span></dt><dt><span class="section"><a href="#idp47751792">1.7. __sfr, __sfr16, __sfr32, __sbit</a></span></dt></dl></dd><dt><span class="section"><a href="#idp47753328">2. Function calls on the 8051</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47754800">2.1. __reentrant functions</a></span></dt><dt><span class="section"><a href="#idp47756992">2.2. Non __reentrant functions</a></span></dt><dt><span class="section"><a href="#idp47759136">2.3. __interrupt functions</a></span></dt><dt><span class="section"><a href="#idp47760704">2.4. __critical functions and statements</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#idp47762768">4. Task functions</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47763824">1. ao_add_task</a></span></dt><dt><span class="section"><a href="#idp47766080">2. ao_exit</a></span></dt><dt><span class="section"><a href="#idp54289280">3. ao_sleep</a></span></dt><dt><span class="section"><a href="#idp54292880">4. ao_wakeup</a></span></dt><dt><span class="section"><a href="#idp54295872">5. ao_alarm</a></span></dt><dt><span class="section"><a href="#idp54299152">6. ao_start_scheduler</a></span></dt><dt><span class="section"><a href="#idp54301120">7. ao_clock_init</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54303088">5. Timer Functions</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54304592">1. ao_time</a></span></dt><dt><span class="section"><a href="#idp54306576">2. ao_delay</a></span></dt><dt><span class="section"><a href="#idp54308416">3. ao_timer_set_adc_interval</a></span></dt><dt><span class="section"><a href="#idp54310464">4. ao_timer_init</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54312656">6. AltOS Mutexes</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54314528">1. ao_mutex_get</a></span></dt><dt><span class="section"><a href="#idp54316368">2. ao_mutex_put</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54318336">7. DMA engine</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54321776">1. CC1111 DMA Engine</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54322448">1.1. ao_dma_alloc</a></span></dt><dt><span class="section"><a href="#idp54324624">1.2. ao_dma_set_transfer</a></span></dt><dt><span class="section"><a href="#idp54326896">1.3. ao_dma_start</a></span></dt><dt><span class="section"><a href="#idp54328912">1.4. ao_dma_trigger</a></span></dt><dt><span class="section"><a href="#idp54330832">1.5. ao_dma_abort</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54332976">2. STM32L DMA Engine</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54333648">2.1. ao_dma_alloc</a></span></dt><dt><span class="section"><a href="#idp54335648">2.2. ao_dma_set_transfer</a></span></dt><dt><span class="section"><a href="#idp54337904">2.3. ao_dma_set_isr</a></span></dt><dt><span class="section"><a href="#idp54340064">2.4. ao_dma_start</a></span></dt><dt><span class="section"><a href="#idp54342368">2.5. ao_dma_done_transfer</a></span></dt><dt><span class="section"><a href="#idp54344352">2.6. ao_dma_abort</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#idp54346624">8. Stdio interface</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54348128">1. putchar</a></span></dt><dt><span class="section"><a href="#idp54350096">2. getchar</a></span></dt><dt><span class="section"><a href="#idp54352192">3. flush</a></span></dt><dt><span class="section"><a href="#idp54354224">4. ao_add_stdio</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54358256">9. Command line interface</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54359664">1. ao_cmd_register</a></span></dt><dt><span class="section"><a href="#idp54368304">2. ao_cmd_lex</a></span></dt><dt><span class="section"><a href="#idp54370384">3. ao_cmd_put16</a></span></dt><dt><span class="section"><a href="#idp54372224">4. ao_cmd_put8</a></span></dt><dt><span class="section"><a href="#idp54374112">5. ao_cmd_white</a></span></dt><dt><span class="section"><a href="#idp54376176">6. ao_cmd_hex</a></span></dt><dt><span class="section"><a href="#idp54378224">7. ao_cmd_decimal</a></span></dt><dt><span class="section"><a href="#idp54380320">8. ao_match_word</a></span></dt><dt><span class="section"><a href="#idp54382400">9. ao_cmd_init</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54384624">10. USB target device</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54386848">1. ao_usb_flush</a></span></dt><dt><span class="section"><a href="#idp54388992">2. ao_usb_putchar</a></span></dt><dt><span class="section"><a href="#idp54391168">3. ao_usb_pollchar</a></span></dt><dt><span class="section"><a href="#idp54393312">4. ao_usb_getchar</a></span></dt><dt><span class="section"><a href="#idp54395328">5. ao_usb_disable</a></span></dt><dt><span class="section"><a href="#idp54398160">6. ao_usb_enable</a></span></dt><dt><span class="section"><a href="#idp54400272">7. ao_usb_init</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54402496">11. Serial peripherals</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54404512">1. ao_serial_getchar</a></span></dt><dt><span class="section"><a href="#idp54406544">2. ao_serial_putchar</a></span></dt><dt><span class="section"><a href="#idp54408512">3. ao_serial_drain</a></span></dt><dt><span class="section"><a href="#idp54410512">4. ao_serial_set_speed</a></span></dt><dt><span class="section"><a href="#idp54412544">5. ao_serial_init</a></span></dt></dl></dd><dt><span class="chapter"><a href="#idp54414736">12. CC1111 Radio peripheral</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54415408">1. Radio Introduction</a></span></dt><dt><span class="section"><a href="#idp54422528">2. ao_radio_set_telemetry</a></span></dt><dt><span class="section"><a href="#idp54424688">3. ao_radio_set_packet</a></span></dt><dt><span class="section"><a href="#idp54426848">4. ao_radio_set_rdf</a></span></dt><dt><span class="section"><a href="#idp54429088">5. ao_radio_idle</a></span></dt><dt><span class="section"><a href="#idp54431136">6. ao_radio_get</a></span></dt><dt><span class="section"><a href="#idp54433168">7. ao_radio_put</a></span></dt><dt><span class="section"><a href="#idp54435104">8. ao_radio_abort</a></span></dt><dt><span class="section"><a href="#idp54437168">9. Radio Telemetry</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54438464">9.1. ao_radio_send</a></span></dt><dt><span class="section"><a href="#idp54440688">9.2. ao_radio_recv</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54443152">10. Radio Direction Finding</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54444304">10.1. ao_radio_rdf</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54446448">11. Radio Packet Mode</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54447760">11.1. ao_packet_putchar</a></span></dt><dt><span class="section"><a href="#idp54449936">11.2. ao_packet_pollchar</a></span></dt><dt><span class="section"><a href="#idp54452016">11.3. ao_packet_slave_start</a></span></dt><dt><span class="section"><a href="#idp54453968">11.4. ao_packet_slave_stop</a></span></dt><dt><span class="section"><a href="#idp54455888">11.5. ao_packet_slave_init</a></span></dt><dt><span class="section"><a href="#idp54457920">11.6. ao_packet_master_init</a></span></dt></dl></dd></dl></dd></dl></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp47731744"></a>Chapter 1. Overview</h1></div></div></div><p>
9       AltOS is a operating system built for a variety of
10       microcontrollers used in Altus Metrum devices. It has a simple
11       porting layer for each CPU while providing a convenient
12       operating enviroment for the developer. AltOS currently
13       supports three different CPUs:
14       </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
15             STM32L series from ST Microelectronics. This ARM Cortex-M3
16             based microcontroller offers low power consumption and a
17             wide variety of built-in peripherals. Altus Metrum uses
18             this in the TeleMega, MegaDongle and TeleLCO projects.
19           </p></li><li class="listitem"><p>
20             CC1111 from Texas Instruments. This device includes a
21             fabulous 10mW digital RF transceiver along with an
22             8051-compatible processor core and a range of
23             peripherals. This is used in the TeleMetrum, TeleMini,
24             TeleDongle and TeleFire projects which share the need for
25             a small microcontroller and an RF interface.
26           </p></li><li class="listitem"><p>
27             ATmega32U4 from Atmel. This 8-bit AVR microcontroller is
28             one of the many used to create Arduino boards. The 32U4
29             includes a USB interface, making it easy to connect to
30             other computers. Altus Metrum used this in prototypes of
31             the TeleScience and TelePyro boards; those have been
32             switched to the STM32L which is more capable and cheaper.
33           </p></li></ul></div><p>
34       Among the features of AltOS are:
35       </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>Multi-tasking. While microcontrollers often don't
36           provide separate address spaces, it's often easier to write
37           code that operates in separate threads instead of tying
38           everything into one giant event loop.
39           </p></li><li class="listitem"><p>Non-preemptive. This increases latency for thread
40           switching but reduces the number of places where context
41           switching can occur. It also simplifies the operating system
42           design somewhat. Nothing in the target system (rocket flight
43           control) has tight timing requirements, and so this seems like
44           a reasonable compromise.
45           </p></li><li class="listitem"><p>Sleep/wakeup scheduling. Taken directly from ancient
46           Unix designs, these two provide the fundemental scheduling
47           primitive within AltOS.
48           </p></li><li class="listitem"><p>Mutexes. As a locking primitive, mutexes are easier to
49           use than semaphores, at least in my experience.
50           </p></li><li class="listitem"><p>Timers. Tasks can set an alarm which will abort any
51           pending sleep, allowing operations to time-out instead of
52           blocking forever.
53           </p></li></ul></div><p>
54     </p><p>
55       The device drivers and other subsystems in AltOS are
56       conventionally enabled by invoking their _init() function from
57       the 'main' function before that calls
58       ao_start_scheduler(). These functions initialize the pin
59       assignments, add various commands to the command processor and
60       may add tasks to the scheduler to handle the device. A typical
61       main program, thus, looks like:
62       </p><pre class="programlisting">
63         void
64         main(void)
65         {
66                 ao_clock_init();
67
68                 /* Turn on the LED until the system is stable */
69                 ao_led_init(LEDS_AVAILABLE);
70                 ao_led_on(AO_LED_RED);
71                 ao_timer_init();
72                 ao_cmd_init();
73                 ao_usb_init();
74                 ao_monitor_init(AO_LED_GREEN, TRUE);
75                 ao_rssi_init(AO_LED_RED);
76                 ao_radio_init();
77                 ao_packet_slave_init();
78                 ao_packet_master_init();
79                 #if HAS_DBG
80                 ao_dbg_init();
81                 #endif
82                 ao_config_init();
83                 ao_start_scheduler();
84         }
85       </pre><p>
86       As you can see, a long sequence of subsystems are initialized
87       and then the scheduler is started.
88     </p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp48618208"></a>Chapter 2. AltOS Porting Layer</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp48619712">1. Low-level CPU operations</a></span></dt><dd><dl><dt><span class="section"><a href="#idp48620944">1.1. ao_arch_block_interrupts/ao_arch_release_interrupts</a></span></dt><dt><span class="section"><a href="#idp48622992">1.2. ao_arch_save_regs, ao_arch_save_stack,
89         ao_arch_restore_stack</a></span></dt><dt><span class="section"><a href="#idp52661280">1.3. ao_arch_wait_interupt</a></span></dt></dl></dd><dt><span class="section"><a href="#idp52663824">2. GPIO operations</a></span></dt><dd><dl><dt><span class="section"><a href="#idp52664992">2.1. GPIO setup</a></span></dt><dt><span class="section"><a href="#idp52674048">2.2. Reading and writing GPIO pins</a></span></dt></dl></dd></dl></div><p>
90       AltOS provides a CPU-independent interface to various common
91       microcontroller subsystems, including GPIO pins, interrupts,
92       SPI, I2C, USB and asynchronous serial interfaces. By making
93       these CPU-independent, device drivers, generic OS and
94       application code can all be written that work on any supported
95       CPU. Many of the architecture abstraction interfaces are
96       prefixed with ao_arch.
97     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp48619712"></a>1. Low-level CPU operations</h2></div></div></div><p>
98         These primitive operations provide the abstraction needed to
99         run the multi-tasking framework while providing reliable
100         interrupt delivery.
101       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp48620944"></a>1.1. ao_arch_block_interrupts/ao_arch_release_interrupts</h3></div></div></div><pre class="programlisting">
102           static inline void
103           ao_arch_block_interrupts(void);
104           
105           static inline void
106           ao_arch_release_interrupts(void);
107         </pre><p>
108           These disable/enable interrupt delivery, they may not
109           discard any interrupts. Use these for sections of code that
110           must be atomic with respect to any code run from an
111           interrupt handler.
112         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp48622992"></a>1.2. ao_arch_save_regs, ao_arch_save_stack,
113         ao_arch_restore_stack</h3></div></div></div><pre class="programlisting">
114           static inline void
115           ao_arch_save_regs(void);
116
117           static inline void
118           ao_arch_save_stack(void);
119
120           static inline void
121           ao_arch_restore_stack(void);
122         </pre><p>
123           These provide all of the support needed to switch between
124           tasks.. ao_arch_save_regs must save all CPU registers to the
125           current stack, including the interrupt enable
126           state. ao_arch_save_stack records the current stack location
127           in the current ao_task structure. ao_arch_restore_stack
128           switches back to the saved stack, restores all registers and
129           branches to the saved return address.
130         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp52661280"></a>1.3. ao_arch_wait_interupt</h3></div></div></div><pre class="programlisting">
131           #define ao_arch_wait_interrupt()
132         </pre><p>
133           This stops the CPU, leaving clocks and interrupts
134           enabled. When an interrupt is received, this must wake up
135           and handle the interrupt. ao_arch_wait_interrupt is entered
136           with interrupts disabled to ensure that there is no gap
137           between determining that no task wants to run and idling the
138           CPU. It must sleep the CPU, process interrupts and then
139           disable interrupts again. If the CPU doesn't have any
140           reduced power mode, this must at the least allow pending
141           interrupts to be processed.
142         </p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp52663824"></a>2. GPIO operations</h2></div></div></div><p>
143         These functions provide an abstract interface to configure and
144         manipulate GPIO pins.
145       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp52664992"></a>2.1. GPIO setup</h3></div></div></div><p>
146           These macros may be invoked at system initialization time to
147           configure pins as needed for system operation. One tricky
148           aspect is that some chips provide direct access to specific
149           GPIO pins while others only provide access to a whole
150           register full of pins. To support this, the GPIO macros
151           provide both port+bit and pin arguments. Simply define the
152           arguments needed for the target platform and leave the
153           others undefined.
154         </p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="idp48624736"></a>2.1.1. ao_enable_output</h4></div></div></div><pre class="programlisting">
155             #define ao_enable_output(port, bit, pin, value)
156           </pre><p>
157             Set the specified port+bit (also called 'pin') for output,
158             initializing to the specified value. The macro must avoid
159             driving the pin with the opposite value if at all
160             possible.
161           </p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="idp52668656"></a>2.1.2. ao_enable_input</h4></div></div></div><pre class="programlisting">
162             #define ao_enable_input(port, bit, mode)
163           </pre><p>
164             Sets the specified port/bit to be an input pin. 'mode' is
165             a combination of one or more of the following. Note that
166             some platforms may not support the desired mode. In that
167             case, the value will not be defined so that the program
168             will fail to compile.
169             </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
170                 AO_EXTI_MODE_PULL_UP. Apply a pull-up to the pin; a
171                 disconnected pin will read as 1.
172 </p></li><li class="listitem"><p>
173                 AO_EXTI_MODE_PULL_DOWN. Apply a pull-down to the pin;
174                 a disconnected pin will read as 0.
175 </p></li><li class="listitem"><p>
176                 0. Don't apply either a pull-up or pull-down. A
177                 disconnected pin will read an undetermined value.
178 </p></li></ul></div><p>
179           </p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp52674048"></a>2.2. Reading and writing GPIO pins</h3></div></div></div><p>
180           These macros read and write individual GPIO pins.
181         </p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="idp52675120"></a>2.2.1. ao_gpio_set</h4></div></div></div><pre class="programlisting">
182             #define ao_gpio_set(port, bit, pin, value)
183           </pre><p>
184             Sets the specified port/bit or pin to the indicated value
185           </p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="idp47736000"></a>2.2.2. ao_gpio_get</h4></div></div></div><pre class="programlisting">
186             #define ao_gpio_get(port, bit, pin)
187           </pre><p>
188             Returns either 1 or 0 depending on whether the input to
189             the pin is high or low.
190           </p></div></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp47738336"></a>Chapter 3. Programming the 8051 with SDCC</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp47740384">1. 8051 memory spaces</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47742320">1.1. __data</a></span></dt><dt><span class="section"><a href="#idp47744496">1.2. __idata</a></span></dt><dt><span class="section"><a href="#idp47745936">1.3. __xdata</a></span></dt><dt><span class="section"><a href="#idp47747344">1.4. __pdata</a></span></dt><dt><span class="section"><a href="#idp47748848">1.5. __code</a></span></dt><dt><span class="section"><a href="#idp47750288">1.6. __bit</a></span></dt><dt><span class="section"><a href="#idp47751792">1.7. __sfr, __sfr16, __sfr32, __sbit</a></span></dt></dl></dd><dt><span class="section"><a href="#idp47753328">2. Function calls on the 8051</a></span></dt><dd><dl><dt><span class="section"><a href="#idp47754800">2.1. __reentrant functions</a></span></dt><dt><span class="section"><a href="#idp47756992">2.2. Non __reentrant functions</a></span></dt><dt><span class="section"><a href="#idp47759136">2.3. __interrupt functions</a></span></dt><dt><span class="section"><a href="#idp47760704">2.4. __critical functions and statements</a></span></dt></dl></dd></dl></div><p>
191       The 8051 is a primitive 8-bit processor, designed in the mists
192       of time in as few transistors as possible. The architecture is
193       highly irregular and includes several separate memory
194       spaces. Furthermore, accessing stack variables is slow, and the
195       stack itself is of limited size. While SDCC papers over the
196       instruction set, it is not completely able to hide the memory
197       architecture from the application designer.
198     </p><p>
199       When built on other architectures, the various SDCC-specific
200       symbols are #defined as empty strings so they don't affect the compiler.
201     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp47740384"></a>1. 8051 memory spaces</h2></div></div></div><p>
202         The __data/__xdata/__code memory spaces below were completely
203         separate in the original 8051 design. In the cc1111, this
204         isn't true&#8212;they all live in a single unified 64kB address
205         space, and so it's possible to convert any address into a
206         unique 16-bit address. SDCC doesn't know this, and so a
207         'global' address to SDCC consumes 3 bytes of memory, 1 byte as
208         a tag indicating the memory space and 2 bytes of offset within
209         that space. AltOS avoids these 3-byte addresses as much as
210         possible; using them involves a function call per byte
211         access. The result is that nearly every variable declaration
212         is decorated with a memory space identifier which clutters the
213         code but makes the resulting code far smaller and more
214         efficient.
215       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47742320"></a>1.1. __data</h3></div></div></div><p>
216           The 8051 can directly address these 128 bytes of
217           memory. This makes them precious so they should be
218           reserved for frequently addressed values. Oh, just to
219           confuse things further, the 8 general registers in the
220           CPU are actually stored in this memory space. There are
221           magic instructions to 'bank switch' among 4 banks of
222           these registers located at 0x00 - 0x1F. AltOS uses only
223           the first bank at 0x00 - 0x07, leaving the other 24
224           bytes available for other data.
225         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47744496"></a>1.2. __idata</h3></div></div></div><p>
226           There are an additional 128 bytes of internal memory
227           that share the same address space as __data but which
228           cannot be directly addressed. The stack normally
229           occupies this space and so AltOS doesn't place any
230           static storage here.
231         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47745936"></a>1.3. __xdata</h3></div></div></div><p>
232           This is additional general memory accessed through a
233           single 16-bit address register. The CC1111F32 has 32kB
234           of memory available here. Most program data should live
235           in this memory space.
236         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47747344"></a>1.4. __pdata</h3></div></div></div><p>
237           This is an alias for the first 256 bytes of __xdata
238           memory, but uses a shorter addressing mode with
239           single global 8-bit value for the high 8 bits of the
240           address and any of several 8-bit registers for the low 8
241           bits. AltOS uses a few bits of this memory, it should
242           probably use more.
243         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47748848"></a>1.5. __code</h3></div></div></div><p>
244           All executable code must live in this address space, but
245           you can stick read-only data here too. It is addressed
246           using the 16-bit address register and special 'code'
247           access opcodes. Anything read-only should live in this space.
248         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47750288"></a>1.6. __bit</h3></div></div></div><p>
249           The 8051 has 128 bits of bit-addressible memory that
250           lives in the __data segment from 0x20 through
251           0x2f. Special instructions access these bits
252           in a single atomic operation. This isn't so much a
253           separate address space as a special addressing mode for
254           a few bytes in the __data segment.
255         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47751792"></a>1.7. __sfr, __sfr16, __sfr32, __sbit</h3></div></div></div><p>
256           Access to physical registers in the device use this mode
257           which declares the variable name, it's type and the
258           address it lives at. No memory is allocated for these
259           variables.
260         </p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp47753328"></a>2. Function calls on the 8051</h2></div></div></div><p>
261         Because stack addressing is expensive, and stack space
262         limited, the default function call declaration in SDCC
263         allocates all parameters and local variables in static global
264         memory. Just like fortran. This makes these functions
265         non-reentrant, and also consume space for parameters and
266         locals even when they are not running. The benefit is smaller
267         code and faster execution.
268       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47754800"></a>2.1. __reentrant functions</h3></div></div></div><p>
269           All functions which are re-entrant, either due to recursion
270           or due to a potential context switch while executing, should
271           be marked as __reentrant so that their parameters and local
272           variables get allocated on the stack. This ensures that
273           these values are not overwritten by another invocation of
274           the function.
275         </p><p>
276           Functions which use significant amounts of space for
277           arguments and/or local variables and which are not often
278           invoked can also be marked as __reentrant. The resulting
279           code will be larger, but the savings in memory are
280           frequently worthwhile.
281         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47756992"></a>2.2. Non __reentrant functions</h3></div></div></div><p>
282           All parameters and locals in non-reentrant functions can
283           have data space decoration so that they are allocated in
284           __xdata, __pdata or __data space as desired. This can avoid
285           consuming __data space for infrequently used variables in
286           frequently used functions.
287         </p><p>
288           All library functions called by SDCC, including functions
289           for multiplying and dividing large data types, are
290           non-reentrant. Because of this, interrupt handlers must not
291           invoke any library functions, including the multiply and
292           divide code.
293         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47759136"></a>2.3. __interrupt functions</h3></div></div></div><p>
294           Interrupt functions are declared with with an __interrupt
295           decoration that includes the interrupt number. SDCC saves
296           and restores all of the registers in these functions and
297           uses the 'reti' instruction at the end so that they operate
298           as stand-alone interrupt handlers. Interrupt functions may
299           call the ao_wakeup function to wake AltOS tasks.
300         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp47760704"></a>2.4. __critical functions and statements</h3></div></div></div><p>
301           SDCC has built-in support for suspending interrupts during
302           critical code. Functions marked as __critical will have
303           interrupts suspended for the whole period of
304           execution. Individual statements may also be marked as
305           __critical which blocks interrupts during the execution of
306           that statement. Keeping critical sections as short as
307           possible is key to ensuring that interrupts are handled as
308           quickly as possible. AltOS doesn't use this form in shared
309           code as other compilers wouldn't know what to do. Use
310           ao_arch_block_interrupts and ao_arch_release_interrupts instead.
311         </p></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp47762768"></a>Chapter 4. Task functions</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp47763824">1. ao_add_task</a></span></dt><dt><span class="section"><a href="#idp47766080">2. ao_exit</a></span></dt><dt><span class="section"><a href="#idp54289280">3. ao_sleep</a></span></dt><dt><span class="section"><a href="#idp54292880">4. ao_wakeup</a></span></dt><dt><span class="section"><a href="#idp54295872">5. ao_alarm</a></span></dt><dt><span class="section"><a href="#idp54299152">6. ao_start_scheduler</a></span></dt><dt><span class="section"><a href="#idp54301120">7. ao_clock_init</a></span></dt></dl></div><p>
312       This chapter documents how to create, destroy and schedule AltOS tasks.
313     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp47763824"></a>1. ao_add_task</h2></div></div></div><pre class="programlisting">
314         void
315         ao_add_task(__xdata struct ao_task * task,
316                     void (*start)(void),
317                     __code char *name);
318       </pre><p>
319         This initializes the statically allocated task structure,
320         assigns a name to it (not used for anything but the task
321         display), and the start address. It does not switch to the
322         new task. 'start' must not ever return; there is no place
323         to return to.
324       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp47766080"></a>2. ao_exit</h2></div></div></div><pre class="programlisting">
325         void
326         ao_exit(void)
327       </pre><p>
328         This terminates the current task.
329       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54289280"></a>3. ao_sleep</h2></div></div></div><pre class="programlisting">
330         void
331         ao_sleep(__xdata void *wchan)
332       </pre><p>
333         This suspends the current task until 'wchan' is signaled
334         by ao_wakeup, or until the timeout, set by ao_alarm,
335         fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise
336         it returns 1. This is the only way to switch to another task.
337       </p><p>
338         Because ao_wakeup wakes every task waiting on a particular
339         location, ao_sleep should be used in a loop that first checks
340         the desired condition, blocks in ao_sleep and then rechecks
341         until the condition is satisfied. If the location may be
342         signaled from an interrupt handler, the code will need to
343         block interrupts around the block of code. Here's a complete
344         example:
345         </p><pre class="programlisting">
346           ao_arch_block_interrupts();
347           while (!ao_radio_done)
348                   ao_sleep(&amp;ao_radio_done);
349           ao_arch_release_interrupts();
350         </pre><p>
351       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54292880"></a>4. ao_wakeup</h2></div></div></div><pre class="programlisting">
352         void
353         ao_wakeup(__xdata void *wchan)
354       </pre><p>
355         Wake all tasks blocked on 'wchan'. This makes them
356         available to be run again, but does not actually switch
357         to another task. Here's an example of using this:
358         </p><pre class="programlisting">
359           if (RFIF &amp; RFIF_IM_DONE) {
360                   ao_radio_done = 1;
361                   ao_wakeup(&amp;ao_radio_done);
362                   RFIF &amp;= ~RFIF_IM_DONE;
363           }
364         </pre><p>
365         Note that this need not block interrupts as the ao_sleep block
366         can only be run from normal mode, and so this sequence can
367         never be interrupted with execution of the other sequence.
368       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54295872"></a>5. ao_alarm</h2></div></div></div><pre class="programlisting">
369         void
370         ao_alarm(uint16_t delay);
371
372         void
373         ao_clear_alarm(void);
374       </pre><p>
375         Schedules an alarm to fire in at least 'delay' ticks. If the
376         task is asleep when the alarm fires, it will wakeup and
377         ao_sleep will return 1. ao_clear_alarm resets any pending
378         alarm so that it doesn't fire at some arbitrary point in the
379         future.
380         </p><pre class="programlisting">
381           ao_alarm(ao_packet_master_delay);
382           ao_arch_block_interrupts();
383           while (!ao_radio_dma_done)
384                   if (ao_sleep(&amp;ao_radio_dma_done) != 0)
385                           ao_radio_abort();
386           ao_arch_release_interrupts();
387           ao_clear_alarm();
388         </pre><p>
389         In this example, a timeout is set before waiting for
390         incoming radio data. If no data is received before the
391         timeout fires, ao_sleep will return 1 and then this code
392         will abort the radio receive operation.
393       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54299152"></a>6. ao_start_scheduler</h2></div></div></div><pre class="programlisting">
394         void
395         ao_start_scheduler(void);
396       </pre><p>
397         This is called from 'main' when the system is all
398         initialized and ready to run. It will not return.
399       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54301120"></a>7. ao_clock_init</h2></div></div></div><pre class="programlisting">
400         void
401         ao_clock_init(void);
402       </pre><p>
403         This initializes the main CPU clock and switches to it.
404       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54303088"></a>Chapter 5. Timer Functions</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54304592">1. ao_time</a></span></dt><dt><span class="section"><a href="#idp54306576">2. ao_delay</a></span></dt><dt><span class="section"><a href="#idp54308416">3. ao_timer_set_adc_interval</a></span></dt><dt><span class="section"><a href="#idp54310464">4. ao_timer_init</a></span></dt></dl></div><p>
405       AltOS sets up one of the CPU timers to run at 100Hz and
406       exposes this tick as the fundemental unit of time. At each
407       interrupt, AltOS increments the counter, and schedules any tasks
408       waiting for that time to pass, then fires off the sensors to
409       collect current data readings. Doing this from the ISR ensures
410       that the values are sampled at a regular rate, independent
411       of any scheduling jitter.
412     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54304592"></a>1. ao_time</h2></div></div></div><pre class="programlisting">
413         uint16_t
414         ao_time(void)
415       </pre><p>
416         Returns the current system tick count. Note that this is
417         only a 16 bit value, and so it wraps every 655.36 seconds.
418       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54306576"></a>2. ao_delay</h2></div></div></div><pre class="programlisting">
419         void
420         ao_delay(uint16_t ticks);
421       </pre><p>
422         Suspend the current task for at least 'ticks' clock units.
423       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54308416"></a>3. ao_timer_set_adc_interval</h2></div></div></div><pre class="programlisting">
424         void
425         ao_timer_set_adc_interval(uint8_t interval);
426       </pre><p>
427         This sets the number of ticks between ADC samples. If set
428         to 0, no ADC samples are generated. AltOS uses this to
429         slow down the ADC sampling rate to save power.
430       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54310464"></a>4. ao_timer_init</h2></div></div></div><pre class="programlisting">
431         void
432         ao_timer_init(void)
433       </pre><p>
434         This turns on the 100Hz tick. It is required for any of the
435         time-based functions to work. It should be called by 'main'
436         before ao_start_scheduler.
437       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54312656"></a>Chapter 6. AltOS Mutexes</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54314528">1. ao_mutex_get</a></span></dt><dt><span class="section"><a href="#idp54316368">2. ao_mutex_put</a></span></dt></dl></div><p>
438       AltOS provides mutexes as a basic synchronization primitive. Each
439       mutexes is simply a byte of memory which holds 0 when the mutex
440       is free or the task id of the owning task when the mutex is
441       owned. Mutex calls are checked&#8212;attempting to acquire a mutex
442       already held by the current task or releasing a mutex not held
443       by the current task will both cause a panic.
444     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54314528"></a>1. ao_mutex_get</h2></div></div></div><pre class="programlisting">
445         void
446         ao_mutex_get(__xdata uint8_t *mutex);
447       </pre><p>
448         Acquires the specified mutex, blocking if the mutex is
449         owned by another task.
450       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54316368"></a>2. ao_mutex_put</h2></div></div></div><pre class="programlisting">
451         void
452         ao_mutex_put(__xdata uint8_t *mutex);
453       </pre><p>
454         Releases the specified mutex, waking up all tasks waiting
455         for it.
456       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54318336"></a>Chapter 7. DMA engine</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54321776">1. CC1111 DMA Engine</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54322448">1.1. ao_dma_alloc</a></span></dt><dt><span class="section"><a href="#idp54324624">1.2. ao_dma_set_transfer</a></span></dt><dt><span class="section"><a href="#idp54326896">1.3. ao_dma_start</a></span></dt><dt><span class="section"><a href="#idp54328912">1.4. ao_dma_trigger</a></span></dt><dt><span class="section"><a href="#idp54330832">1.5. ao_dma_abort</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54332976">2. STM32L DMA Engine</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54333648">2.1. ao_dma_alloc</a></span></dt><dt><span class="section"><a href="#idp54335648">2.2. ao_dma_set_transfer</a></span></dt><dt><span class="section"><a href="#idp54337904">2.3. ao_dma_set_isr</a></span></dt><dt><span class="section"><a href="#idp54340064">2.4. ao_dma_start</a></span></dt><dt><span class="section"><a href="#idp54342368">2.5. ao_dma_done_transfer</a></span></dt><dt><span class="section"><a href="#idp54344352">2.6. ao_dma_abort</a></span></dt></dl></dd></dl></div><p>
457       The CC1111 and STM32L both contain a useful bit of extra
458       hardware in the form of a number of programmable DMA
459       engines. They can be configured to copy data in memory, or
460       between memory and devices (or even between two devices). AltOS
461       exposes a general interface to this hardware and uses it to
462       handle both internal and external devices.
463     </p><p>
464       Because the CC1111 and STM32L DMA engines are different, the
465       interface to them is also different. As the DMA engines are
466       currently used to implement platform-specific drivers, this
467       isn't yet a problem.
468     </p><p>
469       Code using a DMA engine should allocate one at startup
470       time. There is no provision to free them, and if you run out,
471       AltOS will simply panic.
472     </p><p>
473       During operation, the DMA engine is initialized with the
474       transfer parameters. Then it is started, at which point it
475       awaits a suitable event to start copying data. When copying data
476       from hardware to memory, that trigger event is supplied by the
477       hardware device. When copying data from memory to hardware, the
478       transfer is usually initiated by software.
479     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54321776"></a>1. CC1111 DMA Engine</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54322448"></a>1.1. ao_dma_alloc</h3></div></div></div><pre class="programlisting">
480           uint8_t
481           ao_dma_alloc(__xdata uint8_t *done)
482         </pre><p>
483           Allocate a DMA engine, returning the identifier.  'done' is
484           cleared when the DMA is started, and then receives the
485           AO_DMA_DONE bit on a successful transfer or the
486           AO_DMA_ABORTED bit if ao_dma_abort was called. Note that it
487           is possible to get both bits if the transfer was aborted
488           after it had finished.
489         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54324624"></a>1.2. ao_dma_set_transfer</h3></div></div></div><pre class="programlisting">
490           void
491           ao_dma_set_transfer(uint8_t id,
492           void __xdata *srcaddr,
493           void __xdata *dstaddr,
494           uint16_t count,
495           uint8_t cfg0,
496           uint8_t cfg1)
497         </pre><p>
498           Initializes the specified dma engine to copy data
499           from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and
500           cfg1 are values directly out of the CC1111 documentation
501           and tell the DMA engine what the transfer unit size,
502           direction and step are.
503         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54326896"></a>1.3. ao_dma_start</h3></div></div></div><pre class="programlisting">
504           void
505           ao_dma_start(uint8_t id);
506         </pre><p>
507           Arm the specified DMA engine and await a signal from
508           either hardware or software to start transferring data.
509         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54328912"></a>1.4. ao_dma_trigger</h3></div></div></div><pre class="programlisting">
510           void
511           ao_dma_trigger(uint8_t id)
512         </pre><p>
513           Trigger the specified DMA engine to start copying data.
514         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54330832"></a>1.5. ao_dma_abort</h3></div></div></div><pre class="programlisting">
515           void
516           ao_dma_abort(uint8_t id)
517         </pre><p>
518           Terminate any in-progress DMA transation, marking its
519           'done' variable with the AO_DMA_ABORTED bit.
520         </p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54332976"></a>2. STM32L DMA Engine</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54333648"></a>2.1. ao_dma_alloc</h3></div></div></div><pre class="programlisting">
521           uint8_t ao_dma_done[];
522
523           void
524           ao_dma_alloc(uint8_t index);
525         </pre><p>
526           Reserve a DMA engine for exclusive use by one
527           driver.
528         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54335648"></a>2.2. ao_dma_set_transfer</h3></div></div></div><pre class="programlisting">
529           void
530           ao_dma_set_transfer(uint8_t id,
531           void *peripheral,
532           void *memory,
533           uint16_t count,
534           uint32_t ccr);
535         </pre><p>
536           Initializes the specified dma engine to copy data between
537           'peripheral' and 'memory' for 'count' units. 'ccr' is a
538           value directly out of the STM32L documentation and tells the
539           DMA engine what the transfer unit size, direction and step
540           are.
541         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54337904"></a>2.3. ao_dma_set_isr</h3></div></div></div><pre class="programlisting">
542           void
543           ao_dma_set_isr(uint8_t index, void (*isr)(int))
544         </pre><p>
545           This sets a function to be called when the DMA transfer
546           completes in lieu of setting the ao_dma_done bits. Use this
547           when some work needs to be done when the DMA finishes that
548           cannot wait until user space resumes.
549         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54340064"></a>2.4. ao_dma_start</h3></div></div></div><pre class="programlisting">
550           void
551           ao_dma_start(uint8_t id);
552         </pre><p>
553           Arm the specified DMA engine and await a signal from either
554           hardware or software to start transferring data.
555           'ao_dma_done[index]' is cleared when the DMA is started, and
556           then receives the AO_DMA_DONE bit on a successful transfer
557           or the AO_DMA_ABORTED bit if ao_dma_abort was called. Note
558           that it is possible to get both bits if the transfer was
559           aborted after it had finished.
560         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54342368"></a>2.5. ao_dma_done_transfer</h3></div></div></div><pre class="programlisting">
561           void
562           ao_dma_done_transfer(uint8_t id);
563         </pre><p>
564           Signals that a specific DMA engine is done being used. This
565           allows multiple drivers to use the same DMA engine safely.
566         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54344352"></a>2.6. ao_dma_abort</h3></div></div></div><pre class="programlisting">
567           void
568           ao_dma_abort(uint8_t id)
569         </pre><p>
570           Terminate any in-progress DMA transation, marking its
571           'done' variable with the AO_DMA_ABORTED bit.
572         </p></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54346624"></a>Chapter 8. Stdio interface</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54348128">1. putchar</a></span></dt><dt><span class="section"><a href="#idp54350096">2. getchar</a></span></dt><dt><span class="section"><a href="#idp54352192">3. flush</a></span></dt><dt><span class="section"><a href="#idp54354224">4. ao_add_stdio</a></span></dt></dl></div><p>
573       AltOS offers a stdio interface over USB, serial and the RF
574       packet link. This provides for control of the device localy or
575       remotely. This is hooked up to the stdio functions by providing
576       the standard putchar/getchar/flush functions. These
577       automatically multiplex the available communication channels;
578       output is always delivered to the channel which provided the
579       most recent input.
580     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54348128"></a>1. putchar</h2></div></div></div><pre class="programlisting">
581         void
582         putchar(char c)
583       </pre><p>
584         Delivers a single character to the current console
585         device.
586       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54350096"></a>2. getchar</h2></div></div></div><pre class="programlisting">
587         char
588         getchar(void)
589       </pre><p>
590         Reads a single character from any of the available
591         console devices. The current console device is set to
592         that which delivered this character. This blocks until
593         a character is available.
594       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54352192"></a>3. flush</h2></div></div></div><pre class="programlisting">
595         void
596         flush(void)
597       </pre><p>
598         Flushes the current console device output buffer. Any
599         pending characters will be delivered to the target device.
600       xo          </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54354224"></a>4. ao_add_stdio</h2></div></div></div><pre class="programlisting">
601         void
602         ao_add_stdio(char (*pollchar)(void),
603                            void (*putchar)(char),
604                            void (*flush)(void))
605       </pre><p>
606         This adds another console device to the available
607         list.
608       </p><p>
609         'pollchar' returns either an available character or
610         AO_READ_AGAIN if none is available. Significantly, it does
611         not block. The device driver must set 'ao_stdin_ready' to
612         1 and call ao_wakeup(&amp;ao_stdin_ready) when it receives
613         input to tell getchar that more data is available, at
614         which point 'pollchar' will be called again.
615       </p><p>
616         'putchar' queues a character for output, flushing if the output buffer is
617         full. It may block in this case.
618       </p><p>
619         'flush' forces the output buffer to be flushed. It may
620         block until the buffer is delivered, but it is not
621         required to do so.
622       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54358256"></a>Chapter 9. Command line interface</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54359664">1. ao_cmd_register</a></span></dt><dt><span class="section"><a href="#idp54368304">2. ao_cmd_lex</a></span></dt><dt><span class="section"><a href="#idp54370384">3. ao_cmd_put16</a></span></dt><dt><span class="section"><a href="#idp54372224">4. ao_cmd_put8</a></span></dt><dt><span class="section"><a href="#idp54374112">5. ao_cmd_white</a></span></dt><dt><span class="section"><a href="#idp54376176">6. ao_cmd_hex</a></span></dt><dt><span class="section"><a href="#idp54378224">7. ao_cmd_decimal</a></span></dt><dt><span class="section"><a href="#idp54380320">8. ao_match_word</a></span></dt><dt><span class="section"><a href="#idp54382400">9. ao_cmd_init</a></span></dt></dl></div><p>
623       AltOS includes a simple command line parser which is hooked up
624       to the stdio interfaces permitting remote control of the device
625       over USB, serial or the RF link as desired. Each command uses a
626       single character to invoke it, the remaining characters on the
627       line are available as parameters to the command.
628     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54359664"></a>1. ao_cmd_register</h2></div></div></div><pre class="programlisting">
629         void
630         ao_cmd_register(__code struct ao_cmds *cmds)
631       </pre><p>
632         This registers a set of commands with the command
633         parser. There is a fixed limit on the number of command
634         sets, the system will panic if too many are registered.
635         Each command is defined by a struct ao_cmds entry:
636         </p><pre class="programlisting">
637           struct ao_cmds {
638                   char          cmd;
639                   void          (*func)(void);
640                   const char    *help;
641           };
642         </pre><p>
643         'cmd' is the character naming the command. 'func' is the
644         function to invoke and 'help' is a string displayed by the
645         '?' command. Syntax errors found while executing 'func'
646         should be indicated by modifying the global ao_cmd_status
647         variable with one of the following values:
648         </p><div class="variablelist"><dl class="variablelist"><dt><span class="term">ao_cmd_success</span></dt><dd><p>
649                 The command was parsed successfully. There is no
650                 need to assign this value, it is the default.
651               </p></dd><dt><span class="term">ao_cmd_lex_error</span></dt><dd><p>
652                 A token in the line was invalid, such as a number
653                 containing invalid characters. The low-level
654                 lexing functions already assign this value as needed.
655               </p></dd><dt><span class="term">ao_syntax_error</span></dt><dd><p>
656                 The command line is invalid for some reason other
657                 than invalid tokens.
658               </p></dd></dl></div><p>
659       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54368304"></a>2. ao_cmd_lex</h2></div></div></div><pre class="programlisting">
660         void
661         ao_cmd_lex(void);
662       </pre><p>
663         This gets the next character out of the command line
664         buffer and sticks it into ao_cmd_lex_c. At the end of the
665         line, ao_cmd_lex_c will get a newline ('\n') character.
666       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54370384"></a>3. ao_cmd_put16</h2></div></div></div><pre class="programlisting">
667         void
668         ao_cmd_put16(uint16_t v);
669       </pre><p>
670         Writes 'v' as four hexadecimal characters.
671       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54372224"></a>4. ao_cmd_put8</h2></div></div></div><pre class="programlisting">
672         void
673         ao_cmd_put8(uint8_t v);
674       </pre><p>
675         Writes 'v' as two hexadecimal characters.
676       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54374112"></a>5. ao_cmd_white</h2></div></div></div><pre class="programlisting">
677         void
678         ao_cmd_white(void)
679       </pre><p>
680         This skips whitespace by calling ao_cmd_lex while
681         ao_cmd_lex_c is either a space or tab. It does not skip
682         any characters if ao_cmd_lex_c already non-white.
683       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54376176"></a>6. ao_cmd_hex</h2></div></div></div><pre class="programlisting">
684         void
685         ao_cmd_hex(void)
686       </pre><p>
687         This reads a 16-bit hexadecimal value from the command
688         line with optional leading whitespace. The resulting value
689         is stored in ao_cmd_lex_i;
690       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54378224"></a>7. ao_cmd_decimal</h2></div></div></div><pre class="programlisting">
691         void
692         ao_cmd_decimal(void)
693       </pre><p>
694         This reads a 32-bit decimal value from the command
695         line with optional leading whitespace. The resulting value
696         is stored in ao_cmd_lex_u32 and the low 16 bits are stored
697         in ao_cmd_lex_i;
698       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54380320"></a>8. ao_match_word</h2></div></div></div><pre class="programlisting">
699         uint8_t
700         ao_match_word(__code char *word)
701       </pre><p>
702         This checks to make sure that 'word' occurs on the command
703         line. It does not skip leading white space. If 'word' is
704         found, then 1 is returned. Otherwise, ao_cmd_status is set to
705         ao_cmd_syntax_error and 0 is returned.
706       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54382400"></a>9. ao_cmd_init</h2></div></div></div><pre class="programlisting">
707         void
708         ao_cmd_init(void
709       </pre><p>
710         Initializes the command system, setting up the built-in
711         commands and adding a task to run the command processing
712         loop. It should be called by 'main' before ao_start_scheduler.
713       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54384624"></a>Chapter 10. USB target device</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54386848">1. ao_usb_flush</a></span></dt><dt><span class="section"><a href="#idp54388992">2. ao_usb_putchar</a></span></dt><dt><span class="section"><a href="#idp54391168">3. ao_usb_pollchar</a></span></dt><dt><span class="section"><a href="#idp54393312">4. ao_usb_getchar</a></span></dt><dt><span class="section"><a href="#idp54395328">5. ao_usb_disable</a></span></dt><dt><span class="section"><a href="#idp54398160">6. ao_usb_enable</a></span></dt><dt><span class="section"><a href="#idp54400272">7. ao_usb_init</a></span></dt></dl></div><p>
714       AltOS contains a full-speed USB target device driver. It can be
715       programmed to offer any kind of USB target, but to simplify
716       interactions with a variety of operating systems, AltOS provides
717       only a single target device profile, that of a USB modem which
718       has native drivers for Linux, Windows and Mac OS X. It would be
719       easy to change the code to provide an alternate target device if
720       necessary.
721     </p><p>
722       To the rest of the system, the USB device looks like a simple
723       two-way byte stream. It can be hooked into the command line
724       interface if desired, offering control of the device over the
725       USB link. Alternatively, the functions can be accessed directly
726       to provide for USB-specific I/O.
727     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54386848"></a>1. ao_usb_flush</h2></div></div></div><pre class="programlisting">
728         void
729         ao_usb_flush(void);
730       </pre><p>
731         Flushes any pending USB output. This queues an 'IN' packet
732         to be delivered to the USB host if there is pending data,
733         or if the last IN packet was full to indicate to the host
734         that there isn't any more pending data available.
735       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54388992"></a>2. ao_usb_putchar</h2></div></div></div><pre class="programlisting">
736         void
737         ao_usb_putchar(char c);
738       </pre><p>
739         If there is a pending 'IN' packet awaiting delivery to the
740         host, this blocks until that has been fetched. Then, this
741         adds a byte to the pending IN packet for delivery to the
742         USB host. If the USB packet is full, this queues the 'IN'
743         packet for delivery.
744       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54391168"></a>3. ao_usb_pollchar</h2></div></div></div><pre class="programlisting">
745         char
746         ao_usb_pollchar(void);
747       </pre><p>
748         If there are no characters remaining in the last 'OUT'
749         packet received, this returns AO_READ_AGAIN. Otherwise, it
750         returns the next character, reporting to the host that it
751         is ready for more data when the last character is gone.
752       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54393312"></a>4. ao_usb_getchar</h2></div></div></div><pre class="programlisting">
753         char
754         ao_usb_getchar(void);
755       </pre><p>
756         This uses ao_pollchar to receive the next character,
757         blocking while ao_pollchar returns AO_READ_AGAIN.
758       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54395328"></a>5. ao_usb_disable</h2></div></div></div><pre class="programlisting">
759         void
760         ao_usb_disable(void);
761       </pre><p>
762         This turns off the USB controller. It will no longer
763         respond to host requests, nor return characters. Calling
764         any of the i/o routines while the USB device is disabled
765         is undefined, and likely to break things. Disabling the
766         USB device when not needed saves power.
767       </p><p>
768         Note that neither TeleDongle nor TeleMetrum are able to
769         signal to the USB host that they have disconnected, so
770         after disabling the USB device, it's likely that the cable
771         will need to be disconnected and reconnected before it
772         will work again.
773       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54398160"></a>6. ao_usb_enable</h2></div></div></div><pre class="programlisting">
774         void
775         ao_usb_enable(void);
776       </pre><p>
777         This turns the USB controller on again after it has been
778         disabled. See the note above about needing to physically
779         remove and re-insert the cable to get the host to
780         re-initialize the USB link.
781       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54400272"></a>7. ao_usb_init</h2></div></div></div><pre class="programlisting">
782         void
783         ao_usb_init(void);
784       </pre><p>
785         This turns the USB controller on, adds a task to handle
786         the control end point and adds the usb I/O functions to
787         the stdio system. Call this from main before
788         ao_start_scheduler.
789       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54402496"></a>Chapter 11. Serial peripherals</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54404512">1. ao_serial_getchar</a></span></dt><dt><span class="section"><a href="#idp54406544">2. ao_serial_putchar</a></span></dt><dt><span class="section"><a href="#idp54408512">3. ao_serial_drain</a></span></dt><dt><span class="section"><a href="#idp54410512">4. ao_serial_set_speed</a></span></dt><dt><span class="section"><a href="#idp54412544">5. ao_serial_init</a></span></dt></dl></div><p>
790       The CC1111 provides two USART peripherals. AltOS uses one for
791       asynch serial data, generally to communicate with a GPS device,
792       and the other for a SPI bus. The UART is configured to operate
793       in 8-bits, no parity, 1 stop bit framing. The default
794       configuration has clock settings for 4800, 9600 and 57600 baud
795       operation. Additional speeds can be added by computing
796       appropriate clock values.
797     </p><p>
798       To prevent loss of data, AltOS provides receive and transmit
799       fifos of 32 characters each.
800     </p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54404512"></a>1. ao_serial_getchar</h2></div></div></div><pre class="programlisting">
801         char
802         ao_serial_getchar(void);
803       </pre><p>
804         Returns the next character from the receive fifo, blocking
805         until a character is received if the fifo is empty.
806       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54406544"></a>2. ao_serial_putchar</h2></div></div></div><pre class="programlisting">
807         void
808         ao_serial_putchar(char c);
809       </pre><p>
810         Adds a character to the transmit fifo, blocking if the
811         fifo is full. Starts transmitting characters.
812       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54408512"></a>3. ao_serial_drain</h2></div></div></div><pre class="programlisting">
813         void
814         ao_serial_drain(void);
815       </pre><p>
816         Blocks until the transmit fifo is empty. Used internally
817         when changing serial speeds.
818       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54410512"></a>4. ao_serial_set_speed</h2></div></div></div><pre class="programlisting">
819         void
820         ao_serial_set_speed(uint8_t speed);
821       </pre><p>
822         Changes the serial baud rate to one of
823         AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or
824         AO_SERIAL_SPEED_57600. This first flushes the transmit
825         fifo using ao_serial_drain.
826       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54412544"></a>5. ao_serial_init</h2></div></div></div><pre class="programlisting">
827         void
828         ao_serial_init(void)
829       </pre><p>
830         Initializes the serial peripheral. Call this from 'main'
831         before jumping to ao_start_scheduler. The default speed
832         setting is AO_SERIAL_SPEED_4800.
833       </p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="idp54414736"></a>Chapter 12. CC1111 Radio peripheral</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="#idp54415408">1. Radio Introduction</a></span></dt><dt><span class="section"><a href="#idp54422528">2. ao_radio_set_telemetry</a></span></dt><dt><span class="section"><a href="#idp54424688">3. ao_radio_set_packet</a></span></dt><dt><span class="section"><a href="#idp54426848">4. ao_radio_set_rdf</a></span></dt><dt><span class="section"><a href="#idp54429088">5. ao_radio_idle</a></span></dt><dt><span class="section"><a href="#idp54431136">6. ao_radio_get</a></span></dt><dt><span class="section"><a href="#idp54433168">7. ao_radio_put</a></span></dt><dt><span class="section"><a href="#idp54435104">8. ao_radio_abort</a></span></dt><dt><span class="section"><a href="#idp54437168">9. Radio Telemetry</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54438464">9.1. ao_radio_send</a></span></dt><dt><span class="section"><a href="#idp54440688">9.2. ao_radio_recv</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54443152">10. Radio Direction Finding</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54444304">10.1. ao_radio_rdf</a></span></dt></dl></dd><dt><span class="section"><a href="#idp54446448">11. Radio Packet Mode</a></span></dt><dd><dl><dt><span class="section"><a href="#idp54447760">11.1. ao_packet_putchar</a></span></dt><dt><span class="section"><a href="#idp54449936">11.2. ao_packet_pollchar</a></span></dt><dt><span class="section"><a href="#idp54452016">11.3. ao_packet_slave_start</a></span></dt><dt><span class="section"><a href="#idp54453968">11.4. ao_packet_slave_stop</a></span></dt><dt><span class="section"><a href="#idp54455888">11.5. ao_packet_slave_init</a></span></dt><dt><span class="section"><a href="#idp54457920">11.6. ao_packet_master_init</a></span></dt></dl></dd></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54415408"></a>1. Radio Introduction</h2></div></div></div><p>
834         The CC1111 radio transceiver sends and receives digital packets
835         with forward error correction and detection. The AltOS driver is
836         fairly specific to the needs of the TeleMetrum and TeleDongle
837         devices, using it for other tasks may require customization of
838         the driver itself. There are three basic modes of operation:
839         </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>
840               Telemetry mode. In this mode, TeleMetrum transmits telemetry
841               frames at a fixed rate. The frames are of fixed size. This
842               is strictly a one-way communication from TeleMetrum to
843               TeleDongle.
844             </p></li><li class="listitem"><p>
845               Packet mode. In this mode, the radio is used to create a
846               reliable duplex byte stream between TeleDongle and
847               TeleMetrum. This is an asymmetrical protocol with
848               TeleMetrum only transmitting in response to a packet sent
849               from TeleDongle. Thus getting data from TeleMetrum to
850               TeleDongle requires polling. The polling rate is adaptive,
851               when no data has been received for a while, the rate slows
852               down. The packets are checked at both ends and invalid
853               data are ignored.
854             </p><p>
855               On the TeleMetrum side, the packet link is hooked into the
856               stdio mechanism, providing an alternate data path for the
857               command processor. It is enabled when the unit boots up in
858               'idle' mode.
859             </p><p>
860               On the TeleDongle side, the packet link is enabled with a
861               command; data from the stdio package is forwarded over the
862               packet link providing a connection from the USB command
863               stream to the remote TeleMetrum device.
864             </p></li><li class="listitem"><p>
865               Radio Direction Finding mode. In this mode, TeleMetrum
866               constructs a special packet that sounds like an audio tone
867               when received by a conventional narrow-band FM
868               receiver. This is designed to provide a beacon to track
869               the device when other location mechanisms fail.
870             </p></li></ol></div><p>
871       </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54422528"></a>2. ao_radio_set_telemetry</h2></div></div></div><pre class="programlisting">
872           void
873           ao_radio_set_telemetry(void);
874         </pre><p>
875           Configures the radio to send or receive telemetry
876           packets. This includes packet length, modulation scheme and
877           other RF parameters. It does not include the base frequency
878           or channel though. Those are set at the time of transmission
879           or reception, in case the values are changed by the user.
880         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54424688"></a>3. ao_radio_set_packet</h2></div></div></div><pre class="programlisting">
881           void
882           ao_radio_set_packet(void);
883         </pre><p>
884           Configures the radio to send or receive packet data.  This
885           includes packet length, modulation scheme and other RF
886           parameters. It does not include the base frequency or
887           channel though. Those are set at the time of transmission or
888           reception, in case the values are changed by the user.
889         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54426848"></a>4. ao_radio_set_rdf</h2></div></div></div><pre class="programlisting">
890           void
891           ao_radio_set_rdf(void);
892         </pre><p>
893           Configures the radio to send RDF 'packets'. An RDF 'packet'
894           is a sequence of hex 0x55 bytes sent at a base bit rate of
895           2kbps using a 5kHz deviation. All of the error correction
896           and data whitening logic is turned off so that the resulting
897           modulation is received as a 1kHz tone by a conventional 70cm
898           FM audio receiver.
899         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54429088"></a>5. ao_radio_idle</h2></div></div></div><pre class="programlisting">
900           void
901           ao_radio_idle(void);
902         </pre><p>
903           Sets the radio device to idle mode, waiting until it reaches
904           that state. This will terminate any in-progress transmit or
905           receive operation.
906         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54431136"></a>6. ao_radio_get</h2></div></div></div><pre class="programlisting">
907           void
908           ao_radio_get(void);
909         </pre><p>
910           Acquires the radio mutex and then configures the radio
911           frequency using the global radio calibration and channel
912           values.
913         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54433168"></a>7. ao_radio_put</h2></div></div></div><pre class="programlisting">
914           void
915           ao_radio_put(void);
916         </pre><p>
917           Releases the radio mutex.
918         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54435104"></a>8. ao_radio_abort</h2></div></div></div><pre class="programlisting">
919           void
920           ao_radio_abort(void);
921         </pre><p>
922           Aborts any transmission or reception process by aborting the
923           associated DMA object and calling ao_radio_idle to terminate
924           the radio operation.
925         </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54437168"></a>9. Radio Telemetry</h2></div></div></div><p>
926         In telemetry mode, you can send or receive a telemetry
927         packet. The data from receiving a packet also includes the RSSI
928         and status values supplied by the receiver. These are added
929         after the telemetry data.
930       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54438464"></a>9.1. ao_radio_send</h3></div></div></div><pre class="programlisting">
931           void
932           ao_radio_send(__xdata struct ao_telemetry *telemetry);
933         </pre><p>
934           This sends the specific telemetry packet, waiting for the
935           transmission to complete. The radio must have been set to
936           telemetry mode. This function calls ao_radio_get() before
937           sending, and ao_radio_put() afterwards, to correctly
938           serialize access to the radio device.
939         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54440688"></a>9.2. ao_radio_recv</h3></div></div></div><pre class="programlisting">
940           void
941           ao_radio_recv(__xdata struct ao_radio_recv *radio);
942         </pre><p>
943           This blocks waiting for a telemetry packet to be received.
944           The radio must have been set to telemetry mode. This
945           function calls ao_radio_get() before receiving, and
946           ao_radio_put() afterwards, to correctly serialize access
947           to the radio device. This returns non-zero if a packet was
948           received, or zero if the operation was aborted (from some
949           other task calling ao_radio_abort()).
950         </p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54443152"></a>10. Radio Direction Finding</h2></div></div></div><p>
951         In radio direction finding mode, there's just one function to
952         use
953       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54444304"></a>10.1. ao_radio_rdf</h3></div></div></div><pre class="programlisting">
954           void
955           ao_radio_rdf(int ms);
956         </pre><p>
957           This sends an RDF packet lasting for the specified amount
958           of time. The maximum length is 1020 ms.
959         </p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="idp54446448"></a>11. Radio Packet Mode</h2></div></div></div><p>
960         Packet mode is asymmetrical and is configured at compile time
961         for either master or slave mode (but not both). The basic I/O
962         functions look the same at both ends, but the internals are
963         different, along with the initialization steps.
964       </p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54447760"></a>11.1. ao_packet_putchar</h3></div></div></div><pre class="programlisting">
965           void
966           ao_packet_putchar(char c);
967         </pre><p>
968           If the output queue is full, this first blocks waiting for
969           that data to be delivered. Then, queues a character for
970           packet transmission. On the master side, this will
971           transmit a packet if the output buffer is full. On the
972           slave side, any pending data will be sent the next time
973           the master polls for data.
974         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54449936"></a>11.2. ao_packet_pollchar</h3></div></div></div><pre class="programlisting">
975           char
976           ao_packet_pollchar(void);
977         </pre><p>
978           This returns a pending input character if available,
979           otherwise returns AO_READ_AGAIN. On the master side, if
980           this empties the buffer, it triggers a poll for more data.
981         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54452016"></a>11.3. ao_packet_slave_start</h3></div></div></div><pre class="programlisting">
982           void
983           ao_packet_slave_start(void);
984         </pre><p>
985           This is available only on the slave side and starts a task
986           to listen for packet data.
987         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54453968"></a>11.4. ao_packet_slave_stop</h3></div></div></div><pre class="programlisting">
988           void
989           ao_packet_slave_stop(void);
990         </pre><p>
991           Disables the packet slave task, stopping the radio receiver.
992         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54455888"></a>11.5. ao_packet_slave_init</h3></div></div></div><pre class="programlisting">
993           void
994           ao_packet_slave_init(void);
995         </pre><p>
996           Adds the packet stdio functions to the stdio package so
997           that when packet slave mode is enabled, characters will
998           get send and received through the stdio functions.
999         </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp54457920"></a>11.6. ao_packet_master_init</h3></div></div></div><pre class="programlisting">
1000           void
1001           ao_packet_master_init(void);
1002         </pre><p>
1003           Adds the 'p' packet forward command to start packet mode.
1004         </p></div></div></div></div></body></html>