/******************************************************************************
MRF24WB0M Driver Medium Access Control (MAC) Layer
Module for Microchip TCP/IP Stack
-Provides access to MRF24WB0M WiFi controller
-Reference: MRF24WB0M Data sheet, IEEE 802.11 Standard
*******************************************************************************
FileName: WFMac.c
Dependencies: TCP/IP Stack header files
Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
Compiler: Microchip C32 v1.10b or higher
Microchip C30 v3.22 or higher
Microchip C18 v3.34 or higher
Company: Microchip Technology, Inc.
Software License Agreement
Copyright (C) 2002-2010 Microchip Technology Inc. All rights reserved.
Microchip licenses to you the right to use, modify, copy, and distribute:
(i) the Software when embedded on a Microchip microcontroller or digital
signal controller product ("Device") which is integrated into
Licensee's product; or
(ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device used in
conjunction with a Microchip ethernet controller for the sole purpose
of interfacing with the ethernet controller.
You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.
THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL,
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST
OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS BY
THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS
FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON
THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR
OTHERWISE.
Author Date Comment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Michael Palladino 10/13/07 Original
KO 31 Oct 2008 Port to PIC24F and PIC32 for TCP/IP stack v4.52
KH 19 Jun 2009 Modified MACMemCopyAsync to support TCB to TCB copy
******************************************************************************/
/*
*********************************************************************************************************
* INCLUDES
*********************************************************************************************************
*/
#include "TCPIP Stack/WFMac.h"
#if defined(WF_CS_TRIS)
#include "TCPIP Stack/TCPIP.h"
/*
*********************************************************************************************************
* DEFINES
*********************************************************************************************************
*/
/* used for assertions */
#ifdef WF_DEBUG
#define WF_MODULE_NUMBER WF_MODULE_WF_MAC
#endif
#define SNAP_VAL (0xaa)
#define SNAP_CTRL_VAL (0x03)
#define SNAP_TYPE_VAL (0x00)
#define ETHER_IP (0x00)
#define ETHER_ARP (0x06)
#if defined( __PIC32MX__ )
#define IPL_MASK ((UINT32)0x3f << 10)
#endif
#define SNAP_SIZE (6)
#define ENC_PREAMBLE_SIZE (sizeof(ENC_PREAMBLE))
#define ENC_PREAMBLE_OFFSET (10)
#define WF_RX_PREAMBLE_SIZE (sizeof(tWFRxPreamble))
#define WF_TX_PREAMBLE_OFFSET (0)
#define WF_TX_PREAMBLE_SIZE (sizeof(tWFTxPreamble))
#define MCHP_DATA_PACKET_SIZE (4 + MAX_PACKET_SIZE + 4)
//============================================================================
// Rx/Tx Buffer Constants
// Used to correlate former Ethernet packets to MRF24WB0M packets.
//============================================================================
#define ENC_RX_BUF_TO_RAW_RX_BUF_ADJUSTMENT ((RXSTART + ENC_PREAMBLE_SIZE) - (ENC_PREAMBLE_OFFSET + WF_RX_PREAMBLE_SIZE))
#define ENC_TX_BUF_TO_RAW_TX_BUF_ADJUSTMENT ((TXSTART + WF_TX_PREAMBLE_SIZE) - (WF_TX_PREAMBLE_OFFSET + WF_TX_PREAMBLE_SIZE))
#define ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT (BASE_TCB_ADDR)
//============================================================================
// RAW Constants
//============================================================================
#define ENC_RD_PTR_ID (0)
#define ENC_WT_PTR_ID (1)
/*
*********************************************************************************************************
* LOCAL MACROS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
typedef struct
{
UINT8 type;
UINT8 subType;
} tRxPreamble;
/* A header appended at the start of all RX frames by the hardware */
typedef struct _ENC_PREAMBLE
{
WORD NextPacketPointer;
RXSTATUS StatusVector;
MAC_ADDR DestMACAddr;
MAC_ADDR SourceMACAddr;
WORD_VAL Type;
} ENC_PREAMBLE;
typedef struct
{
UINT8 snap[SNAP_SIZE];
MAC_ADDR DestMACAddr;
MAC_ADDR SourceMACAddr;
WORD_VAL Type;
} tWFRxPreamble;
typedef struct
{
UINT8 reserved[4];
} tWFTxPreamble;
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
static BOOL g_wasDiscarded;
static UINT8 g_encPtrRAWId[2]; /* indexed by ENC_RD_PTR_ID (0) and ENC_WT_PTR_ID (1). Values can be: */
/* RAW_RX_ID, RAW_TX_ID, BACKE_TCB_ADDR, RAW_INVALID_ID */
/* keeps track of ENC read and write indexes */
static UINT16 g_encIndex[2]; /* index 0 stores current ENC read index, index 1 stores current ENC write index */
static UINT16 g_rxBufferSize;
static UINT16 g_txPacketLength;
static BOOL g_txBufferFlushed;
static BOOL g_mgmtRxInProgress = FALSE;
static BOOL g_mgmtAppWaiting = FALSE;
#if 0
static UINT16 g_sizeofScratchMemory = 0;
#endif
BOOL g_rxIndexSetBeyondBuffer; // debug -- remove after test
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static BOOL isMgmtTxBufAvailable(void);
static UINT16 MACIFService(void);
/*****************************************************************************
* FUNCTION: SyncENCPtrRAWState
*
* RETURNS: None
*
* PARAMS:
* encPtrId -- Identifies if trying to do a read or write to ENC RAM (RAW Window).
* Values are ENC_RD_PTR_ID, ENC_WT_PTR_ID. g_encIndex[] must be
* valid before this function is called.
*
* NOTES: Any time stack code changes the index within the 'logical' Ethernet RAM
* this function must be called to assure the RAW driver is synced up with
* where the stack code thinks it is within the Ethernet RAM. This applies
* to reading/writing tx data, rx data, or tcb data
*****************************************************************************/
static void SyncENCPtrRAWState(UINT8 encPtrId)
{
UINT8 rawId;
UINT16 rawIndex;
UINT16 byteCount;
UINT32 startTickCount;
UINT32 maxAllowedTicks;
EnsureWFisAwake();
/*----------------------------------------------------*/
/* if encPtr[encPtrId] in the enc rx or enc tx buffer */
/*----------------------------------------------------*/
if ( g_encIndex[encPtrId] < BASE_TCB_ADDR )
{
/*--------------------------------------*/
/* if encPtr[encPtrId] in enc Rx buffer */
/*--------------------------------------*/
if ( g_encIndex[encPtrId] < TXSTART )
{
/* set the rawId */
rawId = RAW_RX_ID;
/* Convert encPtr index to Raw Index */
rawIndex = g_encIndex[encPtrId] - ENC_RX_BUF_TO_RAW_RX_BUF_ADJUSTMENT;
// encPtr[encPtrId] < (RXSTART + ENC_PREAMBLE_SIZE) is an error since we don't have
// the same preamble as the ENC chip
WF_ASSERT( g_encIndex[encPtrId] >= (RXSTART + ENC_PREAMBLE_SIZE) );
}
/*----------------------------------------*/
/* else encPtr[encPtrId] in enc Tx buffer */
/*----------------------------------------*/
else
{
/* if the Tx data raw window has not yet been allocated (the stack is accessing a new Tx data packet) */
if ( !RawWindowReady[RAW_TX_ID] )
{
/* Before we enter the while loop, get the tick timer count and save it */
maxAllowedTicks = TICKS_PER_SECOND / 2; /* 500 ms timeout */
startTickCount = (UINT32)TickGet();
/* Retry until MRF24WB0M has drained it's prior TX pkts - multiple sockets & flows can load the MRF24W10 */
/* The AllocateDataTxBuffer call may not succeed immediately. */
while ( !AllocateDataTxBuffer(MCHP_DATA_PACKET_SIZE) )
{
/* If timed out than lock up */
if (TickGet() - startTickCount >= maxAllowedTicks)
{
WF_ASSERT(FALSE); /* timeout occurred */
}
} /* end while */
}
/* set the rawId */
rawId = RAW_TX_ID;
/* convert enc Ptr index to raw index */
rawIndex = g_encIndex[encPtrId] - ENC_TX_BUF_TO_RAW_TX_BUF_ADJUSTMENT;
/* encPtr[encPtrId] < BASE_TX_ADDR is an error since we don't have the same */
/* pre-BASE_TX_ADDR or post tx buffer as the ENC chip */
WF_ASSERT((g_encIndex[encPtrId] >= BASE_TX_ADDR) && (g_encIndex[encPtrId] <= (BASE_TX_ADDR + MAX_PACKET_SIZE)));
}
/* Buffer should always be ready and enc pointer should always be valid. */
/* For the RX buffer this assert can only happen before we have received */
/* the first data packet. For the TX buffer this could only be the case */
/* after a macflush() where we couldn't re-mount a new buffer and before */
/* a macistxready() that successfully re-mounts a new tx buffer. */
WF_ASSERT(RawWindowReady[rawId]);
/*-----------------------------------------------------------------------------*/
/* if the RAW buffer is ready but not mounted, or to put it another way, if */
/* the RAW buffer was saved, needs to be restored, and it is OK to restore it. */
/*-----------------------------------------------------------------------------*/
if (GetRawWindowState(rawId) != WF_RAW_DATA_MOUNTED)
{
/* if the buffer is not mounted then it must be restored from Mem */
/* a side effect is that if the scratch buffer was mounted in the raw */
/* then it will no longer be mounted */
byteCount = PopRawWindow(rawId);
WF_ASSERT(byteCount > 0);
// set the buffer state
SetRawWindowState(rawId, WF_RAW_DATA_MOUNTED);
}
}
/*------------------------------------------------*/
/* else encPtr[encPtrId] is in the enc tcb buffer */
/*------------------------------------------------*/
else
{
/* if Rx Raw Window already mounted onto Scratch */
if ( GetRawWindowState(RAW_RX_ID) == WF_SCRATCH_MOUNTED )
{
rawId = RAW_RX_ID;
}
/* else if Tx Raw Window already mounted onto Scratch */
else if (GetRawWindowState(RAW_TX_ID) == WF_SCRATCH_MOUNTED)
{
rawId = RAW_TX_ID;
}
/* else Scratch not yet mounted, so need to decide which RAW window to use */
else
{
if ( (g_encPtrRAWId[1 - encPtrId]) == RAW_RX_ID )
{
/* use the Tx RAW window to write to scratch */
rawId = RAW_TX_ID;
}
else
{
// the other enc pointer is in use in the tx buffer raw or invalid
// so use the rx buffer raw to mount the scratch buffer
// set the rawId
rawId = RAW_RX_ID;
}
// if we currently have a buffer mounted then we need to save it
// need to check for both data and mgmt packets
if ( (GetRawWindowState(rawId) == WF_RAW_DATA_MOUNTED) || (GetRawWindowState(rawId) == WF_RAW_MGMT_MOUNTED) )
{
PushRawWindow(rawId);
}
// mount the scratch window in the selected raw
ScratchMount(rawId);
}
/* convert Enc ptr index to raw index */
rawIndex = g_encIndex[encPtrId] - ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT;
}
/* Set RAW index. If false is returned this means that index set beyond end of raw window, which */
/* is OK so long as no read or write access is attempted, hence the flag setting. */
if (RawSetIndex(rawId, rawIndex) == FALSE)
{
if ( rawId == RAW_RX_ID )
{
g_rxIndexSetBeyondBuffer = TRUE;
}
}
else
{
if ( rawId == RAW_RX_ID)
{
g_rxIndexSetBeyondBuffer = FALSE;
}
}
// if we fail the set index we should...
// use a case statement to determine the object that is mounted (rawId==0, could be rxbuffer object or scratch object)
// (rawId==1, could be txbuffer or scratch object
// dismount the object in the appropriate manner (rxbuffer ... save operation, txbuffer save operation, scratch save operation)
// set the index to 0
// mark the RawWindowState[rawId] = WF_RAW_UNMOUNTED
// mark the g_encPtrRAWId[encPtrId] = RAW_INVALID_ID
// set the g_encPtrRAWId
g_encPtrRAWId[encPtrId] = rawId;
// if the opposite encPtr was pointing to the raw window
// that was re-configured by this routine then it is
// no longer in sync
if ( g_encPtrRAWId[1-encPtrId] == g_encPtrRAWId[encPtrId] )
{
g_encPtrRAWId[1-encPtrId] = RAW_INVALID_ID;
}
}
#if defined(STACK_CLIENT_MODE) && defined(USE_GRATUITOUS_ARP)
//following is the workaround algorithm for the 11Mbps broadcast bugfix
extern void ARPResolve(IP_ADDR* IPAddr);
int WFArpBroadcastIntervalSec = 5; //interval in seconds, default to 5, can be changed
/*****************************************************************************
* FUNCTION: WFPeriodicGratuitousArp
*
* RETURNS: None
*
* PARAMS:
* None
*
* NOTES: this is a workaround algorithm for a bug appearing on some APs: they broadcasts
ARP Request over basic rate at 11Mpbs, that leaves our devices in dark. Here
we do ARP Request in the beginning for all the memebers in the subnet, then
periodically do Gratuitous ARP to keep ourselves alive with the AP
*****************************************************************************/
void WFPeriodicGratuitousArp(void)
{
static DWORD oldTime = 0, currTime;
if (!MACIsLinked())
{
return;
}
currTime = TickGet();
if ( (currTime < oldTime) //wrap-around case
||
((currTime - oldTime) > WFArpBroadcastIntervalSec*TICK_SECOND)
)
{
ARPResolve(&(AppConfig.MyIPAddr));
oldTime = currTime;
}
}
#endif //defined(STACK_CLIENT_MODE) && defined(USE_GRATUITOUS_ARP)
/*****************************************************************************
* FUNCTION: MACProcess
*
* RETURNS: None
*
* PARAMS:
* None
*
* NOTES: Called form main loop to support 802.11 operations
*****************************************************************************/
void MACProcess(void)
{
// Let 802.11 processes have a chance to run
WFProcess();
/* SG. Deadlock avoidance code when two applications contend for the one tx pipe */
/* ApplicationA is a data plane application, and applicationB is a control plane application */
/* In this scenario, the data plane application could be the WiFi manager, and the control plane application */
/* a sockets application. If the sockets application keeps doing a IsUDPPutReady() and never follows with */
/* a UDPFlush, then the link manager will be locked out. This would be catescrophic if an AP connection */
/* goes down, then the link manager could never re-establish connection. Why? The link manager is a control */
/* plane application, which does mgmt request/confirms. */
/* */
/* Sequence of events: */
/* T0: ApplicationA will issue a call like UDPIsPutReady(), which results in a AllocateDataTxBuffer */
/* T1: ApplicationB attempts a mgmt request with IsTxMbmtReady() call. The call fails. */
/* T3: Stack process runs and does not deallocate the tx pipe from the data plane application. */
/* T4: ApplicationB attempts N+1th time, and fails. */
if ( g_mgmtAppWaiting )
{
if ( GetRawWindowState(RAW_TX_ID) == WF_RAW_DATA_MOUNTED )
{
/* deallocate the RAW on MRF24WB0M - return memory to pool */
DeallocateDataTxBuffer();
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_RX_ID )
{
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_INVALID_ID;
}
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_TX_ID )
{
g_encPtrRAWId[ENC_WT_PTR_ID] = RAW_INVALID_ID;
}
}
/* This else is important in that it gives the main loop one iteration for the mgmt application to get it's timeslice */
/* Otherwise, a data plane task could snatch away the tx pipe again, especially if it's placed before */
/* the link manager in the main()'s while(1) blk. This code is functionally coupled with isRawRxMgmtInProgress() */
/* as it will keep the dataplane application locked out for 1 iteration, until this else is executed on N+2 iteration */
else
{
g_mgmtAppWaiting = FALSE;
}
}
#if defined(STACK_CLIENT_MODE) && defined(USE_GRATUITOUS_ARP)
//following is the workaround algorithm for the 11Mbps broadcast bugfix
WFPeriodicGratuitousArp();
#endif
}
#if 0
/* Not needed, removing to save g_sizeofScratchMemory storage */
/******************************************************************************
* Function: UINT16 WFGetTCBSize(void)
*
* PreCondition: None
*
* Input: None
*
* Output: Number of bytes in the TCB
*
* Side Effects: None
*
* Overview: Returns number of bytes available in TCP Control Block (TCB) so
* higher-layer code can determine if the number of bytes available
* can support the structures designated to be stored in the TCB.
*
* Note: When running with WiFi the TCB is contained in the Scratch Memory
* on the MRF24W.
*****************************************************************************/
UINT16 WFGetTCBSize(void)
{
return g_sizeofScratchMemory;
}
#endif
/******************************************************************************
* Function: void MACInit(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: MACInit sets up the PIC's SPI module and all the
* registers in the MRF24WB0M so that normal operation can
* begin.
*
* Note: None
*****************************************************************************/
void MACInit(void)
{
WF_Init();
}
void RawInit(void)
{
// By default (on latest B2 firmware) Scratch is mounted to RAW 1 after reset. In order to mount it on RAW0
// we need to first unmount it from RAW 1.
ScratchUnmount(RAW_TX_ID);
// mount scratch temporarily to see how many bytes it has, then unmount it
// g_sizeofScratchMemory = ScratchMount(RAW_RX_ID); /* put back in if need to know size of scratch */
ScratchMount(RAW_RX_ID);
ScratchUnmount(RAW_RX_ID);
RawWindowReady[RAW_RX_ID] = FALSE;
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_RX_ID;
g_encIndex[ENC_RD_PTR_ID] = BASE_TCB_ADDR;
// don't mount tx raw at init because it's needed for raw mgmt messages
RawWindowReady[RAW_TX_ID] = FALSE;
SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
g_encPtrRAWId[ENC_WT_PTR_ID] = RAW_INVALID_ID;
g_encIndex[ENC_WT_PTR_ID] = BASE_TX_ADDR; // set tx encode ptr (index) to start of tx buf + 4 bytes
g_wasDiscarded = TRUE; // set state such that last rx packet was discarded
g_rxBufferSize = 0; // current rx buffer length (none) is 0 bytes
g_txPacketLength = 0; // current tx packet length (none) is 0 bytes
g_txBufferFlushed = TRUE; // tx buffer is flushed
// from ENC MAC init
// encWrPtr is left pointing to BASE_TX_ADDR
// encRdPtr is not initialized... we leave it pointing to BASE_TCB_ADDR
g_rxIndexSetBeyondBuffer = FALSE;
}
/******************************************************************************
* Function: BOOL MACIsLinked(void)
*
* PreCondition: None
*
* Input: None
*
* Output: TRUE: If the PHY reports that a link partner is present
* and the link has been up continuously since the last
* call to MACIsLinked()
* FALSE: If the PHY reports no link partner, or the link went
* down momentarily since the last call to MACIsLinked()
*
* Side Effects: None
*
* Overview: Returns the PHSTAT1.LLSTAT bit.
*
* Note: None
*****************************************************************************/
BOOL MACIsLinked(void)
{
return ( WFisConnected() );
}
/******************************************************************************
* Function: BOOL MACIsTxReady(void)
*
* PreCondition: None
*
* Input: None
*
* Output: TRUE: If no Ethernet transmission is in progress
* FALSE: If a previous transmission was started, and it has
* not completed yet. While FALSE, the data in the
* transmit buffer and the TXST/TXND pointers must not
* be changed.
*
* Side Effects: None
*
* Overview: Returns the ECON1.TXRTS bit
*
* Note: None
*****************************************************************************/
BOOL MACIsTxReady(void)
{
BOOL result = TRUE;
/* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */
EnsureWFisAwake();
/* if waiting for a management response then block data tx until */
/* mgmt response received */
if (isRawRxMgmtInProgress())
{
WFProcess(); // allow mgmt message to be received (stack can call this
// function in an infinite loop so need to allow WiFi state
// machines to run.
return FALSE;
}
if ( !RawWindowReady[RAW_TX_ID] )
{
SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_TX_ID )
{
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_INVALID_ID;
}
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_TX_ID )
{
g_encPtrRAWId[ENC_WT_PTR_ID] = RAW_INVALID_ID;
}
// create the new tx buffer
if (!AllocateDataTxBuffer(MCHP_DATA_PACKET_SIZE) )
{
result = FALSE;
}
}
return result;
}
// determines if a RAW Tx buf is ready for a management msg, and if so, creates the RAW tx buffer.
// Returns TRUE if successful, else FALSE.
BOOL WFisTxMgmtReady(void)
{
BOOL res = TRUE;
if (isMgmtTxBufAvailable())
{
// create and mount tx buffer to hold RAW Mgmt packet
if (AllocateMgmtTxBuffer(WF_MAX_TX_MGMT_MSG_SIZE))
{
res = TRUE;
/* Bug. This flag must be set otherwise the data path does not know */
/* that the tx pipe has been mounted for mgmt operation. SG */
SetRawRxMgmtInProgress(TRUE);
}
else
{
res = FALSE;
}
}
// else Tx RAW not available for Mgmt packet
else
{
res = FALSE;
/* See comment in MACProcess */
g_mgmtAppWaiting = TRUE;
}
return res;
}
void WFFreeMgmtTx(void)
{
// This flag needs to clear so data path can proceed.
SetRawRxMgmtInProgress(FALSE);
}
static BOOL isMgmtTxBufAvailable(void)
{
// if the Tx RAW buf is not being used for a data packet or scratch, then it
// is available for a Mgmt packet.
if ((RawWindowReady[RAW_TX_ID] == FALSE)
&&
((GetRawWindowState(RAW_TX_ID) == WF_RAW_UNMOUNTED) || (GetRawWindowState(RAW_TX_ID) == WF_SCRATCH_MOUNTED)))
{
SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
return TRUE;
}
else
{
return FALSE;
}
}
BOOL SendRAWManagementFrame(UINT16 bufLen)
{
/* Instruct WF chip to transmit the packet data in the raw window */
RawSendTxBuffer(bufLen);
/* let tx buffer be reused (for either data or management tx) */
WFFreeMgmtTx();
return TRUE;
}
// returns TRUE if able to acquire the RAW Rx window for the purpose
// of processing a management receive message
BOOL RawGetMgmtRxBuffer(UINT16 *p_numBytes)
{
BOOL res = TRUE;
// UINT16 numBytes;
*p_numBytes = 0;
// if Raw Rx is not currently mounted, or the Scratch is mounted
if (GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED)
{
// save whatever was mounted to Raw Rx
PushRawWindow(RAW_RX_ID);
}
// mount the mgmt pool rx data, returns number of bytes in mgmt msg. Index
// defaults to 0.
*p_numBytes = RawMountRxBuffer();
/* Should never receive a mgmt msg with 0 bytes */
WF_ASSERT(*p_numBytes > 0);
// set flag so we do not try to mount an incoming data packet until after the rx Mgmt msg
// has been handled.
SetRawRxMgmtInProgress(TRUE);
return res;
}
void SetRawRxMgmtInProgress(BOOL action)
{
if (action == FALSE)
{
// RawWindowReady[RAW_RX_ID] = TRUE;
SetRawWindowState(RAW_RX_ID, WF_RAW_UNMOUNTED);
}
g_mgmtRxInProgress = action;
}
BOOL isRawRxMgmtInProgress(void)
{
return g_mgmtRxInProgress; // RawMgtmAppWaiting flag not needed and was causing problems
}
/******************************************************************************
* Function: void MACDiscardRx(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Marks the last received packet (obtained using
* MACGetHeader())as being processed and frees the buffer
* memory associated with it
*
* Note: It is safe to call this function multiple times between
* MACGetHeader() calls. Extra packets won't be thrown away
* until MACGetHeader() makes it available.
*****************************************************************************/
void MACDiscardRx(void)
{
g_wasDiscarded = TRUE;
}
/******************************************************************************
* Function: WORD MACGetFreeRxSize(void)
*
* PreCondition: None
*
* Input: None
*
* Output: A WORD estimate of how much RX buffer space is free at
* the present time.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
*****************************************************************************/
WORD MACGetFreeRxSize(void)
{
WORD size;
if ( g_wasDiscarded )
{
size = RXSIZE - 1;
}
else
{
if ( (RXSTOP - RXSTART) > g_rxBufferSize )
{
size = (RXSTOP - RXSTART) - g_rxBufferSize;
}
else
{
size = 0;
}
}
return size;
}
/*****************************************************************************
* FUNCTION: MACIFService
*
*
* RETURNS: Number of bytes in the Data Rx packet if one is received, else 0.
*
* PARAMS: None
*
* NOTES: Called by MACGetHeader() to see if any data packets have been received.
* If the MRF24WB0M has received a data packet and the data packet is not
* a management data packet, then this function returns the number of
* bytes in the data packet. Otherwise it returns 0.
*****************************************************************************/
static UINT16 MACIFService(void)
{
UINT16 byteCount = 0; /* num bytes returned */
tRxPreamble wfPreamble;
// if no rx data packet to process or not yet finished with mgmt rx processing
if (!g_HostRAWDataPacketReceived)
{
return byteCount;
}
/* if made it here then External interrupt has signalled a data packet has been received */
g_HostRAWDataPacketReceived = FALSE; /* clear flag for next data packet */
// made it here if RAW rx data packet to handle, so make sure MRF24WB0M is awake
EnsureWFisAwake();
/* Mount Read FIFO to RAW Rx window. Allows use of RAW engine to read rx data packet. */
/* Function call returns number of bytes in the data packet. */
byteCount = RawMountRxBuffer();
WF_ASSERT(byteCount > 0); /* byte count should never be 0 */
// now that buffer mounted it is safe to reenable interrupts
WF_EintEnable();
RawGetByte(RAW_RX_ID, (UINT8*)&wfPreamble, sizeof(tRxPreamble));
WF_ASSERT(wfPreamble.type == WF_DATA_RX_INDICATE_TYPE);
return byteCount;
}
/******************************************************************************
* Function: BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
*
* PreCondition: None
*
* Input: *remote: Location to store the Source MAC address of the
* received frame.
* *type: Location of a BYTE to store the constant
* MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing
* the contents of the Ethernet type field.
*
* Output: TRUE: If a packet was waiting in the RX buffer. The
* remote, and type values are updated.
* FALSE: If a packet was not pending. remote and type are
* not changed.
*
* Side Effects: Last packet is discarded if MACDiscardRx() hasn't already
* been called.
*
* Overview: None
*
* Note: None
*****************************************************************************/
BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
{
UINT16 len;
tWFRxPreamble header;
g_rxIndexSetBeyondBuffer = FALSE;
/* if we currently have a rx buffer mounted then we need to save it */
if ( GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED )
{
EnsureWFisAwake();
/* save state of Rx RAW window */
PushRawWindow(RAW_RX_ID);
}
/* RAW 0 is now unmounted (and available) */
SetRawWindowState(RAW_RX_ID, WF_RAW_UNMOUNTED);
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_RX_ID )
{
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_INVALID_ID;
}
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_RX_ID )
{
g_encPtrRAWId[ENC_WT_PTR_ID] = RAW_INVALID_ID;
}
len = MACIFService();
if ( len == 0 )
{
return FALSE;
}
/* read preamble header */
RawRead(RAW_RX_ID, ENC_PREAMBLE_OFFSET, WF_RX_PREAMBLE_SIZE, (UINT8 *)&header);
/* as a sanity check verify that the expected bytes contain the SNAP header */
if (!(header.snap[0] == SNAP_VAL &&
header.snap[1] == SNAP_VAL &&
header.snap[2] == SNAP_CTRL_VAL &&
header.snap[3] == SNAP_TYPE_VAL &&
header.snap[4] == SNAP_TYPE_VAL &&
header.snap[5] == SNAP_TYPE_VAL) )
{
/* if a vendor proprietary packet, throw away */
DeallocateDataRxBuffer();
return FALSE;
}
// Make absolutely certain that any previous packet was discarded
g_wasDiscarded = TRUE;
/* we can flush any saved RAW state now by saving and restoring the current rx buffer. */
PushRawWindow(RAW_RX_ID);
PopRawWindow(RAW_RX_ID);
// set RAW pointer to 802.11 payload
RawSetIndex(RAW_RX_ID, (ENC_PREAMBLE_OFFSET + WF_RX_PREAMBLE_SIZE));
g_rxBufferSize = len;
///// RawWindowReady[RAW_RX_ID] = TRUE;
///// SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED);
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_RX_ID;
g_encIndex[ENC_RD_PTR_ID] = RXSTART + sizeof(ENC_PREAMBLE);
// The EtherType field, like most items transmitted on the Ethernet medium
// are in big endian.
header.Type.Val = swaps(header.Type.Val);
// Return the Ethernet frame's Source MAC address field to the caller
// This parameter is useful for replying to requests without requiring an
// ARP cycle.
memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));
// Return a simplified version of the EtherType field to the caller
*type = MAC_UNKNOWN;
if( (header.Type.v[1] == 0x08u) &&
((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
{
*type = header.Type.v[0];
}
// Mark this packet as discardable
g_wasDiscarded = FALSE;
return TRUE;
}
/******************************************************************************
* Function: void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
*
* PreCondition: MACIsTxReady() must return TRUE.
*
* Input: *remote: Pointer to memory which contains the destination
* MAC address (6 bytes)
* type: The constant ETHER_ARP or ETHER_IP, defining which
* value to write into the Ethernet header's type field.
* dataLen: Length of the Ethernet data payload
*
* Output: None
*
* Side Effects: None
*
* Overview: None
*
* Note: Because of the dataLen parameter, it is probably
* advantagous to call this function immediately before
* transmitting a packet rather than initially when the
* packet is first created. The order in which the packet
* is constructed (header first or data first) is not
* important.
*****************************************************************************/
void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
{
UINT8 buf[14];
g_txBufferFlushed = FALSE;
g_txPacketLength = dataLen + (WORD)sizeof(ETHER_HEADER) + WF_TX_PREAMBLE_SIZE;
// Set the SPI write pointer to the beginning of the transmit buffer (post WF_TX_PREAMBLE_SIZE)
g_encIndex[ENC_WT_PTR_ID] = TXSTART + WF_TX_PREAMBLE_SIZE;
SyncENCPtrRAWState(ENC_WT_PTR_ID);
/* write the Ethernet destination address to buffer (6 bytes) */
memcpy(&buf[0], (void *)remote, sizeof(*remote));
/* write snap header to buffer (6 bytes) */
buf[6] = SNAP_VAL;
buf[7] = SNAP_VAL;
buf[8] = SNAP_CTRL_VAL;
buf[9] = SNAP_TYPE_VAL;
buf[10] = SNAP_TYPE_VAL;
buf[11] = SNAP_TYPE_VAL;
/* Write the appropriate Ethernet Type WORD for the protocol being used */
buf[12] = 0x08;
buf[13] = (type == MAC_IP) ? ETHER_IP : ETHER_ARP;
/* write buffer to RAW window */
MACPutArray((BYTE *)buf, sizeof(buf));
}
/******************************************************************************
* Function: void MACFlush(void)
*
* PreCondition: A packet has been created by calling MACPut() and
* MACPutHeader().
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: MACFlush causes the current TX packet to be sent out on
* the Ethernet medium. The hardware MAC will take control
* and handle CRC generation, collision retransmission and
* other details.
*
* Note: After transmission completes (MACIsTxReady() returns TRUE),
* the packet can be modified and transmitted again by calling
* MACFlush() again. Until MACPutHeader() or MACPut() is
* called (in the TX data area), the data in the TX buffer
* will not be corrupted.
*****************************************************************************/
void MACFlush(void)
{
/* this function should not be called if no tx buffer is ready to transmit */
WF_ASSERT(RawWindowReady[RAW_TX_ID]);
/* this function should not be called after the current tx buffer has been transmitted */
WF_ASSERT(!g_txBufferFlushed);
g_txBufferFlushed = TRUE;
/* If the RAW engine is not currently mounted */
if ( GetRawWindowState(RAW_TX_ID) != WF_RAW_DATA_MOUNTED )
{
/* then it must have been saved, so pop it */
PopRawWindow(RAW_TX_ID);
}
// at this point the txbuffer should be mounted and ready to go
/* can't send a tx packet of 0 bytes! */
WF_ASSERT(g_txPacketLength != 0);
SendRAWDataFrame(g_txPacketLength);
// make sure to de-sync any affected pointers
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_TX_ID )
{
g_encPtrRAWId[ENC_RD_PTR_ID] = RAW_INVALID_ID;
}
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_TX_ID )
{
g_encPtrRAWId[ENC_WT_PTR_ID] = RAW_INVALID_ID;
}
}
/******************************************************************************
* Function: void MACSetReadPtrInRx(WORD offset)
*
* PreCondition: A packet has been obtained by calling MACGetHeader() and
* getting a TRUE result.
*
* Input: offset: WORD specifying how many bytes beyond the Ethernet
* header's type field to relocate the SPI read
* pointer.
*
* Output: None
*
* Side Effects: None
*
* Overview: SPI read pointer are updated. All calls to
* MACGet() and MACGetArray() will use these new values.
*
* Note: RXSTOP must be statically defined as being > RXSTART for
* this function to work correctly. In other words, do not
* define an RX buffer which spans the 0x1FFF->0x0000 memory
* boundary.
*****************************************************************************/
void MACSetReadPtrInRx(WORD offset)
{
g_encIndex[ENC_RD_PTR_ID] = RXSTART + sizeof(ENC_PREAMBLE) + offset;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
/******************************************************************************
* Function: WORD MACSetWritePtr(WORD Address)
*
* PreCondition: None
*
* Input: Address: Address to seek to
*
* Output: WORD: Old EWRPT location
*
* Side Effects: None
*
* Overview: SPI write pointer is updated. All calls to
* MACPut() and MACPutArray() will use this new value.
*
* Note: None
*****************************************************************************/
PTR_BASE MACSetWritePtr(PTR_BASE address)
{
PTR_BASE oldVal;
oldVal = g_encIndex[ENC_WT_PTR_ID];
g_encIndex[ENC_WT_PTR_ID] = address;
SyncENCPtrRAWState(ENC_WT_PTR_ID);
return oldVal;
}
/******************************************************************************
* Function: WORD MACSetReadPtr(WORD Address)
*
* PreCondition: None
*
* Input: Address: Address to seek to
*
* Output: WORD: Old ERDPT value
*
* Side Effects: None
*
* Overview: SPI write pointer is updated. All calls to
* MACPut() and MACPutArray() will use this new value.
*
* Note: None
*****************************************************************************/
PTR_BASE MACSetReadPtr(PTR_BASE address)
{
PTR_BASE oldVal;
oldVal = g_encIndex[ENC_RD_PTR_ID];
g_encIndex[ENC_RD_PTR_ID] = address;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
return oldVal;
}
/******************************************************************************
* Function: WORD MACCalcRxChecksum(WORD offset, WORD len)
*
* PreCondition: None
*
* Input: offset - Number of bytes beyond the beginning of the
* Ethernet data (first byte after the type field)
* where the checksum should begin
* len - Total number of bytes to include in the checksum
*
* Output: 16-bit checksum as defined by RFC 793.
*
* Side Effects: None
*
* Overview: This function performs a checksum calculation in the MAC
* buffer itself
*
* Note: None
*****************************************************************************/
WORD MACCalcRxChecksum(WORD offset, WORD len)
{
WORD temp;
UINT16 rdSave;
// Add the offset requested by firmware plus the Ethernet header
temp = RXSTART + sizeof(ENC_PREAMBLE) + offset;
rdSave = g_encIndex[ENC_RD_PTR_ID];
g_encIndex[ENC_RD_PTR_ID] = temp;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
temp = CalcIPBufferChecksum(len);
g_encIndex[ENC_RD_PTR_ID] = rdSave;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
return temp;
}
/******************************************************************************
* Function: void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: destAddr: Destination address in the Ethernet memory to
* copy to. If the MSb is set, the current EWRPT
* value will be used instead.
* sourceAddr: Source address to read from. If the MSb is
* set, the current ERDPT value will be used
* instead.
* len: Number of bytes to copy
*
* Output: Byte read from the MRF24W's RAM
*
* Side Effects: None
*
* Overview: Bytes are asynchrnously transfered within the buffer. Call
* MACIsMemCopyDone() to see when the transfer is complete.
*
* Note: If a prior transfer is already in progress prior to
* calling this function, this function will block until it
* can start this transfer.
*
* If a negative value is used for the sourceAddr or destAddr
* parameters, then that pointer will get updated with the
* next address after the read or write.
*****************************************************************************/
void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
{
UINT16 readSave = 0, writeSave = 0;
BOOL updateWritePointer;
BOOL updateReadPointer;
UINT8 rawScratchId = 0xff; /* garbage value to avoid compiler warning */
UINT8 copyBuf[8];
UINT16 writeIndex, readIndex;
UINT16 bytesLeft;
UINT16 origRawIndex;
if( ((WORD_VAL*)&destAddr)->bits.b15 )
{
updateWritePointer = TRUE;
destAddr = g_encIndex[ENC_WT_PTR_ID];
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
}
else
{
updateWritePointer = FALSE;
writeSave = g_encIndex[ENC_WT_PTR_ID];
g_encIndex[ENC_WT_PTR_ID] = destAddr;
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
if( ((WORD_VAL*)&sourceAddr)->bits.b15 )
{
updateReadPointer = TRUE;
sourceAddr = g_encIndex[ENC_RD_PTR_ID];
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
}
else
{
updateReadPointer = FALSE;
readSave = g_encIndex[ENC_RD_PTR_ID];
g_encIndex[ENC_RD_PTR_ID] = sourceAddr;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
// if copying bytes from TCB to TCB
// This is a special case because we cannot do a RAW copy within the same RAW window
// but we can easily copy Scratch data from one section of Scratch to another section of Scratch.
if ( (len > 0u) && (destAddr >= BASE_TCB_ADDR) && (sourceAddr >= BASE_TCB_ADDR) )
{
bytesLeft = len;
// if Raw Rx window mounted to scratch
if (GetRawWindowState(RAW_RX_ID) == WF_SCRATCH_MOUNTED)
{
rawScratchId = RAW_RX_ID;
}
// else if Raw Tx window mounted to scratch
else if (GetRawWindowState(RAW_TX_ID) == WF_SCRATCH_MOUNTED)
{
rawScratchId = RAW_TX_ID;
}
else
{
WF_ASSERT(FALSE); /* this should never happen (that can't mount scratch on either RAW window) */
}
// save the current RAW index in this scratch window
origRawIndex = RawGetIndex(rawScratchId);
// If TCB src block does not overlap TCB dest block, or if destAddr > sourceAddr.
// We can do a forward copy.
if ( ((sourceAddr + len) <= destAddr) || // end of source before dest (no overlap)
((destAddr + len) <= sourceAddr) || // end of dest before source (no overlap)
(destAddr < sourceAddr) // dest before source (overlap)
)
{
// map read index from TCB address to Scratch Index
readIndex = sourceAddr - ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT;
writeIndex = destAddr - ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT;
while (bytesLeft > 0)
{
// if a full copyBuf worth of bytes to copy
if (bytesLeft >= sizeof(copyBuf))
{
RawRead(rawScratchId, readIndex, sizeof(copyBuf), copyBuf);
RawWrite(rawScratchId, writeIndex, sizeof(copyBuf), copyBuf);
// index to next block in source and dest
readIndex += sizeof(copyBuf);
writeIndex += sizeof(copyBuf);
bytesLeft -= sizeof(copyBuf);
}
// else less than a full copyBuf left to copy
else
{
if (bytesLeft > 0)
{
RawRead(rawScratchId, readIndex, bytesLeft, copyBuf);
RawWrite(rawScratchId, writeIndex, bytesLeft, copyBuf);
bytesLeft = 0;
}
}
}
} // end while
// else start of TCB dest block within TCB src block --> destAddr > sourcAddr
// Do a backward copy.
else if (destAddr > sourceAddr)
{
// map read index from TCB address to Scratch Index
readIndex = sourceAddr - ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT + len - 1;
writeIndex = destAddr - ENC_TCB_BUF_TO_RAW_SCRATCH_BUF_ADJUSTMENT + len - 1;
while (bytesLeft > 0)
{
// if a full copyBuf worth of bytes to copy
if (bytesLeft >= sizeof(copyBuf))
{
RawRead(rawScratchId, readIndex - sizeof(copyBuf) + 1, sizeof(copyBuf), copyBuf);
RawWrite(rawScratchId, writeIndex - sizeof(copyBuf) + 1, sizeof(copyBuf), copyBuf);
// index to next block in source and dest
readIndex -= sizeof(copyBuf);
writeIndex -= sizeof(copyBuf);
bytesLeft -= sizeof(copyBuf);
}
// else less than a full copyBuf left to copy
else
{
if (bytesLeft > 0)
{
RawRead(rawScratchId, readIndex - bytesLeft + 1, bytesLeft - 1, copyBuf);
RawWrite(rawScratchId, writeIndex - bytesLeft + 1, bytesLeft - 1, copyBuf);
bytesLeft = 0;
}
}
} // end while
}
// restore raw index to where it was when this function was called
RawSetIndex(rawScratchId, origRawIndex);
}
// else if not copying from TCB to TCB and there is at least one byte to copy
else if ( len > 0)
{
// Check if app is trying to copy data within same RAW window (can't do that)
if ( (g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_INVALID_ID) ||
(g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_INVALID_ID) )
{
WF_ASSERT(FALSE);
}
RawToRawCopy(g_encPtrRAWId[ENC_WT_PTR_ID], len);
}
if ( !updateReadPointer )
{
g_encIndex[ENC_RD_PTR_ID] = readSave;
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
if ( !updateWritePointer )
{
g_encIndex[ENC_WT_PTR_ID] = writeSave;
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
} /* end MACMemCopyAsync */
BOOL MACIsMemCopyDone(void)
{
return TRUE;
}
/******************************************************************************
* Function: BYTE MACGet()
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* ERDPT must point to the place to read from.
*
* Input: None
*
* Output: Byte read from the MRF24W's RAM
*
* Side Effects: None
*
* Overview: MACGet returns the byte pointed to by ERDPT and
* increments ERDPT so MACGet() can be called again. The
* increment will follow the receive buffer wrapping boundary.
*
* Note: None
*****************************************************************************/
BYTE MACGet()
{
BYTE result;
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
RawGetByte(g_encPtrRAWId[ENC_RD_PTR_ID], &result, 1);
g_encIndex[ENC_RD_PTR_ID] += 1;
return result;
}//end MACGet
/******************************************************************************
* Function: WORD MACGetArray(BYTE *val, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* ERDPT must point to the place to read from.
*
* Input: *val: Pointer to storage location
* len: Number of bytes to read from the data buffer.
*
* Output: Byte(s) of data read from the data buffer.
*
* Side Effects: None
*
* Overview: Burst reads several sequential bytes from the data buffer
* and places them into local memory. With SPI burst support,
* it performs much faster than multiple MACGet() calls.
* ERDPT is incremented after each byte, following the same
* rules as MACGet().
*
* Note: None
*****************************************************************************/
WORD MACGetArray(BYTE *val, WORD len)
{
WORD i = 0;
UINT8 byte;
if ( g_encPtrRAWId[ENC_RD_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_RD_PTR_ID);
}
if ( val )
{
RawGetByte(g_encPtrRAWId[ENC_RD_PTR_ID], val, len);
}
else
{
// Read the data
while(i<len)
{
RawGetByte(g_encPtrRAWId[ENC_RD_PTR_ID], &byte, 1);
i++;
}
}
g_encIndex[ENC_RD_PTR_ID] += len;
return len;
}//end MACGetArray
/******************************************************************************
* Function: void MACPut(BYTE val)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* EWRPT must point to the location to begin writing.
*
* Input: Byte to write into the MRF24WB0M buffer memory
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPut outputs the Write Buffer Memory opcode/constant
* (8 bits) and data to write (8 bits) over the SPI.
* EWRPT is incremented after the write.
*
* Note: None
*****************************************************************************/
void MACPut(BYTE val)
{
UINT8 byte = val;
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
RawSetByte(g_encPtrRAWId[ENC_WT_PTR_ID], &byte, 1);
g_encIndex[ENC_WT_PTR_ID] += 1;
}//end MACPut
/******************************************************************************
* Function: void MACPutArray(BYTE *val, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* EWRPT must point to the location to begin writing.
*
* Input: *val: Pointer to source of bytes to copy.
* len: Number of bytes to write to the data buffer.
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPutArray writes several sequential bytes to the
* MRF24WB0M RAM. It performs faster than multiple MACPut()
* calls. EWRPT is incremented by len.
*
* Note: None
*****************************************************************************/
void MACPutArray(BYTE *val, WORD len)
{
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
RawSetByte(g_encPtrRAWId[ENC_WT_PTR_ID], val, len);
g_encIndex[ENC_WT_PTR_ID] += len;
}//end MACPutArray
/******************************************************************************
* Function: void MACPutROMArray(ROM BYTE *val, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* EWRPT must point to the location to begin writing.
*
* Input: *val: Pointer to source of bytes to copy.
* len: Number of bytes to write to the data buffer.
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPutArray writes several sequential bytes to the
* MRF24WB0M RAM. It performs faster than multiple MACPut()
* calls. EWRPT is incremented by len.
*
* Note: None
*****************************************************************************/
#if defined(__18CXX)
void MACPutROMArray(ROM BYTE *val, WORD len)
{
if ( g_encPtrRAWId[ENC_WT_PTR_ID] == RAW_INVALID_ID )
{
SyncENCPtrRAWState(ENC_WT_PTR_ID);
}
RawSetByteROM(g_encPtrRAWId[ENC_WT_PTR_ID], val, len);
g_encIndex[ENC_WT_PTR_ID] += len;
}//end MACPutROMArray
#endif
/******************************************************************************
* Function: void MACPowerDown(void)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPowerDown puts the MRF24WB0M in low power sleep mode. In
* sleep mode, no packets can be transmitted or received.
* All MAC and PHY registers should not be accessed.
*
* Note: If a packet is being transmitted while this function is
* called, this function will block until it is it complete.
* If anything is being received, it will be completed.
*****************************************************************************/
void MACPowerDown(void)
{
}//end MACPowerDown
/******************************************************************************
* Function: void MACPowerUp(void)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPowerUp returns the MRF24WB0M back to normal operation
* after a previous call to MACPowerDown(). Calling this
* function when already powered up will have no effect.
*
* Note: If a link partner is present, it will take 10s of
* milliseconds before a new link will be established after
* waking up. While not linked, packets which are
* transmitted will most likely be lost. MACIsLinked() can
* be called to determine if a link is established.
*****************************************************************************/
void MACPowerUp(void)
{
}//end MACPowerUp
#if 0
/* Not needed for MCHP */
void RawSendUntamperedData(UINT8 *pReq, UINT16 len)
{
BOOL res;
UINT8 preambleBuf[2];
UINT16 byteCount;
if (GetTxRawWindowState() == WF_RAW_DATA_MOUNTED)
{
WF_ASSERT(FALSE);
}
// RAW memory alloc
res = AllocateDataTxBuffer(len);
/* if could not allocate enough bytes */
if (res != TRUE)
{
// Release whatever has been allocated.
DeallocateDataTxBuffer();
WF_ASSERT(FALSE);
}
/* fill out 2 byte preamble of request message */
preambleBuf[0] = WF_DATA_REQUEST_TYPE; // indicate this is a data msg
preambleBuf[1] = WF_UNTAMPERED_DATA_MSG_SUBTYPE; // untampered data subtype
/* write out preamble */
RawWrite(RAW_TX_ID, 0, sizeof(preambleBuf), preambleBuf);
// write out payload
RawSetByte(RAW_TX_ID, (UINT8 *) pReq, len);
// Instruct WF chip to transmit the packet data in the raw window
RawSendTxBuffer(len + sizeof(preambleBuf));
}
#endif
#else
/* dummy func to keep C18 compiler happy when module has no executeable code */
void WFMac_EmptyFunc(void)
{
;
}
#endif /* WF_CS_TRIS*/
|