diff options
author | Keith Packard <keithp@keithp.com> | 2010-11-24 21:39:18 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2010-11-24 21:39:18 -0800 |
commit | bcf78b67717374b5971820021b83061e2e9734cf (patch) | |
tree | c46a2a8aed56bfd8b833bdbedfb912040bb7af0a | |
parent | 51c7741040d95c5deece939dae5e4136cc04afc4 (diff) |
doc: Reformat altos to use sections for each function
This places them in the TOC, making them easier to find.
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | doc/altos.xsl | 2105 |
1 files changed, 983 insertions, 1122 deletions
diff --git a/doc/altos.xsl b/doc/altos.xsl index 9a88a5b5..295864fe 100644 --- a/doc/altos.xsl +++ b/doc/altos.xsl @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" - "/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd"> +"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd"> <book> <title>AltOS</title> @@ -37,41 +37,41 @@ AltOS is a operating system built for the 8051-compatible processor found in the TI cc1111 microcontroller. It's designed to be small and easy to program with. The main features are: - <itemizedlist> - <listitem> - <para>Multi-tasking. While the 8051 doesn't provide separate - address spaces, it's often easier to write code that operates - in separate threads instead of tying everything into one giant - event loop. - </para> - </listitem> - <listitem> - <para>Non-preemptive. This increases latency for thread - switching but reduces the number of places where context - switching can occur. It also simplifies the operating system - design somewhat. Nothing in the target system (rocket flight - control) has tight timing requirements, and so this seems like - a reasonable compromise. - </para> - </listitem> - <listitem> - <para>Sleep/wakeup scheduling. Taken directly from ancient - Unix designs, these two provide the fundemental scheduling - primitive within AltOS. - </para> - </listitem> - <listitem> - <para>Mutexes. As a locking primitive, mutexes are easier to - use than semaphores, at least in my experience. - </para> - </listitem> - <listitem> - <para>Timers. Tasks can set an alarm which will abort any - pending sleep, allowing operations to time-out instead of - blocking forever. - </para> - </listitem> - </itemizedlist> + <itemizedlist> + <listitem> + <para>Multi-tasking. While the 8051 doesn't provide separate + address spaces, it's often easier to write code that operates + in separate threads instead of tying everything into one giant + event loop. + </para> + </listitem> + <listitem> + <para>Non-preemptive. This increases latency for thread + switching but reduces the number of places where context + switching can occur. It also simplifies the operating system + design somewhat. Nothing in the target system (rocket flight + control) has tight timing requirements, and so this seems like + a reasonable compromise. + </para> + </listitem> + <listitem> + <para>Sleep/wakeup scheduling. Taken directly from ancient + Unix designs, these two provide the fundemental scheduling + primitive within AltOS. + </para> + </listitem> + <listitem> + <para>Mutexes. As a locking primitive, mutexes are easier to + use than semaphores, at least in my experience. + </para> + </listitem> + <listitem> + <para>Timers. Tasks can set an alarm which will abort any + pending sleep, allowing operations to time-out instead of + blocking forever. + </para> + </listitem> + </itemizedlist> </para> <para> The device drivers and other subsystems in AltOS are @@ -82,28 +82,28 @@ may add tasks to the scheduler to handle the device. A typical main program, thus, looks like: <programlisting> -void -main(void) -{ - ao_clock_init(); + void + main(void) + { + ao_clock_init(); - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_slave_init(); - ao_packet_master_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_slave_init(); + ao_packet_master_init(); + #if HAS_DBG + ao_dbg_init(); + #endif + ao_config_init(); + ao_start_scheduler(); + } </programlisting> As you can see, a long sequence of subsystems are initialized and then the scheduler is started. @@ -137,96 +137,79 @@ main(void) code but makes the resulting code far smaller and more efficient. </para> - <variablelist> - <title>SDCC 8051 memory spaces</title> - <varlistentry> - <term>__data</term> - <listitem> - <para> - The 8051 can directly address these 128 bytes of - memory. This makes them precious so they should be - reserved for frequently addressed values. Oh, just to - confuse things further, the 8 general registers in the - CPU are actually stored in this memory space. There are - magic instructions to 'bank switch' among 4 banks of - these registers located at 0x00 - 0x1F. AltOS uses only - the first bank at 0x00 - 0x07, leaving the other 24 - bytes available for other data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__idata</term> - <listitem> - <para> - There are an additional 128 bytes of internal memory - that share the same address space as __data but which - cannot be directly addressed. The stack normally - occupies this space and so AltOS doesn't place any - static storage here. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__xdata</term> - <listitem> - <para> - This is additional general memory accessed through a - single 16-bit address register. The CC1111F32 has 32kB - of memory available here. Most program data should live - in this memory space. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__pdata</term> - <listitem> - <para> - This is an alias for the first 256 bytes of __xdata - memory, but uses a shorter addressing mode with - single global 8-bit value for the high 8 bits of the - address and any of several 8-bit registers for the low 8 - bits. AltOS uses a few bits of this memory, it should - probably use more. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__code</term> - <listitem> - <para> - All executable code must live in this address space, but - you can stick read-only data here too. It is addressed - using the 16-bit address register and special 'code' - access opcodes. Anything read-only should live in this space. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__bit</term> - <listitem> - <para> - The 8051 has 128 bits of bit-addressible memory that - lives in the __data segment from 0x20 through - 0x2f. Special instructions access these bits - in a single atomic operation. This isn't so much a - separate address space as a special addressing mode for - a few bytes in the __data segment. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>__sfr, __sfr16, __sfr32, __sbit</term> - <listitem> - <para> - Access to physical registers in the device use this mode - which declares the variable name, it's type and the - address it lives at. No memory is allocated for these - variables. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>__data</title> + <para> + The 8051 can directly address these 128 bytes of + memory. This makes them precious so they should be + reserved for frequently addressed values. Oh, just to + confuse things further, the 8 general registers in the + CPU are actually stored in this memory space. There are + magic instructions to 'bank switch' among 4 banks of + these registers located at 0x00 - 0x1F. AltOS uses only + the first bank at 0x00 - 0x07, leaving the other 24 + bytes available for other data. + </para> + </section> + <section> + <title>__idata</title> + <para> + There are an additional 128 bytes of internal memory + that share the same address space as __data but which + cannot be directly addressed. The stack normally + occupies this space and so AltOS doesn't place any + static storage here. + </para> + </section> + <section> + <title>__xdata</title> + <para> + This is additional general memory accessed through a + single 16-bit address register. The CC1111F32 has 32kB + of memory available here. Most program data should live + in this memory space. + </para> + </section> + <section> + <title>__pdata</title> + <para> + This is an alias for the first 256 bytes of __xdata + memory, but uses a shorter addressing mode with + single global 8-bit value for the high 8 bits of the + address and any of several 8-bit registers for the low 8 + bits. AltOS uses a few bits of this memory, it should + probably use more. + </para> + </section> + <section> + <title>__code</title> + <para> + All executable code must live in this address space, but + you can stick read-only data here too. It is addressed + using the 16-bit address register and special 'code' + access opcodes. Anything read-only should live in this space. + </para> + </section> + <section> + <title>__bit</title> + <para> + The 8051 has 128 bits of bit-addressible memory that + lives in the __data segment from 0x20 through + 0x2f. Special instructions access these bits + in a single atomic operation. This isn't so much a + separate address space as a special addressing mode for + a few bytes in the __data segment. + </para> + </section> + <section> + <title>__sfr, __sfr16, __sfr32, __sbit</title> + <para> + Access to physical registers in the device use this mode + which declares the variable name, it's type and the + address it lives at. No memory is allocated for these + variables. + </para> + </section> </section> <section> <title>Function calls on the 8051</title> @@ -305,124 +288,139 @@ main(void) <para> This chapter documents how to create, destroy and schedule AltOS tasks. </para> - <variablelist> - <title>AltOS Task Functions</title> - <varlistentry> - <term>ao_add_task</term> - <listitem> - <programlisting> -void -ao_add_task(__xdata struct ao_task * task, - void (*start)(void), - __code char *name); - </programlisting> - <para> - This initializes the statically allocated task structure, - assigns a name to it (not used for anything but the task - display), and the start address. It does not switch to the - new task. 'start' must not ever return; there is no place - to return to. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_exit</term> - <listitem> - <programlisting> -void -ao_exit(void) - </programlisting> - <para> - This terminates the current task. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_sleep</term> - <listitem> - <programlisting> -void -ao_sleep(__xdata void *wchan) - </programlisting> - <para> - This suspends the current task until 'wchan' is signaled - by ao_wakeup, or until the timeout, set by ao_alarm, - fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise - it returns 1. This is the only way to switch to another task. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_wakeup</term> - <listitem> - <programlisting> -void -ao_wakeup(__xdata void *wchan) - </programlisting> - <para> - Wake all tasks blocked on 'wchan'. This makes them - available to be run again, but does not actually switch - to another task. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_alarm</term> - <listitem> - <programlisting> -void -ao_alarm(uint16_t delay) - </programlisting> - <para> - Schedules an alarm to fire in at least 'delay' ticks. If - the task is asleep when the alarm fires, it will wakeup - and ao_sleep will return 1. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_wake_task</term> - <listitem> - <programlisting> -void -ao_wake_task(__xdata struct ao_task *task) - </programlisting> - <para> - Force a specific task to wake up, independent of which - 'wchan' it is waiting for. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_start_scheduler</term> - <listitem> - <programlisting> -void -ao_start_scheduler(void) - </programlisting> - <para> - This is called from 'main' when the system is all - initialized and ready to run. It will not return. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_clock_init</term> - <listitem> - <programlisting> -void -ao_clock_init(void) - </programlisting> - <para> - This turns on the external 48MHz clock then switches the - hardware to using it. This is required by many of the - internal devices like USB. It should be called by the - 'main' function first, before initializing any of the - other devices in the system. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_add_task</title> + <programlisting> + void + ao_add_task(__xdata struct ao_task * task, + void (*start)(void), + __code char *name); + </programlisting> + <para> + This initializes the statically allocated task structure, + assigns a name to it (not used for anything but the task + display), and the start address. It does not switch to the + new task. 'start' must not ever return; there is no place + to return to. + </para> + </section> + <section> + <title>ao_exit</title> + <programlisting> + void + ao_exit(void) + </programlisting> + <para> + This terminates the current task. + </para> + </section> + <section> + <title>ao_sleep</title> + <programlisting> + void + ao_sleep(__xdata void *wchan) + </programlisting> + <para> + This suspends the current task until 'wchan' is signaled + by ao_wakeup, or until the timeout, set by ao_alarm, + fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise + it returns 1. This is the only way to switch to another task. + </para> + <para> + Because ao_wakeup wakes every task waiting on a particular + location, ao_sleep should be used in a loop that first + checks the desired condition, blocks in ao_sleep and then + rechecks until the condition is satisfied. If the + location may be signaled from an interrupt handler, the + code will need to block interrupts by using the __critical + label around the block of code. Here's a complete example: + <programlisting> + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); + </programlisting> + </para> + </section> + <section> + <title>ao_wakeup</title> + <programlisting> + void + ao_wakeup(__xdata void *wchan) + </programlisting> + <para> + Wake all tasks blocked on 'wchan'. This makes them + available to be run again, but does not actually switch + to another task. Here's an example of using this: + <programlisting> + if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } + </programlisting> + Note that this need not be enclosed in __critical as the + ao_sleep block can only be run from normal mode, and so + this sequence can never be interrupted with execution of + the other sequence. + </para> + </section> + <section> + <title>ao_alarm</title> + <programlisting> + void + ao_alarm(uint16_t delay) + </programlisting> + <para> + Schedules an alarm to fire in at least 'delay' ticks. If + the task is asleep when the alarm fires, it will wakeup + and ao_sleep will return 1. + <programlisting> + ao_alarm(ao_packet_master_delay); + __critical while (!ao_radio_dma_done) + if (ao_sleep(&ao_radio_dma_done) != 0) + ao_radio_abort(); + </programlisting> + In this example, a timeout is set before waiting for + incoming radio data. If no data is received before the + timeout fires, ao_sleep will return 1 and then this code + will abort the radio receive operation. + </para> + </section> + <section> + <title>ao_wake_task</title> + <programlisting> + void + ao_wake_task(__xdata struct ao_task *task) + </programlisting> + <para> + Force a specific task to wake up, independent of which + 'wchan' it is waiting for. + </para> + </section> + <section> + <title>ao_start_scheduler</title> + <programlisting> + void + ao_start_scheduler(void) + </programlisting> + <para> + This is called from 'main' when the system is all + initialized and ready to run. It will not return. + </para> + </section> + <section> + <title>ao_clock_init</title> + <programlisting> + void + ao_clock_init(void) + </programlisting> + <para> + This turns on the external 48MHz clock then switches the + hardware to using it. This is required by many of the + internal devices like USB. It should be called by the + 'main' function first, before initializing any of the + other devices in the system. + </para> + </section> </chapter> <chapter> <title>Timer Functions</title> @@ -435,62 +433,51 @@ ao_clock_init(void) that the ADC values are sampled at a regular rate, independent of any scheduling jitter. </para> - <variablelist> - <title>AltOS Timer Functions</title> - <varlistentry> - <term>ao_time</term> - <listitem> - <programlisting> -uint16_t -ao_time(void) - </programlisting> - <para> - Returns the current system tick count. Note that this is - only a 16 bit value, and so it wraps every 655.36 seconds. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_delay</term> - <listitem> - <programlisting> -void -ao_delay(uint16_t ticks); - </programlisting> - <para> - Suspend the current task for at least 'ticks' clock units. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_timer_set_adc_interval</term> - <listitem> - <programlisting> -void -ao_timer_set_adc_interval(uint8_t interval); - </programlisting> - <para> - This sets the number of ticks between ADC samples. If set - to 0, no ADC samples are generated. AltOS uses this to - slow down the ADC sampling rate to save power. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_timer_init</term> - <listitem> - <programlisting> -void -ao_timer_init(void) - </programlisting> - <para> - This turns on the 100Hz tick using the CC1111 timer 1. It - is required for any of the time-based functions to - work. It should be called by 'main' before ao_start_scheduler. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_time</title> + <programlisting> + uint16_t + ao_time(void) + </programlisting> + <para> + Returns the current system tick count. Note that this is + only a 16 bit value, and so it wraps every 655.36 seconds. + </para> + </section> + <section> + <title>ao_delay</title> + <programlisting> + void + ao_delay(uint16_t ticks); + </programlisting> + <para> + Suspend the current task for at least 'ticks' clock units. + </para> + </section> + <section> + <title>ao_timer_set_adc_interval</title> + <programlisting> + void + ao_timer_set_adc_interval(uint8_t interval); + </programlisting> + <para> + This sets the number of ticks between ADC samples. If set + to 0, no ADC samples are generated. AltOS uses this to + slow down the ADC sampling rate to save power. + </para> + </section> + <section> + <title>ao_timer_init</title> + <programlisting> + void + ao_timer_init(void) + </programlisting> + <para> + This turns on the 100Hz tick using the CC1111 timer 1. It + is required for any of the time-based functions to + work. It should be called by 'main' before ao_start_scheduler. + </para> + </section> </chapter> <chapter> <title>AltOS Mutexes</title> @@ -502,35 +489,28 @@ ao_timer_init(void) already held by the current task or releasing a mutex not held by the current task will both cause a panic. </para> - <variablelist> - <title>Mutex Functions</title> - <varlistentry> - <term>ao_mutex_get</term> - <listitem> - <programlisting> -void -ao_mutex_get(__xdata uint8_t *mutex); - </programlisting> - <para> - Acquires the specified mutex, blocking if the mutex is - owned by another task. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_mutex_put</term> - <listitem> - <programlisting> -void -ao_mutex_put(__xdata uint8_t *mutex); - </programlisting> - <para> - Releases the specified mutex, waking up all tasks waiting - for it. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_mutex_get</title> + <programlisting> + void + ao_mutex_get(__xdata uint8_t *mutex); + </programlisting> + <para> + Acquires the specified mutex, blocking if the mutex is + owned by another task. + </para> + </section> + <section> + <title>ao_mutex_put</title> + <programlisting> + void + ao_mutex_put(__xdata uint8_t *mutex); + </programlisting> + <para> + Releases the specified mutex, waking up all tasks waiting + for it. + </para> + </section> </chapter> <chapter> <title>CC1111 DMA engine</title> @@ -554,86 +534,73 @@ ao_mutex_put(__xdata uint8_t *mutex); hardware device. When copying data from memory to hardware, the transfer is usually initiated by software. </para> - <variablelist> - <title>AltOS DMA functions</title> - <varlistentry> - <term>ao_dma_alloc</term> - <listitem> - <programlisting> -uint8_t -ao_dma_alloc(__xdata uint8_t *done) - </programlisting> - <para> - Allocates a DMA engine, returning the identifier. Whenever - this DMA engine completes a transfer. 'done' is cleared - when the DMA is started, and then receives the - AO_DMA_DONE bit on a successful transfer or the - AO_DMA_ABORTED bit if ao_dma_abort was called. Note that - it is possible to get both bits if the transfer was - aborted after it had finished. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_dma_set_transfer</term> - <listitem> - <programlisting> -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1) - </programlisting> - <para> - Initializes the specified dma engine to copy data - from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and - cfg1 are values directly out of the CC1111 documentation - and tell the DMA engine what the transfer unit size, - direction and step are. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_dma_start</term> - <listitem> - <programlisting> -void -ao_dma_start(uint8_t id); - </programlisting> - <para> - Arm the specified DMA engine and await a signal from - either hardware or software to start transferring data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_dma_trigger</term> - <listitem> - <programlisting> -void -ao_dma_trigger(uint8_t id) - </programlisting> - <para> - Trigger the specified DMA engine to start copying data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_dma_abort</term> - <listitem> - <programlisting> -void -ao_dma_abort(uint8_t id) - </programlisting> - <para> - Terminate any in-progress DMA transation, marking its - 'done' variable with the AO_DMA_ABORTED bit. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_dma_alloc</title> + <programlisting> + uint8_t + ao_dma_alloc(__xdata uint8_t *done) + </programlisting> + <para> + Allocates a DMA engine, returning the identifier. Whenever + this DMA engine completes a transfer. 'done' is cleared + when the DMA is started, and then receives the + AO_DMA_DONE bit on a successful transfer or the + AO_DMA_ABORTED bit if ao_dma_abort was called. Note that + it is possible to get both bits if the transfer was + aborted after it had finished. + </para> + </section> + <section> + <title>ao_dma_set_transfer</title> + <programlisting> + void + ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) + </programlisting> + <para> + Initializes the specified dma engine to copy data + from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and + cfg1 are values directly out of the CC1111 documentation + and tell the DMA engine what the transfer unit size, + direction and step are. + </para> + </section> + <section> + <title>ao_dma_start</title> + <programlisting> + void + ao_dma_start(uint8_t id); + </programlisting> + <para> + Arm the specified DMA engine and await a signal from + either hardware or software to start transferring data. + </para> + </section> + <section> + <title>ao_dma_trigger</title> + <programlisting> + void + ao_dma_trigger(uint8_t id) + </programlisting> + <para> + Trigger the specified DMA engine to start copying data. + </para> + </section> + <section> + <title>ao_dma_abort</title> + <programlisting> + void + ao_dma_abort(uint8_t id) + </programlisting> + <para> + Terminate any in-progress DMA transation, marking its + 'done' variable with the AO_DMA_ABORTED bit. + </para> + </section> </chapter> <chapter> <title>SDCC Stdio interface</title> @@ -646,82 +613,71 @@ ao_dma_abort(uint8_t id) channels; output is always delivered to the channel which provided the most recent input. </para> - <variablelist> - <title>SDCC stdio functions</title> - <varlistentry> - <term>putchar</term> - <listitem> - <programlisting> -void -putchar(char c) - </programlisting> - <para> - Delivers a single character to the current console - device. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>getchar</term> - <listitem> - <programlisting> -char -getchar(void) - </programlisting> - <para> - Reads a single character from any of the available - console devices. The current console device is set to - that which delivered this character. This blocks until - a character is available. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>flush</term> - <listitem> - <programlisting> -void -flush(void) - </programlisting> - <para> - Flushes the current console device output buffer. Any - pending characters will be delivered to the target device. -xo </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_add_stdio</term> - <listitem> - <programlisting> -void -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char), - void (*flush)(void)) - </programlisting> - <para> - This adds another console device to the available - list. - </para> - <para> - 'pollchar' returns either an available character or - AO_READ_AGAIN if none is available. Significantly, it does - not block. The device driver must set 'ao_stdin_ready' to - 1 and call ao_wakeup(&ao_stdin_ready) when it receives - input to tell getchar that more data is available, at - which point 'pollchar' will be called again. - </para> - <para> - 'putchar' queues a character for output, flushing if the output buffer is - full. It may block in this case. - </para> - <para> - 'flush' forces the output buffer to be flushed. It may - block until the buffer is delivered, but it is not - required to do so. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>putchar</title> + <programlisting> + void + putchar(char c) + </programlisting> + <para> + Delivers a single character to the current console + device. + </para> + </section> + <section> + <title>getchar</title> + <programlisting> + char + getchar(void) + </programlisting> + <para> + Reads a single character from any of the available + console devices. The current console device is set to + that which delivered this character. This blocks until + a character is available. + </para> + </section> + <section> + <title>flush</title> + <programlisting> + void + flush(void) + </programlisting> + <para> + Flushes the current console device output buffer. Any + pending characters will be delivered to the target device. + xo </para> + </section> + <section> + <title>ao_add_stdio</title> + <programlisting> + void + ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) + </programlisting> + <para> + This adds another console device to the available + list. + </para> + <para> + 'pollchar' returns either an available character or + AO_READ_AGAIN if none is available. Significantly, it does + not block. The device driver must set 'ao_stdin_ready' to + 1 and call ao_wakeup(&ao_stdin_ready) when it receives + input to tell getchar that more data is available, at + which point 'pollchar' will be called again. + </para> + <para> + 'putchar' queues a character for output, flushing if the output buffer is + full. It may block in this case. + </para> + <para> + 'flush' forces the output buffer to be flushed. It may + block until the buffer is delivered, but it is not + required to do so. + </para> + </section> </chapter> <chapter> <title>Command line interface</title> @@ -732,176 +688,155 @@ ao_add_stdio(char (*pollchar)(void), character to invoke it, the remaining characters on the line are available as parameters to the command. </para> - <variablelist> - <title>AltOS command line parsing functions</title> - <varlistentry> - <term>ao_cmd_register</term> - <listitem> - <programlisting> -void -ao_cmd_register(__code struct ao_cmds *cmds) - </programlisting> - <para> - This registers a set of commands with the command - parser. There is a fixed limit on the number of command - sets, the system will panic if too many are registered. - Each command is defined by a struct ao_cmds entry: - <programlisting> -struct ao_cmds { - char cmd; - void (*func)(void); - const char *help; -}; - </programlisting> - 'cmd' is the character naming the command. 'func' is the - function to invoke and 'help' is a string displayed by the - '?' command. Syntax errors found while executing 'func' - should be indicated by modifying the global ao_cmd_status - variable with one of the following values: - <variablelist> - <varlistentry> - <term>ao_cmd_success</term> - <listitem> - <para> - The command was parsed successfully. There is no - need to assign this value, it is the default. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_lex_error</term> - <listitem> - <para> - A token in the line was invalid, such as a number - containing invalid characters. The low-level - lexing functions already assign this value as needed. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_syntax_error</term> - <listitem> - <para> - The command line is invalid for some reason other - than invalid tokens. - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_lex</term> - <listitem> - <programlisting> -void -ao_cmd_lex(void); - </programlisting> - <para> - This gets the next character out of the command line - buffer and sticks it into ao_cmd_lex_c. At the end of the - line, ao_cmd_lex_c will get a newline ('\n') character. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_put16</term> - <listitem> - <programlisting> -void -ao_cmd_put16(uint16_t v); - </programlisting> - <para> - Writes 'v' as four hexadecimal characters. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_put8</term> - <listitem> - <programlisting> -void -ao_cmd_put8(uint8_t v); - </programlisting> - <para> - Writes 'v' as two hexadecimal characters. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_white</term> - <listitem> - <programlisting> -void -ao_cmd_white(void) - </programlisting> - <para> - This skips whitespace by calling ao_cmd_lex while - ao_cmd_lex_c is either a space or tab. It does not skip - any characters if ao_cmd_lex_c already non-white. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_hex</term> - <listitem> - <programlisting> -void -ao_cmd_hex(void) - </programlisting> - <para> - This reads a 16-bit hexadecimal value from the command - line with optional leading whitespace. The resulting value - is stored in ao_cmd_lex_i; - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_decimal</term> - <listitem> - <programlisting> -void -ao_cmd_decimal(void) - </programlisting> - <para> - This reads a 32-bit decimal value from the command - line with optional leading whitespace. The resulting value - is stored in ao_cmd_lex_u32 and the low 16 bits are stored - in ao_cmd_lex_i; - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_match_word</term> - <listitem> - <programlisting> -uint8_t -ao_match_word(__code char *word) - </programlisting> - <para> - This checks to make sure that 'word' occurs on the command - line. It does not skip leading white space. If 'word' is - found, then 1 is returned. Otherwise, ao_cmd_status is set to - ao_cmd_syntax_error and 0 is returned. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_cmd_init</term> - <listitem> - <programlisting> -void -ao_cmd_init(void - </programlisting> - <para> - Initializes the command system, setting up the built-in - commands and adding a task to run the command processing - loop. It should be called by 'main' before ao_start_scheduler. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_cmd_register</title> + <programlisting> + void + ao_cmd_register(__code struct ao_cmds *cmds) + </programlisting> + <para> + This registers a set of commands with the command + parser. There is a fixed limit on the number of command + sets, the system will panic if too many are registered. + Each command is defined by a struct ao_cmds entry: + <programlisting> + struct ao_cmds { + char cmd; + void (*func)(void); + const char *help; + }; + </programlisting> + 'cmd' is the character naming the command. 'func' is the + function to invoke and 'help' is a string displayed by the + '?' command. Syntax errors found while executing 'func' + should be indicated by modifying the global ao_cmd_status + variable with one of the following values: + <variablelist> + <varlistentry> + <title>ao_cmd_success</title> + <listitem> + <para> + The command was parsed successfully. There is no + need to assign this value, it is the default. + </para> + </listitem> + </varlistentry> + <varlistentry> + <title>ao_cmd_lex_error</title> + <listitem> + <para> + A token in the line was invalid, such as a number + containing invalid characters. The low-level + lexing functions already assign this value as needed. + </para> + </listitem> + </varlistentry> + <varlistentry> + <title>ao_syntax_error</title> + <listitem> + <para> + The command line is invalid for some reason other + than invalid tokens. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </section> + <section> + <title>ao_cmd_lex</title> + <programlisting> + void + ao_cmd_lex(void); + </programlisting> + <para> + This gets the next character out of the command line + buffer and sticks it into ao_cmd_lex_c. At the end of the + line, ao_cmd_lex_c will get a newline ('\n') character. + </para> + </section> + <section> + <title>ao_cmd_put16</title> + <programlisting> + void + ao_cmd_put16(uint16_t v); + </programlisting> + <para> + Writes 'v' as four hexadecimal characters. + </para> + </section> + <section> + <title>ao_cmd_put8</title> + <programlisting> + void + ao_cmd_put8(uint8_t v); + </programlisting> + <para> + Writes 'v' as two hexadecimal characters. + </para> + </section> + <section> + <title>ao_cmd_white</title> + <programlisting> + void + ao_cmd_white(void) + </programlisting> + <para> + This skips whitespace by calling ao_cmd_lex while + ao_cmd_lex_c is either a space or tab. It does not skip + any characters if ao_cmd_lex_c already non-white. + </para> + </section> + <section> + <title>ao_cmd_hex</title> + <programlisting> + void + ao_cmd_hex(void) + </programlisting> + <para> + This reads a 16-bit hexadecimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_i; + </para> + </section> + <section> + <title>ao_cmd_decimal</title> + <programlisting> + void + ao_cmd_decimal(void) + </programlisting> + <para> + This reads a 32-bit decimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_u32 and the low 16 bits are stored + in ao_cmd_lex_i; + </para> + </section> + <section> + <title>ao_match_word</title> + <programlisting> + uint8_t + ao_match_word(__code char *word) + </programlisting> + <para> + This checks to make sure that 'word' occurs on the command + line. It does not skip leading white space. If 'word' is + found, then 1 is returned. Otherwise, ao_cmd_status is set to + ao_cmd_syntax_error and 0 is returned. + </para> + </section> + <section> + <title>ao_cmd_init</title> + <programlisting> + void + ao_cmd_init(void + </programlisting> + <para> + Initializes the command system, setting up the built-in + commands and adding a task to run the command processing + loop. It should be called by 'main' before ao_start_scheduler. + </para> + </section> </chapter> <chapter> <title>CC1111 USB target device</title> @@ -921,121 +856,104 @@ ao_cmd_init(void USB link. Alternatively, the functions can be accessed directly to provide for USB-specific I/O. </para> - <variablelist> - <title>AltOS USB functions</title> - <varlistentry> - <term>ao_usb_flush</term> - <listitem> - <programlisting> -void -ao_usb_flush(void); - </programlisting> - <para> - Flushes any pending USB output. This queues an 'IN' packet - to be delivered to the USB host if there is pending data, - or if the last IN packet was full to indicate to the host - that there isn't any more pending data available. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_putchar</term> - <listitem> - <programlisting> -void -ao_usb_putchar(char c); - </programlisting> - <para> - If there is a pending 'IN' packet awaiting delivery to the - host, this blocks until that has been fetched. Then, this - adds a byte to the pending IN packet for delivery to the - USB host. If the USB packet is full, this queues the 'IN' - packet for delivery. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_pollchar</term> - <listitem> - <programlisting> -char -ao_usb_pollchar(void); - </programlisting> - <para> - If there are no characters remaining in the last 'OUT' - packet received, this returns AO_READ_AGAIN. Otherwise, it - returns the next character, reporting to the host that it - is ready for more data when the last character is gone. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_getchar</term> - <listitem> - <programlisting> -char -ao_usb_getchar(void); - </programlisting> - <para> - This uses ao_pollchar to receive the next character, - blocking while ao_pollchar returns AO_READ_AGAIN. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_disable</term> - <listitem> - <programlisting> -void -ao_usb_disable(void); - </programlisting> - <para> - This turns off the USB controller. It will no longer - respond to host requests, nor return characters. Calling - any of the i/o routines while the USB device is disabled - is undefined, and likely to break things. Disabling the - USB device when not needed saves power. - </para> - <para> - Note that neither TeleDongle nor TeleMetrum are able to - signal to the USB host that they have disconnected, so - after disabling the USB device, it's likely that the cable - will need to be disconnected and reconnected before it - will work again. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_enable</term> - <listitem> - <programlisting> -void -ao_usb_enable(void); - </programlisting> - <para> - This turns the USB controller on again after it has been - disabled. See the note above about needing to physically - remove and re-insert the cable to get the host to - re-initialize the USB link. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_usb_init</term> - <listitem> - <programlisting> -void -ao_usb_init(void); - </programlisting> - <para> - This turns the USB controller on, adds a task to handle - the control end point and adds the usb I/O functions to - the stdio system. Call this from main before - ao_start_scheduler. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_usb_flush</title> + <programlisting> + void + ao_usb_flush(void); + </programlisting> + <para> + Flushes any pending USB output. This queues an 'IN' packet + to be delivered to the USB host if there is pending data, + or if the last IN packet was full to indicate to the host + that there isn't any more pending data available. + </para> + </section> + <section> + <title>ao_usb_putchar</title> + <programlisting> + void + ao_usb_putchar(char c); + </programlisting> + <para> + If there is a pending 'IN' packet awaiting delivery to the + host, this blocks until that has been fetched. Then, this + adds a byte to the pending IN packet for delivery to the + USB host. If the USB packet is full, this queues the 'IN' + packet for delivery. + </para> + </section> + <section> + <title>ao_usb_pollchar</title> + <programlisting> + char + ao_usb_pollchar(void); + </programlisting> + <para> + If there are no characters remaining in the last 'OUT' + packet received, this returns AO_READ_AGAIN. Otherwise, it + returns the next character, reporting to the host that it + is ready for more data when the last character is gone. + </para> + </section> + <section> + <title>ao_usb_getchar</title> + <programlisting> + char + ao_usb_getchar(void); + </programlisting> + <para> + This uses ao_pollchar to receive the next character, + blocking while ao_pollchar returns AO_READ_AGAIN. + </para> + </section> + <section> + <title>ao_usb_disable</title> + <programlisting> + void + ao_usb_disable(void); + </programlisting> + <para> + This turns off the USB controller. It will no longer + respond to host requests, nor return characters. Calling + any of the i/o routines while the USB device is disabled + is undefined, and likely to break things. Disabling the + USB device when not needed saves power. + </para> + <para> + Note that neither TeleDongle nor TeleMetrum are able to + signal to the USB host that they have disconnected, so + after disabling the USB device, it's likely that the cable + will need to be disconnected and reconnected before it + will work again. + </para> + </section> + <section> + <title>ao_usb_enable</title> + <programlisting> + void + ao_usb_enable(void); + </programlisting> + <para> + This turns the USB controller on again after it has been + disabled. See the note above about needing to physically + remove and re-insert the cable to get the host to + re-initialize the USB link. + </para> + </section> + <section> + <title>ao_usb_init</title> + <programlisting> + void + ao_usb_init(void); + </programlisting> + <para> + This turns the USB controller on, adds a task to handle + the control end point and adds the usb I/O functions to + the stdio system. Call this from main before + ao_start_scheduler. + </para> + </section> </chapter> <chapter> <title>CC1111 Serial peripheral</title> @@ -1052,77 +970,64 @@ ao_usb_init(void); To prevent loss of data, AltOS provides receive and transmit fifos of 32 characters each. </para> - <variablelist> - <title>AltOS serial functions</title> - <varlistentry> - <term>ao_serial_getchar</term> - <listitem> - <programlisting> -char -ao_serial_getchar(void); - </programlisting> - <para> - Returns the next character from the receive fifo, blocking - until a character is received if the fifo is empty. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_serial_putchar</term> - <listitem> - <programlisting> -void -ao_serial_putchar(char c); - </programlisting> - <para> - Adds a character to the transmit fifo, blocking if the - fifo is full. Starts transmitting characters. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_serial_drain</term> - <listitem> - <programlisting> -void -ao_serial_drain(void); - </programlisting> - <para> - Blocks until the transmit fifo is empty. Used internally - when changing serial speeds. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_serial_set_speed</term> - <listitem> - <programlisting> -void -ao_serial_set_speed(uint8_t speed); - </programlisting> - <para> - Changes the serial baud rate to one of - AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or - AO_SERIAL_SPEED_57600. This first flushes the transmit - fifo using ao_serial_drain. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_serial_init</term> - <listitem> - <programlisting> -void -ao_serial_init(void) - </programlisting> - <para> - Initializes the serial peripheral. Call this from 'main' - before jumping to ao_start_scheduler. The default speed - setting is AO_SERIAL_SPEED_4800. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_serial_getchar</title> + <programlisting> + char + ao_serial_getchar(void); + </programlisting> + <para> + Returns the next character from the receive fifo, blocking + until a character is received if the fifo is empty. + </para> + </section> + <section> + <title>ao_serial_putchar</title> + <programlisting> + void + ao_serial_putchar(char c); + </programlisting> + <para> + Adds a character to the transmit fifo, blocking if the + fifo is full. Starts transmitting characters. + </para> + </section> + <section> + <title>ao_serial_drain</title> + <programlisting> + void + ao_serial_drain(void); + </programlisting> + <para> + Blocks until the transmit fifo is empty. Used internally + when changing serial speeds. + </para> + </section> + <section> + <title>ao_serial_set_speed</title> + <programlisting> + void + ao_serial_set_speed(uint8_t speed); + </programlisting> + <para> + Changes the serial baud rate to one of + AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or + AO_SERIAL_SPEED_57600. This first flushes the transmit + fifo using ao_serial_drain. + </para> + </section> + <section> + <title>ao_serial_init</title> + <programlisting> + void + ao_serial_init(void) + </programlisting> + <para> + Initializes the serial peripheral. Call this from 'main' + before jumping to ao_start_scheduler. The default speed + setting is AO_SERIAL_SPEED_4800. + </para> + </section> </chapter> <chapter> <title>CC1111 Radio peripheral</title> @@ -1177,265 +1082,221 @@ ao_serial_init(void) </listitem> </orderedlist> </para> - <variablelist> - <title>AltOS radio functions</title> - <varlistentry> - <term>ao_radio_set_telemetry</term> - <listitem> - <programlisting> -void -ao_radio_set_telemetry(void); - </programlisting> - <para> - Configures the radio to send or receive telemetry - packets. This includes packet length, modulation scheme and - other RF parameters. It does not include the base frequency - or channel though. Those are set at the time of transmission - or reception, in case the values are changed by the user. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_set_packet</term> - <listitem> - <programlisting> -void -ao_radio_set_packet(void); - </programlisting> - <para> - Configures the radio to send or receive packet data. This - includes packet length, modulation scheme and other RF - parameters. It does not include the base frequency or - channel though. Those are set at the time of transmission or - reception, in case the values are changed by the user. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_set_rdf</term> - <listitem> - <programlisting> -void -ao_radio_set_rdf(void); - </programlisting> - <para> - Configures the radio to send RDF 'packets'. An RDF 'packet' - is a sequence of hex 0x55 bytes sent at a base bit rate of - 2kbps using a 5kHz deviation. All of the error correction - and data whitening logic is turned off so that the resulting - modulation is received as a 1kHz tone by a conventional 70cm - FM audio receiver. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_idle</term> - <listitem> - <programlisting> -void -ao_radio_idle(void); - </programlisting> - <para> - Sets the radio device to idle mode, waiting until it reaches - that state. This will terminate any in-progress transmit or - receive operation. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_get</term> - <listitem> - <programlisting> -void -ao_radio_get(void); - </programlisting> - <para> - Acquires the radio mutex and then configures the radio - frequency using the global radio calibration and channel - values. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_put</term> - <listitem> - <programlisting> -void -ao_radio_put(void); - </programlisting> - <para> - Releases the radio mutex. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_abort</term> - <listitem> - <programlisting> -void -ao_radio_abort(void); - </programlisting> - <para> - Aborts any transmission or reception process by aborting the - associated DMA object and calling ao_radio_idle to terminate - the radio operation. - </para> - </listitem> - </varlistentry> - </variablelist> - <variablelist> - <title>AltOS radio telemetry functions</title> - <para> - In telemetry mode, you can send or receive a telemetry - packet. The data from receiving a packet also includes the RSSI - and status values supplied by the receiver. These are added - after the telemetry data. - </para> - <varlistentry> - <term>ao_radio_send</term> - <listitem> - <programlisting> -void -ao_radio_send(__xdata struct ao_telemetry *telemetry); - </programlisting> - <para> - This sends the specific telemetry packet, waiting for the - transmission to complete. The radio must have been set to - telemetry mode. This function calls ao_radio_get() before - sending, and ao_radio_put() afterwards, to correctly - serialize access to the radio device. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_radio_recv</term> - <listitem> - <programlisting> -void -ao_radio_recv(__xdata struct ao_radio_recv *radio); - </programlisting> - <para> - This blocks waiting for a telemetry packet to be received. - The radio must have been set to telemetry mode. This - function calls ao_radio_get() before receiving, and - ao_radio_put() afterwards, to correctly serialize access - to the radio device. This returns non-zero if a packet was - received, or zero if the operation was aborted (from some - other task calling ao_radio_abort()). - </para> - </listitem> - </varlistentry> - </variablelist> - <variablelist> - <title>AltOS radio direction finding function</title> - <para> - In radio direction finding mode, there's just one function to - use - </para> - <varlistentry> - <term>ao_radio_rdf</term> - <listitem> - <programlisting> -void -ao_radio_rdf(int ms); - </programlisting> - <para> - This sends an RDF packet lasting for the specified amount - of time. The maximum length is 1020 ms. - </para> - </listitem> - </varlistentry> - </variablelist> - <variablelist> - <title>Packet mode functions</title> - <para> - Packet mode is asymmetrical and is configured at compile time - for either master or slave mode (but not both). The basic I/O - functions look the same at both ends, but the internals are - different, along with the initialization steps. - </para> - <varlistentry> - <term>ao_packet_putchar</term> - <listitem> - <programlisting> -void -ao_packet_putchar(char c); - </programlisting> - <para> - If the output queue is full, this first blocks waiting for - that data to be delivered. Then, queues a character for - packet transmission. On the master side, this will - transmit a packet if the output buffer is full. On the - slave side, any pending data will be sent the next time - the master polls for data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_packet_pollchar</term> - <listitem> - <programlisting> -char -ao_packet_pollchar(void); - </programlisting> - <para> - This returns a pending input character if available, - otherwise returns AO_READ_AGAIN. On the master side, if - this empties the buffer, it triggers a poll for more data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_packet_slave_start</term> - <listitem> - <programlisting> -void -ao_packet_slave_start(void); - </programlisting> - <para> - This is available only on the slave side and starts a task - to listen for packet data. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_packet_slave_stop</term> - <listitem> - <programlisting> -void -ao_packet_slave_stop(void); - </programlisting> - <para> - Disables the packet slave task, stopping the radio receiver. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_packet_slave_init</term> - <listitem> - <programlisting> -void -ao_packet_slave_init(void); - </programlisting> - <para> - Adds the packet stdio functions to the stdio package so - that when packet slave mode is enabled, characters will - get send and received through the stdio functions. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>ao_packet_master_init</term> - <listitem> - <programlisting> -void -ao_packet_master_init(void); - </programlisting> - <para> - Adds the 'p' packet forward command to start packet mode. - </para> - </listitem> - </varlistentry> - </variablelist> + <section> + <title>ao_radio_set_telemetry</title> + <programlisting> + void + ao_radio_set_telemetry(void); + </programlisting> + <para> + Configures the radio to send or receive telemetry + packets. This includes packet length, modulation scheme and + other RF parameters. It does not include the base frequency + or channel though. Those are set at the time of transmission + or reception, in case the values are changed by the user. + </para> + </section> + <section> + <title>ao_radio_set_packet</title> + <programlisting> + void + ao_radio_set_packet(void); + </programlisting> + <para> + Configures the radio to send or receive packet data. This + includes packet length, modulation scheme and other RF + parameters. It does not include the base frequency or + channel though. Those are set at the time of transmission or + reception, in case the values are changed by the user. + </para> + </section> + <section> + <title>ao_radio_set_rdf</title> + <programlisting> + void + ao_radio_set_rdf(void); + </programlisting> + <para> + Configures the radio to send RDF 'packets'. An RDF 'packet' + is a sequence of hex 0x55 bytes sent at a base bit rate of + 2kbps using a 5kHz deviation. All of the error correction + and data whitening logic is turned off so that the resulting + modulation is received as a 1kHz tone by a conventional 70cm + FM audio receiver. + </para> + </section> + <section> + <title>ao_radio_idle</title> + <programlisting> + void + ao_radio_idle(void); + </programlisting> + <para> + Sets the radio device to idle mode, waiting until it reaches + that state. This will terminate any in-progress transmit or + receive operation. + </para> + </section> + <section> + <title>ao_radio_get</title> + <programlisting> + void + ao_radio_get(void); + </programlisting> + <para> + Acquires the radio mutex and then configures the radio + frequency using the global radio calibration and channel + values. + </para> + </section> + <section> + <title>ao_radio_put</title> + <programlisting> + void + ao_radio_put(void); + </programlisting> + <para> + Releases the radio mutex. + </para> + </section> + <section> + <title>ao_radio_abort</title> + <programlisting> + void + ao_radio_abort(void); + </programlisting> + <para> + Aborts any transmission or reception process by aborting the + associated DMA object and calling ao_radio_idle to terminate + the radio operation. + </para> + </section> + <para> + In telemetry mode, you can send or receive a telemetry + packet. The data from receiving a packet also includes the RSSI + and status values supplied by the receiver. These are added + after the telemetry data. + </para> + <section> + <title>ao_radio_send</title> + <programlisting> + void + ao_radio_send(__xdata struct ao_telemetry *telemetry); + </programlisting> + <para> + This sends the specific telemetry packet, waiting for the + transmission to complete. The radio must have been set to + telemetry mode. This function calls ao_radio_get() before + sending, and ao_radio_put() afterwards, to correctly + serialize access to the radio device. + </para> + </section> + <section> + <title>ao_radio_recv</title> + <programlisting> + void + ao_radio_recv(__xdata struct ao_radio_recv *radio); + </programlisting> + <para> + This blocks waiting for a telemetry packet to be received. + The radio must have been set to telemetry mode. This + function calls ao_radio_get() before receiving, and + ao_radio_put() afterwards, to correctly serialize access + to the radio device. This returns non-zero if a packet was + received, or zero if the operation was aborted (from some + other task calling ao_radio_abort()). + </para> + </section> + <para> + In radio direction finding mode, there's just one function to + use + </para> + <section> + <title>ao_radio_rdf</title> + <programlisting> + void + ao_radio_rdf(int ms); + </programlisting> + <para> + This sends an RDF packet lasting for the specified amount + of time. The maximum length is 1020 ms. + </para> + </section> + <para> + Packet mode is asymmetrical and is configured at compile time + for either master or slave mode (but not both). The basic I/O + functions look the same at both ends, but the internals are + different, along with the initialization steps. + </para> + <section> + <title>ao_packet_putchar</title> + <programlisting> + void + ao_packet_putchar(char c); + </programlisting> + <para> + If the output queue is full, this first blocks waiting for + that data to be delivered. Then, queues a character for + packet transmission. On the master side, this will + transmit a packet if the output buffer is full. On the + slave side, any pending data will be sent the next time + the master polls for data. + </para> + </section> + <section> + <title>ao_packet_pollchar</title> + <programlisting> + char + ao_packet_pollchar(void); + </programlisting> + <para> + This returns a pending input character if available, + otherwise returns AO_READ_AGAIN. On the master side, if + this empties the buffer, it triggers a poll for more data. + </para> + </section> + <section> + <title>ao_packet_slave_start</title> + <programlisting> + void + ao_packet_slave_start(void); + </programlisting> + <para> + This is available only on the slave side and starts a task + to listen for packet data. + </para> + </section> + <section> + <title>ao_packet_slave_stop</title> + <programlisting> + void + ao_packet_slave_stop(void); + </programlisting> + <para> + Disables the packet slave task, stopping the radio receiver. + </para> + </section> + <section> + <title>ao_packet_slave_init</title> + <programlisting> + void + ao_packet_slave_init(void); + </programlisting> + <para> + Adds the packet stdio functions to the stdio package so + that when packet slave mode is enabled, characters will + get send and received through the stdio functions. + </para> + </section> + <section> + <title>ao_packet_master_init</title> + <programlisting> + void + ao_packet_master_init(void); + </programlisting> + <para> + Adds the 'p' packet forward command to start packet mode. + </para> + </section> </chapter> </book> |