#ifndef NRF24L01P_H
#define NRF24L01P_H

#include "NRF24L01P_hw_interface.h"

/*PUBLIC API*/
typedef enum rf24_datarate
{
    /** (0) represents 1 Mbps */
    RF24_1MBPS = 0,
    /** (1) represents 2 Mbps */
    RF24_2MBPS,
    /** (2) represents 250 kbps */
    RF24_250KBPS
} rf24_datarate_e;

typedef enum rf24_pa_dbm
{
    /**
     * (0) represents:
     * nRF24L01 | Si24R1 with<br>lnaEnabled = 1 | Si24R1 with<br>lnaEnabled = 0
     * :-------:|:-----------------------------:|:----------------------------:
     *  -18 dBm | -6 dBm | -12 dBm
     */
    RF24_PA_MIN = 0,
    /**
     * (1) represents:
     * nRF24L01 | Si24R1 with<br>lnaEnabled = 1 | Si24R1 with<br>lnaEnabled = 0
     * :-------:|:-----------------------------:|:----------------------------:
     *  -12 dBm | 0 dBm | -4 dBm
     */
    RF24_PA_LOW,
    /**
     * (2) represents:
     * nRF24L01 | Si24R1 with<br>lnaEnabled = 1 | Si24R1 with<br>lnaEnabled = 0
     * :-------:|:-----------------------------:|:----------------------------:
     *  -6 dBm | 3 dBm | 1 dBm
     */
    RF24_PA_HIGH,
    /**
     * (3) represents:
     * nRF24L01 | Si24R1 with<br>lnaEnabled = 1 | Si24R1 with<br>lnaEnabled = 0
     * :-------:|:-----------------------------:|:----------------------------:
     *  0 dBm | 7 dBm | 4 dBm
     */
    RF24_PA_MAX,
    /**
     * (4) This should not be used and remains for backward compatibility.
     */
    RF24_PA_ERROR
} rf24_pa_dbm_e;

typedef enum rf24_crclength
{
    /** (0) represents no CRC checksum is used */
    RF24_CRC_DISABLED = 0,
    /** (1) represents CRC 8 bit checksum is used */
    RF24_CRC_8,
    /** (2) represents CRC 16 bit checksum is used */
    RF24_CRC_16
} rf24_crclength_e;

typedef struct NRF24L01P
{
    uint8_t status;
    uint8_t payload_size;
    bool dynamic_payloads_enabled;
    bool ack_payloads_enabled;
    uint8_t pipe0_reading_address[5];
    uint8_t addr_width;
    uint8_t config_reg;
    bool is_p_variant;
    bool failure_detected;
} NRF24L01P_t;

bool NRF24L01P_begin(NRF24L01P_t *NRF);

bool NRF24L01P_isChipConnected(NRF24L01P_t *NRF);

void NRF24L01P_startListening(NRF24L01P_t *NRF);

void NRF24L01P_stopListening(NRF24L01P_t *NRF);

bool NRF24L01P_available(NRF24L01P_t *NRF);

void NRF24L01P_read(NRF24L01P_t *NRF, void *payload, uint8_t length);

bool NRF24L01P_write(NRF24L01P_t *NRF, const void *payload, uint8_t length);

void NRF24L01P_openWritingPipe(NRF24L01P_t *NRF, const uint8_t* address);

void NRF24L01P_openReadingPipe(NRF24L01P_t *NRF, uint8_t pipe, const uint8_t *address);

void NRF24L01P_printDetails(NRF24L01P_t *NRF);

bool NRF24L01P_availablePipe(NRF24L01P_t *NRF, uint8_t *pipe);

bool NRF24L01P_rxFifoFull(NRF24L01P_t *NRF);

bool NRF24L01P_txFifoFull(NRF24L01P_t *NRF);

void NRF24L01P_powerDown(NRF24L01P_t *NRF);

void NRF24L01P_powerUp(NRF24L01P_t *NRF);

bool NRF24L01P_writeMulticast(NRF24L01P_t *NRF, const void *payload, uint8_t length, const bool multicast);

bool NRF24L01P_writeFast(NRF24L01P_t *NRF, const void *payload, uint8_t length);

bool NRF24L01P_writeFastMulticast(NRF24L01P_t *NRF, const void *payload, uint8_t length, const bool multicast);

bool NRF24L01P_writeBlocking(NRF24L01P_t *NRF, const void *payload, uint8_t length, uint32_t timeout);

bool NRF24L01P_txStandBy(NRF24L01P_t *NRF);

bool NRF24L01P_txStandByTimeout(NRF24L01P_t *NRF, uint32_t timeout, bool start_tx);

bool NRF24L01P_writeAckPayload(NRF24L01P_t *NRF, uint8_t pipe, const void *payload, uint8_t length);

void NRF24L01P_whatHappened(NRF24L01P_t *NRF, bool *tx_ok, bool *tx_fail, bool *rx_ready);

void NRF24L01P_startFastWrite(NRF24L01P_t *NRF, const void *payload, uint8_t length, const bool multicast, bool start_tx);

bool NRF24L01P_startWrite(NRF24L01P_t *NRF, const void *payload, uint8_t length, const bool multicast);

void NRF24L01P_reUseTX(NRF24L01P_t *NRF);

uint8_t NRF24L01P_flush_tx(NRF24L01P_t *NRF);

uint8_t NRF24L01P_flush_rx(NRF24L01P_t *NRF);

bool NRF24L01P_testCarrier(NRF24L01P_t *NRF);

bool NRF24L01P_testRPD(NRF24L01P_t *NRF);

void NRF24L01P_closeReadingPipe(NRF24L01P_t *NRF, uint8_t pipe);

void NRF24L01P_setAddressWidth(NRF24L01P_t *NRF, uint8_t a_width);

void NRF24L01P_setRetries(NRF24L01P_t *NRF, uint8_t delay, uint8_t count);

void NRF24L01P_setChannel(NRF24L01P_t *NRF, uint8_t channel);

uint8_t NRF24L01P_getChannel(NRF24L01P_t *NRF);

void NRF24L01P_setPayloadSize(NRF24L01P_t *NRF, uint8_t size);

uint8_t NRF24L01P_getPayloadSize(NRF24L01P_t *NRF);

uint8_t NRF24L01P_getDynamicPayloadSize(NRF24L01P_t *NRF);

void NRF24L01P_enableAckPayload(NRF24L01P_t *NRF);

void NRF24L01P_disableAckPayload(NRF24L01P_t *NRF);

void NRF24L01P_enableDynamicPayloads(NRF24L01P_t *NRF);

void NRF24L01P_disableDynamicPayloads(NRF24L01P_t *NRF);

void NRF24L01P_enableDynamicAck(NRF24L01P_t *NRF);

bool NRF24L01P_isPVariant(NRF24L01P_t *NRF);

void NRF24L01P_setAutoAck(NRF24L01P_t *NRF, bool enable);

void NRF24L01P_setAutoAckPipe(NRF24L01P_t *NRF, uint8_t pipe, bool enable);

void NRF24L01P_setPALevel(NRF24L01P_t *NRF, rf24_pa_dbm_e level, bool lna_enable);

rf24_pa_dbm_e NRF24L01P_getPALevel(NRF24L01P_t *NRF);

uint8_t NRF24L01P_getARC(NRF24L01P_t *NRF);

bool NRF24L01P_setDataRate(NRF24L01P_t *NRF, rf24_datarate_e data_rate);

rf24_datarate_e NRF24L01P_getDataRate(NRF24L01P_t *NRF);

void NRF24L01P_setCRCLength(NRF24L01P_t *NRF, rf24_crclength_e length);

rf24_crclength_e NRF24L01P_getCRCLength(NRF24L01P_t *NRF);

void NRF24L01P_disableCRC(NRF24L01P_t *NRF);

void NRF24L01P_maskIRQ(NRF24L01P_t *NRF, bool tx, bool fail, bool rx);

void NRF24L01P_startConstCarrier(NRF24L01P_t *NRF, rf24_pa_dbm_e level, uint8_t channel);

void NRF24L01P_stopConstCarrier(NRF24L01P_t *NRF);

bool NRF24L01P_isAckPayloadAvailable(NRF24L01P_t *NRF);

#endif //NRF24L01P_H