CC2530,zigbee,协议栈,代码集(MAC层)

10 篇文章 1 订阅
8 篇文章 1 订阅

MAC(MAC层)

High Level

mac_cfg.c

#include "mac_api.h"


#ifndef MAC_CFG_TX_DATA_MAX
#define MAC_CFG_TX_DATA_MAX         2
#endif

#ifndef MAC_CFG_TX_MAX
#define MAC_CFG_TX_MAX              5
#endif

#ifndef MAC_CFG_RX_MAX
#define MAC_CFG_RX_MAX              2
#endif

#ifndef MAC_CFG_DATA_IND_OFFSET
#define MAC_CFG_DATA_IND_OFFSET     0
#endif

#ifndef MAC_CFG_APP_PENDING_QUEUE
#define MAC_CFG_APP_PENDING_QUEUE   FALSE
#endif



const macCfg_t macCfg =
{
  MAC_CFG_TX_DATA_MAX,
  MAC_CFG_TX_MAX,
  MAC_CFG_RX_MAX,
  MAC_CFG_DATA_IND_OFFSET,
  MAC_CFG_APP_PENDING_QUEUE
};

mac_`high_level.h

#ifndef MAC_HIGH_LEVEL_H
#define MAC_HIGH_LEVEL_H

#include "mac_api.h"

def MAC_INTERNAL_API
#define MAC_INTERNAL_API
#endif


/* RX flag masks */
#define MAC_RX_FLAG_VERSION           0x03    /* received frame's version */
#define MAC_RX_FLAG_ACK_PENDING       0x04    /* outgoing ACK has pending bit set */
#define MAC_RX_FLAG_SECURITY          0x08    /* received frame has security bit set */
#define MAC_RX_FLAG_PENDING           0x10    /* received frame has pending bit set */
#define MAC_RX_FLAG_ACK_REQUEST       0x20    /* received frame has ack request bit set */
#define MAC_RX_FLAG_INTRA_PAN         0x40    /* received frame has intra pan fcf bit set */
#define MAC_RX_FLAG_CRC_OK            0x80    /* received frame CRC OK bit */


/* Structure for internal data tx */
typedef struct
{
  macEventHdr_t     hdr;
  sData_t           msdu;
  macTxIntData_t    internal;
  macSec_t          sec;
} macTx_t;

/* Structure for internal data rx */
typedef struct
{
  macEventHdr_t     hdr;
  sData_t           msdu;
  macRxIntData_t    internal;
  macSec_t          sec;
  macDataInd_t      mac;
  sData_t           mhr;
} macRx_t;

/* Function pointer for the 16 byte random seed callback */
typedef void (*macRNGFcn_t )(uint8* seed);

/* pointer to current tx frame */
extern macTx_t *pMacDataTx;

/* TRUE if operating as a PAN coordinator */
extern bool macPanCoordinator;

/* functions located in mac_data.c */
MAC_INTERNAL_API uint8 *macDataRxMemAlloc(uint16 len);
MAC_INTERNAL_API uint8 macDataRxMemFree(uint8 **pMsg);
MAC_INTERNAL_API uint8 macDataTxTimeAvailable(void);

#endif /* MAC_HIGH_LEVEL_H */

mac_pib.c

#include "hal_mcu.h"
#include "hal_board.h"
#include "mac_api.h"
#include "mac_spec.h"
#include "mac_low_level.h"
#include "mac_radio_defs.h"
#include "mac_main.h"
#include "mac_pib.h"
#include "OSAL.h"
#include <stddef.h>

/* Attribute index constants, based on attribute ID values from spec */
#define MAC_ATTR_SET1_START       0x40
#define MAC_ATTR_SET1_END         0x5D
#define MAC_ATTR_SET1_OFFSET      0
#define MAC_ATTR_SET2_START       0xE0
#define MAC_ATTR_SET2_END         0xE5
#define MAC_ATTR_SET2_OFFSET      (MAC_ATTR_SET1_END - MAC_ATTR_SET1_START + MAC_ATTR_SET1_OFFSET + 1)

/* frame response values */
#define MAC_MAX_FRAME_RESPONSE_MIN  143
#define MAC_MAX_FRAME_RESPONSE_MAX  25776


/* PIB access and min/max table type */
typedef struct
{
  uint8     offset;
  uint8     len;
  uint8     min;
  uint8     max;
} macPibTbl_t;

/* PIB default values */
static CODE const macPib_t macPibDefaults =
{
  54,                                         /* ackWaitDuration */
  FALSE,                                      /* associationPermit */
  TRUE,                                       /* autoRequest */
  FALSE,                                      /* battLifeExt */
  6,                                          /* battLifeExtPeriods */

  NULL,                                       /* *pMacBeaconPayload */
  0,                                          /* beaconPayloadLength */
  MAC_BO_NON_BEACON,                          /* beaconOrder */
  0,                                          /* beaconTxTime */
  0,                                          /* bsn */

  {0, SADDR_MODE_EXT},                        /* coordExtendedAddress */
  MAC_SHORT_ADDR_NONE,                        /* coordShortAddress */
  0,                                          /* dsn */
  FALSE,                                      /* gtsPermit */
  4,                                          /* maxCsmaBackoffs */

  3,                                          /* minBe */
  0xFFFF,                                     /* panId */
  FALSE,                                      /* promiscuousMode */
  FALSE,                                      /* rxOnWhenIdle */
  MAC_SHORT_ADDR_NONE,                        /* shortAddress */

  MAC_SO_NONE,                                /* superframeOrder */
  0x01F4,                                     /* transactionPersistenceTime */
  FALSE,                                      /* assocciatedPanCoord */
  5,                                          /* maxBe */
  1220,                                       /* maxFrameTotalWaitTime */

  3,                                          /* maxFrameRetries */
  32,                                         /* ResponseWaitTime */
  0,                                          /* syncSymbolOffset */
  TRUE,                                       /* timeStampSupported */
  FALSE,                                      /* securityEnabled */

  /* Proprietary */
#if defined (HAL_PA_LNA)
  19,                                         /* phyTransmitPower for CC2591 */
#elif defined (HAL_PA_LNA_CC2590)
  11,                                         /* phyTransmitPower for CC2590 */
#else
  3,                                          /* phyTransmitPower without frontend */
#endif
  MAC_CHAN_11,                                /* logicalChannel */
  {0, SADDR_MODE_EXT},                        /* extendedAddress */
  1,                                          /* altBe */
  MAC_BO_NON_BEACON,                          /* deviceBeaconOrder */
};

static CODE const macPibTbl_t macPibTbl[] =
{
  {offsetof(macPib_t, ackWaitDuration), sizeof(uint8), 54, 54},                      /* MAC_ACK_WAIT_DURATION */
  {offsetof(macPib_t, associationPermit), sizeof(bool), FALSE, TRUE},                /* MAC_ASSOCIATION_PERMIT */
  {offsetof(macPib_t, autoRequest), sizeof(bool), FALSE, TRUE},                      /* MAC_AUTO_REQUEST */
  {offsetof(macPib_t, battLifeExt), sizeof(bool), FALSE, TRUE},                      /* MAC_BATT_LIFE_EXT */
  {offsetof(macPib_t, battLifeExtPeriods), sizeof(uint8), 6, 6},                     /* MAC_BATT_LIFE_EXT_PERIODS */

  {offsetof(macPib_t, pBeaconPayload), sizeof(uint8 *), 0, 0},                       /* MAC_BEACON_PAYLOAD */
  {offsetof(macPib_t, beaconPayloadLength), sizeof(uint8), 0, 52},                   /* MAC_BEACON_PAYLOAD_LENGTH */
  {offsetof(macPib_t, beaconOrder), sizeof(uint8), 0, 15},                           /* MAC_BEACON_ORDER */
  {offsetof(macPib_t, beaconTxTime), sizeof(uint32), 1, 1},                          /* MAC_BEACON_TX_TIME */
  {offsetof(macPib_t, bsn), sizeof(uint8), 0x00, 0xFF},                              /* MAC_BSN */

  {offsetof(macPib_t, coordExtendedAddress.addr.extAddr), sizeof(sAddrExt_t), 0, 0}, /* MAC_COORD_EXTENDED_ADDRESS */
  {offsetof(macPib_t, coordShortAddress), sizeof(uint16), 0, 0},                     /* MAC_COORD_SHORT_ADDRESS */
  {offsetof(macPib_t, dsn), sizeof(uint8), 0x00, 0xFF},                              /* MAC_DSN */
  {offsetof(macPib_t, gtsPermit), sizeof(bool), FALSE, TRUE},                        /* MAC_GTS_PERMIT */
  {offsetof(macPib_t, maxCsmaBackoffs), sizeof(uint8), 0, 254},                      /* MAC_MAX_CSMA_BACKOFFS */
  {offsetof(macPib_t, minBe), sizeof(uint8), 0, 8},                                  /* MAC_MIN_BE */
  {offsetof(macPib_t, panId), sizeof(uint16), 0, 0},                                 /* MAC_PAN_ID */
  {offsetof(macPib_t, promiscuousMode), sizeof(bool), FALSE, TRUE},                  /* MAC_PROMISCUOUS_MODE */
  {offsetof(macPib_t, rxOnWhenIdle), sizeof(bool), FALSE, TRUE},                     /* MAC_RX_ON_WHEN_IDLE */
  {offsetof(macPib_t, shortAddress), sizeof(uint16), 0, 0},                          /* MAC_SHORT_ADDRESS */
  {offsetof(macPib_t, superframeOrder), sizeof(uint8), 0, 15},                       /* MAC_SUPERFRAME_ORDER */
  {offsetof(macPib_t, transactionPersistenceTime), sizeof(uint16), 0, 0},            /* MAC_TRANSACTION_PERSISTENCE_TIME */
  {offsetof(macPib_t, associatedPanCoord), sizeof(bool), FALSE, TRUE},               /* MAC_ASSOCIATED_PAN_COORD */

  {offsetof(macPib_t, maxBe), sizeof(uint8), 0, 8},                                  /* MAC_MAX_BE */
  {offsetof(macPib_t, maxFrameTotalWaitTime), sizeof(uint16), 0x00, 0xFF},           /* MAC_MAX_FRAME_RESPONSE_TIME */

  {offsetof(macPib_t, maxFrameRetries), sizeof(uint8), 0, 7},                        /* MAC_MAX_FRAME_RETRIES */
  {offsetof(macPib_t, responseWaitTime), sizeof(uint8), 2, 64},                      /* MAC_RESPONSE_WAIT_TIME */
  {offsetof(macPib_t, syncSymbolOffset), sizeof(uint8), 0, 0},                       /* MAC_SYNC_SYMBOL_OFFSET */
  {offsetof(macPib_t, timeStampSupported), sizeof(bool), FALSE, TRUE},               /* MAC_TIMESTAMP_SUPPORTED */
  {offsetof(macPib_t, securityEnabled), sizeof(bool), FALSE, TRUE},                  /* MAC_SECURITY_ENABLED */

  /* Proprietary PIBs */
  {offsetof(macPib_t, phyTransmitPower), sizeof(uint8), 0, 0xFF},                    /* MAC_PHY_TRANSMIT_POWER */
  {offsetof(macPib_t, logicalChannel), sizeof(uint8), MAC_CHAN_11, MAC_CHAN_28},     /* MAC_LOGICAL_CHANNEL */
  {offsetof(macPib_t, extendedAddress.addr.extAddr), sizeof(sAddrExt_t), 0, 0},      /* MAC_EXTENDED_ADDRESS */
  {offsetof(macPib_t, altBe), sizeof(uint8), 0, 8},                                  /* MAC_ALT_BE */
  {offsetof(macPib_t, deviceBeaconOrder), sizeof(uint8), 0, 15},                     /* MAC_DEVICE_BEACON_ORDER */
  {offsetof(macPib_t, phyTransmitPower), sizeof(uint8), 0, 0},                       /* MAC_PHY_TRANSMIT_POWER_SIGNED */
};

/* MAC PIB */
macPib_t macPib;


MAC_INTERNAL_API void macPibReset(void)
{
  /* copy PIB defaults */
  macPib = macPibDefaults;

  /* initialize random sequence numbers */
  macPib.dsn = macRadioRandomByte();
  macPib.bsn = macRadioRandomByte();
}

static uint8 macPibIndex(uint8 pibAttribute)
{
  if ((pibAttribute >= MAC_ATTR_SET1_START) && (pibAttribute <= MAC_ATTR_SET1_END))
  {
    return (pibAttribute - MAC_ATTR_SET1_START + MAC_ATTR_SET1_OFFSET);
  }
  else if ((pibAttribute >= MAC_ATTR_SET2_START) && (pibAttribute <= MAC_ATTR_SET2_END))
  {
    return (pibAttribute - MAC_ATTR_SET2_START + MAC_ATTR_SET2_OFFSET);
  }
  else
  {
    return MAC_PIB_INVALID;
  }
}


uint8 MAC_MlmeGetReq(uint8 pibAttribute, void *pValue)
{
  uint8         i;
  halIntState_t intState;

  if ((i = macPibIndex(pibAttribute)) == MAC_PIB_INVALID)
  {
    return MAC_UNSUPPORTED_ATTRIBUTE;
  }

  HAL_ENTER_CRITICAL_SECTION(intState);
  osal_memcpy(pValue, (uint8 *) &macPib + macPibTbl[i].offset, macPibTbl[i].len);
  HAL_EXIT_CRITICAL_SECTION(intState);
  return MAC_SUCCESS;
}


uint8 MAC_MlmeSetReq(uint8 pibAttribute, void *pValue)
{
  uint8         i;
  halIntState_t intState;

  if (pibAttribute == MAC_BEACON_PAYLOAD)
  {
    macPib.pBeaconPayload = pValue;
    return MAC_SUCCESS;
  }

  /* look up attribute in PIB table */
  if ((i = macPibIndex(pibAttribute)) == MAC_PIB_INVALID)
  {
    return MAC_UNSUPPORTED_ATTRIBUTE;
  }

  /* do range check; no range check if min and max are zero */
  if ((macPibTbl[i].min != 0) || (macPibTbl[i].max != 0))
  {
    /* if min == max, this is a read-only attribute */
    if (macPibTbl[i].min == macPibTbl[i].max)
    {
      return MAC_READ_ONLY;
    }

    /* check for special cases */
    if (pibAttribute == MAC_MAX_FRAME_TOTAL_WAIT_TIME)
    {
      if ((*((uint16 *) pValue) < MAC_MAX_FRAME_RESPONSE_MIN) ||
          (*((uint16 *) pValue) > MAC_MAX_FRAME_RESPONSE_MAX))
      {
        return MAC_INVALID_PARAMETER;
      }
    }

    /* range check for general case */
    if ((*((uint8 *) pValue) < macPibTbl[i].min) || (*((uint8 *) pValue) > macPibTbl[i].max))
    {
      return MAC_INVALID_PARAMETER;
    }

  }

  /* set value in PIB */
  HAL_ENTER_CRITICAL_SECTION(intState);
  osal_memcpy((uint8 *) &macPib + macPibTbl[i].offset, pValue, macPibTbl[i].len);
  HAL_EXIT_CRITICAL_SECTION(intState);

  /* handle special cases */
  switch (pibAttribute)
  {
    case MAC_PAN_ID:
      /* set pan id in radio */
      macRadioSetPanID(macPib.panId);
      break;

    case MAC_SHORT_ADDRESS:
      /* set short address in radio */
      macRadioSetShortAddr(macPib.shortAddress);
      break;

    case MAC_RX_ON_WHEN_IDLE:
      /* turn rx on or off */
      if (macPib.rxOnWhenIdle)
      {
        macRxEnable(MAC_RX_WHEN_IDLE);
      }
      else
      {
        macRxDisable(MAC_RX_WHEN_IDLE);
      }
      break;

    case MAC_LOGICAL_CHANNEL:
      macRadioSetChannel(macPib.logicalChannel);
      break;

    case MAC_EXTENDED_ADDRESS:
      /* set ext address in radio */
      macRadioSetIEEEAddr(macPib.extendedAddress.addr.extAddr);
      break;

#ifndef MAC_OBSOLETE_PHY_TRANSMIT_POWER
    /* Define MAC_OBSOLETE_PHY_TRANSMIT_POWER to save some code */

    case MAC_PHY_TRANSMIT_POWER:
  
      macPib.phyTransmitPower = (uint8)(-(int8)macPib.phyTransmitPower);
#endif 
      /* pass through to next case -- do not break*/

#endif /* MAC_OBSOLETE_PHY_TRANSMIT_POWER */

    case MAC_PHY_TRANSMIT_POWER_SIGNED:
      (void)macRadioSetTxPower(macPib.phyTransmitPower);
      break;

    default:
      break;
  }

  return MAC_SUCCESS;
}

mac_pib.h

#ifndef MAC_PIB_H
#define MAC_PIB_H


#include "mac_api.h"
#include "mac_high_level.h"

/* MAC PIB type */
typedef struct
{
  uint8             ackWaitDuration;
  bool              associationPermit;
  bool              autoRequest;
  bool              battLifeExt;
  uint8             battLifeExtPeriods;

  uint8             *pBeaconPayload;
  uint8             beaconPayloadLength;
  uint8             beaconOrder;
  uint32            beaconTxTime;
  uint8             bsn;

  sAddr_t           coordExtendedAddress;
  uint16            coordShortAddress;
  uint8             dsn;
  bool              gtsPermit;
  uint8             maxCsmaBackoffs;

  uint8             minBe;
  uint16            panId;
  bool              promiscuousMode;
  bool              rxOnWhenIdle;
  uint16            shortAddress;

  uint8             superframeOrder;
  uint16            transactionPersistenceTime;
  bool              associatedPanCoord;
  uint8             maxBe;
  uint16            maxFrameTotalWaitTime;

  uint8             maxFrameRetries;
  uint8             responseWaitTime;
  uint8             syncSymbolOffset;
  bool              timeStampSupported;
  bool              securityEnabled;

  /* Proprietary */
  uint8             phyTransmitPower;
  uint8             logicalChannel;
  sAddr_t           extendedAddress;
  uint8             altBe;
  uint8             deviceBeaconOrder;

} macPib_t;


/* MAC PIB */
extern macPib_t macPib;


MAC_INTERNAL_API void macPibReset(void);


#endif /* MAC_PIB_H */

mac_spec.h

#ifndef MAC_SPEC_H
#define MAC_SPEC_H


#define MAC_PHY_SHR_LEN                 5       /* preamble bytes plus SFD byte */
#define MAC_PHY_PHR_LEN                 1       /* length byte */

/* MAC frame field lengths in bytes */
#define MAC_FCF_FIELD_LEN               2       /* frame control field */
#define MAC_SEQ_NUM_FIELD_LEN           1       /* sequence number  */
#define MAC_PAN_ID_FIELD_LEN            2       /* PAN ID  */
#define MAC_EXT_ADDR_FIELD_LEN          8       /* Extended address */
#define MAC_SHORT_ADDR_FIELD_LEN        2       /* Short address */
#define MAC_FCS_FIELD_LEN               2       /* FCS field */
#define MAC_SEC_CONTROL_FIELD_LEN       1       /* Security control field */

/* Frame offsets in bytes */
#define MAC_FCF_OFFSET                  0       /* offset to frame control field */
#define MAC_SEQ_NUM_OFFSET              2       /* offset to sequence number */
#define MAC_DEST_PAN_ID_OFFSET          3       /* offset to destination PAN ID */
#define MAC_DEST_ADDR_OFFSET            5       /* offset to destination address */

/* Frame control field bit masks */
#define MAC_FCF_FRAME_TYPE_MASK         0x0007
#define MAC_FCF_SEC_ENABLED_MASK        0x0008
#define MAC_FCF_FRAME_PENDING_MASK      0x0010
#define MAC_FCF_ACK_REQUEST_MASK        0x0020
#define MAC_FCF_INTRA_PAN_MASK          0x0040
#define MAC_FCF_DST_ADDR_MODE_MASK      0x0C00
#define MAC_FCF_FRAME_VERSION_MASK      0x3000
#define MAC_FCF_SRC_ADDR_MODE_MASK      0xC000

/* Frame control field bit positions */
#define MAC_FCF_FRAME_TYPE_POS          0
#define MAC_FCF_SEC_ENABLED_POS         3
#define MAC_FCF_FRAME_PENDING_POS       4
#define MAC_FCF_ACK_REQUEST_POS         5
#define MAC_FCF_INTRA_PAN_POS           6
#define MAC_FCF_DST_ADDR_MODE_POS       10
#define MAC_FCF_FRAME_VERSION_POS       12
#define MAC_FCF_SRC_ADDR_MODE_POS       14

/* Security control field bit masks */
#define MAC_SCF_SECURITY_LEVEL_MASK     0x07
#define MAC_SCF_KEY_IDENTIFIER_MASK     0x18

/* Security control field bit positions */
#define MAC_SCF_SECURITY_LEVEL_POS      0
#define MAC_SCF_KEY_IDENTIFIER_POS      3

/* MAC Payload offsets in bytes */
#define MAC_SFS_OFFSET                  0
#define MAC_PENDING_ADDR_OFFSET         3       /* if GTS is not in use */

/* Beacon superframe spec bit positions, low byte */
#define MAC_SFS_BEACON_ORDER_POS        0
#define MAC_SFS_SUPERFRAME_ORDER_POS    4

/* Beacon superframe spec bit positions, high byte */
#define MAC_SFS_FINAL_CAP_SLOT_POS      0
#define MAC_SFS_BATT_LIFE_EXT_POS       4
#define MAC_SFS_PAN_COORD_POS           6
#define MAC_SFS_ASSOC_PERMIT_POS        7


/* Frame type */
#define MAC_FRAME_TYPE_BEACON           0
#define MAC_FRAME_TYPE_DATA             1
#define MAC_FRAME_TYPE_ACK              2
#define MAC_FRAME_TYPE_COMMAND          3
#define MAC_FRAME_TYPE_MAX_VALID        MAC_FRAME_TYPE_COMMAND

/* Command frame identifiers */
#define MAC_ASSOC_REQ_FRAME             1
#define MAC_ASSOC_RSP_FRAME             2
#define MAC_DISASSOC_NOTIF_FRAME        3
#define MAC_DATA_REQ_FRAME              4
#define MAC_PAN_CONFLICT_FRAME          5
#define MAC_ORPHAN_NOTIF_FRAME          6
#define MAC_BEACON_REQ_FRAME            7
#define MAC_COORD_REALIGN_FRAME         8
#define MAC_GTS_REQ_FRAME               9

/* Length of command frame payload (includes command ID byte) */
#define MAC_ZERO_DATA_PAYLOAD           0
#define MAC_ASSOC_REQ_PAYLOAD           2
#define MAC_ASSOC_RSP_PAYLOAD           4
#define MAC_DISASSOC_NOTIF_PAYLOAD      2
#define MAC_DATA_REQ_PAYLOAD            1
#define MAC_PAN_CONFLICT_PAYLOAD        1
#define MAC_ORPHAN_NOTIF_PAYLOAD        1
#define MAC_BEACON_REQ_PAYLOAD          1
#define MAC_COORD_REALIGN_PAYLOAD       9
#define MAC_GTS_REQ_PAYLOAD             2

/* Length of command frames (max header plus payload) */
#define MAC_ZERO_DATA_FRAME_LEN         (21 + MAC_ZERO_DATA_PAYLOAD)
#define MAC_ASSOC_REQ_FRAME_LEN         (23 + MAC_ASSOC_REQ_PAYLOAD)
#define MAC_ASSOC_RSP_FRAME_LEN         (23 + MAC_ASSOC_RSP_PAYLOAD)
#define MAC_DISASSOC_NOTIF_FRAME_LEN    (17 + MAC_DISASSOC_NOTIF_PAYLOAD)
#define MAC_DATA_REQ_FRAME_LEN          (23 + MAC_DATA_REQ_PAYLOAD)
#define MAC_PAN_CONFLICT_FRAME_LEN      (23 + MAC_PAN_CONFLICT_PAYLOAD)
#define MAC_ORPHAN_NOTIF_FRAME_LEN      (17 + MAC_ORPHAN_NOTIF_PAYLOAD)
#define MAC_BEACON_REQ_FRAME_LEN        (7 + MAC_BEACON_REQ_PAYLOAD)
#define MAC_COORD_REALIGN_FRAME_LEN     (23 + MAC_COORD_REALIGN_PAYLOAD)
#define MAC_GTS_REQ_FRAME_LEN           (7 + MAC_GTS_REQ_PAYLOAD)

/* Beacon frame base length (max header plus minimum payload) */
#define MAC_BEACON_FRAME_BASE_LEN       (13 + 4)

/* Maximum number of pending addresses in a beacon */
#define MAC_PEND_ADDR_MAX               7

/* Associate response command frame status values */
#define MAC_ASSOC_SUCCESS               0             /* association successful */
#define MAC_ASSOC_CAPACITY              1             /* PAN at capacity */
#define MAC_ASSOC_DENIED                2             /* PAN access denied */

/* Beacon order and superframe order maximum values */
#define MAC_BO_NON_BEACON               15
#define MAC_SO_NONE                     15

/* Broadcast PAN ID */
#define MAC_PAN_ID_BROADCAST            0xFFFF

/* Number of symbols per octet */
#define MAC_SYMBOLS_PER_OCTET           2

/* Maximum phy frame size in bytes */
#define MAC_A_MAX_PHY_PACKET_SIZE       127

/* Phy RX <--> TX turnaround time in symbols */
#define MAC_A_TURNAROUND_TIME           12

/* Number of backoffs forming a superframe slot when the superframe order is equal to 0 */
#define MAC_A_BASE_SLOT_DURATION        3

/* Number of backoffs forming a superframe when the superframe order is equal to 0 */
#define MAC_A_BASE_SUPERFRAME_DURATION  (MAC_A_BASE_SLOT_DURATION * MAC_A_NUM_SUPERFRAME_SLOTS)

/* Maximum number of bytes added by the MAC sublayer to the payload of its beacon frame */
#define MAC_A_MAX_BEACON_OVERHEAD       75

/* Maximum size in bytes of a beacon payload */
#define MAC_A_MAX_BEACON_PAYLOAD_LENGTH (MAC_A_MAX_PHY_PACKET_SIZE - MAC_A_MAX_BEACON_OVERHEAD)

/* The number of superframes a GTS descriptor exists for in the beacon frame */
#define MAC_A_GTS_DESC_PERSISTENCE_TIME 4

/* Maximum size in bytes of a MAC frame header */
#define MAC_A_MAX_FRAME_OVERHEAD        25

/* The number of consecutive lost beacons that will case the MAC to declare a sync loss */
#define MAC_A_MAX_LOST_BEACONS          4

/* The maximum number of bytes that can be transmitted in the MAC frame payload */
#define MAC_A_MAX_FRAME_SIZE            (MAC_A_MAX_PHY_PACKET_SIZE - MAC_A_MAX_FRAME_OVERHEAD)

/* The maximum frame size in bytes that can be followed by a short interframe spacing period */
#define MAC_A_MAX_SIFS_FRAME_SIZE       18

/* The minimum number of symbols forming the CAP */
#define MAC_A_MIN_CAP_LENGTH            440

/* The minimum number of symbols forming a long interframe spacing period */
#define MAC_A_MIN_LIFS_PERIOD           40

/* The minimum number of symbols forming a short interframe spacing period */
#define MAC_A_MIN_SIFS_PERIOD           12

/* The number of slots contained in any superframe */
#define MAC_A_NUM_SUPERFRAME_SLOTS      16

/* The number of symbols forming a basic CSMA-CA time period */
#define MAC_A_UNIT_BACKOFF_PERIOD       20

/* Maximum value for energy detect */
#define MAC_SPEC_ED_MAX                 0xFF

/* Threshold above receiver sensitivity for minimum energy detect in dBm (see 6.9.7) */
#define MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY    10


#define MAC_SPEC_MIN_RECEIVER_SENSITIVITY   -85

/* Length of preamble field in symbols */
#define MAC_SPEC_PREAMBLE_FIELD_LENGTH      8

/* Length of SFD field in symbols */
#define MAC_SPEC_SFD_FIELD_LENGTH           2

/* Microseconds in one symbol */
#define MAC_SPEC_USECS_PER_SYMBOL           16

/* Microseconds in one backoff period */
#define MAC_SPEC_USECS_PER_BACKOFF          (MAC_SPEC_USECS_PER_SYMBOL * MAC_A_UNIT_BACKOFF_PERIOD)

/* octets (or bytes) per symbol */
#define MAC_SPEC_OCTETS_PER_SYMBOL          2


/* Length of GTS fields in a beacon, not including one byte for GTS specification */
#define MAC_GTS_FIELDS_LEN(gtsSpec)     ((uint8)((((gtsSpec) & 0x07) * 3) + (((gtsSpec) & 0x07) ? 1 : 0)))



#define MAC_FRAME_TYPE(p)       ((p)[MAC_FCF_OFFSET+0] & 0x07)
#define MAC_SEC_ENABLED(p)      ((p)[MAC_FCF_OFFSET+0] & 0x08)  /* note: value is *non-zero* if true */
#define MAC_FRAME_PENDING(p)    ((p)[MAC_FCF_OFFSET+0] & 0x10)  /* note: value is *non-zero* if true */
#define MAC_ACK_REQUEST(p)      ((p)[MAC_FCF_OFFSET+0] & 0x20)  /* note: value is *non-zero* if true */
#define MAC_INTRA_PAN(p)        ((p)[MAC_FCF_OFFSET+0] & 0x40)  /* note: value is *non-zero* if true */
#define MAC_DEST_ADDR_MODE(p)   (((p)[MAC_FCF_OFFSET+1] >> 2) & 0x3)
#define MAC_FRAME_VERSION(p)    (((p)[MAC_FCF_OFFSET+1] >> 4) & 0x3)
#define MAC_SRC_ADDR_MODE(p)    (((p)[MAC_FCF_OFFSET+1] >> 6) & 0x3)
#define MAC_SEQ_NUMBER(p)       ((p)[MAC_SEQ_NUM_OFFSET])
#endif /* MAC_SPEC_H */

Include

mac_api.h

#ifndef MAC_API_H
#define MAC_API_H

#ifdef __cplusplus
extern "C" {
#endif

#include "hal_types.h"
#include "saddr.h"
#include "sdata.h"

#define MAC_SUCCESS                 0x00  /* Operation successful */
#define MAC_AUTOACK_PENDING_ALL_ON  0xFE  /* The AUTOPEND pending all is turned on */
#define MAC_AUTOACK_PENDING_ALL_OFF 0xFF  /* The AUTOPEND pending all is turned off */
#define MAC_BEACON_LOSS             0xE0  /* The beacon was lost following a synchronization request */
#define MAC_CHANNEL_ACCESS_FAILURE  0xE1  /* The operation or data request failed because of
                                             activity on the channel */
#define MAC_COUNTER_ERROR           0xDB  /* The frame counter puportedly applied by the originator of
                                             the received frame is invalid */
#define MAC_DENIED                  0xE2  /* The MAC was not able to enter low power mode. */
#define MAC_DISABLE_TRX_FAILURE     0xE3  /* Unused */
#define MAC_FRAME_TOO_LONG          0xE5  /* The received frame or frame resulting from an operation
                                             or data request is too long to be processed by the MAC */
#define MAC_IMPROPER_KEY_TYPE       0xDC  /* The key purportedly applied by the originator of the
                                             received frame is not allowed */
#define MAC_IMPROPER_SECURITY_LEVEL 0xDD  /* The security level purportedly applied by the originator of
                                             the received frame does not meet the minimum security level */
#define MAC_INVALID_ADDRESS         0xF5  /* The data request failed because neither the source address nor
                                             destination address parameters were present */
#define MAC_INVALID_GTS             0xE6  /* Unused */
#define MAC_INVALID_HANDLE          0xE7  /* The purge request contained an invalid handle */
#define MAC_INVALID_INDEX           0xF9  /* Unused */
#define MAC_INVALID_PARAMETER       0xE8  /* The API function parameter is out of range */
#define MAC_LIMIT_REACHED           0xFA  /* The scan terminated because the PAN descriptor storage limit
                                             was reached */
#define MAC_NO_ACK                  0xE9  /* The operation or data request failed because no
                                             acknowledgement was received */
#define MAC_NO_BEACON               0xEA  /* The scan request failed because no beacons were received or the
                                             orphan scan failed because no coordinator realignment was received */
#define MAC_NO_DATA                 0xEB  /* The associate request failed because no associate response was received
                                             or the poll request did not return any data */
#define MAC_NO_SHORT_ADDRESS        0xEC  /* The short address parameter of the start request was invalid */
#define MAC_ON_TIME_TOO_LONG        0xF6  /* Unused */
#define MAC_OUT_OF_CAP              0xED  /* Unused */
#define MAC_PAN_ID_CONFLICT         0xEE  /* A PAN identifier conflict has been detected and
                                             communicated to the PAN coordinator */
#define MAC_PAST_TIME               0xF7  /* Unused */
#define MAC_READ_ONLY               0xFB  /* A set request was issued with a read-only identifier */
#define MAC_REALIGNMENT             0xEF  /* A coordinator realignment command has been received */
#define MAC_SCAN_IN_PROGRESS        0xFC  /* The scan request failed because a scan is already in progress */
#define MAC_SECURITY_ERROR          0xE4  /* Cryptographic processing of the received secure frame failed */
#define MAC_SUPERFRAME_OVERLAP      0xFD  /* The beacon start time overlapped the coordinator transmission time */
#define MAC_TRACKING_OFF            0xF8  /* The start request failed because the device is not tracking
                                             the beacon of its coordinator */
#define MAC_TRANSACTION_EXPIRED     0xF0  /* The associate response, disassociate request, or indirect
                                             data transmission failed because the peer device did not respond
                                             before the transaction expired or was purged */
#define MAC_TRANSACTION_OVERFLOW    0xF1  /* The request failed because MAC data buffers are full */
#define MAC_TX_ACTIVE               0xF2  /* Unused */
#define MAC_UNAVAILABLE_KEY         0xF3  /* The operation or data request failed because the
                                             security key is not available */
#define MAC_UNSUPPORTED_ATTRIBUTE   0xF4  /* The set or get request failed because the attribute is not supported */
#define MAC_UNSUPPORTED_LEGACY      0xDE  /* The received frame was secured with legacy security which is
                                             not supported */
#define MAC_UNSUPPORTED_SECURITY    0xDF  /* The security of the received frame is not supported */
#define MAC_UNSUPPORTED             0x18  /* The operation is not supported in the current configuration */
#define MAC_BAD_STATE               0x19  /* The operation could not be performed in the current state */
#define MAC_NO_RESOURCES            0x1A  /* The operation could not be completed because no
                                             memory resources were available */
#define MAC_ACK_PENDING             0x1B  /* For internal use only */
#define MAC_NO_TIME                 0x1C  /* For internal use only */
#define MAC_TX_ABORTED              0x1D  /* For internal use only */
#define MAC_DUPLICATED_ENTRY        0x1E  /* For internal use only - A duplicated entry is added to the source matching table */

/* MAC Security Level */
#define MAC_SEC_LEVEL_NONE          0x00  /* No security is used */
#define MAC_SEC_LEVEL_MIC_32        0x01  /* MIC-32 authentication is used */
#define MAC_SEC_LEVEL_MIC_64        0x02  /* MIC-64 authentication is used */
#define MAC_SEC_LEVEL_MIC_128       0x03  /* MIC-128 authentication is used */
#define MAC_SEC_LEVEL_ENC           0x04  /* AES encryption is used */
#define MAC_SEC_LEVEL_ENC_MIC_32    0x05  /* AES encryption and MIC-32 authentication are used */
#define MAC_SEC_LEVEL_ENC_MIC_64    0x06  /* AES encryption and MIC-64 authentication are used */
#define MAC_SEC_LEVEL_ENC_MIC_128   0x07  /* AES encryption and MIC-128 authentication are used */

/* Key Identifier Mode */
#define MAC_KEY_ID_MODE_NONE        0x00  /* Key is is not used */
#define MAC_KEY_ID_MODE_IMPLICIT    0x00  /* Key is determined implicitly */
#define MAC_KEY_ID_MODE_1           0x01  /* Key is determined from the 1-byte key index */
#define MAC_KEY_ID_MODE_4           0x02  /* Key is determined from the 4-byte key index */
#define MAC_KEY_ID_MODE_8           0x03  /* Key is determined from the 8-byte key index */

/* Key identifier field length in bytes */
#define MAC_KEY_ID_IMPLICIT_LEN     0
#define MAC_KEY_ID_1_LEN            1
#define MAC_KEY_ID_4_LEN            5
#define MAC_KEY_ID_8_LEN            9

/* Key source maximum length in bytes */
#define MAC_KEY_SOURCE_MAX_LEN      8

/* Key index length in bytes */
#define MAC_KEY_INDEX_LEN           1

/* Frame counter length in bytes */
#define MAC_FRAME_COUNTER_LEN       4

/* Key length in bytes */
#define MAC_KEY_MAX_LEN             16

/* Key lookup data length in bytes */
#define MAC_KEY_LOOKUP_SHORT_LEN    5
#define MAC_KEY_LOOKUP_LONG_LEN     9
#define MAC_MAX_KEY_LOOKUP_LEN      MAC_KEY_LOOKUP_LONG_LEN


/* Data constants */
#if !defined ( MAC_MAX_FRAME_SIZE )
  #define MAC_MAX_FRAME_SIZE        102   /* Maximum application data length without security */
#endif

#define MAC_DATA_OFFSET             24    /* Bytes required for MAC header in data frame */
#define MAC_ENC_OFFSET              5     /* Data offset required for encryption header */
#define MAC_MIC_32_LEN              4     /* Length required for MIC-32 authentication */
#define MAC_MIC_64_LEN              8     /* Length required for MIC-64 authentication */
#define MAC_MIC_128_LEN             16    /* Length required for MIC-128 authentication */

/* MHR length for received frame */
#define MAC_MHR_LEN                 37    /* FCF (2) + Seq (1) + Addr Fields (20) + Security HDR (14) */

/* TX Options */
#define MAC_TXOPTION_ACK            0x01  /* Acknowledged transmission.  The MAC will attempt to retransmit
                                             the frame until it is acknowledged */
#define MAC_TXOPTION_GTS            0x02  /* GTS transmission (unused) */
#define MAC_TXOPTION_INDIRECT       0x04  /* Indirect transmission.  The MAC will queue the data and wait
                                             for the destination device to poll for it.  This can only be used
                                             by a coordinator device */
#define MAC_TXOPTION_PEND_BIT       0x08  /* This proprietary option forces the pending bit set for direct
                                             transmission */
#define MAC_TXOPTION_NO_RETRANS     0x10  /* This proprietary option prevents the frame from being retransmitted */
#define MAC_TXOPTION_NO_CNF         0x20  /* This proprietary option prevents a MAC_MCPS_DATA_CNF
                                             event from being sent for this frame */
#define MAC_TXOPTION_ALT_BE         0x40  /* Use PIB value MAC_ALT_BE for the minimum backoff exponent */
#define MAC_TXOPTION_PWR_CHAN       0x80  /* Use the power and channel values in macDataReq_t
                                             instead of the PIB values */

/* Channels */
#define MAC_CHAN_11                 11
#define MAC_CHAN_12                 12
#define MAC_CHAN_13                 13
#define MAC_CHAN_14                 14
#define MAC_CHAN_15                 15
#define MAC_CHAN_16                 16
#define MAC_CHAN_17                 17
#define MAC_CHAN_18                 18
#define MAC_CHAN_19                 19
#define MAC_CHAN_20                 20
#define MAC_CHAN_21                 21
#define MAC_CHAN_22                 22
#define MAC_CHAN_23                 23
#define MAC_CHAN_24                 24
#define MAC_CHAN_25                 25
#define MAC_CHAN_26                 26
#define MAC_CHAN_27                 27
#define MAC_CHAN_28                 28


/* This macro converts a channel to a mask */
#define MAC_CHAN_MASK(chan)         ((uint32) 1 << (chan))

/* Channel Masks */
#define MAC_CHAN_11_MASK            MAC_CHAN_MASK(MAC_CHAN_11)
#define MAC_CHAN_12_MASK            MAC_CHAN_MASK(MAC_CHAN_12)
#define MAC_CHAN_13_MASK            MAC_CHAN_MASK(MAC_CHAN_13)
#define MAC_CHAN_14_MASK            MAC_CHAN_MASK(MAC_CHAN_14)
#define MAC_CHAN_15_MASK            MAC_CHAN_MASK(MAC_CHAN_15)
#define MAC_CHAN_16_MASK            MAC_CHAN_MASK(MAC_CHAN_16)
#define MAC_CHAN_17_MASK            MAC_CHAN_MASK(MAC_CHAN_17)
#define MAC_CHAN_18_MASK            MAC_CHAN_MASK(MAC_CHAN_18)
#define MAC_CHAN_19_MASK            MAC_CHAN_MASK(MAC_CHAN_19)
#define MAC_CHAN_20_MASK            MAC_CHAN_MASK(MAC_CHAN_20)
#define MAC_CHAN_21_MASK            MAC_CHAN_MASK(MAC_CHAN_21)
#define MAC_CHAN_22_MASK            MAC_CHAN_MASK(MAC_CHAN_22)
#define MAC_CHAN_23_MASK            MAC_CHAN_MASK(MAC_CHAN_23)
#define MAC_CHAN_24_MASK            MAC_CHAN_MASK(MAC_CHAN_24)
#define MAC_CHAN_25_MASK            MAC_CHAN_MASK(MAC_CHAN_25)
#define MAC_CHAN_26_MASK            MAC_CHAN_MASK(MAC_CHAN_26)
#define MAC_CHAN_27_MASK            MAC_CHAN_MASK(MAC_CHAN_27)
#define MAC_CHAN_28_MASK            MAC_CHAN_MASK(MAC_CHAN_28)

/* Channel Page */
#define MAC_CHANNEL_PAGE_0          0     /* 2.4 GHz band using O-QPSK */
#define MAC_CHANNEL_PAGE_1          1     /* 868 and 915 MHz bands using ASK */
#define MAC_CHANNEL_PAGE_2          2     /* 868 and 915 MHz bands using O-QPSK */

/* Capability Information */
#define MAC_CAPABLE_PAN_COORD       0x01  /* Device is capable of becoming a PAN coordinator */
#define MAC_CAPABLE_FFD             0x02  /* Device is an FFD */
#define MAC_CAPABLE_MAINS_POWER     0x04  /* Device is mains powered rather than battery powered */
#define MAC_CAPABLE_RX_ON_IDLE      0x08  /* Device has its receiver on when idle */
#define MAC_CAPABLE_SECURITY        0x40  /* Device is capable of sending and receiving secured frames */
#define MAC_CAPABLE_ALLOC_ADDR      0x80  /* Request allocation of a short address in the associate procedure */

/* Standard PIB Get and Set Attributes */
#define MAC_ACK_WAIT_DURATION             0x40  /* The maximum number of symbols to wait for an acknowledgment frame */
#define MAC_ASSOCIATION_PERMIT            0x41  /* TRUE if a coordinator is currently allowing association */
#define MAC_AUTO_REQUEST                  0x42  /* TRUE if a device automatically sends a data request if its address
                                                   is listed in the beacon frame */
#define MAC_BATT_LIFE_EXT                 0x43  /* TRUE if battery life extension is enabled */
#define MAC_BATT_LIFE_EXT_PERIODS         0x44  /* The number of backoff periods during which the receiver is
                                                   enabled following a beacon in battery life extension mode */
#define MAC_BEACON_PAYLOAD                0x45  /* The contents of the beacon payload */
#define MAC_BEACON_PAYLOAD_LENGTH         0x46  /* The length in bytes of the beacon payload */
#define MAC_BEACON_ORDER                  0x47  /* How often the coordinator transmits a beacon */
#define MAC_BEACON_TX_TIME                0x48  /* The time the device transmitted its last beacon frame,
                                                   in backoff period units */
#define MAC_BSN                           0x49  /* The beacon sequence number */
#define MAC_COORD_EXTENDED_ADDRESS        0x4A  /* The extended address of the coordinator with which the device
                                                   is associated */
#define MAC_COORD_SHORT_ADDRESS           0x4B  /* The short address assigned to the coordinator with which the
                                                   device is associated.  A value of MAC_ADDR_USE_EXT indicates
                                                   that the coordinator is using its extended address */
#define MAC_DSN                           0x4C  /* The data or MAC command frame sequence number */
#define MAC_GTS_PERMIT                    0x4D  /* TRUE if the PAN coordinator accepts GTS requests */
#define MAC_MAX_CSMA_BACKOFFS             0x4E  /* The maximum number of backoffs the CSMA-CA algorithm will attempt
                                                   before declaring a channel failure */
#define MAC_MIN_BE                        0x4F  /* The minimum value of the backoff exponent in the CSMA-CA algorithm.
                                                   If this value is set to 0, collision avoidance is disabled during
                                                   the first iteration of the algorithm. Also for the slotted version
                                                   of the CSMA-CA algorithm with the battery life extension enabled,
                                                   the minimum value of the backoff exponent will be at least 2 */
#define MAC_PAN_ID                        0x50  /* The PAN identifier.  If this value is 0xffff, the device is not
                                                   associated */
#define MAC_PROMISCUOUS_MODE              0x51  /* TRUE if the MAC is in promiscuous mode */
#define MAC_RX_ON_WHEN_IDLE               0x52  /* TRUE if the MAC enables its receiver during idle periods */
#define MAC_SHORT_ADDRESS                 0x53  /* The short address that the device uses to communicate in the PAN.
                                                   If the device is a PAN coordinator, this value shall be set before
                                                   calling MAC_StartReq().  Otherwise the value is allocated during
                                                   association.  Value MAC_ADDR_USE_EXT indicates that the device is
                                                   associated but not using a short address */
#define MAC_SUPERFRAME_ORDER              0x54  /* This specifies the length of the active portion of the superframe */
#define MAC_TRANSACTION_PERSISTENCE_TIME  0x55  /* The maximum time in beacon intervals that a transaction is stored by
                                                   a coordinator and indicated in the beacon */
#define MAC_ASSOCIATED_PAN_COORD          0x56  /* TRUE if the device is associated to the PAN coordinator */
#define MAC_MAX_BE                        0x57  /* The maximum value of the backoff exponent in the CSMA-CA algorithm */
#define MAC_MAX_FRAME_TOTAL_WAIT_TIME     0x58  /* The maximum number of CAP symbols in a beacon-enabled PAN, or
                                                   symbols in a non beacon-enabled PAN, to wait for a frame intended
                                                   as a response to a data request frame */
#define MAC_MAX_FRAME_RETRIES             0x59  /* The maximum number of retries allowed after a transmission failure */
#define MAC_RESPONSE_WAIT_TIME            0x5A  /* The maximum number of symbols a device shall wait for a response
                                                   command to be available following a request command in multiples
                                                   of aBaseSuperframeDuration */
#define MAC_SYNC_SYMBOL_OFFSET            0x5B  /* The timestamp offset from SFD in symbols */
#define MAC_TIMESTAMP_SUPPORTED           0x5C  /* TRUE if the MAC supports RX and TX timestamps */
#define MAC_SECURITY_ENABLED              0x5D  /* TRUE if security is enabled */

/* Security PIB Get and Set Attributes */
#define MAC_KEY_TABLE                     0x71  /* A table of KeyDescriptor, entries, each containing keys and related
                                                   information required for secured communications */
#define MAC_KEY_TABLE_ENTRIES             0x72  /* The number of entries in macKeyTable */
#define MAC_DEVICE_TABLE                  0x73  /* A table of Device-Descriptor entries, each indicating a remote device
                                                   with which this device securely communicates */
#define MAC_DEVICE_TABLE_ENTRIES          0x74  /* The number of entries in macDeviceTable. */
#define MAC_SECURITY_LEVEL_TABLE          0x75  /* A table of SecurityLevel-Descriptor entries, each with information
                                                   about the minimum security level expected depending on incoming frame
                                                   type and subtype. */
#define MAC_SECURITY_LEVEL_TABLE_ENTRIES  0x76  /* The number of entries in macSecurityLevelTable. */
#define MAC_FRAME_COUNTER                 0x77  /* The outgoing frame counter for this device */
#define MAC_AUTO_REQUEST_SECURITY_LEVEL   0x78  /* The security level used for automatic data requests. */
#define MAC_AUTO_REQUEST_KEY_ID_MODE      0x79  /* The key identifier mode used for automatic data requests */
#define MAC_AUTO_REQUEST_KEY_SOURCE       0x7A  /* The originator of the key used for automatic data requests. */
#define MAC_AUTO_REQUEST_KEY_INDEX        0x7B  /* The index of the key used for automatic data requests. */
#define MAC_DEFAULT_KEY_SOURCE            0x7C  /* The originator of the default key used for key ID mode 0x01 */
#define MAC_PAN_COORD_EXTENDED_ADDRESS    0x7D  /* The 64-bit address of the PAN coordinator. */
#define MAC_PAN_COORD_SHORT_ADDRESS       0x7E  /* The 16-bit short address assigned to the PAN coordinator. */

/* Proprietary Security PIB Get and Set Attributes */
#define MAC_KEY_ID_LOOKUP_ENTRY           0xD0  /* The key lookup table entry, part of an entry of the key table */
#define MAC_KEY_DEVICE_ENTRY              0xD1  /* The key device entry, part of an entry of the key table */
#define MAC_KEY_USAGE_ENTRY               0xD2  /* The key usage entry, part of an entry of the key table */
#define MAC_KEY_ENTRY                     0xD3  /* The MAC key entry, an entry of the key table */
#define MAC_DEVICE_ENTRY                  0xD4  /* The MAC device entry, an entry of the device table */
#define MAC_SECURITY_LEVEL_ENTRY          0xD5  /* The AMC security level entry, an entry of the security level table */

/* Proprietary PIB Get and Set Attributes */
#define MAC_PHY_TRANSMIT_POWER            0xE0  /* The transmit power in units of -1 dBm */
#define MAC_LOGICAL_CHANNEL               0xE1  /* The logical channel */
#define MAC_EXTENDED_ADDRESS              0xE2  /* The extended address of the device */
#define MAC_ALT_BE                        0xE3  /* alternate minimum backoff exponent */
#define MAC_DEVICE_BEACON_ORDER           0xE4  /* Device beacon order */
#define MAC_PHY_TRANSMIT_POWER_SIGNED     0xE5  /* Duplicate transmit power attribute in signed
                                                   (2's complement) dBm unit */
  
/* Disassociate Reason */
#define MAC_DISASSOC_COORD          1     /* The coordinator wishes the device to disassociate */
#define MAC_DISASSOC_DEVICE         2     /* The device itself wishes to disassociate */


/* Scan Type */
#define MAC_SCAN_ED                 0     /* Energy detect scan.  The device will tune to each channel and
                                             perform and energy measurement.  The list of channels and their
                                             associated measurements will be returned at the end of the scan */
#define MAC_SCAN_ACTIVE             1     /* Active scan.  The device tunes to each channel, sends a beacon
                                             request and listens for beacons.  The PAN descriptors are returned
                                             at the end of the scan */
#define MAC_SCAN_PASSIVE            2     /* Passive scan.  The device tunes to each channel and listens for
                                             beacons.  The PAN descriptors are returned at the end of the scan */
#define MAC_SCAN_ORPHAN             3     /* Orphan scan.  The device tunes to each channel and sends an orphan
                                             notification to try and find its coordinator.  The status is returned
                                             at the end of the scan */

/* Special address values */
#define MAC_ADDR_USE_EXT            0xFFFE  /* Short address value indicating extended address is used */
#define MAC_SHORT_ADDR_BROADCAST    0xFFFF  /* Broadcast short address */
#define MAC_SHORT_ADDR_NONE         0xFFFF  /* Short address when there is no short address */

/* Comm status indication reasons */
#define MAC_COMM_ASSOCIATE_RSP      0     /* Event sent in response to MAC_AssociateRsp() */
#define MAC_COMM_ORPHAN_RSP         1     /* Event sent in response to MAC_OrphanRsp() */
#define MAC_COMM_RX_SECURE          2     /* Event sent as a result of receiving a secure frame */

/* Power Mode */
#define MAC_PWR_ON                  0     /* MAC and radio hardware is powered on */
#define MAC_PWR_SLEEP_LITE          1     /* MAC and radio hardware are partially powered off */
#define MAC_PWR_SLEEP_DEEP          2     /* MAC and radio hardware are fully powered off */

/* MAC Callback Events */
#define MAC_MLME_ASSOCIATE_IND      1     /* Associate indication */
#define MAC_MLME_ASSOCIATE_CNF      2     /* Associate confirm */
#define MAC_MLME_DISASSOCIATE_IND   3     /* Disassociate indication */
#define MAC_MLME_DISASSOCIATE_CNF   4     /* Disassociate confirm */
#define MAC_MLME_BEACON_NOTIFY_IND  5     /* Beacon notify indication */
#define MAC_MLME_ORPHAN_IND         6     /* Orphan indication */
#define MAC_MLME_SCAN_CNF           7     /* Scan confirm */
#define MAC_MLME_START_CNF          8     /* Start confirm */
#define MAC_MLME_SYNC_LOSS_IND      9     /* Sync loss indication */
#define MAC_MLME_POLL_CNF           10    /* Poll confirm */
#define MAC_MLME_COMM_STATUS_IND    11    /* Communication status indication */
#define MAC_MCPS_DATA_CNF           12    /* Data confirm */
#define MAC_MCPS_DATA_IND           13    /* Data indication */
#define MAC_MCPS_PURGE_CNF          14    /* Purge confirm */
#define MAC_PWR_ON_CNF              15    /* Power on confirm */
#define MAC_MLME_POLL_IND           16    /* Poll indication */

#define MAC_RANDOM_SEED_LEN         16

/* Returns the number of short addresses in the pending address specification */
#define MAC_PEND_NUM_SHORT(pendAddrSpec)  ((pendAddrSpec) & 0x07)

/* Returns the number of extended addresses in the pending address specification */
#define MAC_PEND_NUM_EXT(pendAddrSpec)    (((pendAddrSpec) & 0x70) >> 4)

/* Returns the length in bytes of the pending address fields in the beacon */
#define MAC_PEND_FIELDS_LEN(pendAddrSpec) ((MAC_PEND_NUM_SHORT(pendAddrSpec) * 2) + \
                                           (MAC_PEND_NUM_EXT(pendAddrSpec) * 8))

/* The following macros are provided to help parse the superframe specification */
#define MAC_SFS_BEACON_ORDER(s)           ((s) & 0x0F)          /* returns the beacon order */
#define MAC_SFS_SUPERFRAME_ORDER(s)       (((s) >> 4) & 0x0F)   /* returns the beacon order */
#define MAC_SFS_FINAL_CAP_SLOT(s)         (((s) >> 8) & 0x0F)   /* returns the final CAP slot */
#define MAC_SFS_BLE(s)                    (((s) >> 12) & 0x01)  /* returns the battery life extension bit */
#define MAC_SFS_PAN_COORDINATOR(s)        (((s) >> 14) & 0x01)  /* returns the PAN coordinator bit */
#define MAC_SFS_ASSOCIATION_PERMIT(s)     ((s) >> 15)           /* returns the association permit bit */

/* MAC event header type */
typedef struct
{
  uint8   event;              /* MAC event */
  uint8   status;             /* MAC status */
} macEventHdr_t;

/* Common security type */
typedef struct
{
  uint8   keySource[MAC_KEY_SOURCE_MAX_LEN];  /* Key source */
  uint8   securityLevel;                      /* Security level */
  uint8   keyIdMode;                          /* Key identifier mode */
  uint8   keyIndex;                           /* Key index */
} macSec_t;

/* Key ID Lookup Descriptor */
typedef struct
{
  uint8              lookupData[MAC_MAX_KEY_LOOKUP_LEN];  /* Data used to identify the key */
  uint8              lookupDataSize;  /* 0x00 indicates 5 octets; 0x01 indicates 9 octets. */
} keyIdLookupDescriptor_t;

/* Key Device Descriptor */
typedef struct
{
  uint8              deviceDescriptorHandle;  /* Handle to the DeviceDescriptor */
  bool               uniqueDevice;            /* Is it a link key or a group key? */
  bool               blackListed;             /* This key exhausted the frame counter. */
} keyDeviceDescriptor_t;

/* Key Usage Descriptor */
typedef struct
{
  uint8              frameType;               /* Frame Type */
  uint8              cmdFrameId;              /* Command Frame Identifier */
} keyUsageDescriptor_t;

/* Key Descriptor */
typedef struct
{
  keyIdLookupDescriptor_t  *keyIdLookupList;   /* A list identifying this KeyDescriptor */
  uint8                    keyIdLookupEntries; /* The number of entries in KeyIdLookupList */

  keyDeviceDescriptor_t    *keyDeviceList;        /* A list indicating which devices are
                                                     currently using this key, including
                                                     their blacklist status. */
  uint8                    keyDeviceListEntries;  /* The number of entries in KeyDeviceList */

  keyUsageDescriptor_t     *keyUsageList;         /* A list indicating which frame types
                                                   * this key may be used with. */
  uint8                    keyUsageListEntries;   /* The number of entries in KeyUsageList */

  uint8                    key[MAC_KEY_MAX_LEN];  /* The actual value of the key */
} keyDescriptor_t;

/* Device Descriptor */
typedef struct
{
  uint16             panID;          /* The 16-bit PAN identifier of the device */
  uint16             shortAddress;   /* The 16-bit short address of the device */
  sAddrExt_t         extAddress;     /* The 64-bit IEEE extended address of the
                                        device. This element is also used in
                                        unsecuring operations on incoming frames. */
  uint32             frameCounter;   /* The incoming frame counter of the device.
                                        This value is used to ensure sequential
                                        freshness of frames. */
  bool               exempt;         /* Device may override the minimum security
                                        level settings. */
} deviceDescriptor_t;

/* Security Level Descriptor */
typedef struct
{
  uint8              frameType;              /* Frame Type */
  uint8              commandFrameIdentifier; /* Command Frame ID */
  uint8              securityMinimum;        /* The minimal required/expected security
                                                level for incoming MAC frames. */
  bool               securityOverrideSecurityMinimum;
                                             /* Indication of whether originating devices
                                                for which the Exempt flag is set may
                                                override the minimum security level
                                                indicated by the SecurityMinimum
                                                element. If TRUE, this indicates that for
                                                originating devices with Exempt status,
                                                the incoming security level zero is
                                                acceptable. */
} securityLevelDescriptor_t;

/* For internal use only */
typedef struct
{
  uint32            timestamp;
  uint16            timestamp2;
  uint16            timeToLive;
  uint8             frameType;
  uint8             txOptions;
  uint8             txMode;
  uint8             txSched;
  uint8             retries;
  uint8             channel;
  uint8             power;
  uint8             mpduLinkQuality;
  uint8             correlation;
  int8              rssi;
} macTxIntData_t;

/* For internal use only */
typedef struct
{
  uint8             frameType;
  uint8             flags;
} macRxIntData_t;

/* Data request parameters type */
typedef struct
{
  sAddr_t         dstAddr;      /* The address of the destination device */
  uint16          dstPanId;     /* The PAN ID of the destination device */
  uint8           srcAddrMode;  /* The source address mode */
  uint8           msduHandle;   /* Application-defined handle value associated with this data request */
  uint8           txOptions;    /* TX options bit mask */
  uint8           channel;      /* Transmit the data frame on this channel */
  uint8           power;        /* Transmit the data frame at this power level */
} macDataReq_t;

/* MCPS data request type */
typedef struct
{
  macEventHdr_t   hdr;        /* Internal use only */
  sData_t         msdu;       /* Data pointer and length */
  macTxIntData_t  internal;   /* Internal use only */
  macSec_t        sec;        /* Security parameters */
  macDataReq_t    mac;        /* Data request parameters */
} macMcpsDataReq_t;

/* Data indication parameters type */
typedef struct
{
  sAddr_t   srcAddr;          /* The address of the sending device */
  sAddr_t   dstAddr;          /* The address of the destination device */
  uint32    timestamp;        /* The time, in backoffs, at which the data were received */
  uint16    timestamp2;       /* The time, in internal MAC timer units, at which the
                                 data were received */
  uint16    srcPanId;         /* The PAN ID of the sending device */
  uint16    dstPanId;         /* The PAN ID of the destination device */
  uint8     mpduLinkQuality;  /* The link quality of the received data frame */
  uint8     correlation;      /* The raw correlation value of the received data frame */
  int8      rssi;             /* The received RF power in units dBm */
  uint8     dsn;              /* The data sequence number of the received frame */
} macDataInd_t;


/* MCPS data indication type */
typedef struct
{
  macEventHdr_t  hdr;         /* Internal use only */
  sData_t        msdu;        /* Data pointer and length */
  macRxIntData_t internal;    /* Internal use only */
  macSec_t       sec;         /* Security parameters */
  macDataInd_t   mac;         /* Data indication parameters */
} macMcpsDataInd_t;

/* MCPS data confirm type */
typedef struct
{
  macEventHdr_t      hdr;              /* Contains the status of the data request operation */
  uint8              msduHandle;       /* Application-defined handle value associated with the data request */
  macMcpsDataReq_t   *pDataReq;        /* Pointer to the data request buffer for this data confirm */
  uint32             timestamp;        /* The time, in backoffs, at which the frame was transmitted */
  uint16             timestamp2;       /* The time, in internal MAC timer units, at which the
                                          frame was transmitted */
  uint8              retries;          /* The number of retries required to transmit the data frame */
  uint8              mpduLinkQuality;  /* The link quality of the received ack frame */
  uint8              correlation;      /* The raw correlation value of the received ack frame */
  int8               rssi;             /* The RF power of the received ack frame in units dBm */
} macMcpsDataCnf_t;


/* MCPS purge confirm type */
typedef struct
{
  macEventHdr_t      hdr;         /* Contains the status of the purge request operation */
  uint8              msduHandle;  /* Application-defined handle value associated with the data request */
} macMcpsPurgeCnf_t;

/* PAN descriptor type */
typedef struct
{
  sAddr_t       coordAddress;     /* The address of the coordinator sending the beacon */
  uint16        coordPanId;       /* The PAN ID of the network */
  uint16        superframeSpec;   /* The superframe specification of the network */
  uint8         logicalChannel;   /* The logical channel of the network */
  uint8         channelPage;      /* The current channel page occupied by the network */
  bool          gtsPermit;        /* TRUE if coordinator accepts GTS requests */
  uint8         linkQuality;      /* The link quality of the received beacon */
  uint32        timestamp;        /* The time at which the beacon was received, in backoffs */
  bool          securityFailure;  /* Set to TRUE if there was an error in the security processing */
  macSec_t      sec;              /* The security parameters for the received beacon frame */
} macPanDesc_t;

/* MLME associate request type */
typedef struct
{
  uint8       logicalChannel;         /* The channel on which to attempt association */
  uint8       channelPage;            /* The channel page on which to attempt association */
  sAddr_t     coordAddress;           /* Address of the coordinator with which to associate */
  uint16      coordPanId;             /* The identifier of the PAN with which to associate */
  uint8       capabilityInformation;  /* The operational capabilities of this device */
  macSec_t    sec;                    /* The security parameters for this message */
} macMlmeAssociateReq_t;

/* MLME associate response type */
typedef struct
{
  sAddrExt_t  deviceAddress;       /* The address of the device requesting association */
  uint16      assocShortAddress;   /* The short address allocated to the device */
  uint8       status;              /* The status of the association attempt */
  macSec_t    sec;                 /* The security parameters for this message */
} macMlmeAssociateRsp_t;

/* MLME disassociate request type */
typedef struct
{
  sAddr_t     deviceAddress;       /* The address of the device with which to disassociate */
  uint16      devicePanId;         /* The PAN ID of the device */
  uint8       disassociateReason;  /* The disassociate reason */
  bool        txIndirect;          /* Transmit Indirect */
  macSec_t    sec;                 /* The security parameters for this message */
} macMlmeDisassociateReq_t;


/* MLME orphan response type */
typedef struct
{
  sAddrExt_t  orphanAddress;      /* The extended address of the device sending the orphan notification */
  uint16      shortAddress;       /* The short address of the orphaned device */
  bool        associatedMember;   /* Set to TRUE if the orphaned device is associated with this coordinator */
  macSec_t    sec;                /* The security parameters for this message */
} macMlmeOrphanRsp_t;

/* MLME poll request type */
typedef struct
{
  sAddr_t     coordAddress;       /* The address of the coordinator device to poll */
  uint16      coordPanId;         /* The PAN ID of the coordinator */
  macSec_t    sec;                /* The security parameters for this message */
} macMlmePollReq_t;

/* MLME scan request type */
typedef struct
{
  uint32           scanChannels;    /* Bit mask indicating which channels to scan */
  uint8            scanType;        /* The type of scan */
  uint8            scanDuration;    /* The exponent used in the scan duration calculation */
  uint8            channelPage;     /* The channel page on which to perform the scan */
  uint8            maxResults;      /* The maximum number of PAN descriptor results */
  macSec_t         sec;             /* The security parameters for orphan scan */
  union {
    uint8         *pEnergyDetect;   /* Pointer to a buffer to store energy detect measurements */
    macPanDesc_t  *pPanDescriptor;  /* Pointer to a buffer to store PAN descriptors */
  } result;
} macMlmeScanReq_t;

/* MLME start request type */
typedef struct
{
  uint32      startTime;          /* The time to begin transmitting beacons relative to the received beacon */
  uint16      panId;              /* The PAN ID to use.  This parameter is ignored if panCoordinator is FALSE */
  uint8       logicalChannel;     /* The logical channel to use.  This parameter is ignored if panCoordinator is FALSE */
  uint8       channelPage;        /* The channel page to use.  This parameter is ignored if panCoordinator is FALSE */
  uint8       beaconOrder;        /* The exponent used to calculate the beacon interval */
  uint8       superframeOrder;    /* The exponent used to calculate the superframe duration */
  bool        panCoordinator;     /* Set to TRUE to start a network as PAN coordinator */
  bool        batteryLifeExt;     /* If this value is TRUE, the receiver is disabled after MAC_BATT_LIFE_EXT_PERIODS
                                     full backoff periods following the interframe spacing period of the beacon frame */
  bool        coordRealignment;   /* Set to TRUE to transmit a coordinator realignment prior to changing
                                     the superframe configuration */
  macSec_t    realignSec;         /* Security parameters for the coordinator realignment frame */
  macSec_t    beaconSec;          /* Security parameters for the beacon frame */
} macMlmeStartReq_t;

/* MAC_MlmeSyncReq type */
typedef struct
{
  uint8       logicalChannel;     /* The logical channel to use */
  uint8       channelPage;        /* The channel page to use */
  bool        trackBeacon;        /* Set to TRUE to continue tracking beacons after synchronizing with the
                                     first beacon.  Set to FALSE to only synchronize with the first beacon */
} macMlmeSyncReq_t;

/* MAC_MLME_ASSOCIATE_IND type */
typedef struct
{
  macEventHdr_t   hdr;                    /* The event header */
  sAddrExt_t      deviceAddress;          /* The address of the device requesting association */
  uint8           capabilityInformation;  /* The operational capabilities of the device requesting association */
  macSec_t        sec;                    /* The security parameters for this message */
} macMlmeAssociateInd_t;

/* MAC_MLME_ASSOCIATE_CNF type */
typedef struct
{
  macEventHdr_t   hdr;                    /* Event header contains the status of the associate attempt */
  uint16          assocShortAddress;      /* If successful, the short address allocated to this device */
  macSec_t        sec;                    /* The security parameters for this message */
} macMlmeAssociateCnf_t;

/* MAC_MLME_DISASSOCIATE_IND type */
typedef struct
{
  macEventHdr_t   hdr;                    /* The event header */
  sAddrExt_t      deviceAddress;          /* The address of the device sending the disassociate command */
  uint8           disassociateReason;     /* The disassociate reason */
  macSec_t        sec;                    /* The security parameters for this message */
} macMlmeDisassociateInd_t;

/* MAC_MLME_DISASSOCIATE_CNF type */
typedef struct
{
  macEventHdr_t   hdr;                    /* Event header contains the status of the disassociate attempt */
  sAddr_t         deviceAddress;          /* The address of the device that has either requested disassociation
                                             or been instructed to disassociate by its coordinator */
  uint16          panId;                  /* The pan ID of the device that has either requested disassociation
                                             or been instructed to disassociate by its coordinator */
} macMlmeDisassociateCnf_t;

/* MAC_MLME_BEACON_NOTIFY_IND type */
typedef struct
{
  macEventHdr_t  hdr;             /* The event header */
  uint8          bsn;             /* The beacon sequence number */
  macPanDesc_t   *pPanDesc;       /* The PAN descriptor for the received beacon */
  uint8          pendAddrSpec;    /* The beacon pending address specification */
  uint8          *pAddrList;      /* The list of device addresses for which the sender of the beacon has data */
  uint8          sduLength;       /* The number of bytes in the beacon payload of the beacon frame */
  uint8          *pSdu;           /* The beacon payload */
} macMlmeBeaconNotifyInd_t;

/* MAC_MLME_ORPHAN_IND type */
typedef struct
{
  macEventHdr_t   hdr;            /* The event header */
  sAddrExt_t      orphanAddress;  /* The address of the orphaned device */
  macSec_t        sec;            /* The security parameters for this message */
} macMlmeOrphanInd_t;

/* MAC_MLME_SCAN_CNF type */
typedef struct
{
  macEventHdr_t   hdr;                /* Event header contains the status of the scan request */
  uint8           scanType;           /* The type of scan requested */
  uint8           channelPage;        /* The channel page of the scan */
  uint32          unscannedChannels;  /* Bit mask of channels that were not scanned */
  uint8           resultListSize;     /* The number of PAN descriptors returned in the results list */
  union
  {
    uint8         *pEnergyDetect;     /* The list of energy measurements, one for each channel scanned */
    macPanDesc_t  *pPanDescriptor;    /* The list of PAN descriptors, one for each beacon found */
  } result;
} macMlmeScanCnf_t;

/* MAC_MLME_START_CNF type */
typedef struct
{
  macEventHdr_t   hdr;            /* Event header contains the status of the start request */
} macMlmeStartCnf_t;

/* MAC_MLME_SYNC_LOSS_IND type */
typedef struct
{
  macEventHdr_t   hdr;            /* Event header contains the reason that synchronization was lost */
  uint16          panId;          /* The PAN ID of the realignment */
  uint8           logicalChannel; /* The logical channel of the realignment */
  uint8           channelPage;    /* The channel page of the realignment */
  macSec_t        sec;            /* The security parameters for this message */
} macMlmeSyncLossInd_t;

/* MAC_MLME_POLL_CNF type */
typedef struct
{
  macEventHdr_t   hdr;            /* Event header contains the status of the poll request */
} macMlmePollCnf_t;

/* MAC_MLME_COMM_STATUS_IND type */
typedef struct
{
  macEventHdr_t   hdr;            /* Event header contains the status for this event */
  sAddr_t         srcAddr;        /* The source address associated with the event */
  sAddr_t         dstAddr;        /* The destination address associated with the event */
  uint16          panId;          /* The PAN ID associated with the event */
  uint8           reason;         /* The reason the event was generated */
  macSec_t        sec;            /* The security parameters for this message */
} macMlmeCommStatusInd_t;

/* MAC_MLME_POLL_IND type */
typedef struct
{
  macEventHdr_t   hdr;
  uint16          srcShortAddr;   /* Short address of the device sending the data request */
  uint16          srcPanId;       /* Pan ID of the device sending the data request */
} macMlmePollInd_t;

/* Union of callback structures */
typedef union
{
  macEventHdr_t            hdr;
  macMlmeAssociateInd_t    associateInd;      /* MAC_MLME_ASSOCIATE_IND */
  macMlmeAssociateCnf_t    associateCnf;      /* MAC_MLME_ASSOCIATE_CNF */
  macMlmeDisassociateInd_t disassociateInd;   /* MAC_MLME_DISASSOCIATE_IND */
  macMlmeDisassociateCnf_t disassociateCnf;   /* MAC_MLME_DISASSOCIATE_CNF */
  macMlmeBeaconNotifyInd_t beaconNotifyInd;   /* MAC_MLME_BEACON_NOTIFY_IND */
  macMlmeOrphanInd_t       orphanInd;         /* MAC_MLME_ORPHAN_IND */
  macMlmeScanCnf_t         scanCnf;           /* MAC_MLME_SCAN_CNF */
  macMlmeStartCnf_t        startCnf;          /* MAC_MLME_START_CNF */
  macMlmeSyncLossInd_t     syncLossInd;       /* MAC_MLME_SYNC_LOSS_IND */
  macMlmePollCnf_t         pollCnf;           /* MAC_MLME_POLL_CNF */
  macMlmeCommStatusInd_t   commStatusInd;     /* MAC_MLME_COMM_STATUS_IND */
  macMlmePollInd_t         pollInd;           /* MAC_MLME_POLL_IND */
  macMcpsDataCnf_t         dataCnf;           /* MAC_MCPS_DATA_CNF */
  macMcpsDataInd_t         dataInd;           /* MAC_MCPS_DATA_IND */
  macMcpsPurgeCnf_t        purgeCnf;          /* MAC_MCPS_PURGE_CNF */
} macCbackEvent_t;

/* Configurable parameters */
typedef struct
{
  uint8   txDataMax;              /* maximum number of data frames in transmit queue */
  uint8   txMax;                  /* maximum number of frames of all types in transmit queue */
  uint8   rxMax;                  /* maximum number of command and data frames in receive queue */
  uint8   dataIndOffset;          /* allocate additional bytes in the data indication for
                                     application-defined headers */
  bool    appPendingQueue;        /* determine whether MAC_MLME_POLL_IND will be sent to the application or not
                                     when data request is received and no pending frame is found in the MAC */
} macCfg_t;



/* These functions are used when creating the OSAL MAC task.  They must not be used for any
 * other purpose.
 */
extern void macTaskInit(uint8 taskId);
extern uint16 macEventLoop(uint8 taskId, uint16 events);


extern void MAC_Init(void);


extern void MAC_InitDevice(void);

extern void MAC_InitCoord(void);

extern void MAC_InitSecurity(void);

extern void MAC_InitBeaconCoord(void);


extern void MAC_InitBeaconDevice(void);


extern void MAC_McpsDataReq(macMcpsDataReq_t *pData);

extern void MAC_McpsPurgeReq(uint8 msduHandle);

extern macMcpsDataReq_t *MAC_McpsDataAlloc(uint8 len, uint8 securityLevel, uint8 keyIdMode);

extern void MAC_MlmeAssociateReq(macMlmeAssociateReq_t *pData);

extern uint8 MAC_MlmeAssociateRsp(macMlmeAssociateRsp_t *pData);


extern void MAC_MlmeDisassociateReq(macMlmeDisassociateReq_t *pData);


extern uint8 MAC_MlmeGetReq(uint8 pibAttribute, void *pValue);


extern uint8 MAC_MlmeGetSecurityReq(uint8 pibAttribute, void *pValue);


extern void MAC_MlmeOrphanRsp(macMlmeOrphanRsp_t *pData);

extern void MAC_MlmePollReq(macMlmePollReq_t *pData);


extern uint8 MAC_MlmeResetReq(bool setDefaultPib);


extern void MAC_MlmeScanReq(macMlmeScanReq_t *pData);


extern uint8 MAC_MlmeSetReq(uint8 pibAttribute, void *pValue);

extern uint8 MAC_MlmeSetSecurityReq(uint8 pibAttribute, void *pValue);


extern void MAC_MlmeStartReq(macMlmeStartReq_t *pData);

extern void MAC_MlmeSyncReq(macMlmeSyncReq_t *pData);


extern uint8 MAC_PwrOffReq(uint8 mode);

extern void MAC_PwrOnReq(void);

extern uint8 MAC_PwrMode(void);

extern uint32 MAC_PwrNextTimeout(void);

extern uint8 MAC_RandomByte(void);

extern uint8 MAC_SrcMatchEnable ( uint8 addrType, uint8 num  );

extern uint8 MAC_SrcMatchAddEntry ( sAddr_t *addr, uint16 panID );


extern uint8 MAC_SrcMatchDeleteEntry ( sAddr_t *addr, uint16 panID  );


extern void MAC_SrcMatchAckAllPending ( uint8 option  );


extern uint8 MAC_SrcMatchCheckAllPending ( void );


extern void MAC_SetRadioRegTable ( uint8 txPwrTblIdx, uint8 rssiAdjIdx );


extern void MAC_CbackEvent(macCbackEvent_t *pData);



extern uint8 MAC_CbackCheckPending(void);


#ifdef __cplusplus
};
#endif

#endif /* MAC_API_H */

Low Level

Common

mac_assert.h
#ifndef MAC_ASSERT_H
#define MAC_ASSERT_H

#include "hal_assert.h"
#ifdef MACNODEBUG
#define MAC_ASSERT(expr)
#define MAC_ASSERT_FORCED()
#define MAC_ASSERT_STATEMENT(statement)
#define MAC_ASSERT_DECLARATION(declaration)
#else
#define MAC_ASSERT(expr)                        HAL_ASSERT( expr )
#define MAC_ASSERT_FORCED()                     HAL_ASSERT_FORCED()
#define MAC_ASSERT_STATEMENT(statement)         HAL_ASSERT_STATEMENT( statement )
#define MAC_ASSERT_DECLARATION(declaration)     HAL_ASSERT_DECLARATION( declaration )
#endif
#endif
mac_autopend.c
#include "mac_api.h"
#include "mac_radio_defs.h"

/* osal */
#include "OSAL.h"
#include "saddr.h"
#include "ZComDef.h"

#include "mac_autopend.h"

#define MAC_SRCMATCH_INVALID_INDEX           0xFF

#define MAC_SRCMATCH_SHORT_ENTRY_SIZE        4
#define MAC_SRCMATCH_EXT_ENTRY_SIZE          Z_EXTADDR_LEN

#define MAC_SRCMATCH_SHORT_MAX_NUM_ENTRIES   24
#define MAC_SRCMATCH_EXT_MAX_NUM_ENTRIES     12

#define MAC_SRCMATCH_ENABLE_BITMAP_LEN       3

bool macSrcMatchIsEnabled = FALSE; 

uint8 macSrcMatchMaxNumEntries = 0;   
uint8 macSrcMatchAddrMode = SADDR_MODE_SHORT;  
bool macSrcMatchIsAckAllPending = FALSE;

static uint8 macSrcMatchFindEmptyEntry( void );
static uint8 macSrcMatchCheckSrcAddr ( sAddr_t *addr, uint16 panID  );
static void macSrcMatchSetPendEnBit( uint8 index );
static void macSrcMatchSetEnableBit( uint8 index, bool option );
static bool macSrcMatchCheckEnableBit( uint8 index );
static uint24 macSrcMatchGetEnableBit( void );
static uint24 macSrcMatchGetPendEnBit( void );

uint8 MAC_SrcMatchEnable ( uint8 addrType, uint8 num  )
{
  uint8 rtn;
  uint8 maxNum;
    
  /* Verify the address type */
  if( addrType != SADDR_MODE_SHORT && addrType != SADDR_MODE_EXT )
  {
    return MAC_INVALID_PARAMETER;
  }
  
  maxNum = ( addrType == SADDR_MODE_SHORT ) ? 
           MAC_SRCMATCH_SHORT_MAX_NUM_ENTRIES : MAC_SRCMATCH_EXT_MAX_NUM_ENTRIES;
           
  if( num > maxNum )
  {
    rtn = MAC_INVALID_PARAMETER;
    num = maxNum;
  }
  else
  {
    rtn = MAC_SUCCESS;
  }
    
  /* Turn on Frame Filter (TIMAC enables frame filter by default), TBD */
  MAC_RADIO_TURN_ON_RX_FRAME_FILTERING();
  
  /* Turn on Auto ACK (TIMAC turn on Auto ACK by default), TBD */
  MAC_RADIO_TURN_ON_AUTO_ACK();
  
  /* Turn on Autopend: set SRCMATCH.AUTOPEND and SRCMATCH.SRC_MATCH_EN */
  MAC_RADIO_TURN_ON_SRC_MATCH();
 
  /* Set SRCMATCH.AUTOPEND */
  MAC_RADIO_TURN_ON_AUTOPEND();
  
  /* Configure all the globals */
  macSrcMatchIsEnabled = TRUE;
  macSrcMatchMaxNumEntries = num;
  macSrcMatchAddrMode = addrType;           

  return rtn;
}


uint8 MAC_SrcMatchAddEntry ( sAddr_t *addr, uint16 panID )
{
  uint8 index;
  uint8 entry[MAC_SRCMATCH_SHORT_ENTRY_SIZE];
  
  /* Check if the input parameters are valid */
  if ( addr == NULL || addr->addrMode != macSrcMatchAddrMode )
  {
    return MAC_INVALID_PARAMETER;  
  }
  
  /* Check if the entry already exists. Do not add duplicated entry */
  if ( macSrcMatchCheckSrcAddr( addr, panID ) != MAC_SRCMATCH_INVALID_INDEX )
  {
    return MAC_DUPLICATED_ENTRY; 
  }
  
  /* If not duplicated, write to the radio RAM and enable the control bit */
  
  /* Find the first empty entry */
  index = macSrcMatchFindEmptyEntry();
  if ( index == macSrcMatchMaxNumEntries )
  {
    return MAC_NO_RESOURCES;   /* Table is full */
  }
  
  if ( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    /* Write the PanID and short address */
    entry[0] = LO_UINT16( panID );  /* Little Endian for the radio RAM */
    entry[1] = HI_UINT16( panID );
    entry[2] = LO_UINT16( addr->addr.shortAddr );
    entry[3] = HI_UINT16( addr->addr.shortAddr );
    MAC_RADIO_SRC_MATCH_TABLE_WRITE( ( index * MAC_SRCMATCH_SHORT_ENTRY_SIZE ), 
                   entry, MAC_SRCMATCH_SHORT_ENTRY_SIZE );
  }
  else
  {
    /* Write the extended address */
    MAC_RADIO_SRC_MATCH_TABLE_WRITE( ( index * MAC_SRCMATCH_EXT_ENTRY_SIZE ), 
                   addr->addr.extAddr, MAC_SRCMATCH_EXT_ENTRY_SIZE ); 
  }
  
  /* Set the Autopend enable bits */
  macSrcMatchSetPendEnBit( index );
  
  /* Set the Src Match enable bits */
  macSrcMatchSetEnableBit( index, TRUE );
  
  return MAC_SUCCESS;
}

uint8 MAC_SrcMatchDeleteEntry ( sAddr_t *addr, uint16 panID  )
{
  uint8 index;
  
  if ( addr == NULL || addr->addrMode != macSrcMatchAddrMode )
  {
    return MAC_INVALID_PARAMETER;  
  }
  
  /* Look up the source address table and find the entry. */
  index = macSrcMatchCheckSrcAddr( addr, panID );

  if( index == MAC_SRCMATCH_INVALID_INDEX )
  {
    return MAC_INVALID_PARAMETER; 
  }
  
  /* Clear Src Match enable bits */
  macSrcMatchSetEnableBit( index, FALSE );

  return MAC_SUCCESS;
}
                  

void MAC_SrcMatchAckAllPending ( uint8 option  ) 
{
  if( option == TRUE )
  {
    macSrcMatchIsAckAllPending = TRUE;
    
    /* Set the PENDING_OR register */
    MAC_RADIO_TURN_ON_PENDING_OR();
  }
  else
  {
    macSrcMatchIsAckAllPending = FALSE;
    
    /* Clear the PENDING_OR register */
    MAC_RADIO_TURN_OFF_PENDING_OR();
  }
}


uint8 MAC_SrcMatchCheckAllPending ( void )
{
  if( macSrcMatchIsAckAllPending == TRUE )
  {
    return MAC_AUTOACK_PENDING_ALL_ON; 
  }
  
  return MAC_AUTOACK_PENDING_ALL_OFF;
}

MAC_INTERNAL_API bool MAC_SrcMatchCheckResult( void )
{
  uint8 resIndex;
  
  if ( macSrcMatchIsAckAllPending )
  {
    return (TRUE);
  }
  
  MAC_RADIO_SRC_MATCH_RESINDEX( resIndex );
  
  return ( resIndex & AUTOPEND_RES );
}


static uint8 macSrcMatchFindEmptyEntry( void )
{
  uint8  index;
  uint24 enable;
     
  enable = MAC_RADIO_SRC_MATCH_GET_EN();
        
  if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    for( index = 0; index < macSrcMatchMaxNumEntries; index++ )
    {  
      if( ( enable & ( (uint24)0x01 << index ) ) == 0 )
      {
        return index;
      }
    }
  }
  else
  {
    for( index = 0; index < macSrcMatchMaxNumEntries; index++ )
    {  
      if( ( enable & ( (uint24)0x01 << ( index * 2 ) ) ) == 0 )
      {
        return index;
      }
    }
  }
  
  /* 
   The value of index shall be macSrcMatchMaxNumEntries when it executes
   here. The table is full.
  */
  return index;
}

static uint8 macSrcMatchCheckSrcAddr ( sAddr_t *addr, uint16 panID  )
{
  uint8 index;     
  uint8 *pAddr;
  uint8 entrySize;
  uint8 entry[MAC_SRCMATCH_SHORT_ENTRY_SIZE];  
  uint8 ramEntry[MAC_SRCMATCH_EXT_ENTRY_SIZE];
      
  /*
   Currently, shadow memory is not supported to optimize SPI traffic.
  */
  
  if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    entry[0] = LO_UINT16( panID );  /* Little Endian for the radio RAM */
    entry[1] = HI_UINT16( panID );
    entry[2] = LO_UINT16( addr->addr.shortAddr );
    entry[3] = HI_UINT16( addr->addr.shortAddr );
    pAddr = entry;
    entrySize = MAC_SRCMATCH_SHORT_ENTRY_SIZE;
  }
  else
  {
    pAddr = addr->addr.extAddr;
    entrySize = MAC_SRCMATCH_EXT_ENTRY_SIZE;
  }
  
  for( index = 0; index < macSrcMatchMaxNumEntries; index++ )
  {
    /* Check if the entry is enabled */
    if( macSrcMatchCheckEnableBit( index ) == FALSE )
    {
      continue; 
    }
      
    /* Compare the short address and pan ID */
    MAC_RADIO_SRC_MATCH_TABLE_READ( ( index * entrySize ), ramEntry, entrySize );
     
    if( osal_memcmp( pAddr, ramEntry, entrySize ) == TRUE )
    {
      /* Match found */
      return index;
    }
  }
  
  return MAC_SRCMATCH_INVALID_INDEX;
}


static void macSrcMatchSetPendEnBit( uint8 index )
{
  uint24 enable;
  uint8 buf[MAC_SRCMATCH_ENABLE_BITMAP_LEN];
       
  enable = MAC_RADIO_SRC_MATCH_GET_PENDEN(); 
      
  if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    enable |= ( (uint24)0x01 << index );
    osal_buffer_uint24( buf, enable );
    MAC_RADIO_SRC_MATCH_SET_SHORTPENDEN( buf );
  }
  else
  {
    enable |= ( (uint24)0x01 << ( index * 2 ) );
    osal_buffer_uint24( buf, enable );
    MAC_RADIO_SRC_MATCH_SET_EXTPENDEN( buf );
  }
}


static void macSrcMatchSetEnableBit( uint8 index, bool option )
{
  uint24 enable;  
  
  enable = MAC_RADIO_SRC_MATCH_GET_EN(); 
      
  if( option == TRUE )
  {
    if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
    {
      enable |= ( (uint24)0x01 << index );
      MAC_RADIO_SRC_MATCH_SET_SHORTEN( enable );
    }
    else
    {
      enable |= ( (uint24)0x01 << ( index * 2 ) );
      MAC_RADIO_SRC_MATCH_SET_EXTEN( enable );
    }
  }
  else
  {
    if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
    {
      enable &= ~( (uint24)0x01 << index );
      MAC_RADIO_SRC_MATCH_SET_SHORTEN( enable );
    }
    else
    {
      enable &= ~( (uint24)0x01 << ( index * 2 ) );
      MAC_RADIO_SRC_MATCH_SET_EXTEN( enable );
    }
  }
}

static bool macSrcMatchCheckEnableBit( uint8 index )
{
  uint24 enable;
  
  if( macSrcMatchAddrMode == SADDR_MODE_EXT )
  {
    index *= 2;
  }
  
  enable = MAC_RADIO_SRC_MATCH_GET_EN();
     
  if( enable & ( (uint24)0x01 << index ) )
  {
    return TRUE;
  }

  return FALSE; 
}
 

static uint24 macSrcMatchGetEnableBit( void )
{ 
  uint8 buf[MAC_SRCMATCH_ENABLE_BITMAP_LEN];
  
  if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    MAC_RADIO_GET_SRC_SHORTEN( buf );
  }
  else
  {
    MAC_RADIO_GET_SRC_EXTEN( buf );
  }
  
  return osal_build_uint32( buf, MAC_SRCMATCH_ENABLE_BITMAP_LEN );
}
static uint24 macSrcMatchGetPendEnBit( void )
{
  uint8 buf[MAC_SRCMATCH_ENABLE_BITMAP_LEN];

  if( macSrcMatchAddrMode == SADDR_MODE_SHORT )
  {
    MAC_RADIO_GET_SRC_SHORTPENDEN( buf );
  }
  else
  {
    MAC_RADIO_GET_SRC_EXTENPEND( buf );
  }
  
  return osal_build_uint32( buf, MAC_SRCMATCH_ENABLE_BITMAP_LEN );
}

mac_autopend.h
#ifndef MAC_AUTOPEND_H
#define MAC_AUTOPEND_H
#include "mac_high_level.h"

extern bool macSrcMatchIsEnabled;

MAC_INTERNAL_API bool MAC_SrcMatchCheckResult(void);

#endif // MAC_AUTOPEND_H
mac_backoff timer.c
#include "hal_types.h"
#include "hal_mcu.h"

/* high-level specific */
#include "mac_spec.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_backoff_timer.h"
#include "mac_tx.h"

/* target specific */
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"

#define COMPARE_STATE_ROLLOVER_BV                 BV(0)
#define COMPARE_STATE_TRIGGER_BV                  BV(1)
#define COMPARE_STATE_ARM_BV                      BV(2)

#define COMPARE_STATE_TRIGGER                     COMPARE_STATE_TRIGGER_BV
#define COMPARE_STATE_ROLLOVER                    COMPARE_STATE_ROLLOVER_BV
#define COMPARE_STATE_ROLLOVER_AND_TRIGGER        (COMPARE_STATE_ROLLOVER_BV | COMPARE_STATE_TRIGGER_BV)
#define COMPARE_STATE_ROLLOVER_AND_ARM_TRIGGER    (COMPARE_STATE_ROLLOVER_BV | COMPARE_STATE_ARM_BV)


#define RX_TX_PROP_DELAY_AVG_USEC         ((MAC_RADIO_RX_TX_PROP_DELAY_MIN_USEC + MAC_RADIO_RX_TX_PROP_DELAY_MAX_USEC) / 2)
#define RX_TX_PROP_DELAY_AVG_TIMER_TICKS  ((uint16)(MAC_RADIO_TIMER_TICKS_PER_USEC() * RX_TX_PROP_DELAY_AVG_USEC + 0.5))

#define SYMBOLS_FROM_STROBE_TO_PREAMBLE   12 /* from datasheet */
#define SYMBOLS_FROM_PREAMBLE_TO_SFD      (MAC_SPEC_PREAMBLE_FIELD_LENGTH + MAC_SPEC_SFD_FIELD_LENGTH)
#define SYMBOLS_FROM_STROBE_TO_SFD        (SYMBOLS_FROM_STROBE_TO_PREAMBLE + SYMBOLS_FROM_PREAMBLE_TO_SFD)
#define SYMBOLS_EXPECTED_AT_SFD           (SYMBOLS_FROM_STROBE_TO_SFD % MAC_A_UNIT_BACKOFF_PERIOD)

/* after all that formal math, make sure the result is as expected */
#if (SYMBOLS_EXPECTED_AT_SFD != 2)
#error "ERROR! Internal problem with pre-processor math of slotted alignment."
#endif

#define TIMER_TICKS_EXPECTED_AT_SFD   ((SYMBOLS_EXPECTED_AT_SFD * MAC_RADIO_TIMER_TICKS_PER_SYMBOL()) \
                                          + RX_TX_PROP_DELAY_AVG_TIMER_TICKS)


static uint32 backoffTimerRollover;
static uint32 backoffTimerTrigger;

MAC_INTERNAL_API void macBackoffTimerInit(void)
{
  MAC_RADIO_BACKOFF_SET_COUNT(0);
  macBackoffTimerSetRollover(MAC_BACKOFF_TIMER_DEFAULT_ROLLOVER);
  MAC_RADIO_BACKOFF_PERIOD_CLEAR_INTERRUPT();
  MAC_RADIO_BACKOFF_PERIOD_ENABLE_INTERRUPT();
  MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT();
  MAC_RADIO_BACKOFF_COMPARE_ENABLE_INTERRUPT();
}


MAC_INTERNAL_API void macBackoffTimerReset(void)
{
  MAC_RADIO_BACKOFF_COMPARE_DISABLE_INTERRUPT();
  MAC_RADIO_BACKOFF_PERIOD_DISABLE_INTERRUPT();
  macBackoffTimerInit();
}

MAC_INTERNAL_API void macBackoffTimerSetRollover(uint32 rolloverBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(rolloverBackoff > MAC_RADIO_BACKOFF_COUNT());  /* rollover value must be greater than count */

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerRollover = rolloverBackoff;
  MAC_RADIO_BACKOFF_SET_PERIOD(rolloverBackoff);
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API void macBackoffTimerSetCount(uint32 backoff)
{
  halIntState_t  s;

  MAC_ASSERT(backoff < backoffTimerRollover);  /* count must be less than rollover value */
  MAC_ASSERT(!(backoff & 0x80000000));  /* count must not represent negative value for int32 */

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_RADIO_BACKOFF_SET_COUNT(backoff);
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API uint32 macBackoffTimerCount(void)
{
  halIntState_t  s;
  uint32 backoffCount;

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffCount = MAC_RADIO_BACKOFF_COUNT();
  HAL_EXIT_CRITICAL_SECTION(s);
  
#ifdef MAC_RADIO_FEATURE_HARDWARE_OVERFLOW_NO_ROLLOVER
 
  if (backoffCount >= backoffTimerRollover)
  {
    return(0);
  }
#endif
  
  return(backoffCount);
}


MAC_INTERNAL_API uint32 macBackoffTimerCapture(void)
{
  halIntState_t  s;
  uint32 backoffCapture;

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffCapture = MAC_RADIO_BACKOFF_CAPTURE();
  HAL_EXIT_CRITICAL_SECTION(s);

#ifdef MAC_RADIO_FEATURE_HARDWARE_OVERFLOW_NO_ROLLOVER
 
  if (backoffCapture >= backoffTimerRollover)
  {
    return(0);
  }
#endif
  
  return(backoffCapture);
}


MAC_INTERNAL_API uint32 macBackoffTimerGetTrigger(void)
{
  return(backoffTimerTrigger);
}

MAC_INTERNAL_API void macBackoffTimerSetTrigger(uint32 triggerBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(triggerBackoff < backoffTimerRollover); /* trigger backoff must be less than rollover backoff */

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerTrigger = triggerBackoff;
  MAC_RADIO_BACKOFF_SET_COMPARE(triggerBackoff);
  if (triggerBackoff == MAC_RADIO_BACKOFF_COUNT())
  {
    /* Clear the interrupt and fire it manually */
    MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT();
    HAL_EXIT_CRITICAL_SECTION(s);
    macBackoffTimerTriggerCallback();
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}

MAC_INTERNAL_API void macBackoffTimerCancelTrigger(void)
{
  /* Stub for high level MAC */
}


MAC_INTERNAL_API int32 macBackoffTimerRealign(macRx_t *pMsg)
{
  uint16 timerDelayTicks;
  int32 backoffDelta;
  int32 backoffCount;

  MAC_ASSERT(!MAC_TX_IS_PHYSICALLY_ACTIVE()); /* realignment during actual transmit corrupts timing */


  /* since expected receive time is zero, the delta is simply the receive time */
  backoffDelta = pMsg->mac.timestamp;

  /* if the frame was received more than halfway to the rollover count, use a negative delta value */
  if (((uint32) backoffDelta) > (backoffTimerRollover / 2))
  {
    backoffDelta = backoffDelta - backoffTimerRollover;    /* result will be negative */
  }

  /* retrieve the timer count when frame was received */
  timerDelayTicks = pMsg->mac.timestamp2;


  if (timerDelayTicks >= TIMER_TICKS_EXPECTED_AT_SFD)
  {
    /* since delay count is greater than or equal to offset, subtract it directly */
    timerDelayTicks = timerDelayTicks - TIMER_TICKS_EXPECTED_AT_SFD;
  }
  else
  {
  
    timerDelayTicks = timerDelayTicks - TIMER_TICKS_EXPECTED_AT_SFD + MAC_RADIO_TIMER_TICKS_PER_BACKOFF();
    backoffDelta--;
  }

  
  backoffCount = MAC_RADIO_BACKOFF_COUNT() - backoffDelta;

  if (backoffCount >= ((int32) backoffTimerRollover))
  {
    backoffCount -= backoffTimerRollover;
  }
  else if (backoffCount < 0)
  {
    backoffCount += backoffTimerRollover;
  }

  MAC_RADIO_TIMER_FORCE_DELAY(timerDelayTicks);
  MAC_RADIO_BACKOFF_SET_COUNT(backoffCount);

  return(backoffDelta);
}

MAC_INTERNAL_API void macBackoffTimerCompareIsr(void)
{
  macBackoffTimerTriggerCallback();
}

MAC_INTERNAL_API void macBackoffTimerPeriodIsr(void)
{
  macMcuAccumulatedOverFlow();
  macBackoffTimerRolloverCallback();
}

MAC_INTERNAL_API uint32 macGetBackOffTimerRollover(void)
{
  return backoffTimerRollover;
}
mac_backoff timer.h
#ifndef MAC_BACKOFF_TIMER_H
#define MAC_BACKOFF_TIMER_H
#include "mac_high_level.h"
MAC_INTERNAL_API void macBackoffTimerInit(void);
MAC_INTERNAL_API void macBackoffTimerReset(void);
MAC_INTERNAL_API uint32 macBackoffTimerCapture(void);
MAC_INTERNAL_API void macBackoffTimerCompareIsr(void);
MAC_INTERNAL_API void macBackoffTimerPeriodIsr(void);
MAC_INTERNAL_API uint32 macGetBackOffTimerRollover(void);
#endif
mac_low_level.c
#include "hal_types.h"
#include "hal_mcu.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_radio.h"
#include "mac_rx.h"
#include "mac_tx.h"
#include "mac_rx_onoff.h"
#include "mac_backoff_timer.h"
#include "mac_sleep.h"

/* target specific */
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"

#if !defined ( HAL_CLOCK_CRYSTAL )
/* DCO has a frequency error of 2% */
const uint16 CODE macBeaconMarginDCO[] =
{
  3,
  3,
  4,
  8,
  16,
  31,
  62,
  123,
  246,
  492,
  983,
  1967,
  3933,
  7865,
  15729,
  0
};
#endif

MAC_INTERNAL_API void macLowLevelInit(void)
{
  /* initialize mcu before anything else */
  MAC_RADIO_MCU_INIT();

  /* initialize (override) beacon margin timing table */
#if !defined ( HAL_CLOCK_CRYSTAL )
  {
    uint8 i;

    for (i = 0; i < sizeof(macBeaconMarginDCO)/sizeof(macBeaconMarginDCO[0]); i++)
    {
      macBeaconMargin[i] = macBeaconMarginDCO[i];
    }
  }
#endif

  /* software initialziation */
  macRadioInit();
  macRxOnOffInit();
  macRxInit();
  macTxInit();
  macBackoffTimerInit();
}


MAC_INTERNAL_API void macLowLevelReset(void)
{
  MAC_ASSERT(!HAL_INTERRUPTS_ARE_ENABLED());   /* interrupts must be disabled */

  /* reset radio modules;  if not awake, skip this */
  if (macSleepState == MAC_SLEEP_STATE_AWAKE)
  {
    macRxTxReset();
    macRadioReset();
  }

  /* reset timer */
  macBackoffTimerReset();

  /* power up the radio */
  macSleepWakeUp();
}

mac_low_level.h

#ifndef MAC_LOW_LEVEL_H
#define MAC_LOW_LEVEL_H

#include "hal_types.h"
#include "mac_high_level.h"

/* identifies low-level code as specific to Chipcon SmartRF03(tm) technology */
#define MAC_LOW_LEVEL_SMARTRF04

#define MAC_BACKOFF_TIMER_DEFAULT_ROLLOVER  (((uint32) MAC_A_BASE_SUPERFRAME_DURATION) << 14)

/* macTxFrame() parameter values for txType */
#define MAC_TX_TYPE_SLOTTED_CSMA            0x00
#define MAC_TX_TYPE_UNSLOTTED_CSMA          0x01
#define MAC_TX_TYPE_SLOTTED                 0x02

/* macSleep() parameter values for sleepState */
#define MAC_SLEEP_STATE_OSC_OFF             0x01
#define MAC_SLEEP_STATE_RADIO_OFF           0x02

/* macRxPromiscuousMode() parameter values */
#define MAC_PROMISCUOUS_MODE_OFF            0x00  /* must be zero; reserved for boolean use */
#define MAC_PROMISCUOUS_MODE_COMPLIANT      0x01
#define MAC_PROMISCUOUS_MODE_WITH_BAD_CRC   0x02

extern uint8 const macTxSlottedDelay;

/* beacon interval margin */
extern uint16 macBeaconMargin[];

/* mac_low_level.c */
MAC_INTERNAL_API void macLowLevelInit(void);
MAC_INTERNAL_API void macLowLevelReset(void);

/* mac_sleep.c */
MAC_INTERNAL_API void macSleepWakeUp(void);
MAC_INTERNAL_API uint8 macSleep(uint8 sleepState);

/* mac_radio.c */
MAC_INTERNAL_API uint8 macRadioRandomByte(void);
MAC_INTERNAL_API void macRadioSetPanCoordinator(uint8 panCoordinator);
MAC_INTERNAL_API void macRadioSetPanID(uint16 panID);
MAC_INTERNAL_API void macRadioSetShortAddr(uint16 shortAddr);
MAC_INTERNAL_API void macRadioSetIEEEAddr(uint8 * pIEEEAddr);
MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower);
MAC_INTERNAL_API void macRadioSetChannel(uint8 channel);
MAC_INTERNAL_API void macRadioStartScan(uint8 scanType);
MAC_INTERNAL_API void macRadioStopScan(void);
void macRadioEnergyDetectStart(void);
uint8 macRadioEnergyDetectStop(void);

/* mac_backoff_timer.c */
MAC_INTERNAL_API void macBackoffTimerSetRollover(uint32 rolloverBackoff);
MAC_INTERNAL_API void macBackoffTimerSetCount(uint32 backoff);
MAC_INTERNAL_API uint32 macBackoffTimerCount(void);
MAC_INTERNAL_API uint32 macBackoffTimerGetTrigger(void);
MAC_INTERNAL_API void macBackoffTimerSetTrigger(uint32 triggerBackoff);
MAC_INTERNAL_API void macBackoffTimerCancelTrigger(void);
MAC_INTERNAL_API void macBackoffTimerTriggerCallback(void);
MAC_INTERNAL_API void macBackoffTimerRolloverCallback(void);
MAC_INTERNAL_API int32 macBackoffTimerRealign(macRx_t *pMsg);

/* mac_tx.c */
MAC_INTERNAL_API void macTxFrame(uint8 txType);
MAC_INTERNAL_API void macTxFrameRetransmit(void);
MAC_INTERNAL_API void macTxCompleteCallback(uint8 status);

/* mac_rx.c */
MAC_INTERNAL_API bool macRxCheckPendingCallback(void);
MAC_INTERNAL_API bool macRxCheckMACPendingCallback(void);
MAC_INTERNAL_API void macRxCompleteCallback(macRx_t * pMsg);
MAC_INTERNAL_API void macRxPromiscuousMode(uint8 mode);

/* mac_rx_onoff.c */
MAC_INTERNAL_API void macRxEnable(uint8 flags);
MAC_INTERNAL_API void macRxSoftEnable(uint8 flags);
MAC_INTERNAL_API void macRxDisable(uint8 flags);
MAC_INTERNAL_API void macRxHardDisable(void);
#endif

mac_radio.c
#include "hal_types.h"

/* high-level */
#include "mac_pib.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_radio.h"
#include "mac_tx.h"
#include "mac_rx.h"
#include "mac_rx_onoff.h"
#include "mac_sleep.h"
#include "mac_backoff_timer.h"

/* target specific */
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"


#define ED_RF_POWER_MIN_DBM   (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY)
#define ED_RF_POWER_MAX_DBM   MAC_RADIO_RECEIVER_SATURATION_DBM

uint8 macPhyTxPower;
uint8 macPhyChannel;

static uint8 reqChannel;
static uint8 reqTxPower;

static uint8 radioComputeED(int8 rssiDbm);

MAC_INTERNAL_API void macRadioInit(void)
{
  /* variable initialization for this module */
  reqChannel    = MAC_RADIO_CHANNEL_DEFAULT;
  macPhyChannel = MAC_RADIO_CHANNEL_INVALID;
  reqTxPower    = MAC_RADIO_TX_POWER_INVALID;
  macPhyTxPower = MAC_RADIO_TX_POWER_INVALID;
}

MAC_INTERNAL_API void macRadioReset(void)
{
  macRadioStopScan();
  macRadioEnergyDetectStop();
}

MAC_INTERNAL_API uint8 macRadioRandomByte(void)
{
  return(MAC_RADIO_RANDOM_BYTE());
}

MAC_INTERNAL_API void macRadioSetPanCoordinator(uint8 panCoordFlag)
{
  /* abstracted radio configuration */
  MAC_RADIO_SET_PAN_COORDINATOR(panCoordFlag);
}


void macRadioSetPanID(uint16 panID)
{
  /* abstracted radio configuration */
  MAC_RADIO_SET_PAN_ID(panID);
}

MAC_INTERNAL_API void macRadioSetShortAddr(uint16 shortAddr)
{
  /* abstracted radio configuration */
  MAC_RADIO_SET_SHORT_ADDR(shortAddr);
}

MAC_INTERNAL_API void macRadioSetIEEEAddr(uint8 * pIEEEAddr)
{
  /* abstracted radio configuration */
  MAC_RADIO_SET_IEEE_ADDR(pIEEEAddr);
}

#ifndef HAL_MAC_USE_REGISTER_POWER_VALUES


MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
{
  halIntState_t  s;
#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590
  const uint8 CODE *pTable = macRadioDefsTxPwrTables[macRadioDefsRefTableId >> 4];
#elif defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
  const uint8 CODE *pTable = macRadioDefsTxPwrTables[0];
#else
  const uint8 CODE *pTable = macRadioDefsTxPwrBare;
#endif

  /* if the selected dBm is out of range, use the closest available */
  if ((int8)txPower > (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY])
  {
    /* greater than base value -- out of table range */
    txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY];
  }
  else if ((int8)txPower < (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY])
  {
    /* smaller than the lowest power level -- out of table range */
    txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY];
  }

  HAL_ENTER_CRITICAL_SECTION(s);
  /* When calculating index to the power register value table,
   * either txPower (of uint8 type) has to be explicitly type-casted to int8
   * or the subtraction expression has to be type-casted to uint8 to work
   * with the integral promotions.
   * The latter is more code size efficient and hence the latter is used.
   */
  {
    uint8 index = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY] - txPower
      + MAC_RADIO_DEFS_TBL_TXPWR_ENTRIES;
    reqTxPower = pTable[index];
  }
  HAL_EXIT_CRITICAL_SECTION(s);

  /* update the radio power setting */
  macRadioUpdateTxPower();

  return txPower;
}

#else


MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
{
  halIntState_t  s;

  /* same as above but with no lookup table, use raw register value */
  HAL_ENTER_CRITICAL_SECTION(s);
  reqTxPower = txPower;
  HAL_EXIT_CRITICAL_SECTION(s);

  /* update the radio power setting */
  macRadioUpdateTxPower();

  return txPower;
}

#endif

MAC_INTERNAL_API void macRadioUpdateTxPower(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (reqTxPower != macPhyTxPower)
  {
   
    if (!macRxOutgoingAckFlag && !MAC_TX_IS_PHYSICALLY_ACTIVE())
    {

      macPhyTxPower = reqTxPower;
      MAC_RADIO_SET_TX_POWER(macPhyTxPower);
    }
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macRadioSetChannel(uint8 channel)
{
  halIntState_t  s;

  MAC_ASSERT((channel >= 11) && (channel <= 28));  /* illegal channel */

  /* critical section to make sure transmit does not start while updating channel */
  HAL_ENTER_CRITICAL_SECTION(s);

  /* set requested channel */
  reqChannel = channel;

  if (!macTxActive)
  {
    macRadioUpdateChannel();
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macRadioUpdateChannel(void)
{
  halIntState_t  s;

  MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */

  /* if the channel has changed, set the radio to the new channel */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (reqChannel != macPhyChannel)
  {
    macPhyChannel = reqChannel;
    HAL_EXIT_CRITICAL_SECTION(s);

    /* changing the channel stops any receive in progress */
    macRxOff();
    MAC_RADIO_SET_CHANNEL(macPhyChannel);

    macRxHaltCleanup();

    macRxOnRequest();
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}


MAC_INTERNAL_API void macRadioStartScan(uint8 scanMode)
{
  MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake */
  MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* all filtering must be off to start scan */

  /* set the receive filter based on the selected scan mode */
  if (scanMode == MAC_SCAN_ED)
  {
    macRxFilter = RX_FILTER_ALL;
  }
  else if (scanMode == MAC_SCAN_ORPHAN)
  {
    macRxFilter = RX_FILTER_NON_COMMAND_FRAMES;
  }
  else
  {
    MAC_ASSERT((scanMode == MAC_SCAN_ACTIVE) || (scanMode == MAC_SCAN_PASSIVE)); /* invalid scan type */
    macRxFilter = RX_FILTER_NON_BEACON_FRAMES;

    /* for active and passive scans, per spec the pan ID must be 0xFFFF */
    MAC_RADIO_SET_PAN_ID(0xFFFF);
  }
}


MAC_INTERNAL_API void macRadioStopScan(void)
{
  macRxFilter = RX_FILTER_OFF;

  /* restore the pan ID (passive and active scans set pan ID to 0xFFFF) */
  MAC_RADIO_SET_PAN_ID(macPib.panId);
}

void macRadioEnergyDetectStart(void)
{
  /* Energy Detection Scan should be run with CC2591 compresson workaround off */
  COMPRESSION_WORKAROUND_OFF();

  MAC_RADIO_RECORD_MAX_RSSI_START();
}


uint8 macRadioEnergyDetectStop(void)
{
  uint8 rssiDbm;
  uint8 energyDetectMeasurement;

  rssiDbm = MAC_RADIO_RECORD_MAX_RSSI_STOP() + MAC_RADIO_RSSI_OFFSET;
  MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
  energyDetectMeasurement = radioComputeED(rssiDbm);

  /* Trun on CC2591 compresson workaround */
  COMPRESSION_WORKAROUND_ON();

  return(energyDetectMeasurement);
}

static uint8 radioComputeED(int8 rssiDbm)
{
  uint8 ed;

  if (rssiDbm < ED_RF_POWER_MIN_DBM)
  {
    rssiDbm = ED_RF_POWER_MIN_DBM;
  }
  else if (rssiDbm > ED_RF_POWER_MAX_DBM)
  {
    rssiDbm = ED_RF_POWER_MAX_DBM;
  }

  ed = (MAC_SPEC_ED_MAX * (rssiDbm - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);

  return(ed);
}


MAC_INTERNAL_API uint8 macRadioComputeLQI(int8 rssiDbm, uint8 corr)
{
  (void) corr; /* suppress compiler warning of unused parameter */

  return(radioComputeED(rssiDbm));
}
mac_radio.h
#ifndef MAC_RADIO_H
#define MAC_RADIO_H

#include "hal_types.h"
#include "mac_high_level.h"
extern uint8 macPhyChannel;
extern uint8 macPhyTxPower;
MAC_INTERNAL_API void macRadioInit(void);
MAC_INTERNAL_API void macRadioReset(void);
MAC_INTERNAL_API void macRadioUpdateTxPower(void);
MAC_INTERNAL_API void macRadioUpdateChannel(void);
MAC_INTERNAL_API uint8 macRadioComputeLQI(int8 rssiDbm, uint8 correlation);
#endif
mac_rx.c
#include "hal_defs.h"
#include "hal_types.h"

/* OSAL */
#include "OSAL.h"

/* high-level */
#include "mac_high_level.h"
#include "mac_spec.h"

/* MAC security */
#include "mac_security.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_rx.h"
#include "mac_tx.h"
#include "mac_rx_onoff.h"
#include "mac_radio.h"

/* target specific */
#include "mac_radio_defs.h"
#include "mac_autopend.h"

/* debug */
#include "mac_assert.h"


#define MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT   16   /* adjustable to tune performance */

/* receive FIFO bytes needed to start a valid receive (see function rxStartIsr for details) */
#define RX_THRESHOLD_START_LEN    (MAC_PHY_PHR_LEN        +  \
                                   MAC_FCF_FIELD_LEN      +  \
                                   MAC_SEQ_NUM_FIELD_LEN  +  \
                                   MAC_FCS_FIELD_LEN)

/* maximum size of addressing fields (note: command frame identifier processed as part of address) */
#define MAX_ADDR_FIELDS_LEN  ((MAC_EXT_ADDR_FIELD_LEN + MAC_PAN_ID_FIELD_LEN) * 2)

/* addressing mode reserved value */
#define ADDR_MODE_RESERVERED  1

/* length of command frame identifier */
#define CMD_FRAME_ID_LEN      1

/* packet size mask is equal to the maximum value */
#define PHY_PACKET_SIZE_MASK  0x7F

/* value for promiscuous off, must not conflict with other mode variants from separate include files */
#define PROMISCUOUS_MODE_OFF  0x00

/* bit of proprietary FCS format that indicates if the CRC is OK */
#define PROPRIETARY_FCS_CRC_OK_BIT  0x80

/* dummy length value for unused entry in lookup table */
#define DUMMY_LEN   0xBE

/* value for rxThresholdIntState */
#define RX_THRESHOLD_INT_STATE_INACTIVE   0
#define RX_THRESHOLD_INT_STATE_ACTIVE     1
#define RX_THRESHOLD_INT_STATE_RESET      2


#define MEM_ALLOC(x)   macDataRxMemAlloc(x)
#define MEM_FREE(x)    macDataRxMemFree((uint8 **)x)

#define INTERNAL_FCF_FLAGS(p)  ((((p)[1] >> 4) & 0x03) | ((p)[0] & 0x78))

#define PROPRIETARY_FCS_RSSI(p)                 ((int8)((p)[0]))
#define PROPRIETARY_FCS_CRC_OK(p)               ((p)[1] & PROPRIETARY_FCS_CRC_OK_BIT)
#define PROPRIETARY_FCS_CORRELATION_VALUE(p)    ((p)[1] & ~PROPRIETARY_FCS_CRC_OK_BIT)

#define SECURITY_LEVEL(s)                       (s & 0x07)
#define KEY_IDENTIFIER_MODE(s)                  ((s & 0x18) >> 3)
#define SECURITY_CONTROL_RESERVED(s)            ((s & 0xE0) >> 5)


uint8 macRxActive;
uint8 macRxFilter;
uint8 macRxOutgoingAckFlag;

static const uint8 CODE macRxAddrLen[] =
{
  0,                                                /* no address */
  DUMMY_LEN,                                        /* reserved */
  MAC_PAN_ID_FIELD_LEN + MAC_SHORT_ADDR_FIELD_LEN,  /* short address + pan id */
  MAC_PAN_ID_FIELD_LEN + MAC_EXT_ADDR_FIELD_LEN     /* extended address + pan id */
};

static void rxHaltCleanupFinalStep(void);

static void rxStartIsr(void);
static void rxAddrIsr(void);

#ifdef MAC_SECURITY
  static void rxSecurityHdrIsr(void);
#endif
  
static void rxPayloadIsr(void);
static void rxDiscardIsr(void);
static void rxFcsIsr(void);

static void rxPrepPayload(void);
static void rxDiscardFrame(void);
static void rxDone(void);
static void rxPostRxUpdates(void);

static void    (* pFuncRxState)(void);
static macRx_t  * pRxBuf;

static uint8  rxBuf[MAC_PHY_PHR_LEN + MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN];
static uint8  rxUnreadLen;
static uint8  rxNextLen;
static uint8  rxPayloadLen;
static uint8  rxFilter;
static uint8  rxPromiscuousMode;
static uint8  rxIsrActiveFlag;
static uint8  rxResetFlag;
static uint8  rxFifoOverflowCount;

#ifdef PACKET_FILTER_STATS
  uint32      rxCrcFailure = 0;
  uint32      rxCrcSuccess = 0;
#endif /* PACKET_FILTER_STATS */

#ifdef CC2591_COMPRESSION_WORKAROUND
  void macRxResetRssi(void);
#endif

MAC_INTERNAL_API void macRxInit(void)
{
  macRxFilter          = RX_FILTER_OFF;
  rxPromiscuousMode    = PROMISCUOUS_MODE_OFF;
  pRxBuf               = NULL; /* required for macRxReset() to function correctly */
  macRxActive          = MAC_RX_ACTIVE_NO_ACTIVITY;
  pFuncRxState         = &rxStartIsr;
  macRxOutgoingAckFlag = 0;
  rxIsrActiveFlag      = 0;
  rxResetFlag          = 0;
  rxFifoOverflowCount  = 0;
}


MAC_INTERNAL_API void macRxRadioPowerUpInit(void)
{
  /* set threshold at initial value */
  MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);

  /* clear any accidental threshold interrupt that happened as part of power up sequence */
  MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();

  /* enable threshold interrupts */
  MAC_RADIO_ENABLE_RX_THRESHOLD_INTERRUPT();
}


MAC_INTERNAL_API void macRxTxReset(void)
{
  /* forces receiver off, cleans up by calling macRxHaltCleanup() and macTxHaltCleanup() */
  macRxHardDisable();


  /* restore deault filter mode to off */
  macRxFilter = RX_FILTER_OFF;

  /* return promiscuous mode to default off state */
  macRxPromiscuousMode(MAC_PROMISCUOUS_MODE_OFF);
}

MAC_INTERNAL_API void macRxHaltCleanup(void)
{
  rxResetFlag = 1;
  if (!rxIsrActiveFlag)
  {
    rxHaltCleanupFinalStep();
    rxResetFlag = 0;
  }
}


static void rxHaltCleanupFinalStep(void)
{
  /* cancel any upcoming ACK transmit complete callback */
  MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();

  /* set start of frame threshold */
  MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);

  /* flush the receive FIFO */
  MAC_RADIO_FLUSH_RX_FIFO();

  /* clear any receive interrupt that happened to squeak through */
  MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();

  /* if data buffer has been allocated, free it */
  if (pRxBuf != NULL)
  {
    MEM_FREE((uint8 **)&pRxBuf);
  }
  /* MEM_FREE() sets parameter to NULL. */

  pFuncRxState = &rxStartIsr;

  /* if receive was active, perform the post receive updates */
  if (macRxActive || macRxOutgoingAckFlag)
  {
    macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;
    macRxOutgoingAckFlag = 0;

    rxPostRxUpdates();
  }
}


MAC_INTERNAL_API void macRxThresholdIsr(void)
{
  /* if currently reseting, do not execute receive ISR logic */
  if (rxResetFlag)
  {
    return;
  }

  rxIsrActiveFlag = 1;
  (*pFuncRxState)();
  rxIsrActiveFlag = 0;

  /* if a reset occurred during the ISR, peform cleanup here */
  if (rxResetFlag)
  {
    rxHaltCleanupFinalStep();
    rxResetFlag = 0;
  }
}


static void rxStartIsr(void)
{
  uint8  addrLen;
  uint8  ackWithPending;
  uint8  dstAddrMode;
  uint8  srcAddrMode;
  uint8  mhrLen = 0;

  MAC_ASSERT(!macRxActive); /* receive on top of receive */

  /* indicate rx is active */
  macRxActive = MAC_RX_ACTIVE_STARTED;

  if (!macRxOnFlag || MAC_RADIO_RX_FIFO_IS_EMPTY())
  {
    /* reset active flag */
    macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;

    rxPostRxUpdates();

    /* return immediately from here */
    return;
  }

 
  MAC_RADIO_FORCE_TX_DONE_IF_PENDING();

  MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
  macRxOutgoingAckFlag = 0;

  rxFilter = macRxFilter;


  /* read frame length, frame control field, and sequence number from FIFO */
  MAC_RADIO_READ_RX_FIFO(rxBuf, MAC_PHY_PHR_LEN + MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN);

  /* bytes to read from FIFO equals frame length minus length of MHR fields just read from FIFO */
  rxUnreadLen = (rxBuf[0] & PHY_PACKET_SIZE_MASK) - MAC_FCF_FIELD_LEN - MAC_SEQ_NUM_FIELD_LEN;

  if (macChipVersion == REV_A)
  {
    if ((rxUnreadLen > (MAC_A_MAX_PHY_PACKET_SIZE - MAC_FCF_FIELD_LEN - MAC_SEQ_NUM_FIELD_LEN)) ||
        (MAC_FRAME_TYPE(&rxBuf[1]) > MAC_FRAME_TYPE_MAX_VALID))
    {
      MAC_RADIO_FLUSH_RX_FIFO();
      rxDone();
      return;
    }
  }
  else
  {
    /* radio supplied a corrupted receive buffer length */
    MAC_ASSERT(rxUnreadLen <= (MAC_A_MAX_PHY_PACKET_SIZE - MAC_FCF_FIELD_LEN - MAC_SEQ_NUM_FIELD_LEN));
  }


  if ((MAC_FRAME_TYPE(&rxBuf[1]) == MAC_FRAME_TYPE_ACK) && (rxPromiscuousMode == PROMISCUOUS_MODE_OFF))
  {
    halIntState_t  s;
    uint8 fcsBuf[MAC_FCF_FIELD_LEN];
   

    /* read FCS from FIFO (threshold set so bytes are guaranteed to be there) */
    MAC_RADIO_READ_RX_FIFO(fcsBuf, MAC_FCS_FIELD_LEN);

  
    HAL_ENTER_CRITICAL_SECTION(s);

    /* see if transmit is listening for an ACK */
    if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
    {
      MAC_ASSERT(pMacDataTx != NULL); /* transmit buffer must be present */

      /* record link quality metrics for the receive ACK */
      {
        int8 rssiDbm;
        uint8 corr;

        rssiDbm = PROPRIETARY_FCS_RSSI(fcsBuf) + MAC_RADIO_RSSI_OFFSET;
        MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
        corr = PROPRIETARY_FCS_CORRELATION_VALUE(fcsBuf);

        pMacDataTx->internal.mpduLinkQuality = macRadioComputeLQI(rssiDbm, corr);
        pMacDataTx->internal.correlation = corr;
        pMacDataTx->internal.rssi= rssiDbm;
      }

      HAL_EXIT_CRITICAL_SECTION(s);

      
      if (PROPRIETARY_FCS_CRC_OK(fcsBuf))
      {
        /* call transmit logic to indicate ACK was received */
        macTxAckReceivedCallback(MAC_SEQ_NUMBER(&rxBuf[1]), MAC_FRAME_PENDING(&rxBuf[1]));
      }
      else
      {
        macTxAckNotReceivedCallback();
      }
    }
    else
    {
      HAL_EXIT_CRITICAL_SECTION(s);
    }

    /* receive is done, exit from here */
    rxDone();
    return;
  }
  else if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxAckNotReceivedCallback();
  }

  if ((rxFilter != RX_FILTER_OFF) && !rxPromiscuousMode)
  {
    if (/* filter all frames */
         (rxFilter == RX_FILTER_ALL) ||

         /* filter non-beacon frames */
         ((rxFilter == RX_FILTER_NON_BEACON_FRAMES) &&
          (MAC_FRAME_TYPE(&rxBuf[1]) != MAC_FRAME_TYPE_BEACON)) ||

         /* filter non-command frames */
         ((rxFilter == RX_FILTER_NON_COMMAND_FRAMES) &&
          ((MAC_FRAME_TYPE(&rxBuf[1]) != MAC_FRAME_TYPE_COMMAND))))
    {
      /* discard rest of frame */
      rxDiscardFrame();
      return;
    }
  }


  /* decode addressing modes */
  dstAddrMode = MAC_DEST_ADDR_MODE(&rxBuf[1]);
  srcAddrMode = MAC_SRC_ADDR_MODE(&rxBuf[1]);

  if (macChipVersion == REV_A)
  {
    if ((srcAddrMode == ADDR_MODE_RESERVERED) || (dstAddrMode == ADDR_MODE_RESERVERED))
    {
      MAC_RADIO_FLUSH_RX_FIFO();
      rxDone();
      return;
    }
  }

  addrLen = macRxAddrLen[dstAddrMode] + macRxAddrLen[srcAddrMode];
  if ((srcAddrMode != SADDR_MODE_NONE) && MAC_INTRA_PAN(&rxBuf[1]))
  {
    addrLen -= MAC_PAN_ID_FIELD_LEN;
  }

 
  if ((addrLen + MAC_FCS_FIELD_LEN) > rxUnreadLen)
  {
    /* discard frame and exit */
    rxDiscardFrame();
    return;
  }

  rxPayloadLen = rxUnreadLen - addrLen - MAC_FCS_FIELD_LEN;

  if (MAC_SEC_ENABLED(&rxBuf[1]))
  {
    /* increase the allocation size of MAC header for security */
    mhrLen = MAC_MHR_LEN;
  }

  pRxBuf = (macRx_t *) MEM_ALLOC(sizeof(macRx_t) + mhrLen + rxPayloadLen);
  if (pRxBuf == NULL)
  {
    /* Cancel the outgoing TX ACK */
    MAC_RADIO_CANCEL_TX_ACK();

    /* buffer allocation failed, discard the frame and exit*/
    rxDiscardFrame();
    return;
  }

  ackWithPending = 0;
  if (!rxPromiscuousMode)
  {
    macRxOutgoingAckFlag = MAC_ACK_REQUEST(&rxBuf[1]);
  }


  if (macRxOutgoingAckFlag)
  {
    halIntState_t  s;

    HAL_ENTER_CRITICAL_SECTION(s);

    /* Do not ack data packet with pending more data */
    if( MAC_FRAME_TYPE(&rxBuf[1]) == MAC_FRAME_TYPE_COMMAND )
    {
      if( macRxCheckMACPendingCallback())
      {
        /* Check is any mac data pending for end devices */
        ackWithPending = MAC_RX_FLAG_ACK_PENDING;
      }
      else
      {
        if( macSrcMatchIsEnabled )
        {
          /* When autopend is enabled, check if allpending is set to true */
          if( MAC_SrcMatchCheckAllPending() == MAC_AUTOACK_PENDING_ALL_ON )
          {
            ackWithPending = MAC_RX_FLAG_ACK_PENDING;
          }
        }
        else
        {
          /* When autopend is disabled, check the application pending callback */
          if( macRxCheckPendingCallback() )
          {
            ackWithPending = MAC_RX_FLAG_ACK_PENDING;
          }
        }
      }
    }

    if( ackWithPending == MAC_RX_FLAG_ACK_PENDING )
    {
      MAC_RADIO_TX_ACK_PEND();
    }
    else
    {
      MAC_RADIO_TX_ACK();
    }


    /* request a callback to macRxAckTxDoneCallback() when the ACK transmit has finished */
    MAC_RADIO_REQUEST_ACK_TX_DONE_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);
  }


  pRxBuf->mhr.p   = pRxBuf->msdu.p   = (uint8 *) (pRxBuf + 1);
  pRxBuf->mhr.len = pRxBuf->msdu.len =  rxPayloadLen;

  if (MAC_SEC_ENABLED(&rxBuf[1]))
  {
    /* Copy FCF and sequence number to RX buffer */
    pRxBuf->mhr.len = MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN;
    osal_memcpy(pRxBuf->mhr.p, &rxBuf[1], pRxBuf->mhr.len);
    pRxBuf->mhr.p += pRxBuf->mhr.len;
  }

  /* set internal values */
  pRxBuf->mac.srcAddr.addrMode  = srcAddrMode;
  pRxBuf->mac.dstAddr.addrMode  = dstAddrMode;
  pRxBuf->mac.timestamp         = MAC_RADIO_BACKOFF_CAPTURE();
  pRxBuf->mac.timestamp2        = MAC_RADIO_TIMER_CAPTURE();
  pRxBuf->internal.frameType    = MAC_FRAME_TYPE(&rxBuf[1]);
  pRxBuf->mac.dsn               = MAC_SEQ_NUMBER(&rxBuf[1]);
  pRxBuf->internal.flags        = INTERNAL_FCF_FLAGS(&rxBuf[1]) | ackWithPending;

  if (addrLen == 0)
  {
    /* no addressing fields to read, prepare for payload interrupts */
    pFuncRxState = &rxPayloadIsr;
    rxPrepPayload();
  }
  else
  {
    /* need to read and process addressing fields, prepare for address interrupt */
    rxNextLen = addrLen;
    if (MAC_SEC_ENABLED(&rxBuf[1]))
    {
      /* When security is enabled, read off security control field as well */
      MAC_RADIO_SET_RX_THRESHOLD(rxNextLen + MAC_SEC_CONTROL_FIELD_LEN);
    }
    else
    {
      MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
    }
    pFuncRxState = &rxAddrIsr;
  }
}


static void rxAddrIsr(void)
{
  uint8 buf[MAX_ADDR_FIELDS_LEN];
  uint8 dstAddrMode;
  uint8 srcAddrMode;
#ifdef MAC_SECURITY  
  uint8 securityControl;
#endif /* MAC_SECURITY */  
  uint8  * p;

  MAC_ASSERT(rxNextLen != 0); /* logic assumes at least one address byte in buffer */

  /*  read out address fields into local buffer in one shot */
  MAC_RADIO_READ_RX_FIFO(buf, rxNextLen);

  /* set pointer to buffer with addressing fields */
  p = buf;

  /* destination address */
  dstAddrMode = MAC_DEST_ADDR_MODE(&rxBuf[1]);
  if (dstAddrMode != SADDR_MODE_NONE)
  {
    pRxBuf->mac.srcPanId = pRxBuf->mac.dstPanId = BUILD_UINT16(p[0], p[1]);
    p += MAC_PAN_ID_FIELD_LEN;
    if (dstAddrMode == SADDR_MODE_EXT)
    {
      sAddrExtCpy(pRxBuf->mac.dstAddr.addr.extAddr, p);
      p += MAC_EXT_ADDR_FIELD_LEN;
    }
    else
    {
      pRxBuf->mac.dstAddr.addr.shortAddr = BUILD_UINT16(p[0], p[1]);
      p += MAC_SHORT_ADDR_FIELD_LEN;
    }
  }

  /* sources address */
  srcAddrMode = MAC_SRC_ADDR_MODE(&rxBuf[1]);
  if (srcAddrMode != SADDR_MODE_NONE)
  {
    if (!(pRxBuf->internal.flags & MAC_RX_FLAG_INTRA_PAN))
    {
      pRxBuf->mac.srcPanId = BUILD_UINT16(p[0], p[1]);
      p += MAC_PAN_ID_FIELD_LEN;
    }
    if (srcAddrMode == SADDR_MODE_EXT)
    {
      sAddrExtCpy(pRxBuf->mac.srcAddr.addr.extAddr, p);
    }
    else
    {
      pRxBuf->mac.srcAddr.addr.shortAddr = BUILD_UINT16(p[0], p[1]);
    }
  }

#ifdef MAC_SECURITY
  if (MAC_SEC_ENABLED(&rxBuf[1]))
  {
    uint8 keyIdMode;

    if (MAC_FRAME_VERSION(&rxBuf[1]) == 0)
    {
      /* MAC_UNSUPPORTED_LEGACY - Cancel the outgoing TX ACK.
       * It may be too late but we have to try.
       */
      MAC_RADIO_CANCEL_TX_ACK();

      /* clean up after unsupported security legacy */
      macRxHaltCleanup();
      return;
    }

    /* Copy addressing fields to RX buffer */
    osal_memcpy(pRxBuf->mhr.p, buf, rxNextLen);
    pRxBuf->mhr.p   += rxNextLen;
    pRxBuf->mhr.len += rxNextLen;

    /* read out security control field from FIFO (threshold set so bytes are guaranteed to be there) */
    MAC_RADIO_READ_RX_FIFO(&securityControl, MAC_SEC_CONTROL_FIELD_LEN);

    /* Copy security fields to MHR buffer */
    *pRxBuf->mhr.p   = securityControl;
    pRxBuf->mhr.p   += MAC_SEC_CONTROL_FIELD_LEN;
    pRxBuf->mhr.len += MAC_SEC_CONTROL_FIELD_LEN;

    /* store security level and key ID mode */
    pRxBuf->sec.securityLevel = SECURITY_LEVEL(securityControl);
    pRxBuf->sec.keyIdMode = keyIdMode = KEY_IDENTIFIER_MODE(securityControl);

    /* Corrupted RX frame, should never occur. */
    if ((keyIdMode > MAC_KEY_ID_MODE_8)
 
    || ((macKeySourceLen[keyIdMode] + MAC_FRAME_COUNTER_LEN) >= rxPayloadLen)
   
    || (pRxBuf->sec.securityLevel == MAC_SEC_LEVEL_NONE))
    {
      /* It may be too late but we have to try. */
      MAC_RADIO_CANCEL_TX_ACK();

      /* clean up after unsupported security or corrupted RX frame. */
      macRxHaltCleanup();
      return;
    }


    rxNextLen = macKeySourceLen[keyIdMode] + MAC_FRAME_COUNTER_LEN;
    MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
    pFuncRxState = &rxSecurityHdrIsr;
  }
  else
#endif /* MAC_SECURITY */
  {
    /* clear security level */
    pRxBuf->sec.securityLevel = MAC_SEC_LEVEL_NONE;

    pFuncRxState = &rxPayloadIsr;
    rxPrepPayload();
  }
}


#ifdef MAC_SECURITY

static void rxSecurityHdrIsr(void)
{
  uint8 buf[MAC_FRAME_COUNTER_LEN + MAC_KEY_ID_8_LEN];

  /* read out frame counter and key ID */
  MAC_RADIO_READ_RX_FIFO(buf, rxNextLen);

  /* Incoming frame counter */
  macFrameCounter = BUILD_UINT32(buf[0], buf[1], buf[2], buf[3]);
  if (rxNextLen - MAC_FRAME_COUNTER_LEN > 0)
  {
    /* Explicit mode */
    osal_memcpy(pRxBuf->sec.keySource, &buf[MAC_FRAME_COUNTER_LEN], rxNextLen - MAC_FRAME_COUNTER_LEN - 1);
    pRxBuf->sec.keyIndex = buf[rxNextLen - MAC_KEY_INDEX_LEN];
  }

  /* Copy security fields to RX buffer */
  osal_memcpy(pRxBuf->mhr.p, buf, rxNextLen);
  pRxBuf->mhr.p   += rxNextLen;
  pRxBuf->mhr.len += rxNextLen;

  rxPayloadLen    -= (rxNextLen + MAC_SEC_CONTROL_FIELD_LEN);
  pRxBuf->msdu.len = rxPayloadLen;
  pRxBuf->mhr.len += rxPayloadLen;

  pFuncRxState = &rxPayloadIsr;
  rxPrepPayload();
}
#endif /* MAC_SECURITY */

static void rxPrepPayload(void)
{
  if (rxPayloadLen == 0)
  {
    MAC_RADIO_SET_RX_THRESHOLD(MAC_FCS_FIELD_LEN);
    pFuncRxState = &rxFcsIsr;
  }
  else
  {
    rxNextLen = MIN(rxPayloadLen, MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT);
    MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
  }
}


static void rxPayloadIsr(void)
{
  MAC_RADIO_READ_RX_FIFO(pRxBuf->mhr.p, rxNextLen);
  pRxBuf->mhr.p += rxNextLen;

  rxPayloadLen -= rxNextLen;

  rxPrepPayload();
}


static void rxFcsIsr(void)
{
  uint8 crcOK;
  uint8 ackWithPending = 0;

  /* read FCS, rxBuf is now available storage */
  MAC_RADIO_READ_RX_FIFO(rxBuf, MAC_FCS_FIELD_LEN);


  /* save the "CRC-is-OK" status */
  crcOK = PROPRIETARY_FCS_CRC_OK(rxBuf);

  if (crcOK || (rxPromiscuousMode == MAC_PROMISCUOUS_MODE_WITH_BAD_CRC))
  {
    int8 rssiDbm;
    uint8 corr;

#ifdef PACKET_FILTER_STATS
    rxCrcSuccess++;
#endif /* PACKET_FILTER_STATS */

    macRxActive = MAC_RX_ACTIVE_DONE;
    macRxOffRequest();

    /* decode RSSI and correlation values */
    rssiDbm = PROPRIETARY_FCS_RSSI(rxBuf) + MAC_RADIO_RSSI_OFFSET;
    MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
    corr = PROPRIETARY_FCS_CORRELATION_VALUE(rxBuf);

    /* Read the source matching result back */
    if( macSrcMatchIsEnabled && MAC_RADIO_SRC_MATCH_RESULT() )
    {
      /* This result will not overwrite the previously determined pRxBuf->internal.flags */
      ackWithPending = MAC_RX_FLAG_ACK_PENDING;
    }

    /* record parameters that get passed up to high-level */
    pRxBuf->internal.flags |= ( crcOK | ackWithPending );
    pRxBuf->mac.mpduLinkQuality = macRadioComputeLQI(rssiDbm, corr);
    pRxBuf->mac.rssi = rssiDbm;
    pRxBuf->mac.correlation = corr;

    /* set the MSDU pointer to point at start of data */
    pRxBuf->mhr.p   = (uint8 *) (pRxBuf + 1);
    pRxBuf->msdu.p += (pRxBuf->mhr.len - pRxBuf->msdu.len);

    /* finally... execute callback function */
    macRxCompleteCallback(pRxBuf);
    pRxBuf = NULL; /* needed to indicate buffer is no longer allocated */
  }
  else
  {
#ifdef PACKET_FILTER_STATS
    rxCrcFailure++;
#endif /* PACKET_FILTER_STATS */

    MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
    macRxOutgoingAckFlag = 0;

    /* the CRC failed so the packet must be discarded */
    MEM_FREE((uint8 **)&pRxBuf);
    pRxBuf = NULL;  /* needed to indicate buffer is no longer allocated */
  }

  /* reset threshold level, reset receive state, and complete receive logic */
  MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
  pFuncRxState = &rxStartIsr;
  rxDone();
}

static void rxDone(void)
{
  /* Make sure the peak RSSI is reset */
  COMPRESSION_WORKAROUND_RESET_RSSI();
  
  /* if the receive FIFO has overflowed, flush it here */
  if (MAC_RADIO_RX_FIFO_HAS_OVERFLOWED())
  {
    MAC_RADIO_FLUSH_RX_FIFO();
  }

  /* mark receive as inactive */
  macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;

  /* if there is no outgoing ACK, run the post receive updates */
  if (!macRxOutgoingAckFlag)
  {
    rxPostRxUpdates();
  }
}

void macRxAckTxDoneCallback(void)
{
  macRxOutgoingAckFlag = 0;

  if (!macRxActive)
  {
    rxPostRxUpdates();
  }
}

static void rxPostRxUpdates(void)
{
  /* turn off receiver if permitted */
  macRxOffRequest();

  /* update the transmit power, update may have been blocked by transmit of outgoing ACK */
  macRadioUpdateTxPower();

  /* initiate and transmit that was queued during receive */
  macTxStartQueuedFrame();
}

static void rxDiscardFrame(void)
{
  MAC_ASSERT(pFuncRxState == &rxStartIsr); /* illegal state for calling discard frame function */

  if (rxUnreadLen == 0)
  {
    rxDone();
  }
  else
  {
    rxNextLen = MIN(rxUnreadLen, MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT);
    MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
    pFuncRxState = &rxDiscardIsr;
  }
}


static void rxDiscardIsr(void)
{
  uint8 buf[MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT];

  MAC_RADIO_READ_RX_FIFO(buf, rxNextLen);
  rxUnreadLen -= rxNextLen;

  /* read out and discard bytes until all bytes of packet are disposed of */
  if (rxUnreadLen != 0)
  {
    if (rxUnreadLen < MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT)
    {
      rxNextLen = rxUnreadLen;
      MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
    }
  }
  else
  {
    /* reset threshold level, reset receive state, and complete receive logic */
    MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
    pFuncRxState = &rxStartIsr;
    rxDone();
  }
}


MAC_INTERNAL_API void macRxFifoOverflowIsr(void)
{
  rxFifoOverflowCount++; /* This flag is used for debug purpose only */
  macRxHaltCleanup();
}


MAC_INTERNAL_API void macRxPromiscuousMode(uint8 mode)
{
  rxPromiscuousMode = mode;

  if (rxPromiscuousMode == MAC_PROMISCUOUS_MODE_OFF)
  {
    MAC_RADIO_TURN_ON_RX_FRAME_FILTERING();
  }
  else
  {
    MAC_ASSERT((mode == MAC_PROMISCUOUS_MODE_WITH_BAD_CRC)   ||
               (mode == MAC_PROMISCUOUS_MODE_COMPLIANT));  /* invalid mode */

    MAC_RADIO_TURN_OFF_RX_FRAME_FILTERING();
  }
}

#ifdef CC2591_COMPRESSION_WORKAROUND

void macRxResetRssi(void)
{
  if ( !(macRxActive || macRxOutgoingAckFlag || macTxActive) )
  {
    COMPRESSION_WORKAROUND_RESET_RSSI();
  }
}
#endif /* CC2591_COMPRESSION_WORKAROUND */

/* check for changes to the spec that would affect the source code */
#if ((MAC_A_MAX_PHY_PACKET_SIZE   !=  0x7F )   ||  \
     (MAC_FCF_FIELD_LEN           !=  2    )   ||  \
     (MAC_FCF_FRAME_TYPE_POS      !=  0    )   ||  \
     (MAC_FCF_FRAME_PENDING_POS   !=  4    )   ||  \
     (MAC_FCF_ACK_REQUEST_POS     !=  5    )   ||  \
     (MAC_FCF_INTRA_PAN_POS       !=  6    )   ||  \
     (MAC_FCF_DST_ADDR_MODE_POS   !=  10   )   ||  \
     (MAC_FCF_FRAME_VERSION_POS   !=  12   )   ||  \
     (MAC_FCF_SRC_ADDR_MODE_POS   !=  14   ))
#error "ERROR!  Change to the spec that requires modification of source code."
#endif

/* check for changes to the internal flags format */
#if ((MAC_RX_FLAG_VERSION      !=  0x03)  ||  \
     (MAC_RX_FLAG_ACK_PENDING  !=  0x04)  ||  \
     (MAC_RX_FLAG_SECURITY     !=  0x08)  ||  \
     (MAC_RX_FLAG_PENDING      !=  0x10)  ||  \
     (MAC_RX_FLAG_ACK_REQUEST  !=  0x20)  ||  \
     (MAC_RX_FLAG_INTRA_PAN    !=  0x40))
#error "ERROR!  Change to the internal RX flags format.  Requires modification of source code."
#endif

/* validate CRC OK bit optimization */
#if (MAC_RX_FLAG_CRC_OK != PROPRIETARY_FCS_CRC_OK_BIT)
#error "ERROR!  Optimization relies on these bits having the same position."
#endif

#if (MAC_RX_ACTIVE_NO_ACTIVITY != 0x00)
#error "ERROR! Zero is reserved value of macRxActive. Allows boolean operations, e.g !macRxActive."
#endif

#if (MAC_PROMISCUOUS_MODE_OFF != 0x00)
#error "ERROR! Zero is reserved value of rxPromiscuousMode. Allows boolean operations, e.g !rxPromiscuousMode."
#endif
mac_rx.h

#ifndef MAC_RX_H
#define MAC_RX_H

#include "hal_types.h"
#include "mac_high_level.h"

#define RX_FILTER_OFF                   0
#define RX_FILTER_ALL                   1
#define RX_FILTER_NON_BEACON_FRAMES     2
#define RX_FILTER_NON_COMMAND_FRAMES    3

/* bit value used to form values of macRxActive */
#define MAC_RX_ACTIVE_PHYSICAL_BV       0x80
#define MAC_RX_ACTIVE_NO_ACTIVITY       0x00  /* zero reserved for boolean use, e.g. !macRxActive */
#define MAC_RX_ACTIVE_STARTED           (0x01 | MAC_RX_ACTIVE_PHYSICAL_BV)
#define MAC_RX_ACTIVE_DONE              0x02
#define MAC_RX_IS_PHYSICALLY_ACTIVE()   ((macRxActive & MAC_RX_ACTIVE_PHYSICAL_BV) || macRxOutgoingAckFlag)
extern uint8 macRxActive;
extern uint8 macRxFilter;
extern uint8 macRxOutgoingAckFlag;

#ifdef PACKET_FILTER_STATS
  extern uint32 rxCrcFailure;
  extern uint32 rxCrcSuccess;
#endif /* PACKET_FILTER_STATS */

#ifdef CC2591_COMPRESSION_WORKAROUND
  extern void macRxResetRssi(void);
#endif

MAC_INTERNAL_API void macRxInit(void);
MAC_INTERNAL_API void macRxRadioPowerUpInit(void);
MAC_INTERNAL_API void macRxTxReset(void);
MAC_INTERNAL_API void macRxHaltCleanup(void);
MAC_INTERNAL_API void macRxThresholdIsr(void);
MAC_INTERNAL_API void macRxFifoOverflowIsr(void);
MAC_INTERNAL_API void macRxAckTxDoneCallback(void);
#endif

mac_rx_onoff.c
#include "hal_defs.h"
#include "hal_types.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_rx_onoff.h"
#include "mac_rx.h"
#include "mac_tx.h"
/* target specific */
#include "mac_radio_defs.h"
/* debug */
#include "mac_assert.h"
uint8 macRxOnFlag;
uint8 macRxEnableFlags;

MAC_INTERNAL_API void macRxOnOffInit(void)
{
  macRxEnableFlags = 0;
  macRxOnFlag = 0;
}

MAC_INTERNAL_API void macRxEnable(uint8 flags)
{
  halIntState_t  s;

  MAC_ASSERT(flags != 0); /* rx flags not affected */

  /* set enable flags and then turn on receiver */
  HAL_ENTER_CRITICAL_SECTION(s);
  macRxEnableFlags |= flags;
  macRxOn();
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API void macRxSoftEnable(uint8 flags)
{
  halIntState_t  s;

  MAC_ASSERT(flags != 0); /* rx flags not affected */

  /* set the enable flags but do not turn on the receiver */
  HAL_ENTER_CRITICAL_SECTION(s);
  macRxEnableFlags |= flags;
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API void macRxDisable(uint8 flags)
{
  halIntState_t  s;

  MAC_ASSERT(flags != 0); /* rx flags not affected */
  /* clear the indicated flags */
  HAL_ENTER_CRITICAL_SECTION(s);
  macRxEnableFlags &= (flags ^ 0xFF);
  HAL_EXIT_CRITICAL_SECTION(s);
  /* turn off the radio if it is allowed */
  macRxOffRequest();
}


MAC_INTERNAL_API void macRxHardDisable(void)
{
  halIntState_t  s;
  HAL_ENTER_CRITICAL_SECTION(s);

  macRxEnableFlags = 0;
  macRxOnFlag = 0;

  /* force receiver off */
  MAC_RADIO_RXTX_OFF();
  MAC_RADIO_FLUSH_RX_FIFO();
  MAC_DEBUG_TURN_OFF_RX_LED();

  HAL_EXIT_CRITICAL_SECTION(s);
  /* clean up after being forced off */
  macRxHaltCleanup();
}

MAC_INTERNAL_API void macRxOnRequest(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macRxEnableFlags)
  {
    macRxOn();
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API void macRxOffRequest(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (!macRxEnableFlags)
  {
    if (!MAC_RX_IS_PHYSICALLY_ACTIVE() && !MAC_TX_IS_PHYSICALLY_ACTIVE())
    {
      macRxOff();
    }
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macRxOn(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (!macRxOnFlag)
  {
    macRxOnFlag = 1;
    MAC_RADIO_RX_ON();
    MAC_DEBUG_TURN_ON_RX_LED();
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macRxOff(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macRxOnFlag)
  {
    macRxOnFlag = 0;
    MAC_RADIO_RXTX_OFF();
    MAC_DEBUG_TURN_OFF_RX_LED();
    
    /* just in case a receive was about to start, flush the receive FIFO */
    MAC_RADIO_FLUSH_RX_FIFO();

    /* clear any receive interrupt that happened to squeak through */
    MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();

  }
  HAL_EXIT_CRITICAL_SECTION(s);
}
mac_rx_onoff.h

#ifndef MAC_RX_ONOFF_H
#define MAC_RX_ONOFF_H

#include "hal_defs.h"
#include "hal_types.h"
#include "mac_high_level.h"

MAC_INTERNAL_API void macRxOnOffInit(void);
MAC_INTERNAL_API void macRxOnRequest(void);
MAC_INTERNAL_API void macRxOffRequest(void);
MAC_INTERNAL_API void macRxOn(void);
MAC_INTERNAL_API void macRxOff(void);

extern uint8 macRxOnFlag;
extern uint8 macRxEnableFlags;

/* debug macros */
#ifdef MAC_RX_ONOFF_DEBUG_LED
#include "hal_board.h"
#define MAC_DEBUG_TURN_ON_RX_LED()    HAL_TURN_ON_LED2()
#define MAC_DEBUG_TURN_OFF_RX_LED()   HAL_TURN_OFF_LED2()
#else
#define MAC_DEBUG_TURN_ON_RX_LED()
#define MAC_DEBUG_TURN_OFF_RX_LED()
#endif

/* interface macros */
#define MAC_RX_WAS_FORCED_OFF()     st( macRxOnFlag = 0; MAC_DEBUG_TURN_OFF_RX_LED(); )
#define MAC_RX_WAS_FORCED_ON()      st( macRxOnFlag = 1;  MAC_DEBUG_TURN_ON_RX_LED(); )
#endif
mac__sleep.c
#include "hal_types.h"
/* high-level */
#include "mac_pib.h"
/* exported low-level */
#include "mac_low_level.h"
/* low-level specific */
#include "mac_sleep.h"
#include "mac_radio.h"
#include "mac_tx.h"
#include "mac_rx.h"
#include "mac_rx_onoff.h"
/* target specific */
#include "mac_radio_defs.h"
/* debug */
#include "mac_assert.h"


uint8 macSleepState = MAC_SLEEP_STATE_RADIO_OFF;

MAC_INTERNAL_API void macSleepWakeUp(void)
{
  /* don't wake up radio if it's already awake */
  if (macSleepState == MAC_SLEEP_STATE_AWAKE)
  {
    return;
  }

  /* wake up MAC timer */
  MAC_RADIO_TIMER_WAKE_UP();

  /* if radio was completely off, restore from that state first */
  if (macSleepState == MAC_SLEEP_STATE_RADIO_OFF)
  {
    /* turn on radio power (turns on oscillator too) */
    MAC_RADIO_TURN_ON_POWER();

    /* power-up initialization of receive logic */
    macRxRadioPowerUpInit();
  }
  else
  {
    MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_OSC_OFF);

    /* turn on the oscillator */
    MAC_RADIO_TURN_ON_OSC();
  }

  /* update sleep state here before requesting to turn on receiver */
  macSleepState = MAC_SLEEP_STATE_AWAKE;

  /* turn on the receiver if enabled */
  macRxOnRequest();
}


MAC_INTERNAL_API uint8 macSleep(uint8 sleepState)
{
  halIntState_t  s;

  /* disable interrupts until macSleepState can be set */
  HAL_ENTER_CRITICAL_SECTION(s);

  /* assert checks */
  MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake to put it to sleep */
  MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* do not sleep when scanning or in promiscuous mode */

  /* if either RX or TX is active or any RX enable flags are set, it's not OK to sleep */
  if (macRxActive || macRxOutgoingAckFlag || macTxActive || macRxEnableFlags)
  {
    HAL_EXIT_CRITICAL_SECTION(s);
    return(FALSE);
  }

  /* turn off the receiver */
  macRxOff();
  /* update sleep state variable */
  macSleepState = sleepState;
  /* macSleepState is now set, re-enable interrupts */
  HAL_EXIT_CRITICAL_SECTION(s);
  /* put MAC timer to sleep */
  MAC_RADIO_TIMER_SLEEP();
  /* put radio in selected sleep mode */
  if (sleepState == MAC_SLEEP_STATE_OSC_OFF)
  {
    MAC_RADIO_TURN_OFF_OSC();
  }
  else
  {
    MAC_ASSERT(sleepState == MAC_SLEEP_STATE_RADIO_OFF); /* unknown sleep state */
    MAC_RADIO_TURN_OFF_POWER();
  }

  /* radio successfully entered sleep mode */
  return(TRUE);
}


#if ((MAC_SLEEP_STATE_AWAKE == MAC_SLEEP_STATE_OSC_OFF) ||  \
     (MAC_SLEEP_STATE_AWAKE == MAC_SLEEP_STATE_RADIO_OFF))
#error "ERROR!  Non-unique state values."
#endif
mac__sleep.h
#ifndef MAC_SLEEP_H
#define MAC_SLEEP_H
#include "hal_types.h"
#define MAC_SLEEP_STATE_AWAKE       0x00
extern uint8 macSleepState;
#endif
mac_tx.c
#include "hal_types.h"
#include "hal_defs.h"
#include "hal_mcu.h"
#include "hal_mac_cfg.h"

/* high-level */
#include "mac_spec.h"
#include "mac_pib.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_tx.h"
#include "mac_backoff_timer.h"
#include "mac_rx.h"
#include "mac_rx_onoff.h"
#include "mac_radio.h"
#include "mac_sleep.h"

/* target specific */
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"

#define MFR_LEN                   MAC_FCS_FIELD_LEN
#define PREPENDED_BYTE_LEN        1


#ifndef HAL_MAC_TX_SLOTTED_DELAY
#define HAL_MAC_TX_SLOTTED_DELAY    3
#endif
uint8 const macTxSlottedDelay = HAL_MAC_TX_SLOTTED_DELAY;

uint8 macTxActive;
uint8 macTxType;
uint8 macTxBe;
uint8 macTxCsmaBackoffDelay;

static uint8 nb;
static uint8 txSeqn;
static uint8 txAckReq;
static uint8 txRetransmitFlag;

static void txCsmaPrep(void);
static void txGo(void);
static void txCsmaGo(void);
static void txComplete(uint8 status);

MAC_INTERNAL_API void macTxInit(void)
{
  macTxActive      = MAC_TX_ACTIVE_NO_ACTIVITY;
  txRetransmitFlag = 0;
}


MAC_INTERNAL_API void macTxHaltCleanup(void)
{
  MAC_RADIO_TX_RESET();
  macTxInit();
}


MAC_INTERNAL_API void macTxFrame(uint8 txType)
{
  MAC_ASSERT(!macTxActive);            /* transmit on top of transmit */

  /* mark transmit as active */
  macTxActive = MAC_TX_ACTIVE_INITIALIZE;

  if (macSleepState != MAC_SLEEP_STATE_AWAKE)
  {
    /* notify high-level that transmit had to be aborted */
    txComplete(MAC_TX_ABORTED);

    /* exit from transmit logic */
    return;
  }

  /* save transmit type */
  macTxType = txType;

  if (macTxType == MAC_TX_TYPE_SLOTTED)
  {
    MAC_RADIO_TX_PREP_SLOTTED();
  }
  else
  {
    MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

    nb = 0;
    macTxBe = (pMacDataTx->internal.txOptions & MAC_TXOPTION_ALT_BE) ? macPib.altBe : macPib.minBe;

    if ((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) && (macPib.battLifeExt))
    {
      macTxBe = MIN(2, macTxBe);
    }

    txCsmaPrep();
  }

  if (!txRetransmitFlag)
  {
    uint8 * p;
    uint8   lenMhrMsdu;

    MAC_ASSERT(pMacDataTx != NULL); /* must have data to transmit */

    /* save needed parameters */
    txAckReq = MAC_ACK_REQUEST(pMacDataTx->msdu.p);
    txSeqn   = MAC_SEQ_NUMBER(pMacDataTx->msdu.p);

    /* set length of frame (note: use of term msdu is a misnomer, here it's actually mhr + msdu) */
    lenMhrMsdu = pMacDataTx->msdu.len;

    /* calling code guarantees an unused prepended byte  */
    p = pMacDataTx->msdu.p - PREPENDED_BYTE_LEN;

    /* first byte of buffer is length of MPDU */
    *p = lenMhrMsdu + MFR_LEN;

    MAC_RADIO_FLUSH_TX_FIFO();

    /* write bytes to FIFO, prepended byte is included, MFR is not (it's generated by hardware) */
    MAC_RADIO_WRITE_TX_FIFO(p, PREPENDED_BYTE_LEN + lenMhrMsdu);
  }


  {
    halIntState_t  s;

    HAL_ENTER_CRITICAL_SECTION(s);
    if (!macRxActive && !macRxOutgoingAckFlag)
    {
      macTxActive = MAC_TX_ACTIVE_GO;
      HAL_EXIT_CRITICAL_SECTION(s);
      txGo();
    }
    else
    {
      macTxActive = MAC_TX_ACTIVE_QUEUED;
      HAL_EXIT_CRITICAL_SECTION(s);
    }
  }
}

static void txCsmaPrep(void)
{
  macTxCsmaBackoffDelay = macRadioRandomByte() & ((1 << macTxBe) - 1);

  if (macTxType == MAC_TX_TYPE_SLOTTED_CSMA)
  {
    MAC_RADIO_TX_PREP_CSMA_SLOTTED();
  }
  else
  {
    MAC_RADIO_TX_PREP_CSMA_UNSLOTTED();
  }
}


static void txGo(void)
{
  MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
  macRxOutgoingAckFlag = 0;

  /* based on type of transmit, call the correct "go" functionality */
  if (macTxType == MAC_TX_TYPE_SLOTTED)
  {
    MAC_RADIO_TX_GO_SLOTTED();
  }
  else
  {
    txCsmaGo();
  }
}

static void txCsmaGo(void)
{
  COMPRESSION_WORKAROUND_OFF();

  if (macTxType == MAC_TX_TYPE_SLOTTED_CSMA)
  {
    if (macTxCsmaBackoffDelay >= macDataTxTimeAvailable())
    {
      txComplete(MAC_NO_TIME);
      return;
    }
    MAC_RADIO_TX_GO_SLOTTED_CSMA();
  }
  else
  {
    MAC_RADIO_TX_GO_CSMA();
  }
}

MAC_INTERNAL_API void macTxFrameRetransmit(void)
{
  txRetransmitFlag = 1;
  macTxFrame(macTxType);
}

MAC_INTERNAL_API void macTxStartQueuedFrame(void)
{
  halIntState_t  s;

  MAC_ASSERT(!macRxActive && !macRxOutgoingAckFlag); /* queued frames should not transmit in middle of a receive */

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_QUEUED)
  {
    macTxActive = MAC_TX_ACTIVE_GO;
    HAL_EXIT_CRITICAL_SECTION(s);
    txGo();
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}


MAC_INTERNAL_API void macTxChannelBusyCallback(void)
{
  MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

  /* turn off receiver if allowed */
  macTxActive = MAC_TX_ACTIVE_CHANNEL_BUSY;
  macRxOffRequest();

  /*  clear channel assement failed, follow through with CSMA algorithm */
  nb++;
  if (nb > macPib.maxCsmaBackoffs)
  {
    txComplete(MAC_CHANNEL_ACCESS_FAILURE);
  }
  else
  {
    macTxBe = MIN(macTxBe+1, macPib.maxBe);
    txCsmaPrep();
    macTxActive = MAC_TX_ACTIVE_GO;
    txCsmaGo();
  }
}

MAC_INTERNAL_API void macTxDoneCallback(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_GO)
  {
    /* see if ACK was requested */
    if (!txAckReq)
    {
      macTxActive = MAC_TX_ACTIVE_DONE;
      HAL_EXIT_CRITICAL_SECTION(s);

      /* ACK was not requested, transmit is complete */
      txComplete(MAC_SUCCESS);
    }
    else
    {
   
      macTxActive = MAC_TX_ACTIVE_LISTEN_FOR_ACK;
      MAC_RADIO_TX_REQUEST_ACK_TIMEOUT_CALLBACK();
      HAL_EXIT_CRITICAL_SECTION(s);
    }
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}

MAC_INTERNAL_API void macTxAckReceivedCallback(uint8 seqn, uint8 pendingFlag)
{
  halIntState_t  s;

  /* only process if listening for an ACK; critical section prevents race condition problems */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxActive = MAC_TX_ACTIVE_POST_ACK;
    MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);

    /* see if the sequence number of received ACK matches sequence number of packet just sent */
    if (seqn == txSeqn)
    {
      if (pendingFlag)
      {
        txComplete(MAC_ACK_PENDING);
      }
      else
      {
        txComplete(MAC_SUCCESS);
      }
    }
    else
    {
      /* sequence number did not match; per spec, transmit failed at this point */
      txComplete(MAC_NO_ACK);
    }
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}


MAC_INTERNAL_API void macTxAckNotReceivedCallback(void)
{
  halIntState_t  s;

  /* only process if listening for an ACK; critical section prevents race condition problems */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxActive = MAC_TX_ACTIVE_POST_ACK;
    MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);

    /* a non-ACK was received when expecting an ACK, per spec transmit is over at this point */
    txComplete(MAC_NO_ACK);
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}

static void txComplete(uint8 status)
{
  /* reset the retransmit flag */
  txRetransmitFlag = 0;

  /* update tx state; turn off receiver if nothing is keeping it on */
  macTxActive = MAC_TX_ACTIVE_NO_ACTIVITY;

  /* turn off receive if allowed */
  macRxOffRequest();

  /* update transmit power in case there was a change */
  macRadioUpdateTxPower();

  macRadioUpdateChannel();

  /* return status of transmit via callback function */
  macTxCompleteCallback(status);
}


MAC_INTERNAL_API void macTxTimestampCallback(void)
{
  MAC_ASSERT(pMacDataTx != NULL); /* transmit structure must be there */

  pMacDataTx->internal.timestamp  = macBackoffTimerCapture();
  pMacDataTx->internal.timestamp2 = MAC_RADIO_TIMER_CAPTURE();
}


MAC_INTERNAL_API void macTxCollisionWithRxCallback(void)
{
  macRxHaltCleanup();
}

#if (MAC_TX_ACTIVE_NO_ACTIVITY != 0x00)
#error "ERROR! Zero is reserved value of macTxActive. Allows boolean operations, e.g !macTxActive."
#endif
mac_tx.h
#ifndef MAC_TX_H
#define MAC_TX_H
#include "hal_types.h"
#include "mac_high_level.h"

/* bit value used to form values of macTxActive */
#define MAC_TX_ACTIVE_PHYSICALLY_BV      0x80

/* state values for macTxActive; note zero is reserved for inactive state */
#define MAC_TX_ACTIVE_NO_ACTIVITY           0x00 /* zero reserved for boolean use, e.g. !macTxActive */
#define MAC_TX_ACTIVE_INITIALIZE            0x01
#define MAC_TX_ACTIVE_QUEUED                0x02
#define MAC_TX_ACTIVE_GO                   (0x03 | MAC_TX_ACTIVE_PHYSICALLY_BV)
#define MAC_TX_ACTIVE_CHANNEL_BUSY          0x04
#define MAC_TX_ACTIVE_DONE                 (0x05 | MAC_TX_ACTIVE_PHYSICALLY_BV)
#define MAC_TX_ACTIVE_LISTEN_FOR_ACK       (0x06 | MAC_TX_ACTIVE_PHYSICALLY_BV)
#define MAC_TX_ACTIVE_POST_ACK             (0x07 | MAC_TX_ACTIVE_PHYSICALLY_BV)

#define MAC_TX_IS_PHYSICALLY_ACTIVE()       (macTxActive & MAC_TX_ACTIVE_PHYSICALLY_BV)


extern uint8 macTxActive;
extern uint8 macTxBe;
extern uint8 macTxType;
extern uint8 macTxCsmaBackoffDelay;


MAC_INTERNAL_API void macTxInit(void);
MAC_INTERNAL_API void macTxHaltCleanup(void);
MAC_INTERNAL_API void macTxStartQueuedFrame(void);
MAC_INTERNAL_API void macTxChannelBusyCallback(void);
MAC_INTERNAL_API void macTxDoneCallback(void);
MAC_INTERNAL_API void macTxAckReceivedCallback(uint8 seqn, uint8 pendingFlag);
MAC_INTERNAL_API void macTxAckNotReceivedCallback(void);
MAC_INTERNAL_API void macTxTimestampCallback(void);
MAC_INTERNAL_API void macTxCollisionWithRxCallback(void);
#endif

System

mac_csp_tx.c
#include "hal_types.h"
#include "hal_mcu.h"

/* high-level */
#include "mac_spec.h"
#include "mac_pib.h"

/* exported low-level */
#include "mac_low_level.h"

/* low-level specific */
#include "mac_csp_tx.h"
#include "mac_tx.h"
#include "mac_rx.h"
#include "mac_rx_onoff.h"

/* target specific */
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"


/* immediate strobe commands */
#define ISSTART     0xE1
#define ISSTOP      0xE2
#define ISCLEAR     0xFF

/* strobe processor instructions */
#define SKIP(s,c)   (0x00 | (((s) & 0x07) << 4) | ((c) & 0x0F))   /* skip 's' instructions if 'c' is true  */
#define WHILE(c)    SKIP(0,c)              /* pend while 'c' is true (derived instruction)        */
#define WAITW(w)    (0x80 | ((w) & 0x1F))  /* wait for 'w' number of MAC timer overflows          */
#define WEVENT1     (0xB8)                 /* wait for MAC timer compare                          */
#define WAITX       (0xBC)                 /* wait for CSPX number of MAC timer overflows         */
#define LABEL       (0xBB)                 /* set next instruction as start of loop               */
#define RPT(c)      (0xA0 | ((c) & 0x0F))  /* if condition is true jump to last label             */
#define INT         (0xBA)                 /* assert IRQ_CSP_INT interrupt                        */
#define INCY        (0xC1)                 /* increment CSPY                                      */
#define INCMAXY(m)  (0xC8 | ((m) & 0x07))  /* increment CSPY but not above maximum value of 'm'   */
#define DECY        (0xC4)                 /* decrement CSPY                                      */
#define DECZ        (0xC5)                 /* decrement CSPZ                                      */
#define RANDXY      (0xBD)                 /* load the lower CSPY bits of CSPX with random value  */

/* strobe processor command instructions */
#define SSTOP       (0xD2)    /* stop program execution                                      */
#define SNOP        (0xD0)    /* no operation                                                */
#define STXCAL      (0xDC)    /* enable and calibrate frequency synthesizer for TX           */
#define SRXON       (0xD3)    /* turn on receiver                                            */
#define STXON       (0xD9)    /* transmit after calibration                                  */
#define STXONCCA    (0xDA)    /* transmit after calibration if CCA indicates clear channel   */
#define SRFOFF      (0xDF)    /* turn off RX/TX                                              */
#define SFLUSHRX    (0xDD)    /* flush receive FIFO                                          */
#define SFLUSHTX    (0xDE)    /* flush transmit FIFO                                         */
#define SACK        (0xD6)    /* send ACK frame                                              */
#define SACKPEND    (0xD7)    /* send ACK frame with pending bit set                         */

/* conditions for use with instructions SKIP and RPT */
#define C_CCA_IS_VALID        0x00
#define C_SFD_IS_ACTIVE       0x01
#define C_CPU_CTRL_IS_ON      0x02
#define C_END_INSTR_MEM       0x03
#define C_CSPX_IS_ZERO        0x04
#define C_CSPY_IS_ZERO        0x05
#define C_CSPZ_IS_ZERO        0x06
#define C_RSSI_IS_VALID       0x07

/* negated conditions for use with instructions SKIP and RPT */
#define C_NEGATE(c)   ((c) | 0x08)
#define C_CCA_IS_INVALID      C_NEGATE(C_CCA_IS_VALID)
#define C_SFD_IS_INACTIVE     C_NEGATE(C_SFD_IS_ACTIVE)
#define C_CPU_CTRL_IS_OFF     C_NEGATE(C_CPU_CTRL_IS_ON)
#define C_NOT_END_INSTR_MEM   C_NEGATE(C_END_INSTR_MEM)
#define C_CSPX_IS_NON_ZERO    C_NEGATE(C_CSPX_IS_ZERO)
#define C_CSPY_IS_NON_ZERO    C_NEGATE(C_CSPY_IS_ZERO)
#define C_CSPZ_IS_NON_ZERO    C_NEGATE(C_CSPZ_IS_ZERO)
#define C_RSSI_IS_INVALID     C_NEGATE(C_RSSI_IS_VALID)


/* CSPZ return values from CSP program */
#define CSPZ_CODE_TX_DONE           0
#define CSPZ_CODE_CHANNEL_BUSY      1
#define CSPZ_CODE_TX_ACK_TIME_OUT   2


static void  cspPrepForTxProgram(void);
static void  cspWeventSetTriggerNow(void);
static void  cspWeventSetTriggerSymbols(uint8 symbols);
static uint8 cspReadCountSymbols(void);


#define CSP_STOP_AND_CLEAR_PROGRAM()          st( RFST = ISSTOP; RFST = ISCLEAR; )
#define CSP_START_PROGRAM()                   st( RFST = ISSTART; )

#define T2THD_TICKS_PER_SYMBOL                (MAC_RADIO_TIMER_TICKS_PER_SYMBOL() >> 8)

#define CSP_WEVENT_CLEAR_TRIGGER()            st( T2IRQF = ~TIMER2_COMPARE1F; )
#define CSP_WEVENT_SET_TRIGGER_NOW()          cspWeventSetTriggerNow()
#define CSP_WEVENT_SET_TRIGGER_SYMBOLS(x)     cspWeventSetTriggerSymbols(x)
#define CSP_WEVENT_READ_COUNT_SYMBOLS()       cspReadCountSymbols()

#define SLOTTED_TX_MAX_BACKOFF_COUNTDOWN_NUM_BITS     4
#define SLOTTED_TX_MAX_BACKOFF_COUNTDOWN              (1 << SLOTTED_TX_MAX_BACKOFF_COUNTDOWN_NUM_BITS)
#define SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK       (SLOTTED_TX_MAX_BACKOFF_COUNTDOWN - 1)


MAC_INTERNAL_API void macCspTxReset(void)
{
  MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
  MAC_MCU_CSP_INT_DISABLE_INTERRUPT();
  CSP_STOP_AND_CLEAR_PROGRAM();
}


static void cspWeventSetTriggerNow(void)
{
  halIntState_t  s;
  uint8          temp0, temp1;

  /* Clear the compare interrupt flag for debugging purpose. */
  CSP_WEVENT_CLEAR_TRIGGER();

  /* copy current timer count to compare */
  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_COUNT_VALUE();
  temp0 = T2M0;
  temp1 = T2M1;

  if ((macChipVersion <= REV_B) && (temp0 == 0) && (temp1 == 0))
  {
    temp0++;
  }

  MAC_MCU_T2_ACCESS_CMP1_VALUE();
  T2M0 = temp0;
  T2M1 = temp1;
  HAL_EXIT_CRITICAL_SECTION(s);
}


static void cspWeventSetTriggerSymbols(uint8 symbols)
{
  halIntState_t  s;
  uint16         cmp;

  MAC_ASSERT(symbols <= MAC_A_UNIT_BACKOFF_PERIOD);

  /* Clear the compare interrupt flag for debugging purpose. */
  CSP_WEVENT_CLEAR_TRIGGER();

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_CMP1_VALUE();
  cmp  = (symbols) * MAC_RADIO_TIMER_TICKS_PER_SYMBOL();

  if ((macChipVersion <= REV_B) && (cmp == 0))
  {
    cmp++;
  }
  T2M0 = (cmp & 0xFF);
  T2M1 = (cmp >> 8);
  HAL_EXIT_CRITICAL_SECTION(s);
}

static uint8 cspReadCountSymbols(void)
{
  uint8          countLow, countHigh;
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_COUNT_VALUE();
  countLow  = T2M0;
  countHigh = T2M1;
  HAL_EXIT_CRITICAL_SECTION(s);

  return (((countHigh << 8) | countLow) / MAC_RADIO_TIMER_TICKS_PER_SYMBOL());
}

static void cspPrepForTxProgram(void)
{
  MAC_ASSERT(!(RFIRQM1 & IM_CSP_STOP)); /* already an active CSP program */

  /* set CSP EVENT1 to T2 CMP1 */
  MAC_MCU_CONFIG_CSP_EVENT1();

  /* set up parameters for CSP transmit program */
  CSPZ = CSPZ_CODE_CHANNEL_BUSY;

  /* clear the currently loaded CSP, this generates a stop interrupt which must be cleared */
  CSP_STOP_AND_CLEAR_PROGRAM();
  MAC_MCU_CSP_STOP_CLEAR_INTERRUPT();
  MAC_MCU_CSP_INT_CLEAR_INTERRUPT();
}


MAC_INTERNAL_API void macCspTxPrepCsmaUnslotted(void)
{
  cspPrepForTxProgram();

  RFST = WAITX;
  RFST = WEVENT1;

  /* wait until RSSI is valid */
  RFST = WHILE(C_RSSI_IS_INVALID);

  /* sample CCA, if it fails exit from here, CSPZ indicates result */
  RFST = SKIP(1, C_CCA_IS_VALID);
  RFST = SSTOP;

  /* CSMA has passed so transmit (actual frame starts one backoff from when strobe is sent) */
  RFST = STXON;

  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = WHILE(C_SFD_IS_INACTIVE);

 
  RFST = INT;

  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = DECZ;

  RFST = SSTOP;
}


MAC_INTERNAL_API void macCspTxPrepCsmaSlotted(void)
{
  cspPrepForTxProgram();


  /* wait for X number of backoffs */
  RFST = WAITX;
  
  /* sample RSSI, if it is valid then skip one extra backoff. */
  RFST = SKIP(1, C_RSSI_IS_VALID);
  
  /* wait for one backoff to guarantee receiver has been on at least that long */
  RFST = WAITW(1);

  /* sample CCA, if it fails exit from here, CSPZ indicates result */
  RFST = SKIP(1, C_CCA_IS_VALID);
  RFST = SSTOP;

  /* per slotted CSMA-CCA in specification, wait one backoff */
  RFST = WAITW(1);

  /* sample CCA again, if it fails exit from here, CSPZ indicates result */
  RFST = SKIP(1, C_CCA_IS_VALID);
  RFST = SSTOP;

  /* CSMA has passed so transmit */
  RFST = STXON;

  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = WHILE(C_SFD_IS_INACTIVE);
  RFST = INT;

  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = DECZ;

  RFST = SSTOP;
}


MAC_INTERNAL_API void macCspTxGoCsma(void)
{

  CSPX = macTxCsmaBackoffDelay;

  CSP_WEVENT_SET_TRIGGER_NOW();

  MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
  MAC_MCU_CSP_INT_ENABLE_INTERRUPT();

  macRxOn();

  /* start the CSP program */
  CSP_START_PROGRAM();
}

MAC_INTERNAL_API void macCspTxPrepSlotted(void)
{
  cspPrepForTxProgram();


  /* wait for X number of backoffs */
  RFST = WAITX;

  /* just transmit, no CSMA required */
  RFST = STXON;

  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = WHILE(C_SFD_IS_INACTIVE);

  RFST = INT;
  RFST = WHILE(C_SFD_IS_ACTIVE);
  RFST = DECZ;
  RFST = SSTOP;

}

MAC_INTERNAL_API void macCspTxGoSlotted(void)
{
  halIntState_t  s;
  uint8 lowByteOfBackoffCount;
  uint8 backoffCountdown;

  MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
  MAC_MCU_CSP_INT_ENABLE_INTERRUPT();

  /* critical section needed for timer accesses */
  HAL_ENTER_CRITICAL_SECTION(s);

  /* store lowest byte of backoff count (same as lowest byte of overflow count) */
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* Latch T2MOVFx */
  T2M0;
  lowByteOfBackoffCount = T2MOVF0;

  backoffCountdown = SLOTTED_TX_MAX_BACKOFF_COUNTDOWN - (lowByteOfBackoffCount & SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK) - 1;

  CSPX = backoffCountdown;

  /* Disable Rx and flush RXFIFO due to chip bug #1546 */
  macRxHardDisable();

  MAC_RX_WAS_FORCED_ON();

  /* start the CSP program */
  CSP_START_PROGRAM();

  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* Latch T2MOVFx */
  T2M0;
  if ((lowByteOfBackoffCount != T2MOVF0) && (backoffCountdown > 1))
  {
    CSPX = backoffCountdown - 1;
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macCspForceTxDoneIfPending(void)
{
  if ((CSPZ == CSPZ_CODE_TX_DONE) &&  MAC_MCU_CSP_STOP_INTERRUPT_IS_ENABLED())
  {
    MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
    if (MAC_MCU_CSP_INT_INTERRUPT_IS_ENABLED())
    {
      macCspTxIntIsr();
    }
    macTxDoneCallback();
  }
}


MAC_INTERNAL_API void macCspTxRequestAckTimeoutCallback(void)
{
  uint8 startSymbol;
  uint8 symbols;
  uint8 rollovers;

  MAC_ASSERT(!(RFIRQM1 & IM_CSP_STOP)); /* already an active CSP program */

  /* record current symbol count */
  startSymbol = CSP_WEVENT_READ_COUNT_SYMBOLS();

  /* set symbol timeout from PIB */
  symbols = macPib.ackWaitDuration;

  /* make sure delay value is not too small for logic to handle */
  MAC_ASSERT(symbols > MAC_A_UNIT_BACKOFF_PERIOD);  /* symbols timeout period must be great than a backoff */

  /* subtract out symbols left in current backoff period */
  symbols = symbols - (MAC_A_UNIT_BACKOFF_PERIOD - startSymbol);

  /* calculate rollovers needed for remaining symbols */
  rollovers = symbols / MAC_A_UNIT_BACKOFF_PERIOD;

  /* calculate symbols that still need counted after last rollover */
  symbols = symbols - (rollovers * MAC_A_UNIT_BACKOFF_PERIOD);

  /* add one to rollovers to account for symbols remaining in the current backoff period */
  rollovers++;

  /* set up parameters for CSP program */
  CSPZ = CSPZ_CODE_TX_ACK_TIME_OUT;
  CSPX = rollovers;
  CSP_WEVENT_SET_TRIGGER_SYMBOLS(symbols);

  /* clear the currently loaded CSP, this generates a stop interrupt which must be cleared */
  CSP_STOP_AND_CLEAR_PROGRAM();
  MAC_MCU_CSP_STOP_CLEAR_INTERRUPT();

  RFST = WAITX;
  RFST = WEVENT1;
  RFST = SSTOP;


  /* run CSP program */
  MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
  CSP_START_PROGRAM();

  if (CSP_WEVENT_READ_COUNT_SYMBOLS() < startSymbol)
  {
    /* a rollover has occurred, make sure it was accounted for */
    if (CSPX == rollovers)
    {
      
      CSPX--;
    }
  }
}

MAC_INTERNAL_API void macCspTxCancelAckTimeoutCallback(void)
{
  MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
  CSP_STOP_AND_CLEAR_PROGRAM();
}


MAC_INTERNAL_API void macCspTxIntIsr(void)
{
  MAC_MCU_CSP_INT_DISABLE_INTERRUPT();

  /* execute callback function that records transmit timestamp */
  macTxTimestampCallback();
}


MAC_INTERNAL_API void macCspTxStopIsr(void)
{
  MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();

  COMPRESSION_WORKAROUND_ON();
  
  if (CSPZ == CSPZ_CODE_TX_DONE)
  {
    macTxDoneCallback();
  }
  else if (CSPZ == CSPZ_CODE_CHANNEL_BUSY)
  {
    macTxChannelBusyCallback();
  }
  else
  {
    MAC_ASSERT(CSPZ == CSPZ_CODE_TX_ACK_TIME_OUT); /* unexpected CSPZ value */
    macTxAckNotReceivedCallback();
  }
}

#if ((CSPZ_CODE_TX_DONE != 0) || (CSPZ_CODE_CHANNEL_BUSY != 1))
#error "ERROR!  The CSPZ return values are very specific and tied into the actual CSP program."
#endif

#if (MAC_TX_TYPE_SLOTTED_CSMA != 0)
#error "WARNING!  This define value changed.  It was selected for optimum performance."
#endif

#if (T2THD_TICKS_PER_SYMBOL == 0)
#error "ERROR!  Timer compare will not work on high byte.  Clock speed is probably too slow."
#endif

#define BACKOFFS_PER_BASE_SUPERFRAME  (MAC_A_BASE_SLOT_DURATION * MAC_A_NUM_SUPERFRAME_SLOTS)
#if (((BACKOFFS_PER_BASE_SUPERFRAME - 1) & SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK) != SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK)
#error "ERROR!  The specified bit mask for backoff alignment of slotted transmit does not rollover 'cleanly'."

#endif
#if (SLOTTED_TX_MAX_BACKOFF_COUNTDOWN_NUM_BITS < 2)
#error "ERROR!  Not enough backoff countdown bits to be practical."
#endif

mac_csp_tx.h
#ifndef MAC_CSP_TX_H
#define MAC_CSP_TX_H

#include "hal_mcu.h"
#include "mac_mcu.h"
#include "mac_high_level.h"


MAC_INTERNAL_API void macCspTxReset(void);

MAC_INTERNAL_API void macCspTxPrepCsmaUnslotted(void);
MAC_INTERNAL_API void macCspTxPrepCsmaSlotted(void);
MAC_INTERNAL_API void macCspTxPrepSlotted(void);

MAC_INTERNAL_API void macCspTxGoCsma(void);
MAC_INTERNAL_API void macCspTxGoSlotted(void);

MAC_INTERNAL_API void macCspForceTxDoneIfPending(void);

MAC_INTERNAL_API void macCspTxRequestAckTimeoutCallback(void);
MAC_INTERNAL_API void macCspTxCancelAckTimeoutCallback(void);

MAC_INTERNAL_API void macCspTxStopIsr(void);
MAC_INTERNAL_API void macCspTxIntIsr(void);

#endif
mac_mcu.c
#include "hal_defs.h"
#include "hal_mcu.h"

/* low-level specific */
#include "mac_rx.h"
#include "mac_tx.h"
#include "mac_backoff_timer.h"
#include "mac_csp_tx.h"
#include "mac_rx_onoff.h"
#include "mac_low_level.h"

/* target specific */
#include "mac_mcu.h"
#include "mac_radio_defs.h"

/* debug */
#include "mac_assert.h"



/* for optimized indexing of uint32's */
#if HAL_MCU_LITTLE_ENDIAN()
#define UINT32_NDX0   0
#define UINT32_NDX1   1
#define UINT32_NDX2   2
#define UINT32_NDX3   3
#else
#define UINT32_NDX0   3
#define UINT32_NDX1   2
#define UINT32_NDX2   1
#define UINT32_NDX3   0
#endif

uint8       macChipVersion = 0;
static int8 maxRssi;
static uint32 prevAccumulatedOverflowCount = 0;
static bool updateRolloverflag = FALSE;
static uint32 prevoverflowCount = 0;

/*
 *  This number is used to calculate the precision count for OSAL timer update. In Beacon mode,
 *  the overflow count may be initialized to zero or to a constant. The "skip" in overflow count
 *  needs to be accounted for in this variable.
 */
static uint32 accumulatedOverflowCount = 0;

/* Function pointer for the random seed callback */
static macRNGFcn_t pRandomSeedCB = NULL;

static void mcuRecordMaxRssiIsr(void);
static uint32 macMcuOverflowGetCompare(void);

void MAC_SetRandomSeedCB(macRNGFcn_t pCBFcn);

void MAC_SetRandomSeedCB(macRNGFcn_t pCBFcn)
{
  pRandomSeedCB = pCBFcn;
}


MAC_INTERNAL_API void macMcuInit(void)
{
  halIntState_t  s;

  MDMCTRL1 = CORR_THR;

#ifdef FEATURE_CC253X_LOW_POWER_RX

  RXCTRL = 0x00;
  FSCTRL = 0x50;
#else
  /* tuning adjustments for optimal radio performance; details available in datasheet */
  RXCTRL = 0x3F;
  
  /* Adjust current in synthesizer; details available in datasheet. */
  FSCTRL = 0x55;
#endif /* #ifdef FEATURE_CC253X_LOW_POWER_RX */ 

#if !(defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590)
  /* Raises the CCA threshold from about -108 dBm to about -80 dBm input level.
   */
  CCACTRL0 = CCA_THR;
#endif

#ifdef CC2591_COMPRESSION_WORKAROUND
  /* For Coordinators/Routers with CC2591, increase preamble from 4 to 12 bytes */
  MDMCTRL0 = 0x95; 

  /* For End devices without CC2591, increase preamble from 4 to 8 bytes */
  /* MDMCTRL0 = 0x8D; */
#else

  MDMCTRL0 = 0x85;
#endif /* CC2591_COMPRESSION_WORKAROUND */

  if (*(uint8 *)(P_INFOPAGE+0x03) == 0x95)  // Device is a CC2533
  {
    /* In case the device is a 2533, just update the IVCTRL regoster which is 2533 specific */
    #define IVCTRL          XREG( 0x6265 )  
    IVCTRL = 0xF;
  }
  /* Adjust current in VCO; details available in datasheet. */
  FSCAL1 = 0x00;

  /* Adjust target value for AGC control loop; details available in datasheet. */
  AGCCTRL1 = 0x15;

  /* Disable source address matching an autopend for now */
  SRCMATCH = 0;

  /* Tune ADC performance, details available in datasheet. */
  ADCTEST0 = 0x10;
  ADCTEST1 = 0x0E;
  ADCTEST2 = 0x03;

  /* Sets TX anti-aliasing filter to appropriate bandwidth.
   * Reduces spurious emissions close to signal.
   */
  TXFILTCFG = TXFILTCFG_RESET_VALUE;

  /* disable the CSPT register compare function */
  CSPT = 0xFF;

  /* enable general RF interrupts */
  IEN2 |= RFIE;

  /* enable general REERR interrupts */
  IEN0 |= RFERRIE;

  /* set RF interrupts one notch above lowest priority (four levels available) */
  IP0 |=  IP_RFERR_RF_DMA_BV;
  IP1 &= ~IP_RFERR_RF_DMA_BV;

  IP0 |=  IP_RXTX0_T2_BV;
  IP1 &= ~IP_RXTX0_T2_BV;

  /* read chip version */
  macChipVersion = CHVER;


  /* set timer rollover */
  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_PERIOD_VALUE();
  T2M0 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFF;
  T2M1 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8;
  HAL_EXIT_CRITICAL_SECTION(s);

  /* start timer */
  MAC_RADIO_TIMER_WAKE_UP();

  T2CTRL |= (LATCH_MODE | TIMER2_SYNC);
  
  /* enable timer interrupts */
  T2IE = 1;


  FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_INFINITE_RECEPTION;

  /* turn on the receiver */
  macRxOn();

  while (!(RSSISTAT & 0x01));

  /* put 16 random bits into the seed value */
  {
    uint16 rndSeed;
    uint8  i;

    rndSeed = 0;

    for(i=0; i<16; i++)
    {
      /* use most random bit of analog to digital receive conversion to populate the random seed */
      rndSeed = (rndSeed << 1) | (RFRND & 0x01);
    }

  
    if (rndSeed == 0x0000 || rndSeed == 0x0380)
    {
      rndSeed = 0xBABE; /* completely arbitrary "random" value */
    }

    RNDL = rndSeed & 0xFF;
    RNDL = rndSeed >> 8;
  }

  /* Read 16*8 random bits and store them in flash for future use in random
     key generation for CBKE key establishment */
  if( pRandomSeedCB )
  {
    uint8 randomSeed[MAC_RANDOM_SEED_LEN];
    uint8 i,j;

    for(i = 0; i < 16; i++)
    {
      uint8 rndByte = 0;
      for(j = 0; j < 8; j++)
      {
        /* use most random bit of analog to digital receive conversion to
           populate the random seed */
        rndByte = (rndByte << 1) | (RFRND & 0x01);
      }
      randomSeed[i] = rndByte;

    }
    pRandomSeedCB( randomSeed );
  }

  /* turn off the receiver */
  macRxOff();

  /* take receiver out of infinite reception mode; set back to normal operation */
  FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_NORMAL_OPERATION;

  /* Turn on autoack */
  MAC_RADIO_TURN_ON_AUTO_ACK();

  /* Initialize SRCEXTPENDEN and SRCSHORTPENDEN to zeros */
  MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN();
  MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN();
}


MAC_INTERNAL_API uint8 macMcuRandomByte(void)
{
  /* clock the random generator to get a new random value */
  ADCCON1 = (ADCCON1 & ~RCTRL_BITS) | RCTRL_CLOCK_LFSR;

  /* return new randomized value from hardware */
  return(RNDH);
}


MAC_INTERNAL_API uint16 macMcuRandomWord(void)
{
  uint16 random_word;

  /* clock the random generator to get a new random value */
  ADCCON1 = (ADCCON1 & ~RCTRL_BITS) | RCTRL_CLOCK_LFSR;

  /* read random word */
  random_word  = (RNDH << 8);
  random_word +=  RNDL;

  /* return new randomized value from hardware */
  return(random_word);
}


MAC_INTERNAL_API void macMcuTimerForceDelay(uint16 x)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_COUNT_VALUE();
  T2M0 = (x) & 0xFF;
  T2M1 = (x) >> 8;
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API uint16 macMcuTimerCapture(void)
{
  uint16         timerCapture;
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_CAPTURE_VALUE();
  timerCapture = T2M1 << 8;
  timerCapture |= T2M0;
  HAL_EXIT_CRITICAL_SECTION(s);

  return (timerCapture);
}

MAC_INTERNAL_API uint32 macMcuOverflowCount(void)
{
  uint32         overflowCount;
  halIntState_t  s;

  /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */

  HAL_ENTER_CRITICAL_SECTION(s);

  /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* Latch the entire T2MOVFx first by reading T2M0. */
  T2M0;
  ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;
  ((uint8 *)&overflowCount)[UINT32_NDX3] = 0;
  HAL_EXIT_CRITICAL_SECTION(s);

  return (overflowCount);
}


MAC_INTERNAL_API uint32 macMcuOverflowCapture(void)
{
  uint32         overflowCapture;
  halIntState_t  s;

  /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */
  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_OVF_CAPTURE_VALUE();
  ((uint8 *)&overflowCapture)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&overflowCapture)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&overflowCapture)[UINT32_NDX2] = T2MOVF2;
  ((uint8 *)&overflowCapture)[UINT32_NDX3] = 0;
  HAL_EXIT_CRITICAL_SECTION(s);

  return (overflowCapture);
}

MAC_INTERNAL_API void macMcuOverflowSetCount(uint32 count)
{
  halIntState_t  s;

  MAC_ASSERT(! (count >> 24) );   /* illegal count value */

  /* save the current overflow count */
  accumulatedOverflowCount += macMcuOverflowCount();
  
  /* deduct the initial count */
  accumulatedOverflowCount -= count;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  /* T2OF2 must be written last */
  T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];
  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macMcuOverflowSetCompare(uint32 count)
{
  halIntState_t  s;
  uint8 enableCompareInt = 0;

  MAC_ASSERT( !(count >> 24) );   /* illegal count value */

  HAL_ENTER_CRITICAL_SECTION(s);

  /*  Disable overflow compare interrupts. */
  if (T2IRQM & TIMER2_OVF_COMPARE1M)
  {
    enableCompareInt = 1;
    T2IRQM &= ~TIMER2_OVF_COMPARE1M;
  }

  MAC_MCU_T2_ACCESS_OVF_CMP1_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];

  T2IRQF = ~TIMER2_OVF_COMPARE1F;

  /* re-enable overflow compare interrupts if they were previously enabled */
  if (enableCompareInt)
  {
    T2IRQM |= TIMER2_OVF_COMPARE1M;
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}


MAC_INTERNAL_API void macMcuOverflowSetPeriod(uint32 count)
{
  halIntState_t  s;
  uint8 enableCompareInt = 0;

  MAC_ASSERT( !(count >> 24) );   /* illegal count value */

  HAL_ENTER_CRITICAL_SECTION(s);

  /*  Disable overflow compare interrupts. */
  if (T2IRQM & TIMER2_OVF_PERM)
  {
    enableCompareInt = 1;
    T2IRQM &= ~TIMER2_OVF_PERM;
  }

  MAC_MCU_T2_ACCESS_OVF_PERIOD_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];

  T2IRQF &= ~TIMER2_OVF_PERF;

  /* re-enable overflow compare interrupts if they were previously enabled */
  if (enableCompareInt)
  {
    T2IRQM |= TIMER2_OVF_PERM;
  }

  halSetMaxSleepLoopTime(count);
  HAL_EXIT_CRITICAL_SECTION(s);
}

MAC_INTERNAL_API uint32 macMcuOverflowGetCompare(void)
{
  halIntState_t  s;
  uint32         compare;

  HAL_ENTER_CRITICAL_SECTION(s);

  MAC_MCU_T2_ACCESS_OVF_CMP1_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  ((uint8 *)&compare)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&compare)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&compare)[UINT32_NDX2] = T2MOVF2;
  ((uint8 *)&compare)[UINT32_NDX3] = 0;

  HAL_EXIT_CRITICAL_SECTION(s);

  return(compare);
}

HAL_ISR_FUNCTION( macMcuTimer2Isr, T2_VECTOR )
{
  uint8 t2irqm;
  uint8 t2irqf;
  
  HAL_ENTER_ISR();

  t2irqm = T2IRQM;
  t2irqf = T2IRQF;

  if ((t2irqf & TIMER2_OVF_COMPARE1F) & t2irqm)
  {

    /* call function for dealing with the timer compare interrupt */
    macBackoffTimerCompareIsr();

    /* clear overflow compare interrupt flag */
    T2IRQF = ~TIMER2_OVF_COMPARE1F;
  }

  if ((t2irqf & TIMER2_OVF_PERF) & t2irqm)
  {

    /* call function for dealing with the timer compare interrupt */
    macBackoffTimerPeriodIsr();

    /* clear overflow compare interrupt flag */
    T2IRQF = ~TIMER2_OVF_PERF;
  }

  else if ((t2irqf & TIMER2_PERF) & t2irqm)
  {
    /* call energy detect interrupt function, this interrupt not used for any other functionality */
    mcuRecordMaxRssiIsr();

    /* clear the interrupt flag */
    T2IRQF = ~TIMER2_PERF;
  }
  
  CLEAR_SLEEP_MODE();
  HAL_EXIT_ISR();  
}


void macMcuTimer2OverflowWorkaround(void)
{
  if (T2IRQM & TIMER2_OVF_COMPARE1F)
  {
    /* T2 comapre 1 interrupt is enabled but T2 compare 1 intererrupt is not generated */
    if (!(T2IRQF & TIMER2_OVF_COMPARE1F))
    {
      if (MAC_RADIO_BACKOFF_COUNT() > macMcuOverflowGetCompare())
      {
        /* Set the flag to trigger the timer compare interrupt */
        macBackoffTimerCompareIsr();
        T2IRQF = ~TIMER2_OVF_COMPARE1F;
      }
    }
  }
}

uint32 macMcuPrecisionCount(void)
{
  uint32         overflowCount = 0;
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);

  /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  T2M0;
  ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;

  /* the overflowCount needs to account for the accumulated overflow count in Beacon mode.
   */
  overflowCount += accumulatedOverflowCount;
  
   if((prevoverflowCount > overflowCount) && (prevAccumulatedOverflowCount == accumulatedOverflowCount))
  {
    accumulatedOverflowCount += macGetBackOffTimerRollover();
    overflowCount += macGetBackOffTimerRollover();
    /*don't update the rollover since it has been updated already */
    updateRolloverflag = TRUE;
  }

  /* store the current value of overflowcount and accumulatedOverflowCount */
  prevoverflowCount = overflowCount;
  prevAccumulatedOverflowCount = accumulatedOverflowCount;
  HAL_EXIT_CRITICAL_SECTION(s);

  return(overflowCount);
}

HAL_ISR_FUNCTION( macMcuRfIsr, RF_VECTOR )
{
  uint8 rfim;
  
  HAL_ENTER_ISR();

  rfim = RFIRQM1;

  /*  The CPU level RF interrupt flag must be cleared here (before clearing RFIRQFx).
   *  to allow the interrupts to be nested.
   */
  S1CON = 0x00;

  if ((RFIRQF1 & IRQ_CSP_MANINT) & rfim)
  {
  
    /* clear flag */
    RFIRQF1 = ~IRQ_CSP_MANINT;
    macCspTxIntIsr();
  }
  else if ((RFIRQF1 & IRQ_CSP_STOP) & rfim)
  {
    /* clear flag */
    RFIRQF1 = ~IRQ_CSP_STOP;
    macCspTxStopIsr();
  }
  else if ((RFIRQF1 & IRQ_TXACKDONE) & rfim)
  {
    /* disable interrupt - set up is for "one shot" operation */
    RFIRQM1 &= ~IM_TXACKDONE;
    macRxAckTxDoneCallback();
  }

  rfim = RFIRQM0;

  /* process RFIRQF0 next */
  if ((RFIRQF0 & IRQ_FIFOP) & rfim)
  {
    /* continue to execute interrup                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        t handler as long as FIFOP is active */
    do
    {
      macRxThresholdIsr();
      RFIRQF0 = ~IRQ_FIFOP;
    } while (FSMSTAT1 & FIFOP);
  }
  
  CLEAR_SLEEP_MODE();
  HAL_EXIT_ISR();  
}

HAL_ISR_FUNCTION( macMcuRfErrIsr, RFERR_VECTOR )
{
  uint8 rferrm;
  
  HAL_ENTER_ISR();
  
  rferrm = RFERRM;

  if ((RFERRF & RFERR_RXOVERF) & rferrm)
  {
    RFERRF = ~RFERR_RXOVERF;
    macRxFifoOverflowIsr();
  }

  CLEAR_SLEEP_MODE();
  HAL_EXIT_ISR();  
}

MAC_INTERNAL_API void macMcuRecordMaxRssiStart(void)
{
  /* start maximum recorded value at the lowest possible value */
  maxRssi = -128;

  /* enable timer overflow interrupt */
  T2IRQM |= TIMER2_PERM;
}

MAC_INTERNAL_API int8 macMcuRecordMaxRssiStop(void)
{
  /* disable timer overflow interrupt */
  T2IRQM &= ~TIMER2_PERM;

  return(maxRssi);
}

static void mcuRecordMaxRssiIsr(void)
{
  int8 rssi;

  /* read latest RSSI value */
  rssi = RSSI;

  /* if new RSSI value is greater than the maximum already received, it is the new maximum */
  if (rssi > maxRssi)
  {
    maxRssi = rssi;
  }
}

MAC_INTERNAL_API void macMcuAccumulatedOverFlow(void)
{
  halIntState_t  s;
  HAL_ENTER_CRITICAL_SECTION(s);

  if(updateRolloverflag == FALSE)
  {
    accumulatedOverflowCount += macGetBackOffTimerRollover();
  }
  else
  {
    updateRolloverflag = FALSE;
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}

#if ((IRQ_SFD != IM_SFD) || (IRQ_FIFOP != IM_FIFOP) || (IRQ_TXACKDONE != IM_TXACKDONE))
#error "ERROR: Compile time error with RFIRQFx vs RFIRQMx register defines."
#endif

#if defined (FEATURE_CC253X_LOW_POWER_RX) && !(defined (HAL_MCU_CC2530) || defined (HAL_MCU_CC2533))
#error "ERROR: FEATURE_CC253X_LOW_POWER_RX can only be used with CC2530 or CC2533."
#endif
mac_mcu.h
#ifndef MAC_MCU_H
#define MAC_MCU_H

lude "hal_mcu.h"
#include "hal_types.h"
#include "hal_defs.h"
#include "hal_board.h"
#include "mac_high_level.h"

/* IP0, IP1 */
#define IPX_0                 BV(0)
#define IPX_1                 BV(1)
#define IPX_2                 BV(2)
#define IP_RFERR_RF_DMA_BV    IPX_0
#define IP_RXTX0_T2_BV        IPX_2

/* T2CTRL */
#define LATCH_MODE            BV(3)
#define TIMER2_STATE          BV(2)
#define TIMER2_SYNC           BV(1)
#define TIMER2_RUN            BV(0)

/* T2IRQF */
#define TIMER2_OVF_COMPARE2F  BV(5)
#define TIMER2_OVF_COMPARE1F  BV(4)
#define TIMER2_OVF_PERF       BV(3)
#define TIMER2_COMPARE2F      BV(2)
#define TIMER2_COMPARE1F      BV(1)
#define TIMER2_PERF           BV(0)

/* T2IRQM */
#define TIMER2_OVF_COMPARE2M  BV(5)
#define TIMER2_OVF_COMPARE1M  BV(4)
#define TIMER2_OVF_PERM       BV(3)
#define TIMER2_COMPARE2M      BV(2)
#define TIMER2_COMPARE1M      BV(1)
#define TIMER2_PERM           BV(0)

/* T2PEROF2 */
#define CMPIM           BV(7)
#define PERIM           BV(6)
#define OFCMPIM         BV(5)
#define PEROF2_BITS     (BV(3) | BV(2) | BV(1) | BV(0))

/* RFIRQF0 */
#define IRQ_SFD         BV(1)
#define IRQ_FIFOP       BV(2)

/* RFIRQF1 */
#define IRQ_TXACKDONE   BV(0)
#define IRQ_TXDONE      BV(1)
#define IRQ_CSP_MANINT  BV(3)
#define IRQ_CSP_STOP    BV(4)

/* RFIRQM0 */
#define IM_SFD          BV(1)
#define IM_FIFOP        BV(2)

/* RFIRQM1 */
#define IM_TXACKDONE    BV(0)
#define IM_TXDONE       BV(1)
#define IM_CSP_MANINT   BV(3)
#define IM_CSP_STOP     BV(4)

/* IRQSRC */
#define TXACK           BV(0)

/* RFERRM and RFERRF */
#define RFERR_RXOVERF   BV(2)

#define MAC_MCU_WRITE_RFIRQF0(x)      HAL_CRITICAL_STATEMENT( S1CON = 0x00; RFIRQF0 = x; )
#define MAC_MCU_WRITE_RFIRQF1(x)      HAL_CRITICAL_STATEMENT( S1CON = 0x00; RFIRQF1 = x; )
#define MAC_MCU_OR_RFIRQM0(x)         st( RFIRQM0 |= x; )  /* compiler must use atomic ORL instruction */
#define MAC_MCU_AND_RFIRQM0(x)        st( RFIRQM0 &= x; )  /* compiler must use atomic ANL instruction */
#define MAC_MCU_OR_RFIRQM1(x)         st( RFIRQM1 |= x; )  /* compiler must use atomic ORL instruction */
#define MAC_MCU_AND_RFIRQM1(x)        st( RFIRQM1 &= x; )  /* compiler must use atomic ANL instruction */

#define MAC_MCU_FIFOP_ENABLE_INTERRUPT()              MAC_MCU_OR_RFIRQM0(IM_FIFOP)
#define MAC_MCU_FIFOP_DISABLE_INTERRUPT()             MAC_MCU_AND_RFIRQM0(~IM_FIFOP)
#define MAC_MCU_FIFOP_CLEAR_INTERRUPT()               MAC_MCU_WRITE_RFIRQF0(~IRQ_FIFOP)

#define MAC_MCU_TXACKDONE_ENABLE_INTERRUPT()          MAC_MCU_OR_RFIRQM1(IM_TXACKDONE)
#define MAC_MCU_TXACKDONE_DISABLE_INTERRUPT()         MAC_MCU_AND_RFIRQM1(~IM_TXACKDONE)
#define MAC_MCU_TXACKDONE_CLEAR_INTERRUPT()           MAC_MCU_WRITE_RFIRQF1(~IRQ_TXACKDONE)

#define MAC_MCU_CSP_STOP_ENABLE_INTERRUPT()           MAC_MCU_OR_RFIRQM1(IM_CSP_STOP)
#define MAC_MCU_CSP_STOP_DISABLE_INTERRUPT()          MAC_MCU_AND_RFIRQM1(~IM_CSP_STOP)
#define MAC_MCU_CSP_STOP_CLEAR_INTERRUPT()            MAC_MCU_WRITE_RFIRQF1(~IRQ_CSP_STOP)
#define MAC_MCU_CSP_STOP_INTERRUPT_IS_ENABLED()       (RFIRQM1 & IM_CSP_STOP)

#define MAC_MCU_CSP_INT_ENABLE_INTERRUPT()            MAC_MCU_OR_RFIRQM1(IM_CSP_MANINT)
#define MAC_MCU_CSP_INT_DISABLE_INTERRUPT()           MAC_MCU_AND_RFIRQM1(~IM_CSP_MANINT)
#define MAC_MCU_CSP_INT_CLEAR_INTERRUPT()             MAC_MCU_WRITE_RFIRQF1(~IRQ_CSP_MANINT)
#define MAC_MCU_CSP_INT_INTERRUPT_IS_ENABLED()        (RFIRQM1 & IM_CSP_MANINT)

#define MAC_MCU_RFERR_ENABLE_INTERRUPT()              st( RFERRM |=  RFERR_RXOVERF; )
#define MAC_MCU_RFERR_DISABLE_INTERRUPT()             st( RFERRM &= ~RFERR_RXOVERF; )

#define T2M_OVF_BITS    (BV(6) | BV(5) | BV(4))
#define T2M_BITS        (BV(2) | BV(1) | BV(0))

#define T2M_OVFSEL(x)   ((x) << 4)
#define T2M_SEL(x)      (x)

#define T2M_T2OVF       T2M_OVFSEL(0)
#define T2M_T2OVF_CAP   T2M_OVFSEL(1)
#define T2M_T2OVF_PER   T2M_OVFSEL(2)
#define T2M_T2OVF_CMP1  T2M_OVFSEL(3)
#define T2M_T2OVF_CMP2  T2M_OVFSEL(4)

#define T2M_T2TIM       T2M_SEL(0)
#define T2M_T2_CAP      T2M_SEL(1)
#define T2M_T2_PER      T2M_SEL(2)
#define T2M_T2_CMP1     T2M_SEL(3)
#define T2M_T2_CMP2     T2M_SEL(4)

#define MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE()   st( T2MSEL = T2M_T2OVF; )
#define MAC_MCU_T2_ACCESS_OVF_CAPTURE_VALUE() st( T2MSEL = T2M_T2OVF_CAP; )
#define MAC_MCU_T2_ACCESS_OVF_PERIOD_VALUE()  st( T2MSEL = T2M_T2OVF_PER; )
#define MAC_MCU_T2_ACCESS_OVF_CMP1_VALUE()    st( T2MSEL = T2M_T2OVF_CMP1; )
#define MAC_MCU_T2_ACCESS_OVF_CMP2_VALUE()    st( T2MSEL = T2M_T2OVF_CMP2; )

#define MAC_MCU_T2_ACCESS_COUNT_VALUE()       st( T2MSEL = T2M_T2TIM; )
#define MAC_MCU_T2_ACCESS_CAPTURE_VALUE()     st( T2MSEL = T2M_T2_CAP; )
#define MAC_MCU_T2_ACCESS_PERIOD_VALUE()      st( T2MSEL = T2M_T2_PER; )
#define MAC_MCU_T2_ACCESS_CMP1_VALUE()        st( T2MSEL = T2M_T2_CMP1; )
#define MAC_MCU_T2_ACCESS_CMP2_VALUE()        st( T2MSEL = T2M_T2_CMP2; )

#define MAC_MCU_CONFIG_CSP_EVENT1()           st( T2CSPCFG = 1; )

extern uint8 macChipVersion;

MAC_INTERNAL_API void macMcuInit(void);
MAC_INTERNAL_API uint8 macMcuRandomByte(void);
MAC_INTERNAL_API uint16 macMcuRandomWord(void);
MAC_INTERNAL_API void macMcuTimerForceDelay(uint16 count);
MAC_INTERNAL_API uint16 macMcuTimerCapture(void);
MAC_INTERNAL_API uint32 macMcuOverflowCount(void);
MAC_INTERNAL_API uint32 macMcuOverflowCapture(void);
MAC_INTERNAL_API void macMcuOverflowSetCount(uint32 count);
MAC_INTERNAL_API void macMcuOverflowSetCompare(uint32 count);
MAC_INTERNAL_API void macMcuOverflowSetPeriod(uint32 count);
MAC_INTERNAL_API void macMcuRecordMaxRssiStart(void);
MAC_INTERNAL_API int8 macMcuRecordMaxRssiStop(void);
MAC_INTERNAL_API void macMcuRecordMaxRssiIsr(void);
MAC_INTERNAL_API void macMcuAccumulatedOverFlow(void);
uint32 macMcuPrecisionCount(void);
void macMcuTimer2OverflowWorkaround(void);

#endif
mac_mem.c
#include "hal_types.h"

/* low-level specific */
#include "mac_mem.h"

/* target specific */
#include "hal_mcu.h"

/* debug */
#include "mac_assert.h"
uint8 macMemReadRamByte(macRam_t * pRam)
{
  return(*pRam);
}


MAC_INTERNAL_API void macMemWriteRam(macRam_t * pRam, uint8 * pData, uint8 len)
{
  while (len)
  {
    len--;
    *pRam = *pData;
    pRam++;
    pData++;
  }
}

MAC_INTERNAL_API void macMemReadRam(macRam_t * pRam, uint8 * pData, uint8 len)
{
  while (len)
  {
    len--;
    *pData = *pRam;
    pRam++;
    pData++;
  }
}

MAC_INTERNAL_API void macMemWriteTxFifo(uint8 * pData, uint8 len)
{
  MAC_ASSERT(len != 0); /* pointless to write zero bytes */

  do
  {
    RFD = *pData;
    pData++;
    len--;
  }
  while (len);
}

MAC_INTERNAL_API void macMemReadRxFifo(uint8 * pData, uint8 len)
{
  MAC_ASSERT(len != 0); /* pointless to read zero bytes */

  do
  {
    *pData = RFD;
    pData++;
    len--;
  }
  while (len);
}

mac_mem.h
#ifndef MAC_MEM_H
#define MAC_MEM_H
#include "hal_types.h"
#include "mac_high_level.h"
typedef volatile unsigned char XDATA macRam_t;
MAC_INTERNAL_API uint8 macMemReadRamByte(macRam_t * pRam);
MAC_INTERNAL_API void macMemWriteRam(macRam_t * pRam, uint8 * pData, uint8 len);
MAC_INTERNAL_API void macMemReadRam(macRam_t * pRam, uint8 * pData, uint8 len);
MAC_INTERNAL_API void macMemWriteTxFifo(uint8 * pData, uint8 len);
MAC_INTERNAL_API void macMemReadRxFifo(uint8 * pData, uint8 len);
#endif
mac_radio_defs.c
#include "mac_radio_defs.h"
#include "hal_types.h"
#include "hal_assert.h"
#include "hal_mcu.h"
#include "mac_pib.h"

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  (!defined HAL_PA_LNA && !defined HAL_PA_LNA_CC2590)

#ifdef HAL_MCU_CC2533
const uint8 CODE macRadioDefsTxPwrBare[] =
{
  4,  /* tramsmit power level of the first entry */
  (uint8)(int8)-21, /* transmit power level of the last entry */
  /*   4 dBm */   0xEC,   /* characterized as  4.5 dBm in datasheet */
  /*   3 dBm */   0xDC,   /* characterized as  3   dBm in datasheet */
  /*   2 dBm */   0xDC,   
  /*   1 dBm */   0xCC,   /* characterized as  1.7 dBm in datasheet */
  /*   0 dBm */   0xBC,   /* characterized as  0.3 dBm in datasheet */
  /*  -1 dBm */   0xAC,   /* characterized as -1   dBm in datasheet */
  /*  -2 dBm */   0xAC,
  /*  -3 dBm */   0x9C,   /* characterized as -2.8 dBm in datasheet */
  /*  -4 dBm */   0x9C,   
  /*  -5 dBm */   0x8C,   /* characterized as -4.1 dBm in datasheet */
  /*  -6 dBm */   0x7C,   /* characterized as -5.9 dBm in datasheet */
  /*  -7 dBm */   0x7C,
  /*  -8 dBm */   0x6C,   /* characterized as -7.7 dBm in datasheet */
  /*  -9 dBm */   0x6C,
  /* -10 dBm */   0x5C,   /* characterized as -9.9 dBm in datasheet */
  /* -11 dBm */   0x5C,
  /* -12 dBm */   0x5C,   /* characterized as -9.9 dBm in datasheet */
  /* -13 dBm */   0x4C,   /* characterized as -12.8 dBm in datasheet */
  /* -14 dBm */   0x4C,
  /* -15 dBm */   0x3C,   /* characterized as -14.9 dBm in datasheet */
  /* -16 dBm */   0x3C, 
  /* -17 dBm */   0x2C,   /* characterized as -16.6 dBm in datasheet */
  /* -18 dBm */   0x2C,
  /* -19 dBm */   0x1C,   /* characterized as -18.7 dBm in datasheet */
  /* -20 dBm */   0x1C,   /* characterized as -18.7 dBm in datasheet */
  /* -21 dBm */   0x0C
};
#else /* HAL_MCU_CC2533 */
const uint8 CODE macRadioDefsTxPwrBare[] =
{
  3,  /* tramsmit power level of the first entry */
  (uint8)(int8)-22, /* transmit power level of the last entry */
  /*   3 dBm */   0xF5,   /* characterized as  4.5 dBm in datasheet */
  /*   2 dBm */   0xE5,   /* characterized as  2.5 dBm in datasheet */
  /*   1 dBm */   0xD5,   /* characterized as  1   dBm in datasheet */
  /*   0 dBm */   0xD5,   /* characterized as  1   dBm in datasheet */
  /*  -1 dBm */   0xC5,   /* characterized as -0.5 dBm in datasheet */
  /*  -2 dBm */   0xB5,   /* characterized as -1.5 dBm in datasheet */
  /*  -3 dBm */   0xA5,   /* characterized as -3   dBm in datasheet */
  /*  -4 dBm */   0x95,   /* characterized as -4   dBm in datasheet */
  /*  -5 dBm */   0x95,
  /*  -6 dBm */   0x85,   /* characterized as -6   dBm in datasheet */
  /*  -7 dBm */   0x85,
  /*  -8 dBm */   0x75,   /* characterized as -8   dBm in datasheet */
  /*  -9 dBm */   0x75,
  /* -10 dBm */   0x65,   /* characterized as -10  dBm in datasheet */
  /* -11 dBm */   0x65,
  /* -12 dBm */   0x55,   /* characterized as -12  dBm in datasheet */
  /* -13 dBm */   0x55,
  /* -14 dBm */   0x45,   /* characterized as -14  dBm in datasheet */
  /* -15 dBm */   0x45,
  /* -16 dBm */   0x35,   /* characterized as -16  dBm in datasheet */
  /* -17 dBm */   0x35,
  /* -18 dBm */   0x25,   /* characterized as -18  dBm in datasheet */
  /* -19 dBm */   0x25,
  /* -20 dBm */   0x15,   /* characterized as -20  dBm in datasheet */
  /* -21 dBm */   0x15,
  /* -22 dBm */   0x05    /* characterized as -22  dBm in datasheet */
};
#endif /* HAL_MCU_CC2533 */
#endif /* defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || 
          (!defined HAL_PA_LNA && !defined HAL_PA_LNA_CC2590) */

#if defined HAL_PA_LNA || defined MAC_RUNTIME_CC2591
const uint8 CODE macRadioDefsTxPwrCC2591[] =
{
  20,  /* tramsmit power level of the first entry */
  (uint8)(int8)10, /* transmit power level of the last entry */
  /*  20 dBm */   0xE5,   /* characterized as 20 dBm in datasheet */
  /*  19 dBm */   0xD5,   /* characterized as 19 dBm in datasheet */
  /*  18 dBm */   0xC5,   /* characterized as 18 dBm in datasheet */
  /*  17 dBm */   0xB5,   /* characterized as 17 dBm in datasheet */
  /*  16 dBm */   0xA5,   /* characterized as 16 dBm in datasheet */
  /*  15 dBm */   0xA5,
  /*  14 dBm */   0x95,   /* characterized as 14.5 dBm in datasheet */
  /*  13 dBm */   0x85,   /* characterized as 13 dBm in datasheet */
  /*  12 dBm */   0x85,
  /*  11 dBm */   0x75,   /* characterized as 11.5 dBm in datasheet */
  /*  10 dBm */   0x65    /* characterized as 10 dBm in datasheet */
};
#endif


/* Placeholder for CC2590 */
#if defined HAL_PA_LNA_CC2590 || defined MAC_RUNTIME_CC2590
const uint8 CODE macRadioDefsTxPwrCC2590[] =
{
  11,  /* tramsmit power level of the first entry */
  (uint8)(int8)-12, /* transmit power level of the last entry */
  /* Note that the characterization is preliminary */
  /* 11 dBm */   0xF5,   /* characterized as 11.8 dBm */
  /* 10 dBm */   0xE5,   /* characterized as 10.6 dBm */
  /*  9 dBm */   0xD5,   /* characterized as 9.5 dBm */
  /*  8 dBm */   0xC5,   /* characterized as 8.5 dBm */
  /*  7 dBm */   0xB5,   /* characterized as 7.6 dBm */
  /*  6 dBm */   0xA5,   /* characterized as 6.4 dBm */
  /*  5 dBm */   0xA5,   /* characterized as 6.4 dBm */
  /*  4 dBm */   0x95,   /* characterized as 4.7 dBm */
  /*  3 dBm */   0x85,   /* characterized as 3.5 dBm */
  /*  2 dBm */   0x75,   /* characterized as 2.0 dBm */
  /*  1 dBm */   0x75,   /* characterized as 2.0 dBm */
  /*  0 dBm */   0x65,   /* characterized as 0.3 dBm */
  /* -1 dBm */   0x65,   /* characterized as 0.3 dBm */
  /* -2 dBm */   0x55,   /* characterized as -1.7 dBm */
  /* -3 dBm */   0x55,   /* characterized as -1.7 dBm */
  /* -4 dBm */   0x45,   /* characterized as -3.9 dBm */
  /* -5 dBm */   0x45,   /* characterized as -3.9 dBm */
  /* -6 dBm */   0x45,   /* characterized as -3.9 dBm */
  /* -7 dBm */   0x35,   /* characterized as -6.3 dBm*/
  /* -8 dBm */   0x25,   /* characterized as -7.8 dBm */
  /* -9 dBm */   0x25,   /* characterized as -7.8 dBm */
  /* -10 dBm */  0x15,   /* characterized as -9.8 dBm */
  /* -11 dBm */  0x15,   /* characterized as -9.8 dBm */
  /* -12 dBm */  0x05,   /* characterized as -11.8 dBm */
};
#endif

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590

/* TX power table array */
const uint8 CODE *const CODE macRadioDefsTxPwrTables[] =
{
#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  (!defined HAL_PA_LNA && !defined HAL_PA_LNA_CC2590)
  macRadioDefsTxPwrBare,
#endif

#if defined HAL_PA_LNA || defined MAC_RUNTIME_CC2591
  macRadioDefsTxPwrCC2591,
#endif

#if defined HAL_PA_LNA_CC2590 || defined MAC_RUNTIME_CC2590
  macRadioDefsTxPwrCC2590,
#endif
};

/* RSSI offset adjustment value array */
const int8 CODE macRadioDefsRssiAdj[] =
{
#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  (!defined HAL_PA_LNA && !defined HAL_PA_LNA_CC2590)
  0,
#endif

#if defined HAL_PA_LNA || defined MAC_RUNTIME_CC2591
  -6, /* high gain mode */
  6,  /* low gain mode */
#endif

#if defined HAL_PA_LNA_CC2590 || defined MAC_RUNTIME_CC2590
-10,  /* TBD: place holder for high gain mode */
  0,  /* TBD: place holder for low gain mode */
#endif
};

#endif /* defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || ... */

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
uint8 macRadioDefsRefTableId = 0;
#endif

/* RF observable control register value to output PA signal */
#define RFC_OBS_CTRL_PA_PD_INV        0x68

/* RF observable control register value to output LNA signal */
#define RFC_OBS_CTRL_LNAMIX_PD_INV    0x6A

/* OBSSELn register value to select RF observable 0 */
#define OBSSEL_OBS_CTRL0             0xFB

/* OBSSELn register value to select RF observable 1 */
#define OBSSEL_OBS_CTRL1             0xFC

extern void MAC_SetRadioRegTable ( uint8 txPwrTblIdx, uint8 rssiAdjIdx )
{
  /* Depending on compile flags, the parameters may not be used */
  (void) txPwrTblIdx;
  (void) rssiAdjIdx;

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590
  if (txPwrTblIdx >= sizeof(macRadioDefsTxPwrTables)/sizeof(macRadioDefsTxPwrTables[0]))
  {
    txPwrTblIdx = 0;
  }
#endif /* defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 */

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590

  if (rssiAdjIdx >= sizeof(macRadioDefsRssiAdj)/sizeof(macRadioDefsRssiAdj[0]))
  {
    rssiAdjIdx = 0;
  }

  macRadioDefsRefTableId = (txPwrTblIdx << 4) | rssiAdjIdx;

#endif /* defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || .. */
}

MAC_INTERNAL_API void macRadioTurnOnPower(void)
{
  /* Enable RF error trap */
  MAC_MCU_RFERR_ENABLE_INTERRUPT();

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590
  /* table ID is referenced only when runtime configuratino is enabled */
  if (macRadioDefsRefTableId & 0xf0)
#endif /* defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 */

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
  defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
  { /* either if compound statement or non-conditional compound statement */

    /* (Re-)Configure PA and LNA control signals to RF frontend chips.
    * Note that The register values are not retained during sleep.
    */

    /* P1_1 -> PAEN */
    //RFC_OBS_CTRL0 = RFC_OBS_CTRL_PA_PD_INV;
    //OBSSEL1       = OBSSEL_OBS_CTRL0;

    /* P1_5 -> PAEN  2401芯片中用P1_5代替P1_1当功放的PAEN*/
    RFC_OBS_CTRL0 = RFC_OBS_CTRL_PA_PD_INV;
    OBSSEL5       = OBSSEL_OBS_CTRL0;   
    
    /* P1_4 -> EN (LNA control) */
    //RFC_OBS_CTRL1 = RFC_OBS_CTRL_LNAMIX_PD_INV;
    //OBSSEL4       = OBSSEL_OBS_CTRL1;
    P1SEL &= ~0X10;    
    P1DIR |= 0X10;
    P1_4 = 1;         //P1_4 RXEN   andy pa    
    
    /* For any RX, change CCA settings for CC2591 compression workaround.
     * This will override LNA control if CC2591_COMPRESSION_WORKAROUND 
     * flag is defined. 
     */
    COMPRESSION_WORKAROUND_ON();
  }
#endif /* defined MAC_RUNTIME_CC2591 || ... || defined HAL_PA_LNA_CC2590 */

  if (macChipVersion <= REV_B)
  {
    /* radio initializations for disappearing RAM; PG1.0 and before only */
    MAC_RADIO_SET_PAN_ID(macPib.panId);
    MAC_RADIO_SET_SHORT_ADDR(macPib.shortAddress);
    MAC_RADIO_SET_IEEE_ADDR(macPib.extendedAddress.addr.extAddr);
  }

  /* Turn on frame filtering */
  MAC_RADIO_TURN_ON_RX_FRAME_FILTERING();
}

MAC_INTERNAL_API void macRadioTurnOffPower(void)
{
  /* Disable RF error trap */
  MAC_MCU_RFERR_DISABLE_INTERRUPT();
}

#if (HAL_CPU_CLOCK_MHZ != 32)
#error "ERROR: The only tested/supported clock speed is 32 MHz."
#endif

#if (MAC_RADIO_RECEIVER_SENSITIVITY_DBM > MAC_SPEC_MIN_RECEIVER_SENSITIVITY)
#error "ERROR: Radio sensitivity does not meet specification."
#endif

#if defined (HAL_PA_LNA) && defined (HAL_PA_LNA_CC2590)
#error "ERROR: HAL_PA_LNA and HAL_PA_LNA_CC2590 cannot be both defined."
#endif

#if defined (HAL_PA_LNA) && defined (MAC_RUNTIME_CC2591)
#error "ERROR: HAL_PA_LNA and MAC_RUNTIME_CC2591 cannot be both defined."
#endif

#if defined (HAL_PA_LNA_CC2590) && defined (MAC_RUNTIME_CC2590)
#error "ERROR: HAL_PA_LNA_CC2590 and MAC_RUNTIME_CC2590 cannot be both defined."
#endif

#if defined (CC2591_COMPRESSION_WORKAROUND) && !defined (HAL_PA_LNA)
#error "ERROR: CC2591_COMPRESSION_WORKAROUND can only be defined when HAL_PA_LNA is defined."
#endif

#if defined (CC2591_COMPRESSION_WORKAROUND)
#warning "WARNING: Contact TI customer support if your reference design is based on CC2530-CC2591EM rev 2.0 or prior."
#endif

mac_radio_defs.h
#define ISTXCAL       0xEC
#define ISRXON        0xE3
#define ISTXON        0xE9
#define ISTXONCCA     0xEA
#define ISRFOFF       0xEF
#define ISFLUSHRX     0xED
#define ISFLUSHTX     0xEE
#define ISACK         0xE6
#define ISACKPEND     0xE7
#define ISNACK        0xE8

/* FSCTRLL */
#define FREQ_2405MHZ                  0x0B

/* FSMSTAT1 */
#define TX_ACTIVE                     BV(1)
#define CCA                           BV(4)
#define SFD                           BV(5)
#define FIFOP                         BV(6)
#define FIFO                          BV(7)

/* IEN0 */
#define RFERRIE                       BV(0)

/* IEN2 */
#define RFIE                          BV(0)

/* FRMCTRL0 */
#define FRMCTRL0_RESET_VALUE          0x40
#define ENERGY_SCAN                   BV(4)
#define AUTOACK                       BV(5)
#define RX_MODE(x)                    ((x) << 2)
#define RX_MODE_INFINITE_RECEPTION    RX_MODE(2)
#define RX_MODE_NORMAL_OPERATION      RX_MODE(0)

/* FRMCTRL1 */
#define PENDING_OR                    BV(2)

/* FRMFILT0 */
#define PAN_COORDINATOR               BV(1)
#define FRAME_FILTER_EN               BV(0)

#define FRAME_VERSION(x)              ((x) << 2)
#define FRAME_FILTER_MAX_VERSION      FRAME_VERSION(1)

/* SRCMATCH */
#define PEND_DATAREQ_ONLY             BV(2)
#define AUTOPEND                      BV(1)
#define SRC_MATCH_EN                  BV(0)

/* SRCRESINDEX */
#define AUTOPEND_RES                  BV(6)

/* MDMCTRL1 */
#define CORR_THR_SFD                  BV(5)
#define CORR_THR                      0x14

/* CCACTRL0 */
#define CCA_THR                       0xFC   /* -4-76=-80dBm when CC2530 operated alone or with CC2591 in LGM */
#define CCA_THR_HGM                   0x06   /* 6-76=-70dBm when CC2530 operated with CC2591 in HGM */
#define CCA_THR_MINUS_20              0x38

/* CCACTRL1 */
#define CCA_OTHER_MODE_11             0x1A
#define CCA_OTHER_MODE_01             0x0A

/* FSMSTATE */
#define FSM_FFCTRL_STATE_RX_INF       31      /* infinite reception state - not documented in datasheet */

/* ADCCON1 */
#define RCTRL1                        BV(3)
#define RCTRL0                        BV(2)
#define RCTRL_BITS                    (RCTRL1 | RCTRL0)
#define RCTRL_CLOCK_LFSR              RCTRL0

/* CSPCTRL */
#define CPU_CTRL                      BV(0)
#define CPU_CTRL_ON                   CPU_CTRL
#define CPU_CTRL_OFF                  (!(CPU_CTRL))

/* TXFILTCFG */
#define TXFILTCFG                     XREG( 0x61FA )
#define TXFILTCFG_RESET_VALUE         0x09

#define MAC_RADIO_CC2530
#define MAC_RADIO_FEATURE_HARDWARE_OVERFLOW_NO_ROLLOVER

#define MAC_RADIO_CHANNEL_DEFAULT               11
#define MAC_RADIO_CHANNEL_INVALID               0xFF
#define MAC_RADIO_TX_POWER_INVALID              0xFF

#define MAC_RADIO_RECEIVER_SENSITIVITY_DBM      -97 /* dBm */
#define MAC_RADIO_RECEIVER_SATURATION_DBM       10  /* dBm */

#ifdef FEATURE_CC253X_LOW_POWER_RX
#undef  HAL_MAC_RSSI_OFFSET
#define HAL_MAC_RSSI_OFFSET                     -61 /* no unit */
#endif

/* offset applied to hardware RSSI value to get RF power level in dBm units */
#define MAC_RADIO_RSSI_OFFSET                   HAL_MAC_RSSI_OFFSET

#if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590 || \
    defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
# define MAC_RADIO_RSSI_LNA_OFFSET(x)            st(  x += macRadioDefsRssiAdj[macRadioDefsRefTableId&0x0F]; )
#else
# define MAC_RADIO_RSSI_LNA_OFFSET(x)
#endif

/* precise values for small delay on both receive and transmit side */
#define MAC_RADIO_RX_TX_PROP_DELAY_MIN_USEC     3.076  /* usec */
#define MAC_RADIO_RX_TX_PROP_DELAY_MAX_USEC     3.284  /* usec */

/* register value table offset */
#define MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY   0
#define MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY    1
#define MAC_RADIO_DEFS_TBL_TXPWR_ENTRIES       2

/* RF observable control register value to output PA signal */
#define RFC_OBS_CTRL_PA_PD_INV        0x68

/* RF observable control register value to output LNA signal */
#define RFC_OBS_CTRL_LNAMIX_PD_INV    0x6A

/* RF observable control register value to output LNA signal 
 * for CC2591 compression workaround. 
 */
#define RFC_OBS_CTRL_DEMOD_CCA        0x0D

/* OBSSELn register value to select RF observable 0 */
#define OBSSEL_OBS_CTRL0             0xFB

/* OBSSELn register value to select RF observable 1 */
#define OBSSEL_OBS_CTRL1             0xFC

#define MAC_RADIO_MCU_INIT()                          macMcuInit()

#define MAC_RADIO_TURN_ON_POWER()                     macRadioTurnOnPower()
#define MAC_RADIO_TURN_OFF_POWER()                    macRadioTurnOffPower()
#define MAC_RADIO_TURN_ON_OSC()                       MAC_ASSERT(SLEEPSTA & XOSC_STB)/* oscillator should already be stable, it's mcu oscillator too */
#define MAC_RADIO_TURN_OFF_OSC()                      /* don't do anything, oscillator is also mcu oscillator */

#define MAC_RADIO_RX_FIFO_HAS_OVERFLOWED()            ((FSMSTAT1 & FIFOP) && !(FSMSTAT1 & FIFO))
#define MAC_RADIO_RX_FIFO_IS_EMPTY()                  (!(FSMSTAT1 & FIFO) && !(FSMSTAT1 & FIFOP))

#define MAC_RADIO_SET_RX_THRESHOLD(x)                 st( FIFOPCTRL = ((x)-1); )
#define MAC_RADIO_RX_IS_AT_THRESHOLD()                (FSMSTAT1 & FIFOP)
#define MAC_RADIO_ENABLE_RX_THRESHOLD_INTERRUPT()     MAC_MCU_FIFOP_ENABLE_INTERRUPT()
#define MAC_RADIO_DISABLE_RX_THRESHOLD_INTERRUPT()    MAC_MCU_FIFOP_DISABLE_INTERRUPT()
#define MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG() MAC_MCU_FIFOP_CLEAR_INTERRUPT()

#define MAC_RADIO_TX_ACK()                            MAC_RADIO_TURN_OFF_PENDING_OR()
#define MAC_RADIO_TX_ACK_PEND()                       MAC_RADIO_TURN_ON_PENDING_OR()

#define MAC_RADIO_RX_ON()                             st( RFST = ISRXON;    )
#define MAC_RADIO_RXTX_OFF()                          st( RFST = ISRFOFF;   )
#define MAC_RADIO_FLUSH_RX_FIFO()                     st( RFST = ISFLUSHRX; RFST = ISFLUSHRX; )
#define MAC_RADIO_FLUSH_TX_FIFO()                     st( RFST = ISFLUSHTX; )

#define MAC_RADIO_READ_RX_FIFO(pData,len)             macMemReadRxFifo((pData),(uint8)(len))
#define MAC_RADIO_WRITE_TX_FIFO(pData,len)            macMemWriteTxFifo((pData),(uint8)(len))

#define MAC_RADIO_SET_PAN_COORDINATOR(b)              st( FRMFILT0 = (FRMFILT0 & ~PAN_COORDINATOR) | (PAN_COORDINATOR * (b!=0)); )
#define MAC_RADIO_SET_CHANNEL(x)                      st( FREQCTRL = FREQ_2405MHZ + 5 * ((x) - 11); )
#define MAC_RADIO_SET_TX_POWER(x)                     st( TXPOWER = x; )

#define MAC_RADIO_SET_PAN_ID(x)                       st( PAN_ID0 = (x) & 0xFF; PAN_ID1 = (x) >> 8; )
#define MAC_RADIO_SET_SHORT_ADDR(x)                   st( SHORT_ADDR0 = (x) & 0xFF; SHORT_ADDR1 = (x) >> 8; )
#define MAC_RADIO_SET_IEEE_ADDR(p)                    macMemWriteRam((macRam_t *) &EXT_ADDR0, p, 8)

#define MAC_RADIO_REQUEST_ACK_TX_DONE_CALLBACK()      st( MAC_MCU_TXACKDONE_CLEAR_INTERRUPT(); MAC_MCU_TXACKDONE_ENABLE_INTERRUPT(); )
#define MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK()       MAC_MCU_TXACKDONE_DISABLE_INTERRUPT()

#define MAC_RADIO_RANDOM_BYTE()                       macMcuRandomByte()
#define MAC_RADIO_RANDOM_WORD()                       macMcuRandomWord()

#define MAC_RADIO_TX_RESET()                          macCspTxReset()
#define MAC_RADIO_TX_PREP_CSMA_UNSLOTTED()            macCspTxPrepCsmaUnslotted()
#define MAC_RADIO_TX_PREP_CSMA_SLOTTED()              macCspTxPrepCsmaSlotted()
#define MAC_RADIO_TX_PREP_SLOTTED()                   macCspTxPrepSlotted()
#define MAC_RADIO_TX_GO_CSMA()                        macCspTxGoCsma()
#define MAC_RADIO_TX_GO_SLOTTED()                     macCspTxGoSlotted()
#define MAC_RADIO_TX_GO_SLOTTED_CSMA()                macCspTxGoCsma()

#define MAC_RADIO_FORCE_TX_DONE_IF_PENDING()          macCspForceTxDoneIfPending()

#define MAC_RADIO_TX_REQUEST_ACK_TIMEOUT_CALLBACK()   macCspTxRequestAckTimeoutCallback()
#define MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK()    macCspTxCancelAckTimeoutCallback()

#define MAC_RADIO_TIMER_TICKS_PER_USEC()              HAL_CPU_CLOCK_MHZ /* never fractional */
#define MAC_RADIO_TIMER_TICKS_PER_BACKOFF()           (HAL_CPU_CLOCK_MHZ * MAC_SPEC_USECS_PER_BACKOFF)
#define MAC_RADIO_TIMER_TICKS_PER_SYMBOL()            (HAL_CPU_CLOCK_MHZ * MAC_SPEC_USECS_PER_SYMBOL)

#define MAC_RADIO_TIMER_CAPTURE()                     macMcuTimerCapture()
#define MAC_RADIO_TIMER_FORCE_DELAY(x)                macMcuTimerForceDelay(x)

#define MAC_RADIO_TIMER_SLEEP()                       st( T2CTRL &= ~TIMER2_RUN; while(T2CTRL & TIMER2_STATE); )
#define MAC_RADIO_TIMER_WAKE_UP()                     st( HAL_CLOCK_STABLE(); \
                                                          T2CTRL |= (TIMER2_RUN | TIMER2_SYNC); \
                                                          while(!(T2CTRL & TIMER2_STATE)); )

#define MAC_RADIO_BACKOFF_COUNT()                     macMcuOverflowCount()
#define MAC_RADIO_BACKOFF_CAPTURE()                   macMcuOverflowCapture()
#define MAC_RADIO_BACKOFF_SET_COUNT(x)                macMcuOverflowSetCount(x)
#define MAC_RADIO_BACKOFF_SET_COMPARE(x)              macMcuOverflowSetCompare(x)

#define MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT()    st( T2IRQF  = ~TIMER2_OVF_COMPARE1F; )
#define MAC_RADIO_BACKOFF_COMPARE_ENABLE_INTERRUPT()   st( T2IRQM |= TIMER2_OVF_COMPARE1M; )
#define MAC_RADIO_BACKOFF_COMPARE_DISABLE_INTERRUPT()  st( T2IRQM &= ~TIMER2_OVF_COMPARE1M; )

#define MAC_RADIO_BACKOFF_SET_PERIOD(x)               macMcuOverflowSetPeriod(x)
#define MAC_RADIO_BACKOFF_PERIOD_CLEAR_INTERRUPT()    st( T2IRQF  = ~TIMER2_OVF_PERF; )
#define MAC_RADIO_BACKOFF_PERIOD_ENABLE_INTERRUPT()   st( T2IRQM |= TIMER2_OVF_PERM; )
#define MAC_RADIO_BACKOFF_PERIOD_DISABLE_INTERRUPT()  st( T2IRQM &= ~TIMER2_OVF_PERM; )

#define MAC_RADIO_RECORD_MAX_RSSI_START()             macMcuRecordMaxRssiStart()
#define MAC_RADIO_RECORD_MAX_RSSI_STOP()              macMcuRecordMaxRssiStop()

#define MAC_RADIO_TURN_ON_RX_FRAME_FILTERING()        st( FRMFILT0  = 0; \
                                                          FRMFILT0 |= (FRAME_FILTER_EN | FRAME_FILTER_MAX_VERSION); )
#define MAC_RADIO_TURN_OFF_RX_FRAME_FILTERING()       st( FRMFILT0 &= ~FRAME_FILTER_EN; )


#define MAC_RADIO_TURN_ON_AUTO_ACK()                  st( FRMCTRL0 |= AUTOACK; )
#define MAC_RADIO_CANCEL_TX_ACK()                     st( RFST = ISNACK; )

#define MAC_RADIO_TURN_ON_SRC_MATCH()                 st( SRCMATCH |= SRC_MATCH_EN; )
#define MAC_RADIO_TURN_ON_AUTOPEND()                  st( SRCMATCH |= AUTOPEND; )
#define MAC_RADIO_IS_AUTOPEND_ON()                    ( SRCMATCH & AUTOPEND )
#define MAC_RADIO_SRC_MATCH_RESINDEX(p)               st( p = SRCRESINDEX; )

#define MAC_RADIO_TURN_ON_PENDING_OR()                st( FRMCTRL1 |= PENDING_OR; )
#define MAC_RADIO_TURN_OFF_PENDING_OR()               st( FRMCTRL1 &= ~PENDING_OR; )

#define MAC_RADIO_SRC_MATCH_GET_EN()                  macSrcMatchGetEnableBit()
#define MAC_RADIO_SRC_MATCH_GET_PENDEN()              macSrcMatchGetPendEnBit()

#define MAC_RADIO_GET_SRC_SHORTPENDEN(p)              macMemReadRam( (uint8*)&SRCSHORTPENDEN0, (p), 3 )
#define MAC_RADIO_GET_SRC_EXTENPEND(p)                macMemReadRam( (uint8*)&SRCEXTPENDEN0, (p), 3 )
#define MAC_RADIO_GET_SRC_SHORTEN(p)                  macMemReadRam( (uint8*)&SRCSHORTEN0, (p), 3 )
#define MAC_RADIO_GET_SRC_EXTEN(p)                    macMemReadRam( (uint8*)&SRCEXTEN0, (p), 3 )

#define MAC_RADIO_SRC_MATCH_SET_SHORTPENDEN(p)        macMemWriteRam( (uint8*)&SRCSHORTPENDEN0, (p), 3 )
#define MAC_RADIO_SRC_MATCH_SET_EXTPENDEN(p)          macMemWriteRam( (uint8*)&SRCEXTPENDEN0, (p), 3 )
#define MAC_RADIO_SRC_MATCH_SET_SHORTEN(x)            osal_buffer_uint24( (uint8*)&SRCSHORTEN0, (x) )
#define MAC_RADIO_SRC_MATCH_SET_EXTEN(x)              osal_buffer_uint24( (uint8*)&SRCEXTEN0, (x) )
#define MAC_RADIO_SRC_MATCH_RESULT()                  MAC_SrcMatchCheckResult()

#define MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN()          st( SRCEXTPENDEN0 = 0; \
                                                          SRCEXTPENDEN1 = 0; \
                                                          SRCEXTPENDEN2 = 0; )
#define MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN()        st( SRCSHORTPENDEN0 = 0; \
                                                          SRCSHORTPENDEN1 = 0; \
                                                          SRCSHORTPENDEN2 = 0; )

#define MAC_RADIO_SRC_MATCH_TABLE_WRITE(offset, p, len)    macMemWriteRam( (macRam_t *)(SRC_ADDR_TABLE + (offset)), (p), (len) )
#define MAC_RADIO_SRC_MATCH_TABLE_READ(offset, p, len)     macMemReadRam( SRC_ADDR_TABLE + (offset), (p), (len))


//#define HAL_PA_LNA_RX_HGM()                           st( P0_7 = 1; )
//#define HAL_PA_LNA_RX_LGM()                           st( P0_7 = 0; ) andy del pa
#define HAL_PA_LNA_RX_HGM()
#define HAL_PA_LNA_RX_LGM()

#ifdef CC2591_COMPRESSION_WORKAROUND
/* If your PCB reference design is based on CC2530-CC2591EM rev 2.0 or prior, contact TI customer support for details. 
 * Basically, switch the external LNA control from internal LNAMIX to CCA. Note taht this workaround is not 
 * intended for MSP430+CC2520.
 */
#define COMPRESSION_WORKAROUND_ON()                   st( CCACTRL0      =  CCA_THR_MINUS_20;       \
                                                          CCACTRL1      =  CCA_OTHER_MODE_01;      \
                                                          FRMCTRL0     |=  ENERGY_SCAN;            \
                                                          RFC_OBS_CTRL1 =  RFC_OBS_CTRL_DEMOD_CCA; \
                                                          OBSSEL4       =  OBSSEL_OBS_CTRL1; )

#define COMPRESSION_WORKAROUND_OFF()                  st( CCACTRL0      =  CCA_THR;                    \
                                                          CCACTRL1      =  CCA_OTHER_MODE_11;          \
                                                          FRMCTRL0     &= ~ENERGY_SCAN;                \
                                                          RFC_OBS_CTRL1 =  RFC_OBS_CTRL_LNAMIX_PD_INV; \
                                                          OBSSEL4       =  OBSSEL_OBS_CTRL1; ) 

#define COMPRESSION_WORKAROUND_RESET_RSSI()           st( FRMCTRL0     &= ~ENERGY_SCAN;            \
                                                          asm("NOP");                              \
                                                          asm("NOP");                              \
                                                          FRMCTRL0     |=  ENERGY_SCAN; )

#else
#define COMPRESSION_WORKAROUND_ON()                   /* Nothing */
#define COMPRESSION_WORKAROUND_OFF()                  /* Nothing */
#define COMPRESSION_WORKAROUND_RESET_RSSI()           /* Nothing */
#endif /* CC2591_COMPRESSION_WORKAROUND */

extern uint8 macRadioDefsRefTableId;
extern const uint8 CODE *const CODE macRadioDefsTxPwrTables[];
extern const int8 CODE macRadioDefsRssiAdj[];
extern const uint8 CODE macRadioDefsTxPwrBare[];
MAC_INTERNAL_API void macRadioTurnOnPower(void);
MAC_INTERNAL_API void macRadioTurnOffPower(void);
//#define HAL_MAC_USE_REGISTER_POWER_VALUES

#endif

mac__rffrontend.c
#include "hal_types.h"
#include "hal_board_cfg.h"
#include "hal_assert.h"
#include "mac_api.h"
#include "mac_radio_defs.h"
/* The following table index definitions are specific to a particular MAC build */
#define MAC_CC2591_TX_PWR_TABLE_IDX   1
#define MAC_CC2590_TX_PWR_TABLE_IDX   2
#define MAC_CC2591_HGM_RSSI_ADJ_IDX   1
#define MAC_CC2591_LGM_RSSI_ADJ_IDX   2
#define MAC_CC2590_HGM_RSSI_ADJ_IDX   3
#define MAC_CC2590_LGM_RSSI_ADJ_IDX   4

void MAC_RfFrontendSetup(void);
void MAC_RfFrontendSetup(void)
{

  HAL_PA_LNA_RX_HGM();
 
  CCACTRL0 = CCA_THR_HGM;

  /* Select power register value table and RSSI adjustment value table */
  MAC_SetRadioRegTable(MAC_CC2591_TX_PWR_TABLE_IDX, MAC_CC2591_HGM_RSSI_ADJ_IDX);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃橘子的橘猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值