Zigbee Module Examples

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Macros | Enumerations | Functions | Variables
zm_phy_uart.c File Reference

Physical Interface Layer to the Module using the Universal Asynchronous Receiver/Transmitter interface. This file acts as an interface between the module library methods and the hardware (hal file). More...

`#include "../HAL/hal.h"`
`#include "zm_phy_uart.h"`
`#include "module_errors.h"`
`#include "../Common/utilities.h"`
`#include <stdint.h>`
`#include <string.h>`

## Macros
#define | MODULE_BUFFER_SIZE 0xFF
#define | CHECK_MESSAGE_COMPLETE_INTERVAL_MS 2
#define | CHECK_MESSAGE_COMPLETE_TIMEOUT_MS 2000

## Enumerations
enum | messageBufferStates { NOT_STARTED, STARTED, AWAITING_FCS, COMPLETE, ERROR }

## Functions
void | zm_phy_init ()
uint8_t | moduleHasMessageWaiting ()
void | resetMessage ()
void | auxSerialPortHandler (char c)
moduleResult_t | sendSreq ()
moduleResult_t | getMessage ()
moduleResult_t | receiveAreq (uint8_t intervalMs, int16_t timeoutMs)
moduleResult_t | sendMessage ()
void | displayMessageBuffer ()

## Variables
uint8_t | zmBuf [MODULE_BUFFER_SIZE]
void(* | auxSerialPort )(char)
volatile uint8_t | messageFlags = 0
uint8_t | messageBufferIndex = 0
uint8_t | messageBuffer [MESSAGE_BUFFER_SIZE]
uint8_t | fcs = 0
enum messageBufferStates | messageBufferState

## Detailed Description

Physical Interface Layer to the Module using the Universal Asynchronous Receiver/Transmitter interface. This file acts as an interface between the module library methods and the hardware (hal file).

Note:
  To output SPI transmit information, define ZM_PHY_UART_VERBOSE. It is recommended to define this on a per-project basis. In IAR, this can be done in Project Options : C/C++ compiler : Preprocessor In the defined symbols box, add: ZM_PHY_UART_VERBOSE

# Troubleshooting

Module UART requires 115,200 kbs, with flow control enabled. Most problems with the UART interface are caused by flow control errors, so check these first.

# Concurrency

To prevent code in two places accessing the messageBuffer at the same time, we use a mutex. This mutex is implemented as a bit flag in the messageFlags variable. Accessing the mutex is through a spinlock, which waits until the buffer becomes available before using it. For example:

      while (messageFlags & MESSAGE_BUFFER_IN_USE);   //wait for msgBuffer to be available
      messageFlags |= MESSAGE_BUFFER_IN_USE;          //lock the buffer

Rev:
  1528

Author:
  dsmith

Date:
  2012-08-30 15:58:08 -0700 (Thu, 30 Aug 2012)

# Support

Please refer to the wiki at www.anaren.com/air-wiki-zigbee for more information. Additional support is available via email at the following addresses:

- Questions on how to use the product: AIR@a.nosp@m.nare.nosp@m.n.com
- Feature requests, comments, and improvements: featu.nosp@m.rere.nosp@m.quest.nosp@m.s@te.nosp@m.slaco.nosp@m.ntro.nosp@m.ls.co.nosp@m.m
- Consulting engagements: sales.nosp@m.@tes.nosp@m.lacon.nosp@m.trol.nosp@m.s.com

# License

Copyright (c) 2012 Tesla Controls. All rights reserved. This Software may only be used with an Anaren A2530E24AZ1, A2530E24CZ1, A2530R24AZ1, or A2530R24CZ1 module. Redistribution and use in source and binary forms, with or without modification, are subject to the Software License Agreement in the file "anaren_eula.txt"

YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL ANAREN MICROWAVE OR TESLA CONTROLS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSE INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

## Enumeration Type Documentation

enum messageBufferStates

The states of the messageBuffer receive state machine. This is private and should not be needed to be accessed outside this file

Enumerator:

  NOT_STARTED | awaiting the start of a new message
  STARTED | a message has started, but not yet completed
  AWAITING_FCS | all the bytes of message body received, need to check FCS
  COMPLETE | FCS check complete, message can now be read
  ERROR | there was an error in parsing

## Function Documentation

void auxSerialPortHandler | ( | char | c | ) |

Processes bytes received from the Module. Should be called in the serial port ISR for the module serial port. For example:

    #pragma vector=USCIAB1RX_VECTOR
    __interrupt void USCI1RX_ISR(void)
    {
      if (UC1IFG & UCA1RXIFG)
      {
        auxSerialPort(UCA1RXBUF);    //reading this register clears the interrupt flag
      }
    }

Message processing is handled according to a simple state machine. If a message has already started, then append bytes to messageBuffer. When a byte is received:

1. Assert RTS so that the module doesn't send another byte while we're processing this one
2. Set messageFlags.MESSAGE_BUFFER_IN_USE. This is a simple mutex to control access to messageBufferIndex, messageBuffer, and fcs to prevent concurrency issues
3. Process received byte based on the state of messageBufferState
4. Clear messageFlags.MESSAGE_BUFFER_IN_USE mutex
5. Deassert RTS to allow more bytes to be received
   Parameters:

     c | the byte that was received in the ISR.

void displayMessageBuffer | ( |  | ) |

Displays the contents of the messageBuffer. Locks the messageBuffer while reading to prevent a concurrency problem.

Note:
  If you have sufficient memory and the printf is slow then it would be better to copy messageBuffer to a new buffer and then printf that. Or use a circular buffer on the debug UART.

moduleResult_t getMessage | ( |  | ) |

Get a message that is in messageBuffer and copy to zmBuf for further processing.

Precondition:
  moduleHasMessageWaiting() is true

Postcondition:
  zmBuf holds the message that was in messageBuffer

uint8_t moduleHasMessageWaiting | ( |  | ) |

Indicates whether the module has a message ready to be processed.

Returns:
  true (1) if there is a complete message in messageBuffer ready for processing, or 0 otherwise.

moduleResult_t receiveAreq | ( | uint8_t | intervalMs,
|  | int16_t | timeoutMs
| ) |  |

    Wait to receive an asynchronous message. Similar to spiPoll() but with wait.

Parameters:

  intervalMs | how often to check that we received the message.
  timeoutMs | how long to wait, total, for the message

Returns:
  MODULE_SUCCESS if message received before timeoutMs or else ZM_PHY_SRSP_TIMEOUT if no message was received before timeout.

Postcondition:
  received data is written to zmBuf and messageBuffer is reset

void resetMessage | ( |  | ) |

Clears the messageFlags and sets messageBufferIndex back to zero. After this method is called we are ready to receive a new message from the Module.

moduleResult_t sendMessage | ( |  | ) |

Public method to send messages to the Module. This will send one message and then receive the Synchronous Response (SRSP) message from the Module to indicate the command was received.

Precondition:
  zmBuf contains a properly formatted message
  Module has been initialized

Postcondition:
  buffer zmBuf contains the response (if any) from the Module.

moduleResult_t sendSreq | ( |  | ) |

Sends a Module Synchronous Request (SREQ) message and retrieves the response. A SREQ is a message to the Module that is immediately followed by a Synchronous Response (SRSP) message from the Module. As opposed to an Asynchronous Request (AREQ) message, which does not have a SRSP. This is a private method that gets wrapped by sendMessage().

Precondition:
  Module has been initialized
  zmBuf contains a properly formatted message. No validation is done.

Postcondition:
  received data is written to zmBuf

## Variable Documentation

void(* auxSerialPort)(char)

    Function pointer for the ISR called when a byte is received on the serial

port connected to the module. This must be defined in the hal file.

Function pointer for the ISR called when a byte is received on the aux. serial port

volatile uint8_t messageFlags = 0

Used to indicate an entire message has arrived. Set by ISR, cleared by main method

uint8_t zmBuf[MODULE_BUFFER_SIZE]

    This buffer will hold the transmitted messages and received SRSP Payload after sendMessage() was

called. If fragmentation support is not required then this can be smaller, e.g. 100B.