A n 9 3 – Silicon Laboratories SI2493/57/34/15/04 User Manual
Page 296

A N 9 3
296
Rev. 1.3
Buffer Management, Status and Control Layer
Buffer Management
Sample code for this layer can be found in the application_buffers.c file. This code can be ported to other
applications with minimal changes needed to compile on the host platform. This block contains the buffer-
management routines for both modem and UART access. The buffer structure consists of two circular buffers
implemented as the following array variables:
char gModemToUARTBuffer[ BUFFERSIZE ];
The above buffer is typically filled by modemInterrupt() and emptied by UART0Interrupt(). Once the buffer
is empty, subsequent TI0 (UART) interrupts have no effect. If the buffer is filled again after all TI0 interrupts have
been serviced, the TI0 interrupt needs jump starting. This is accomplished by calling
UARTCommunicationUpdate()
after filling the buffer.
char gUARTToModemBuffer[ BUFFERSIZE ];
The above buffer is typically filled by UART0Interrupt() and emptied by modemInterrupt(). Once the buffer
is empty, subsequent TXE (modem) interrupts have no effect. If the buffer is filled again after all TXE interrupts
have been serviced, the TXE interrupt needs jump starting. This is accomplished by calling
modemCommunicationUpdate()
after filling the buffer.
The two arrays above must be sized by choosing a power of two for the value of BUFFERSIZE, defined in
modem_80C51.h
. This is because keeping track of the circular-buffer indexes requires modulus operations.
Instead of costly integer divisions with remainder, the modulus operation is achieved by bit masking using the all-
one bit pattern equal to BUFFERSIZE minus one. For example, if BUFFERSIZE is 1024 (2
10
), the bit mask
(MODULUS_MASK) used for updating buffer pointers modulo BUFFERSIZE must be 1023 (0011 1111 1111). When a
buffer index reaches the value 1024 (0100 0000 0000), a bitwise-AND operation with MODULUS_MASK will reset the
index value to zero. If the value of BUFFERSIZE is changed in the header file, then the value of MODULUS_MASK
must be set to the same value minus one. The following global variables track the state of the buffers. A value of
zero indicates an empty buffer.
int gModemToUARTBufferSize;
int gUARTToModemBufferSize;
Read and write addresses to the above buffers are tracked by the following pointers:
int gLastFromUART; // The last byte that was added to gUARTToModemBuffer[]
int gNextToModem; // The first byte that will be taken out of gUARTToModemBuffer[]
int gLastFromModem; // The last byte that was added to gModemToUARTBuffer[]
int gNextToUART; // The first byte that will be taken out of gModemToUARTBuffer[]
The flow of data between the modem and the UART is managed by the following functions:
char pullByteForModem( void ); // Remove a byte from gUARTToModemBuffer[]
char pullByteForUART( void ); // Remove a byte from gModemToUARTBuffer[]
void pushByteToModem( char byteToSend ); // Add a byte to gUARTToModemBuffer[]
void pushByteToUART( char byteToSend ); // Add a byte to gModemToUARTBuffer[]
Figure 77 summarizes the interactions between the function calls, pointers and buffers described above.