/* ###################################################################
**     This component module is generated by Processor Expert. Do not modify it.
**     Filename    : McuNRF24L01.c
**     Component   : nRF24L01
**     Version     : Component 01.103, Driver 01.00, CPU db: 3.00.000
**     Compiler    : GNU C Compiler
**     Date/Time   : 2021-07-06, 16:35, # CodeGen: 0
**     Abstract    :
**         This component implements a driver for the Nordic Semiconductor nRF24L01 2.4 GHz transceiver.
**     Settings    :
**     Contents    :
**         ConfigureSPI               - void McuNRF24L01_ConfigureSPI(void);
**         WriteRegister              - void McuNRF24L01_WriteRegister(uint8_t reg, uint8_t val);
**         ReadRegister               - uint8_t McuNRF24L01_ReadRegister(uint8_t reg);
**         ReadRegisterData           - void McuNRF24L01_ReadRegisterData(uint8_t reg, uint8_t *buf, uint8_t bufSize);
**         WriteRegisterData          - void McuNRF24L01_WriteRegisterData(uint8_t reg, uint8_t *buf, uint8_t bufSize);
**         WriteRead                  - uint8_t McuNRF24L01_WriteRead(uint8_t val);
**         Write                      - void McuNRF24L01_Write(uint8_t val);
**         GetStatus                  - uint8_t McuNRF24L01_GetStatus(void);
**         GetStatusClrIRQ            - uint8_t McuNRF24L01_GetStatusClrIRQ(void);
**         ResetStatusIRQ             - void McuNRF24L01_ResetStatusIRQ(uint8_t flags);
**         TxPayload                  - void McuNRF24L01_TxPayload(uint8_t *payload, uint8_t payloadSize);
**         RxPayload                  - void McuNRF24L01_RxPayload(uint8_t *payload, uint8_t payloadSize);
**         StopRxTx                   - void McuNRF24L01_StopRxTx(void);
**         StartRxTx                  - void McuNRF24L01_StartRxTx(void);
**         EnableAutoAck              - uint8_t McuNRF24L01_EnableAutoAck(uint8_t pipes);
**         SetStaticPipePayload       - uint8_t McuNRF24L01_SetStaticPipePayload(uint8_t pipe, uint8_t payloadBytes);
**         EnableDynamicPayloadLength - uint8_t McuNRF24L01_EnableDynamicPayloadLength(uint8_t pipeMask);
**         WriteFeature               - uint8_t McuNRF24L01_WriteFeature(uint8_t featureMask);
**         ReadFeature                - uint8_t McuNRF24L01_ReadFeature(uint8_t *featureMask);
**         ReadNofRxPayload           - uint8_t McuNRF24L01_ReadNofRxPayload(uint8_t *nof);
**         ReadObserveTxRegister      - uint8_t McuNRF24L01_ReadObserveTxRegister(uint8_t *nofLoss, uint8_t *nofRetransmitted);
**         ReadReceivedPowerDetector  - uint8_t McuNRF24L01_ReadReceivedPowerDetector(uint8_t *rpd);
**         SetChannel                 - uint8_t McuNRF24L01_SetChannel(uint8_t channel);
**         GetChannel                 - uint8_t McuNRF24L01_GetChannel(uint8_t *channel);
**         ConstantCarrierWave        - uint8_t McuNRF24L01_ConstantCarrierWave(bool turnOn);
**         SetOutputPower             - uint8_t McuNRF24L01_SetOutputPower(int8_t power);
**         GetOutputPower             - uint8_t McuNRF24L01_GetOutputPower(int8_t *power);
**         SetDataRate                - uint8_t McuNRF24L01_SetDataRate(uint16_t rate);
**         GetDataRate                - uint8_t McuNRF24L01_GetDataRate(uint16_t *rate);
**         SetAddressWidth            - uint8_t McuNRF24L01_SetAddressWidth(uint8_t width);
**         GetAddressWidth            - uint8_t McuNRF24L01_GetAddressWidth(uint8_t *pAddrWidth);
**         SetTxAddress               - uint8_t McuNRF24L01_SetTxAddress(uint8_t *address, uint8_t nofAddressBytes);
**         GetTxAddress               - uint8_t McuNRF24L01_GetTxAddress(uint8_t *address, uint8_t nofAddressBytes);
**         SetRxAddress               - uint8_t McuNRF24L01_SetRxAddress(uint8_t pipe, uint8_t *address, uint8_t...
**         GetRxAddress               - uint8_t McuNRF24L01_GetRxAddress(uint8_t pipe, uint8_t *address, uint8_t...
**         GetFifoStatus              - uint8_t McuNRF24L01_GetFifoStatus(uint8_t *status);
**         PollInterrupt              - bool McuNRF24L01_PollInterrupt(void);
**         Deinit                     - void McuNRF24L01_Deinit(void);
**         Init                       - void McuNRF24L01_Init(void);
**
** * Copyright (c) 2013-2018, Erich Styger
**  * Web:         https://mcuoneclipse.com
**  * SourceForge: https://sourceforge.net/projects/mcuoneclipse
**  * Git:         https://github.com/ErichStyger/McuOnEclipse_PEx
**  * All rights reserved.
**  *
**  * Redistribution and use in source and binary forms, with or without modification,
**  * are permitted provided that the following conditions are met:
**  *
**  * - Redistributions of source code must retain the above copyright notice, this list
**  *   of conditions and the following disclaimer.
**  *
**  * - Redistributions in binary form must reproduce the above copyright notice, this
**  *   list of conditions and the following disclaimer in the documentation and/or
**  *   other materials provided with the distribution.
**  *
**  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
**  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
**  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
**  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
**  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
**  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
**  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
**  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
**  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
**  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** ###################################################################*/
/*!
** @file McuNRF24L01.c
** @version 01.00
** @brief
**         This component implements a driver for the Nordic Semiconductor nRF24L01 2.4 GHz transceiver.
*/         
/*!
**  @addtogroup McuNRF24L01_module McuNRF24L01 module documentation
**  @{
*/         

/* MODULE McuNRF24L01. */

#include "McuNRF24L01.h"
#if McuNRF24L01_CONFIG_IS_ENABLED
#include "McuWait.h"
#include "McuSPI.h"
#include "McuGPIO.h"
#include "McuLog.h"
#include "McuUtility.h"

static McuGPIO_Handle_t cePin;  /* CE pin, HIGH active, if active, device is in RX/TX mode */
static McuGPIO_Handle_t csnPin; /* CSN pin, LOW active, used to select device (chip select) to send commands */

/* Macros to hide low level functionality */
#define McuNRF24L01_WAIT_US(x)  McuWait_Waitus(x)          /* wait for the given number of micro-seconds */
#define McuNRF24L01_CE_LOW()    McuGPIO_SetLow(cePin)      /* put CE LOW */
#define McuNRF24L01_CE_HIGH()   McuGPIO_SetHigh(cePin)     /* put CE HIGH */
#define McuNRF24L01_CSN_LOW()   McuGPIO_SetLow(csnPin)     /* put CSN LOW, activate bus */
#define McuNRF24L01_CSN_HIGH()  McuGPIO_SetHigh(csnPin)    /* put CSN HIGH, deactivate bus */

#define McuNRF24L01_USE_SPI_BLOCK_MODE   0                 /* using SPI block read/write */

#if 0
static void SM1_Enable(void) {
  /*! \todo */
}

static void SM1_Disable(void) {
  /*! \todo */
}

static int SM1_SetShiftClockPolarity(int pol) {
  /*! \todo */
  return ERR_OK;
}

static int SM1_SetIdleClockPolarity(int pol) {
  /*! \todo */
  return ERR_OK;
}

static int SM1_SetBaudRate(int baud) {
  return McuSPI_SetBaudRate(baud);
}
#endif
#if 0
static int SM1_GetCharsInTxBuf(void) {
  return 0;
}

static int SM1_GetCharsInRxBuf(void) {
  return 1;
}

static int SM1_SendChar(unsigned char ch) {
  return McuSPI_SendByte(ch);
}
#endif
void McuNRF24L01_OnActivate(void) {
#if PL_HAS_SPI
  SPI_OnSPIActivate(SPI_BAUD_INDEX_NRF);
#endif
}

void McuNRF24L01_OnDeactivate(void) {
#if PL_HAS_SPI
  SPI_OnSPIDeactivate(SPI_BAUD_INDEX_NRF);
#endif
}

/* HW SPI */
#define McuNRF24L01_SPI_Enable()                   SM1_Enable()
#define McuNRF24L01_SPI_Disable()                  SM1_Disable()
#define McuNRF24L01_SPI_SetShiftClockPolarity(val) (void)SM1_SetShiftClockPolarity(val)
#define McuNRF24L01_SPI_SetIdleClockPolarity(val)  (void)SM1_SetIdleClockPolarity(val)
#define McuNRF24L01_SPI_GetCharsInTxBuf()          SM1_GetCharsInTxBuf()
#define McuNRF24L01_SPI_GetCharsInRxBuf()          SM1_GetCharsInRxBuf()
#define McuNRF24L01_SPI_SendChar(ch)               SM1_SendChar(ch)
#define McuNRF24L01_SPI_RecvChar(p)                McuSPI_ReceiveByte(p)
#define McuNRF24L01_SPI_SetBaudRateMode(m)         SM1_SetBaudRateMode(m)

#if McuNRF24L01_CONFIG_USE_MUTEX
  #include "McuRTOS.h"

  static SemaphoreHandle_t McuNRF24L01_Mutex = NULL; /* Mutex to allow mutual exclusive access to the bus */
#endif
/* Internal method prototypes */
static uint8_t SPIWriteRead(uint8_t val);
static void SPIWriteReadBuffer(uint8_t *bufOut, uint8_t *bufIn, uint8_t bufSize);
static void SPIWriteBuffer(uint8_t *bufOut, uint8_t bufSize);

/*
** ===================================================================
**     Method      :  ConfigureSPI (component nRF24L01)
**
**     Description :
**         Configures the SPI bus
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_ConfigureSPI(void)
{
#if McuNRF24L01_SWITCH_BUS
  (void)McuNRF24L01_SPI_Disable();
  (void)McuNRF24L01_SPI_SetShiftClockPolarity(0); /* falling edge */
  (void)McuNRF24L01_SPI_SetIdleClockPolarity(0); /* low idle clock polarity */
  (void)McuNRF24L01_SPI_SetBaudRateMode(McuNRF24L01_BAUD_RATE_MODE); /* set bus speed */
  McuSPI_SetBaudRate(baud);
  (void)McuNRF24L01_SPI_Enable();
#endif
}

/*
** ===================================================================
**     Method      :  SPIWriteRead (component nRF24L01)
**
**     Description :
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static uint8_t SPIWriteRead(uint8_t val)
{
  uint8_t ch;
#if 0
  while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until tx is empty */
  while(McuNRF24L01_SPI_SendChar(val)!=ERR_OK) {} /* send character */
  while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until data has been sent */
  while(McuNRF24L01_SPI_GetCharsInRxBuf()==0) {} /* wait until we receive data */
  while(McuNRF24L01_SPI_RecvChar(&ch)!=ERR_OK) {} /* get data */
#else
  int res = McuSPI_SendReceiveByte(val, &ch);
  if (res!=0) {
    McuLog_fatal("failed SPI send and receive");
  }
#endif
  return ch;
}

/*
** ===================================================================
**     Method      :  SPIWriteReadBuffer (component nRF24L01)
**
**     Description :
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SPIWriteReadBuffer(uint8_t *bufOut, uint8_t *bufIn, uint8_t bufSize)
{
#if McuNRF24L01_USE_SPI_BLOCK_MODE
  uint16_t snt, rcvd;

  while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until tx is empty */
  while(SPI_SendBlock(bufOut, bufSize, &snt)!=ERR_OK) {
    /* send buffer */
  }
  while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until data has been sent */
  while(McuNRF24L01_SPI_GetCharsInRxBuf()==0) {} /* wait until we receive data */
  while(SPI_RecvBlock(bufIn, bufSize, &rcvd)!=ERR_OK) {
    /* get data */
  }
#else
  uint8_t i;

  for(i=0;i<bufSize;i++) {
    bufIn[i] = SPIWriteRead(bufOut[i]);
  }
#endif
}

/*
** ===================================================================
**     Method      :  SPIWriteBuffer (component nRF24L01)
**
**     Description :
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SPIWriteBuffer(uint8_t *bufOut, uint8_t bufSize)
{
#if McuNRF24L01_USE_SPI_BLOCK_MODE
  uint16_t snt, rcvd;
  static uint8_t dummyBuf[SPI_INP_BUF_SIZE];

  if (bufSize>SPI_INP_BUF_SIZE) { /* not enough dummy buffer */
    uint8_t i;

    for(i=0;i<bufSize;i++) {
      (void)SPIWriteRead(bufOut[i]);
    }
  } else {
    while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until tx is empty */
    while(SPI_SendBlock(bufOut, bufSize, &snt)!=ERR_OK) {
      /* send buffer */
    }
    while(McuNRF24L01_SPI_GetCharsInTxBuf()!=0) {} /* wait until data has been sent */
    while(McuNRF24L01_SPI_GetCharsInRxBuf()==0) {} /* wait until we receive data */
    while(SPI_SPI.RecvBlock(dummyBuf, bufSize, &rcvd)!=ERR_OK) {
      /* get data */
    }
  }
#else
  uint8_t i;

  for(i=0;i<bufSize;i++) {
    (void)SPIWriteRead(bufOut[i]);
  }
#endif
}

/*
** ===================================================================
**     Method      :  Deinit (component nRF24L01)
**
**     Description :
**         Driver deinitialization
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_Deinit(void)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  vQueueUnregisterQueue(McuNRF24L01_Mutex);
  vSemaphoreDelete(McuNRF24L01_Mutex);
  McuNRF24L01_Mutex = NULL;
#endif
}

/*
** ===================================================================
**     Method      :  Init (component nRF24L01)
**
**     Description :
**         Initialization method
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
static void InitCS(void) {
  McuGPIO_Config_t config;

  McuNRF24L01_CONFIG_CE_CSN_PIN_PRE_INIT();
  McuGPIO_GetDefaultConfig(&config);

#if McuLib_CONFIG_CPU_IS_ESP32
  config.hw.pin = McuNRF24L01_CONFIG_CE_PIN_NUMBER;
#elif McuLib_CONFIG_CPU_IS_RPxxxx
  config.hw.pin   = McuNRF24L01_CONFIG_CE_PIN_NUMBER;
#else
  config.hw.gpio  = McuNRF24L01_CONFIG_CE_PIN_GPIO;
  config.hw.port  = McuNRF24L01_CONFIG_CE_PIN_PORT;
  config.hw.pin   = McuNRF24L01_CONFIG_CE_PIN_NUMBER;
#endif
  config.isInput = false;
  config.isHighOnInit = false; /* CE is HIGH active */

  cePin = McuGPIO_InitGPIO(&config);
  if (cePin==NULL) {
    McuLog_fatal("failed initializing SPI CE pin");
    for(;;) {} /* error */
  }

#if McuLib_CONFIG_CPU_IS_ESP32
  config.hw.pin = McuNRF24L01_CONFIG_CSN_PIN_NUMBER;
#elif McuLib_CONFIG_CPU_IS_RPxxxx
  config.hw.pin   = McuNRF24L01_CONFIG_CSN_PIN_NUMBER;
#else
  config.hw.gpio  = McuNRF24L01_CONFIG_CSN_PIN_GPIO;
  config.hw.port  = McuNRF24L01_CONFIG_CSN_PIN_PORT;
  config.hw.pin   = McuNRF24L01_CONFIG_CSN_PIN_NUMBER;
#endif
  config.isInput = false;
  config.isHighOnInit = true; /* CSN is LOW active */

  csnPin = McuGPIO_InitGPIO(&config);
  if (csnPin==NULL) {
    McuLog_fatal("failed initializing SPI CSN pin");
    for(;;) {} /* error */
  }
}

void McuNRF24L01_Init(void)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  #if configSUPPORT_STATIC_ALLOCATION
  static StaticSemaphore_t xMutexBuffer;
  #endif

  #if configSUPPORT_STATIC_ALLOCATION
  McuNRF24L01_Mutex = xSemaphoreCreateRecursiveMutexStatic(&xMutexBuffer);
  #else
  McuNRF24L01_Mutex = xSemaphoreCreateRecursiveMutex();
  #endif
  if (McuNRF24L01_Mutex==NULL) { /* semaphore creation failed */
    for(;;) {} /* error, not enough memory? */
  }
  vQueueAddToRegistry(McuNRF24L01_Mutex, "McuNRF24L01_Mutex");
#endif
  InitCS();
  McuNRF24L01_CE_LOW();   /* CE high: do not send or receive data */
  McuNRF24L01_CSN_HIGH(); /* CSN low: not sending commands to the device */
  McuNRF24L01_ConfigureSPI(); /* set up SPI bus */
}

/*
** ===================================================================
**     Method      :  WriteRegister (component nRF24L01)
**
**     Description :
**         Write a register value to the transceiver
**     Parameters  :
**         NAME            - DESCRIPTION
**         reg             - Register address to write
**         val             - Value to write
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_WriteRegister(uint8_t reg, uint8_t val)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW(); /* initiate command sequence */
  (void)SPIWriteRead(McuNRF24L01_W_REGISTER|reg); /* write register command */
  (void)SPIWriteRead(val); /* write value */
  McuNRF24L01_CSN_HIGH(); /* end command sequence */
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10); /* insert a delay until next command */
  /*lint -restore */
}

/*
** ===================================================================
**     Method      :  ReadRegister (component nRF24L01)
**
**     Description :
**         Reads a register from the transceiver
**     Parameters  :
**         NAME            - DESCRIPTION
**         reg             - Register address
**     Returns     :
**         ---             - value read
** ===================================================================
*/
uint8_t McuNRF24L01_ReadRegister(uint8_t reg)
{
  uint8_t val;

#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW();
  (void)SPIWriteRead(reg);
  val = SPIWriteRead(0); /* write dummy */
  McuNRF24L01_CSN_HIGH();
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10);
  /*lint -restore */
  return val;
}

/*
** ===================================================================
**     Method      :  ReadRegisterData (component nRF24L01)
**
**     Description :
**         Read multiple bytes from the bus.
**     Parameters  :
**         NAME            - DESCRIPTION
**         reg             - Register address
**       * buf             - Pointer to buffer where to store the values
**         bufSize         - Size of the destination buffer
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_ReadRegisterData(uint8_t reg, uint8_t *buf, uint8_t bufSize)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW();
  (void)SPIWriteRead(McuNRF24L01_R_REGISTER|reg);
  SPIWriteReadBuffer(buf, buf, bufSize);
  McuNRF24L01_CSN_HIGH();
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10);
  /*lint -restore */
}

/*
** ===================================================================
**     Method      :  WriteRegisterData (component nRF24L01)
**
**     Description :
**         Write multiple bytes to the bus.
**     Parameters  :
**         NAME            - DESCRIPTION
**         reg             - Register address
**       * buf             - Pointer to data buffer to write
**         bufSize         - Size of buffer in bytes
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_WriteRegisterData(uint8_t reg, uint8_t *buf, uint8_t bufSize)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW();
  (void)SPIWriteRead(McuNRF24L01_W_REGISTER|reg); /* not masking registers as it would conflict with McuNRF24L01_W_TX_PAYLOAD */
  SPIWriteBuffer(buf, bufSize);
  McuNRF24L01_CSN_HIGH();
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10);
  /*lint -restore */
}

/*
** ===================================================================
**     Method      :  WriteRead (component nRF24L01)
**
**     Description :
**         Writes a byte and reads back one byte
**     Parameters  :
**         NAME            - DESCRIPTION
**         val             - Value to write to the bus
**     Returns     :
**         ---             - Value read from the bus
** ===================================================================
*/
uint8_t McuNRF24L01_WriteRead(uint8_t val)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW();
  val = SPIWriteRead(val);
  McuNRF24L01_CSN_HIGH();
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10);
  /*lint -restore */
  return val;
}

/*
** ===================================================================
**     Method      :  Write (component nRF24L01)
**
**     Description :
**         Writes a byte to the bus, without returning the byte read.
**     Parameters  :
**         NAME            - DESCRIPTION
**         val             - Value to write
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_Write(uint8_t val)
{
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW();
  (void)SPIWriteRead(val);
  McuNRF24L01_CSN_HIGH();
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10);
  /*lint -restore */
}

/*
** ===================================================================
**     Method      :  GetStatus (component nRF24L01)
**
**     Description :
**         Returns the device status byte
**     Parameters  : None
**     Returns     :
**         ---             - status byte
** ===================================================================
*/
uint8_t McuNRF24L01_GetStatus(void)
{
  return McuNRF24L01_WriteRead(McuNRF24L01_NOP);
}

/*
** ===================================================================
**     Method      :  ResetStatusIRQ (component nRF24L01)
**
**     Description :
**         Reset the given flags mask of status bits
**     Parameters  :
**         NAME            - DESCRIPTION
**         flags           - Flags, one or more of
**                           RF24_STATUS_RX_DR, RF24_STATUS_TX_DS,
**                           RF24_STATUS_MAX_RT
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_ResetStatusIRQ(uint8_t flags)
{
  McuNRF24L01_WriteRegister(McuNRF24L01_STATUS, flags); /* reset all IRQ in status register */
}

/*
** ===================================================================
**     Method      :  GetStatusClrIRQ (component nRF24L01)
**
**     Description :
**         Returns the device status byte and clears any IRQ bits in
**         the status register.
**     Parameters  : None
**     Returns     :
**         ---             - status byte
** ===================================================================
*/
uint8_t McuNRF24L01_GetStatusClrIRQ(void)
{
  uint8_t status;

#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreTakeRecursive(McuNRF24L01_Mutex, portMAX_DELAY);
#endif
#if McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_SWITCH_BUS
  McuNRF24L01_ConfigureSPI(); /* change bus speed */
#endif
  McuNRF24L01_CSN_LOW(); /* initiate command sequence */
  status = SPIWriteRead(McuNRF24L01_W_REGISTER|McuNRF24L01_STATUS); /* get status */
  (void)SPIWriteRead(status&(McuNRF24L01_STATUS_RX_DR|McuNRF24L01_STATUS_TX_DS|McuNRF24L01_STATUS_MAX_RT)); /* reset IRQ Bits */
  McuNRF24L01_CSN_HIGH(); /* end command sequence */
#if McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
  McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK(); /* call user event */
#endif
#if McuNRF24L01_CONFIG_USE_MUTEX
  (void)xSemaphoreGiveRecursive(McuNRF24L01_Mutex);
#endif
  /*lint -save -e522 function lacks side-effects */
  McuNRF24L01_WAIT_US(10); /* insert a delay until next command */
  /*lint -restore */
  return status;
}

/*
** ===================================================================
**     Method      :  TxPayload (component nRF24L01)
**
**     Description :
**         Send the payload to the Tx FIFO and send it
**     Parameters  :
**         NAME            - DESCRIPTION
**       * payload         - Pointer to buffer with payload to
**                           send
**         payloadSize     - Size of payload buffer
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_TxPayload(uint8_t *payload, uint8_t payloadSize)
{
  McuNRF24L01_Write(McuNRF24L01_FLUSH_TX); /* flush old data */
  McuNRF24L01_WriteRegisterData(McuNRF24L01_W_TX_PAYLOAD, payload, payloadSize); /* write payload */
  McuNRF24L01_CE_HIGH(); /* start transmission */
  /*lint -save -e522 function lacks side effect  */
  McuNRF24L01_WAIT_US(15); /* keep signal high for 15 micro-seconds */
  /*lint -restore */
  McuNRF24L01_CE_LOW();  /* back to normal */
}

void McuNRF24L01_TxPayloadNoAck(uint8_t *payload, uint8_t payloadSize)
{
  McuNRF24L01_Write(McuNRF24L01_FLUSH_TX); /* flush old data */
  McuNRF24L01_WriteRegisterData(McuNRF24L01_W_TX_PAYLOAD_NO_ACK, payload, payloadSize); /* write payload */
  McuNRF24L01_CE_HIGH(); /* start transmission */
  /*lint -save -e522 function lacks side effect  */
  McuNRF24L01_WAIT_US(15); /* keep signal high for 15 micro-seconds */
  /*lint -restore */
  McuNRF24L01_CE_LOW();  /* back to normal */
}
/*
** ===================================================================
**     Method      :  RxPayload (component nRF24L01)
**
**     Description :
**         Receive the Rx payload from the FIFO and stores it in a
**         buffer.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * payload         - Pointer to the payload buffer
**         payloadSize     - Size of the payload buffer
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_RxPayload(uint8_t *payload, uint8_t payloadSize)
{
  McuNRF24L01_CE_LOW(); /* need to disable rx mode during reading RX data */
  McuNRF24L01_ReadRegisterData(McuNRF24L01_R_RX_PAYLOAD, payload, payloadSize); /* rx payload */
  McuNRF24L01_CE_HIGH(); /* re-enable rx mode */
}

/*
** ===================================================================
**     Method      :  StopRxTx (component nRF24L01)
**
**     Description :
**         Stops sending or receiving (sets CE pin to LOW).
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_StopRxTx(void)
{
  McuNRF24L01_CE_LOW(); /* disable RX or TX with pulling CE LOW */
}

/*
** ===================================================================
**     Method      :  StartRxTx (component nRF24L01)
**
**     Description :
**         Starts sending or receiving (sets CE pin to HIGH).
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuNRF24L01_StartRxTx(void)
{
  McuNRF24L01_CE_HIGH(); /* enabling RX or TX with pulling CE HIGH */
}

/*
** ===================================================================
**     Method      :  SetChannel (component nRF24L01)
**
**     Description :
**         Sets the radio channel (RF_CH register).
**     Parameters  :
**         NAME            - DESCRIPTION
**         channel         - Channel number, valid channel
**                           numbers are 0x0 to 0x7F
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetChannel(uint8_t channel)
{
  McuNRF24L01_WriteRegister(McuNRF24L01_RF_CH, channel&0x7F); /* set channel */
  /* need to flush data after channel change */
  McuNRF24L01_Write(McuNRF24L01_FLUSH_RX); /* flush old data */
  McuNRF24L01_Write(McuNRF24L01_FLUSH_TX); /* flush old data */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  GetChannel (component nRF24L01)
**
**     Description :
**         Returns the radio channel (RF_CH register).
**     Parameters  :
**         NAME            - DESCRIPTION
**       * channel         - Pointer to where to store the
**                           channel number.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetChannel(uint8_t *channel)
{
  *channel = McuNRF24L01_ReadRegister(McuNRF24L01_RF_CH); /* read channel */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  EnableAutoAck (component nRF24L01)
**
**     Description :
**         Enables Auto-Acknowledgment for the given pipe(s) (RF_EN_AA
**         register).
**     Parameters  :
**         NAME            - DESCRIPTION
**         pipes           - mask of pipes to be enabled (ENAA_P0
**                           to ENAA_P5)
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_EnableAutoAck(uint8_t pipes)
{
  McuNRF24L01_WriteRegister(McuNRF24L01_EN_AA, pipes&McuNRF24L01_EN_AA_ENAA_ALL); /* enable auto acknowledge for the given pipes */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  ReadNofRxPayload (component nRF24L01)
**
**     Description :
**         Returns the number of received payload bytes for the top
**         R_RX_PAYLOAD in the RX FIFO
**     Parameters  :
**         NAME            - DESCRIPTION
**       * nof             - Pointer to where to store the number of
**                           bytes. A return value of 0 means that the
**                           pipe is not used, and if the value is >32
**                           then the data is not valid.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_ReadNofRxPayload(uint8_t *nof)
{
  *nof = McuNRF24L01_ReadRegister(McuNRF24L01_R_RX_PL_WID); /* read number of RX payload for pipe */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  SetStaticPipePayload (component nRF24L01)
**
**     Description :
**         Specifies the static payload for a pipe.
**     Parameters  :
**         NAME            - DESCRIPTION
**         pipe            - Pipe number, 0 to 5
**         payloadBytes    - Number of payload pipes
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetStaticPipePayload(uint8_t pipe, uint8_t payloadBytes)
{
  if (pipe > 5) {
    return ERR_FAULT; /* only pipe 0 to 5 allowed */
  }
  if (payloadBytes>32) {
    return ERR_FAULT;
  }
  McuNRF24L01_WriteRegister(McuNRF24L01_RX_PW_P0+pipe, payloadBytes); /* write number of RX payload for pipe */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  EnableDynamicPayloadLength (component nRF24L01)
**
**     Description :
**         Enables dynamic payload length for the give pipes
**     Parameters  :
**         NAME            - DESCRIPTION
**         pipeMask        - Mask of pipes, with 1 for pipe 0,
**                           2 for pipe 1, 4 for pipe 2 and so on.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_EnableDynamicPayloadLength(uint8_t pipeMask)
{
  /* note: dynamic payload requires EN_DPL and ENAA_Px set for the pipe */
  if (pipeMask>0x3F) {
    return ERR_FAULT; /* only pipe 0 to 5 allowed */
  }
  McuNRF24L01_WriteRegister(McuNRF24L01_DYNPD, pipeMask); /* write number of RX payload for pipe */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  WriteFeature (component nRF24L01)
**
**     Description :
**         Writes the FEATURE register
**     Parameters  :
**         NAME            - DESCRIPTION
**         featureMask     - Mask of FEATURE, e.g.
**                           FEATURE_EN_DPL
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_WriteFeature(uint8_t featureMask)
{
  if (featureMask>(McuNRF24L01_FEATURE_EN_DPL|McuNRF24L01_FEATURE_EN_ACK_PAY|McuNRF24L01_FEATURE_EN_DYN_PAY)) {
    return ERR_FAULT; /* mismatch of feature mask */
  }
  McuNRF24L01_WriteRegister(McuNRF24L01_FEATURE, featureMask); /* write number of RX payload for pipe */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  ReadFeature (component nRF24L01)
**
**     Description :
**         Reads the FEATURE register
**     Parameters  :
**         NAME            - DESCRIPTION
**       * featureMask     - Pointer to value of
**                           FEATURE register
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_ReadFeature(uint8_t *featureMask)
{
  *featureMask = McuNRF24L01_ReadRegister(McuNRF24L01_FEATURE); /* read FEATURE register */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  ReadObserveTxRegister (component nRF24L01)
**
**     Description :
**         Reads the OBSERVE_TX register to return the count of loss
**         packets and count of retransmitted packets.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * nofLoss         - Pointer to number of lost packets
**       * nofRetransmitted - Pointer to
**                           number of retransmitted packets
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_ReadObserveTxRegister(uint8_t *nofLoss, uint8_t *nofRetransmitted)
{
  uint8_t val;

  val = McuNRF24L01_ReadRegister(McuNRF24L01_OBSERVE_TX); /* read OBSERVE_TX register */
  *nofLoss = (uint8_t)((val&0xF0)>>4); /* high nibble */
  *nofRetransmitted = (uint8_t)(val&0x0F); /* high nibble */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  ReadReceivedPowerDetector (component nRF24L01)
**
**     Description :
**         Reads the RPD (Received Power Detector) register. 
**     Parameters  :
**         NAME            - DESCRIPTION
**       * rpd             - Pointer to RPD bit. Bit is one for
**                           received power levels above -64 dBm, zero
**                           for less than -64 dBm.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_ReadReceivedPowerDetector(uint8_t *rpd)
{
  *rpd = McuNRF24L01_ReadRegister(McuNRF24L01_RPD); /* read RPD register */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  ConstantCarrierWave (component nRF24L01)
**
**     Description :
**         Put the transceiver into contant carrier wave output for
**         testing. The output power of a radio is a critical factor
**         for achieving wanted range. Output power is also the first
**         test
**     Parameters  :
**         NAME            - DESCRIPTION
**         turnOn          - Set to true to start constant
**                           carrier wave, false to stop it.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_ConstantCarrierWave(bool turnOn)
{
  /* note: RF channel, output power should be set independently */
  uint8_t val;

  if (turnOn) {
    /* Set PWR_UP = 1 and PRIM_RX = 0 in the CONFIG register. */
    McuNRF24L01_WriteRegister(McuNRF24L01_CONFIG, McuNRF24L01_PWR_UP|McuNRF24L01_PRIM_TX);
    /*lint -save -e522 function lacks side effect  */
    McuNRF24L01_WAIT_US(1500); /* Wait 1.5ms PWR_UP->standby */
    /*lint -restore */
    /* In the RF register set:
       - CONT_WAVE = 1.
       - PLL_LOCK = 1.
       - RF_PWR (is set independently)
    */
    val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
    val |= McuNRF24L01_RF_SETUP_CONT_WAVE|McuNRF24L01_RF_SETUP_PLL_LOCK; /* set bits */
    McuNRF24L01_WriteRegister(McuNRF24L01_RF_SETUP, val);
    McuNRF24L01_CE_HIGH(); /* CE is high for carrier transmission */
    /* CE is kept high as long the carrier is needed */
  } else {
    val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
    val &= ~(McuNRF24L01_RF_SETUP_CONT_WAVE|McuNRF24L01_RF_SETUP_PLL_LOCK); /* clear bits */
    McuNRF24L01_WriteRegister(McuNRF24L01_RF_SETUP, val); /* write back value */
    McuNRF24L01_CE_LOW(); /* pull CE Low to disable transceiver */
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  SetOutputPower (component nRF24L01)
**
**     Description :
**         Sets the output power
**     Parameters  :
**         NAME            - DESCRIPTION
**         power           - Output power in dBm, either 0, -10, -12
**                           or -18
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetOutputPower(int8_t power)
{
  uint8_t val;

  /* get current register value */
  val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
  val &= ~McuNRF24L01_RF_SETUP_RF_PWR_MASK; /* clear bits */
  if (power==-18) {
    val |= McuNRF24L01_RF_SETUP_RF_PWR_18;
  } else if (power==-12) {
    val |= McuNRF24L01_RF_SETUP_RF_PWR_12;
  } else if (power==-10) {
    val |= McuNRF24L01_RF_SETUP_RF_PWR_10;
  } else if (power==0) {
    val |= McuNRF24L01_RF_SETUP_RF_PWR_0;
  } else {
    return ERR_RANGE;
  }
  McuNRF24L01_WriteRegister(McuNRF24L01_RF_SETUP, val);
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  GetOutputPower (component nRF24L01)
**
**     Description :
**         Returns the current output power
**     Parameters  :
**         NAME            - DESCRIPTION
**       * power           - Pointer to where to store the value.
**                           Returns the output power in dBm
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetOutputPower(int8_t *power)
{
  uint8_t val;

  val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
  if ((val&McuNRF24L01_RF_SETUP_RF_PWR_MASK)==McuNRF24L01_RF_SETUP_RF_PWR_18) {
    *power = -18;
  } else if ((val&McuNRF24L01_RF_SETUP_RF_PWR_MASK)==McuNRF24L01_RF_SETUP_RF_PWR_12) {
    *power = -12;
  } else if ((val&McuNRF24L01_RF_SETUP_RF_PWR_MASK)==McuNRF24L01_RF_SETUP_RF_PWR_10) {
    *power = -10;
  } else if ((val&McuNRF24L01_RF_SETUP_RF_PWR_MASK)==McuNRF24L01_RF_SETUP_RF_PWR_0) {
    *power = 0;
  } else {
    return ERR_RANGE;
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  SetDataRate (component nRF24L01)
**
**     Description :
**         Sets the data rate
**     Parameters  :
**         NAME            - DESCRIPTION
**         rate            - Data rate, either 250, 1000 or 2000
**                           (kbps)
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetDataRate(uint16_t rate)
{
  uint8_t val;

  /* get current register value */
  val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
  val &= ~McuNRF24L01_RF_SETUP_RF_DR_MASK; /* clear bits */
  if (rate==250) {
    val |= McuNRF24L01_RF_SETUP_RF_DR_250;
  } else if (rate==1000) {
    val |= McuNRF24L01_RF_SETUP_RF_DR_1000;
  } else if (rate==2000) {
    val |= McuNRF24L01_RF_SETUP_RF_DR_2000;
  } else { /* illegal parameter */
    return ERR_RANGE;
  }
  McuNRF24L01_WriteRegister(McuNRF24L01_RF_SETUP, val);
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  GetDataRate (component nRF24L01)
**
**     Description :
**         Returns the current data rate
**     Parameters  :
**         NAME            - DESCRIPTION
**       * rate            - Pointer to where to store the value.
**                           Returns the data rate, either 250, 1000 or
**                           2000 (kbps)
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetDataRate(uint16_t *rate)
{
  uint8_t val;

  val = McuNRF24L01_ReadRegister(McuNRF24L01_RF_SETUP); /* read RF_SETUP register */
  if ((val&McuNRF24L01_RF_SETUP_RF_DR_MASK)==McuNRF24L01_RF_SETUP_RF_DR_250) {
    *rate = 250;
  } else if ((val&McuNRF24L01_RF_SETUP_RF_DR_MASK)==McuNRF24L01_RF_SETUP_RF_DR_1000) {
    *rate = 1000;
  } else if ((val&McuNRF24L01_RF_SETUP_RF_DR_MASK)==McuNRF24L01_RF_SETUP_RF_DR_2000) {
    *rate = 2000;
  } else {
    return ERR_RANGE;
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  PollInterrupt (component nRF24L01)
**
**     Description :
**         If there is no interrupt line available, this method polls
**         the device to check if there is an interrupt. If 
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
bool McuNRF24L01_PollInterrupt(void)
{
  /*lint -save -e522 function lacks side effect  */
  uint8_t status;
  bool interrupt = false;
  extern void RADIO_OnInterrupt(void); /* prototype */

  status = McuNRF24L01_GetStatus();
  if (status&(McuNRF24L01_STATUS_RX_DR|McuNRF24L01_STATUS_TX_DS|McuNRF24L01_STATUS_MAX_RT)) {
    McuNRF24L01_CE_LOW(); /* pull CE Low to disable transceiver */
    RADIO_OnInterrupt();
    McuNRF24L01_OnInterrupt(); /* call user event (if enabled)... */
    interrupt = true;
  }
  return interrupt;
  /*lint -restore */
}

/*
** ===================================================================
**     Method      :  GetFifoStatus (component nRF24L01)
**
**     Description :
**         Returns the FIFO_STATUS register value
**     Parameters  :
**         NAME            - DESCRIPTION
**       * status          - Pointer to where to store the FIFO
**                           status value.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetFifoStatus(uint8_t *status)
{
  *status = McuNRF24L01_ReadRegister(McuNRF24L01_FIFO_STATUS); /* read FIFO_STATUS register */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  SetAddressWidth (component nRF24L01)
**
**     Description :
**         Sets the address width using the SETUP_AW register
**     Parameters  :
**         NAME            - DESCRIPTION
**         width           - only 3, 4 or 5 is allowed
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetAddressWidth(uint8_t width)
{
  if (width==3) {
    McuNRF24L01_WriteRegister(McuNRF24L01_SETUP_AW, McuNRF24L01_SETUP_AW_3BYTES);
  } else if (width==4) {
    McuNRF24L01_WriteRegister(McuNRF24L01_SETUP_AW, McuNRF24L01_SETUP_AW_4BYTES);
  } else if (width==5) {
    McuNRF24L01_WriteRegister(McuNRF24L01_SETUP_AW, McuNRF24L01_SETUP_AW_5BYTES);
  } else {
    return ERR_FAILED; /* only 3, 4 or 5 allowed */
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  GetAddressWidth (component nRF24L01)
**
**     Description :
**         Returns the address width stored in the SETUP_AW register
**     Parameters  :
**         NAME            - DESCRIPTION
**       * pAddrWidth      - Pointer to where to store
**                           the value.
**     Returns     :
**         ---             - number of address bytes (3, 4 or 5)
** ===================================================================
*/
uint8_t McuNRF24L01_GetAddressWidth(uint8_t *pAddrWidth)
{
  uint8_t val;

  val = McuNRF24L01_ReadRegister(McuNRF24L01_SETUP_AW); /* read RF_SETUP_AW register */
  if (val==McuNRF24L01_SETUP_AW_3BYTES) {
    *pAddrWidth = 3;
    return ERR_OK;
  } else if (val==McuNRF24L01_SETUP_AW_4BYTES) {
    *pAddrWidth = 4;
    return ERR_OK;
  } else if (val==McuNRF24L01_SETUP_AW_5BYTES) {
    *pAddrWidth = 5;
    return ERR_OK;
  } else {
    /* failure */
    *pAddrWidth = 0; /* illegal value */
    return ERR_FAILED;
  }
}

/*
** ===================================================================
**     Method      :  SetTxAddress (component nRF24L01)
**
**     Description :
**         Sets the TX address using the RF_TX_ADDR register.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * address         - Pointer to the buffer with the
**                           address bytes.
**         nofAddressBytes - Number of address
**                           bytes and size of buffer, typically 5.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetTxAddress(uint8_t *address, uint8_t nofAddressBytes)
{
  int i, j;
  uint8_t swap[5]; /* address is max 5 bytes */

  if (nofAddressBytes>=3 && nofAddressBytes<=5) {
    for(j=0,i=nofAddressBytes-1; i>=0 && j<(int)sizeof(swap); i--,j++) { /* need to send LSB first */
      swap[j] = address[i];
    }
    McuNRF24L01_WriteRegisterData(McuNRF24L01_TX_ADDR, &swap[0], nofAddressBytes);
    return ERR_OK;
  } else {
    return ERR_FAILED; /* only 3, 4 or 5 address bytes allowed */
  }
}

/*
** ===================================================================
**     Method      :  GetTxAddress (component nRF24L01)
**
**     Description :
**         Returns the TX address using the RF_TX_ADDR register.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * address         - Pointer to array where the return
**                           the address bytes.
**         nofAddressBytes - Number of address
**                           bytes and size of buffer, typically 5.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetTxAddress(uint8_t *address, uint8_t nofAddressBytes)
{
  int i, j;
  uint8_t swap[5]; /* address is max 5 bytes */

  if (nofAddressBytes>=3 && nofAddressBytes<=5) {
    McuNRF24L01_ReadRegisterData(McuNRF24L01_TX_ADDR, swap, nofAddressBytes);
    for(j=0,i=nofAddressBytes-1; i>=0 && j<nofAddressBytes; i--,j++) {
      address[j] = swap[i];
    }
    return ERR_OK;
  } else {
    return ERR_FAILED; /* only 3, 4 or 5 address bytes allowed */
  }
}

/*
** ===================================================================
**     Method      :  SetRxAddress (component nRF24L01)
**
**     Description :
**         Set the TX address using the RF_RX_ADDR_Px register.
**     Parameters  :
**         NAME            - DESCRIPTION
**         pipe            - pipe number (0-5)
**       * address         - Pointer to array where the return
**                           the address bytes.
**         nofAddressBytes - Number of address
**                           bytes and size of buffer, typically 5.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_SetRxAddress(uint8_t pipe, uint8_t *address, uint8_t nofAddressBytes)
{
  uint8_t swap[5]; /* address is max 5 bytes */
  int i, j;

  if (pipe>5) {
    return ERR_FAILED; /* only pipe 0 to 5 allowed */
  }
  if (!(nofAddressBytes>=3 && nofAddressBytes<=5)) {
    return ERR_FAILED; /* only 3, 4 or 5 allowed */
  }
  if (pipe==0 || pipe==1) { /* full number of address bytes */
    for(j=0,i=nofAddressBytes-1; i>=0 && j<(int)sizeof(swap); i--,j++) { /* need to send LSB first */
      swap[j] = address[i];
    }
    McuNRF24L01_WriteRegisterData(McuNRF24L01_RX_ADDR_P0+pipe, &swap[0], nofAddressBytes);
  } else { /* P2-P5: only last byte */
    McuNRF24L01_WriteRegisterData(McuNRF24L01_RX_ADDR_P0+pipe, &address[nofAddressBytes-1], 1);
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  GetRxAddress (component nRF24L01)
**
**     Description :
**         Returns the RX address using the RF_RX_ADDR_Px register.
**     Parameters  :
**         NAME            - DESCRIPTION
**         pipe            - pipe number (0-5)
**       * address         - Pointer to array where the return
**                           the address bytes.
**         nofAddressBytes - Number of address
**                           bytes and size of buffer, typically 5.
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
uint8_t McuNRF24L01_GetRxAddress(uint8_t pipe, uint8_t *address, uint8_t nofAddressBytes)
{
  int i, j;
  uint8_t swap[5]; /* address is max 5 bytes */

  if (pipe>5) {
    return ERR_FAILED; /* only pipe 0 to 5 allowed */
  }
  if (!(nofAddressBytes>=3 && nofAddressBytes<=5)) {
    return ERR_FAILED; /* only 3, 4 or 5 allowed */
  }
  for(i=0; i<nofAddressBytes; i++) {
    swap[i] = 0; /* init */
  }
  if (pipe==0 || pipe==1) { /* full number of address bytes */
    McuNRF24L01_ReadRegisterData(McuNRF24L01_RX_ADDR_P0+pipe, swap, nofAddressBytes);
  } else if (pipe>=2 && pipe<=5) {
    McuNRF24L01_ReadRegisterData(McuNRF24L01_RX_ADDR_P1, swap, nofAddressBytes); /* read base address from P1 */
    McuNRF24L01_ReadRegisterData(McuNRF24L01_RX_ADDR_P0+pipe, &swap[0], 1); /* pipe 2-5 only have one address byte */
  }
  /* swap back into correct order */
  for(j=0,i=nofAddressBytes-1; i>=0 && j<(int)nofAddressBytes; i--,j++) {
    address[j] = swap[i];
  }
  return ERR_OK;
}

static uint8_t PrintHelp(const McuShell_StdIOType *io) {
  McuShell_SendHelpStr((unsigned char*)"McuNRF", (unsigned char*)"Group of nRF24L01+ commands\r\n", io->stdOut);
  McuShell_SendHelpStr((unsigned char*)"  help|status", (unsigned char*)"Shows help or status\r\n", io->stdOut);
  return ERR_OK;
}

static uint8_t PrintStatus(const McuShell_StdIOType *io) {
  uint8_t buf[64];

  McuShell_SendStatusStr((unsigned char*)"McuNRF", (unsigned char*)"nRF24L01+ status\r\n", io->stdOut);

  McuGPIO_GetPinStatusString(cePin, buf, sizeof(buf));
  McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
  McuShell_SendStatusStr((const unsigned char*)"  CE", (const unsigned char*)buf, io->stdOut);

  McuGPIO_GetPinStatusString(csnPin, buf, sizeof(buf));
  McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
  McuShell_SendStatusStr((const unsigned char*)"  CSN", (const unsigned char*)buf, io->stdOut);
  return ERR_OK;
}

uint8_t McuNRF24L01_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) {
  uint8_t res = ERR_OK;

  if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, (char*)"McuNRF help")==0) {
    *handled = TRUE;
    return PrintHelp(io);
  } else if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_STATUS)==0 || McuUtility_strcmp((char*)cmd, (char*)"McuNRF status")==0) {
    *handled = TRUE;
    return PrintStatus(io);
  }
  return res;
}

#endif /* McuNRF24L01_CONFIG_IS_ENABLED */

/* END McuNRF24L01. */

/*!
** @}
*/
