ISM RF transmitter library for MAX4146X family devices

Library for MAX41460, MAX41461, MAX41462, MAX41463, MAX41464 RF Transmitter ICs.

Max4146x.h

Committer:
Ibrahim Tilki
Date:
2022-01-13
Revision:
2:80969d8f6d2b
Parent:
1:ccf0e1d28860

File content as of revision 2:80969d8f6d2b:

/*******************************************************************************
* Copyright (C) 2019 Maxim Integrated Products, Inc., All rights Reserved.
*
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/

#ifndef MAX4146x_H_
#define MAX4146x_H_

#include "mbed.h"
#include "Max41460_regs.h"
#include "Max41461_2_regs.h"
#include "Max41463_4_regs.h"

#define I2C_ADDRESS    0xD2

/**
 * @brief Base Class for All Maxim Max4146x RF Transmitters
 *
 * @details The MAX4146X is a UHF sub-GHz ISM/SRD transmitter
 */
template <class REG>
class MAX4146X
{
private:
    REG *reg;
    I2C *i2c_handler;
    SPI *spi_handler;
    DigitalOut *ssel;

    //manchester coding variables
    unsigned char *manchester_bit_array;
    unsigned char *bits_array;
    static const unsigned char mask = 1; // Bit mask
    char data_rate;
    DigitalOut *data_sent; // data sent pin

    uint8_t preset_mode;
    float crystal_frequency ;
    float center_frequency;
    float baud_rate;

    typedef enum {
        CFG1_ADDR       = 0x00,
        CFG2_ADDR       = 0x01,
        CFG3_ADDR       = 0x02,
        CFG4_ADDR       = 0x03,
        CFG5_ADDR       = 0x04,
        SHDN_ADDR       = 0x05,
        PA1_ADDR        = 0x06,
        PA2_ADDR        = 0x07,
        PLL1_ADDR       = 0x08,
        PLL2_ADDR       = 0x09,
        CFG6_ADDR       = 0x0A,
        PLL3_ADDR       = 0x0B,
        PLL4_ADDR       = 0x0C,
        PLL5_ADDR       = 0x0D,
        PLL6_ADDR       = 0x0E,
        PLL7_ADDR       = 0x0F,
        CFG7_ADDR       = 0x10,
        I2C1_ADDR       = 0x11,
        I2C2_ADDR       = 0x12,
        I2C3_ADDR       = 0x13,
        I2C4_ADDR       = 0x14,
        I2C5_ADDR       = 0x15,
        I2C6_ADDR       = 0x16,
        CFG8_ADDR       = 0x17,
        CFG9_ADDR       = 0x18,
        ADDL1_ADDR      = 0x19,
        ADDL2_ADDR      = 0x1A,
    } register_address_t;

//Functions

protected:

    //Functions
    int io_write(uint8_t *data, uint32_t length);

public:

    //Constructors
    MAX4146X(REG *reg, SPI *spi, DigitalOut *cs);

    MAX4146X(REG *reg, SPI *spi);

    MAX4146X(REG *reg, I2C *i2c);

    MAX4146X(DigitalOut *cs);


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG1(0x00)
     *  - Bit Fields    : [7:6]
     *  - Default       : 0x2
     *  - Description   : Start delay before enabling XO clock to digital block
     */
    typedef enum {
        XOCLKDELAY_0_CYCLE,     /**< 0x0: No delay. XO clock is immediately enabled to rest of digital block */
        XOCLKDELAY_16_CYCLE,    /**< 0x1: XO clock is enabled after 16 cycles to rest of digital block */
        XOCLKDELAY_32_CYCLE,    /**< 0x2: XO clock is enabled after 32 cycles to rest of digital block */
        XOCLKDELAY_64_CYCLE,    /**< 0x3: XO clock is enabled after 64 cycles to rest of digital block */
    } xoclkdelay_t;

    /**
     * @brief Set start delay before enabling XO clock to digital block
     *
     * @param[in] delay delay cycle
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_xoclkdelay(xoclkdelay_t delay);

    /**
     * @brief Get start delay before enabling XO clock to digital block
     *
     * @param[in] delay delay cycle
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_xoclkdelay(xoclkdelay_t *delay);

    /**
     * @brief Register Configuration
     *
     * @details
     *  -Register       : CFG1(0x00)
     *  - Bit Fields    : [5:4]
     *  - Default       : 0x2
     *  - Description   : XO clock division ratio for digital block
     */
    typedef enum {
        XOCLKDIV_BY_4, /**< 0x0: Divide XO clock by 4 for digital clock */
        XOCLKDIV_BY_5, /**< 0x1: Divide XO clock by 5 for digital clock. High time is 2 cycles, low time is 3 cycles */
        XOCLKDIV_BY_6, /**< 0x2: Divide XO clock by 6 for digital clock */
        XOCLKDIV_BY_7, /**< 0x3: Divide XO clock by 7 for digital clock. High time is 3 cycles,
                            and low time is 4 cycles */
    } xoclkdiv_t;

    /**
     * @brief Set XO clock division ratio for digital block
     *
     * @param[in] div division ratio
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_xoclkdiv(xoclkdiv_t div);

    /**
     * @brief Get XO clock division ratio for digital block
     *
     * @param[in] div division ratio
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_xoclkdiv(xoclkdiv_t *div);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG1(0x00)
     *  - Bit Fields    : [2]
     *  - Default       : 0b0
     *  - Description   : Sets the state of FSK Gaussian Shaping
     */
    typedef enum {
        FSKSHAPE_DISABLE,   /**< 0x0: FSK Shaping disabled */
        FSKSHAPE_ENABLE,    /**< 0x1: FSK Shaping enabled */
    } fskshape_t;

    /**
     * @brief Sets the state of FSK Gaussian Shaping
     *
     * @param[in] shape enable/disable fskshaping
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_fskshape(fskshape_t shape);

    /**
     * @brief Gets the state of FSK Gaussian Shaping
     *
     * @param[in] shape enable/disable fskshaping
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_fskshape(fskshape_t *shape);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG1(0x00)
     *  - Bit Fields    : [1]
     *  - Default       : 0b0
     *  - Description   : Controls if clock output acts as an input. When an input,
     *                    it will sample the DATA pin.
     */
    typedef enum {
        SYNC_0,     /**< 0x0: asynchronous transmission mode */
        SYNC_1,     /**< 0x1: synchronous transmission mode */
    } sync_t;

    /**
     * @brief Sets the state of clock pin
     *
     * @param[in] state pin state async/sync
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_sync(sync_t state);

    /**
     * @brief Gets the state of clock pin
     *
     * @param[in] state pin state async/sync
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_sync(sync_t *state);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register       : CFG1(0x00)
     *  - Bit Fields     : [0]
     *  - Default        : 0b0
     *  - Description    : Configures modulator mode
     */
    typedef enum {
        MODMODE_ASK,    /**< 0x0: ASK Mode */
        MODMODE_FSK,    /**< 0x1: FSK Mode */
    } modmode_t;

    /**
     * @brief Sets modulator mode to ASK or FSK
     *
     * @param[in] mode ASK or FSK
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_modmode(modmode_t mode);

    /**
     * @brief Gets modulator mode
     *
     * @param[in] mode ASK or FSK
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_modmode(modmode_t* mode);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG2(0x01)
     *  - Bit Fields    : [7:6]
     *  - Default       : 0x2
     *  - Description   : Selects the delay when CLKOUT starts
     *                    toggling upon exiting SHUTDOWN mode,
     *                    in divided XO clock cycles
     */
    typedef enum {
        CLKOUT_DELAY_64_CYCLE,  /**< 0x0: CLKOUT will start toggling after 64 cycles
                                     whenever moving into normal mode from shutdown mode */
        CLKOUT_DELAY_128_CYCLE, /**< 0x1: CLKOUT will start toggling after 128 cycles
                                     whenever moving into normal mode from shutdown mode */
        CLKOUT_DELAY_256_CYCLE, /**< 0x2: CLKOUT will start toggling after 256 cycles
                                     whenever moving into normal mode from shutdown mode */
        CLKOUT_DELAY_512_CYCLE, /**< 0x3: CLKOUT will start toggling after 512 cycles
                                     whenever moving into normal mode from shutdown mode */
    } clkout_delay_t;

    /**
     * @brief Sets clkout delay
     *
     * @param[in] delay delay cycles
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_clkout_delay(clkout_delay_t delay);

    /**
     * @brief Gets clkout delay
     *
     * @param[in] delay delay cycles
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_clkout_delay(clkout_delay_t* delay);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG2(0x01)
     *  - Bit Fields    : [2:0]
     *  - Default       : 0x1
     *  - Description   : Baud clock post-divider setting.
     */
    typedef enum {
        BCLK_POSTDIV_RESERVED_0,    /**< 0x0: RESERVED */
        BCLK_POSTDIV_BY_1,          /**< 0x1: Divide by 1 */
        BCLK_POSTDIV_BY_2,          /**< 0x2: Divide by 2 */
        BCLK_POSTDIV_BY_3,          /**< 0x3: Divide by 3 */
        BCLK_POSTDIV_BY_4,          /**< 0x4: Divide by 4 */
        BCLK_POSTDIV_BY_5,          /**< 0x5: Divide by 5 */
        BCLK_POSTDIV_RESERVED_6,    /**< 0x6: RESERVED */
        BCLK_POSTDIV_RESERVED_7,    /**< 0x7: RESERVED */
    } bclk_postdiv_t;

    /**
     * @brief Sets baud clock post-divider
     *
     * @param[in] div divider value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_bclk_postdiv(bclk_postdiv_t div);

    /**
     * @brief Gets baud clock post-divider
     *
     * @param[in] div divider value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_bclk_postdiv(bclk_postdiv_t* div);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG4(0x03)
     *  - Bit Fields    : [1:0]
     *  - Default       : 0x0
     *  - Description   : Power Down Mode Select.
     */
    typedef enum {
        PWDN_MODE_SHUTDOWN,                 /**< 0x0: SHUTDOWN low power state is enabled. While entering
                                                 low power state, XO, PLL, and PA are shutdown. */
        PWDN_MODE_STANDBY,                  /**< 0x1: STANDBY low power state is enabled. While entering
                                                 low power state, XO is enabled. PLL and PA are shutdown */
        PWDN_MODE_FAST_WAKEUP,              /**< 0x2: FAST WAKEUP low power state is enabled. While entering
                                                 low power state, XO and PLL are enabled. PA is shutdown. */
        PWDN_MODE_REVERT_TO_FAST_WAKEUP,    /**< 0x3: Will revert to 0x2 */
    } pwdn_mode_t;

    /**
     * @brief Sets power down mode
     *
     * @param[in] pwdn_mode power down mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_pwdn_mode(pwdn_mode_t pwdn_mode);

    /**
     * @brief Gets power down mode
     *
     * @param[in] pwdn_mode power down mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_pwdn_mode(pwdn_mode_t* pwdn_mode);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : SHDN(0x05)
     *  - Bit Fields    : [0]
     *  - Default       : 0x0
     *  - Description   : Enables a boost in PA output power for frequencies above 850MHz.
     *                    This requires a different PA match compared to normal operation.
     */
    typedef enum {
        PA_BOOST_NORMAL_MODE,   /**< 0x0: PA Output power in normal operation. */
        PA_BOOST_BOOST_MODE,    /**< 0x1: PA Output power in boost mode for more output power. */
    } pa_boost_t;

    /**
     * @brief enable/disable boost mode
     *
     * @param[in] pa_boost power amplifier output mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_pa_boost(pa_boost_t pa_boost);

    /**
     * @brief Gets boost mode
     *
     * @param[in] pa_boost power amplifier output mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_pa_boost(pa_boost_t* pa_boost);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PA1(0x06)
     *  - Bit Fields    : [2:0]
     *  - Default       : 0x0
     *  - Description   : Controls the PA output power by enabling parallel drivers.
     */
    typedef enum {
        PAPWR_1_DRIVER, /**< 0x0: Minimum, 1 driver */
        PAPWR_2_DRIVER, /**< 0x1: 2 Drivers */
        PAPWR_3_DRIVER, /**< 0x2: 3 Drivers */
        PAPWR_4_DRIVER, /**< 0x3: 4 Drivers */
        PAPWR_5_DRIVER, /**< 0x4: 5 Drivers */
        PAPWR_6_DRIVER, /**< 0x5: 6 Drivers */
        PAPWR_7_DRIVER, /**< 0x6: 7 Drivers */
        PAPWR_8_DRIVER, /**< 0x7: 8 Drivers */
    } papwr_t;

    /**
     * @brief set PA output power by enabling parallel drivers
     *
     * @param[in] papwr number of parallel drivers
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_papwr(papwr_t papwr);

    /**
     * @brief Gets PA output power
     *
     * @param[in] papwr number of parallel drivers
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_papwr(papwr_t* papwr);


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PA2(0x07)
     *  - Bit Fields    : [4:0]
     *  - Default       : 0x00
     *  - Description   : Controls shunt capacitance on PA output in fF.
     */
    typedef enum {
        PACAP_0_fF,
        PACAP_175_fF,
        PACAP_350_fF,
        PACAP_525_fF,
        PACAP_700_fF,
        PACAP_875_fF,
        PACAP_1050_fF,
        PACAP_1225_fF,
        PACAP_1400_fF,
        PACAP_1575_fF,
        PACAP_1750_fF,
        PACAP_1925_fF,
        PACAP_2100_fF,
        PACAP_2275_fF,
        PACAP_2450_fF,
        PACAP_2625_fF,
        PACAP_2800_fF,
        PACAP_2975_fF,
        PACAP_3150_fF,
        PACAP_3325_fF,
        PACAP_3500_fF,
        PACAP_3675_fF,
        PACAP_3850_fF,
        PACAP_4025_fF,
        PACAP_4200_fF,
        PACAP_4375_fF,
        PACAP_4550_fF,
        PACAP_4725_fF,
        PACAP_4900_fF,
        PACAP_5075_fF,
        PACAP_5250_fF,
        PACAP_5425_fF,
    } pacap_t;

    /**
     * @brief set shunt capacitance value
     *
     * @param[in] pacap shunt capacitance value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_pacap(pacap_t pacap);

    /**
     * @brief Gets shunt capacitance value
     *
     * @param[in] pacap shunt capacitance value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_pacap(pacap_t* pacap);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PLL1(0x08)
     *  - Bit Fields    : [7:6]
     *   -Default       : 0x1
     *  - Description   : Sets the level of charge pump offset current
     *                    for fractional N mode to improve close in
     *                    phase noise. Set to 'DISABLED' for integer N mode.
     */
    typedef enum {
        CPLIN_NO_EXTRA_CURRENT,                 /**< 0x0: No extra current */
        CPLIN_CHARGE_PUMP_CURRENT_5_PERCENT,    /**< 0x1: 5% of charge pump current */
        CPLIN_CHARGE_PUMP_CURRENT_10_PERCENT,   /**< 0x2: 10% of charge pump current */
        CPLIN_CHARGE_PUMP_CURRENT_15_PERCENT,   /**< 0x3: 15% of charge pump current */
    } cplin_t;

    /**
     * @brief set level of charge pump offset current
     *
     * @param[in] cplin percentage of charge pump current
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_cplin(cplin_t cplin);

    /**
     * @brief Gets level of charge pump offset current
     *
     * @param[in] cplin percentage of charge pump current
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_cplin(cplin_t* cplin);


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PLL1(0x08)
     *  - Bit Fields    : [5]
     *  - Default       : 0b1
     *  - Description   : Sets PLL between fractional-N and integer-N mode.
     *
     */
    typedef enum {
        FRACMODE_INTEGER_N,      /**< 0x0: Integer N Mode */
        RACMODE_FRACTIONAL_N,    /**< 0x1: Fractional N Mode */
    } fracmode_t;

    /**
     * @brief set PLL mode
     *
     * @param[in] fracmode Integer N/Fractional N mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_fracmode(fracmode_t fracmode);

    /**
     * @brief Gets PLL mode
     *
     * @param[in] fracmode Integer N/Fractional N mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_fracmode(fracmode_t* fracmode);

    /*  Register Configuration
     *
     *  @Register       : PLL1(0x08)
     *  @Bit Fields     : [2:1]
     *  @Default        : 0x0
     *  @Description    :
     */
    typedef enum {
        LODIV_DISABLED,     /**< 0x0: Disabled */
        LODIV_DIVIDE_BY_4,  /**< 0x1: LC VCO divided by 4 */
        LODIV_DIVIDE_BY_8,  /**< 0x2: LC VCO divided by 8 */
        LODIV_DIVIDE_BY_12, /**< 0x3: LC VCO divided by 12 */
    } lodiv_t;

    /**
     * @brief set divider of LC VCO
     *
     * @param[in] lodiv divider value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_lodiv(lodiv_t lodiv);

    /**
     * @brief Gets divider of LC VCO
     *
     * @param[in] lodiv divider value
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_lodiv(lodiv_t* lodiv);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PLL1(0x08)
     *  - Bit Fields    : [0]
     *  - Default       : 0b0
     *  - Description   : Sets LO generation. For lower power, choose LOWCURRENT.
     *                    For higher performance, choose LOWNOISE
     */
    typedef enum {
        LOMODE_RING_OSCILLATOR,     /**< 0x0: Ring Oscillator Mode */
        LOMODE_LC_VCO,              /**< 0x1: LC VCO Mode */
    } lomode_t;

    /**
     * @brief set LO generation
     *
     * @param[in] lomode selection of mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int set_lomode(lomode_t lomode);

    /**
     * @brief Gets LO generation
     *
     * @param[in] lomode selection of mode
     *
     * @returns 0 on success, negative error code on failure.
     */
    int get_lomode(lomode_t* lomode);

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : PLL2(0x09)
     *  - Bit Fields    : [1:0]
     *  - Default       : 0x0
     *  - Description   : Sets Charge Pump Current in microAmpere
     *
     */
    typedef enum {
        CPVAL_5_UA,     /**< 0x0: 5µA */
        CPVAL_10_UA,    /**< 0x1: 10µA */
        CPVAL_15_UA,    /**< 0x2: 15µA */
        CPVAL_20_UA,    /**< 0x3: 20µA */
    } cpval_t;

    /**
     * @brief    set charge pump current
     *
     * @param[in]    cpval current value
     *
     * @returns    0 on success, negative error code on failure.
     */
    int set_cpval(cpval_t cpval);

    /**
     * @brief        Gets charge pump current
     *
     * @param[in]    cpval current value
     *
     * @returns      0 on success, negative error code on failure.
     */
    int get_cpval(cpval_t* cpval);

    /**
     * Register Configuration
     *
     * @details
     *  - Register      : CFG6(0x0A)
     *  - Bit Fields    : [2]
     *  - Default       : 0b0
     *  - Description   : Enables DATA transmission in I2C mode. Aliased address for I2C_TXEN1.
     */
    typedef enum {
        I2C_TXEN1_DISABLE,  /**< 0x0: Data transmission not enabled in I2C mode. */
        I2C_TXEN1_ENABLE,   /**< 0x1: Data transmission enabled in I2C mode. */
    } i2c_txen1_t;


    /** Register Configuration
     *
     * @details
     *  - Register      : CFG6(0x0A)
     *  - Bit Fields    : [1]
     *  - Default       : 0b0
     *  - Description   : Transmission enable.
     */
    typedef enum {
        SPI_TXEN1_DISABLE,  /**< 0x0: Transmission disabled. */
        SPI_TXEN1_ENABLE,   /**< 0x1: Transmission enabled. */
    } spi_txen1_t;

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG6(0x0A)
     *  - Bit Fields    : [0]
     *  - Default       : 0b0
     *  - Description   : Four wire readback on CLKOUT pin mode.
     *
     */
    typedef enum {
        FOURWIRE1_READBACK_DISABLE, /**< 0x0: Four wire readback disabled. */
        FOURWIRE1_READBACK_ENABLE,  /**< 0x1: Four wire readback enabled. */
    } fourwire1_t;


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG7(0x10)
     *  - Bit Fields    : [2]
     *  - Default       : 0b0
     *  - Description   : Enables DATA transmission in I2C mode. Aliased address for I2C_TXEN1
     */
    typedef enum {
        I2C_TXEN2_DISABLE,  /**< 0x0: Data transmission not enabled in I2C mode. */
        I2C_TXEN2_ENABLE,   /**< 0x1: Data transmission enabled in I2C mode. */
    } i2c_txen2_t;

    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG7(0x10)
     *  - Bit Fields    : [1]
     *  - Default       : 0b0
     *  - Description   : Transmission enable.
     */
    typedef enum {
        SPI_TXEN2_DISABLE,    /**< 0x0: Transmission disabled. */
        SPI_TXEN2_ENABLE,    /**< 0x1: Transmission enabled. */
    } spi_txen2_t;


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG7(0x10)
     *  - Bit Fields    : [0]
     *  - Default       : 0b0
     *  - Description   : Four wire readback on CLKOUT pin mode. Aliased address for FOURWIRE1
     */
    typedef enum {
        FOURWIRE2_READBACK_DISABLE,    /**< 0x0: Four wire readback disabled. */
        FOURWIRE2_READBACK_ENABLE,    /**< 0x1: Four wire readback enabled. */
    } fourwire2_t;



    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : I2C1(0x11)
     *  - Bit Fields    : [7]
     *  - Default       : 0b0
     *  - Description   : Packet Length Mode
     *
     */
    typedef enum {
        PKTLEN_MODE_SET_LENGTH,        /**< 0x0: PKTLEN[14:0] need not be programmed. FIFO underflow event will
                                            be treated as end of packet event. For cases where actual packet length
                                            is greater than 32767 bits, it is expected that the µC will pad
                                            such a packet to make it an integral multiple of 8-bits */
        PKTLEN_MODE_NO_SET_LENGTH,    /**< 0x1: PKTLEN[14:0] will provide the length of packet. Once FIFO is
                                           read for PKTLEN[14:0] bits, or if FIFO underflow, MAX4146x will consider
                                           that as an end of packet event. */
    } pktlen_mode_t;

    /**
    * @brief set packet length
    *
    * @param[in] pktlen_mode packet length mode
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_pktlen_mode(pktlen_mode_t pktlen_mode);

    /**
    * @brief Gets packet length
    *
    * @param[in] pktlen_mode packet length mode
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_pktlen_mode(pktlen_mode_t* pktlen_mode);


    /**
     * @brief Register Configuration
     *
     * @details
     *  - Register      : CFG8(0x17)
     *  - Bit Fields    : [0]
     *  - Default       : 0b0
     *  - Description   : Places DUT into software reset.
     */
    typedef enum {
        SOFTRESET_DEASSERT,     /**< 0x0: Deassert the reset */
        SOFTRESET_RESET,        /**< 0x1: Resets the entire digital, until this bit is set to 0 */
    } softreset_t;

    /**
    * @brief set softreset bit
    *
    * @param[in] softreset enable/disable
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_softreset(softreset_t softreset);

    /**
     * @brief Operation state of the rf transmitter
     *
     * @details
     *  - Default       : 0b0
     *  - Description   : Places DUT into software reset.
     */
    typedef enum {
        INITIALIZED = 0,
        UNINITIALIZED = 1,
        UNKNOWN = 2,
    } operation_mode_t;


    // Indicates whether initialization is successful
    operation_mode_t operation_mode;

    /**
    * @brief get fifo flags (I2C6) Read only
    *
    * @param[in] fifo_flags 8-bit fifo flags
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_fifo_flags(uint8_t *fifo_flags);

    /**
    * @brief get pktcomplete bit field flags (I2C4) Read only
    *
    * @param[in] pktcomplete  0x0: Packet transmission is not completed
    *                         0x1: Packet transmission is completed
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_pktcomplete(uint8_t *pktcomplete);

    /**
    * @brief get packet length of transmitted packet
    *
    * @param[in] pktlen Provides status information of bits transmitted for the current packet
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_tx_pktlen(uint16_t *pktlen);


    /* PUBLIC FUNCTION DECLARATIONS */

    /**
    * @brief Read from a register.
    *
    * @param[in] reg Address of a register to be read.
    * @param[out] value Pointer to save result value.
    * @param[in] len Size of result to be read.
    *
    * @returns 0 on success, negative error code on failure.
    */
    int read_register(uint8_t reg, uint8_t *value, uint8_t len);

    /**
    * @brief Write to a register.
    *
    * @param[in] reg Address of a register to be written.
    * @param[out] value Pointer of value to be written to register.
    * @param[in] len Size of result to be written.
    *
    * @returns 0 on success, negative error code on failure.
    */
    int write_register(uint8_t reg, const uint8_t *value, uint8_t len);

    /**
    * @brief Initial programming steps after power on or soft reset.
    *
    * @returns 0 on success, negative error code on failure.
    */
    int initial_programming(void);

    /**
    * @brief Set Baud clock predivision ratio
    *
    * @param[in] prediv values between 3 and 255
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_bclk_prediv(uint8_t prediv);

    /**
    * @brief Gets Baud clock predivision ratio
    *
    * @param[in] prediv values between 3 and 255
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_bclk_prediv(uint8_t* prediv);

    /**
    * @brief Controls GFSK shaping
    *
    * @param[in] tstep values between 0 and 31
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_tstep(uint8_t tstep);

    /**
    * @brief Gets tstep
    *
    * @param[in] tstep values between 0 and 31
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_tstep(uint8_t* tstep);

    /**
    * @brief Set PLL frequency
    *
    * @param[in] freq FREQ value to PLL between 0x00 and 0xFFFFFF
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description LO frequency = FREQ<23:0>/2^16*fXTAL
    */
    int set_frequency(uint32_t freq);

    /**
    * @brief Gets PLL frequency
    *
    * @param[in] freq FREQ value to PLL between 0x00 and 0xFFFFFF
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description LO frequency = FREQ<23:0>/2^16*fXTAL
    */
    int get_frequency(uint32_t* freq);

    /**
    * @brief Set frequency deviation from the space frequency for the mark frequency
    *
    * @param[in] deltaf frequency deviation value
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description fDELTA = DELTAF[6:0]* fXTAL/8192
    */
    int set_deltaf(uint8_t deltaf);

    /**
    * @brief Get frequency deviation from the space frequency for the mark frequency
    *
    * @param[in] deltaf frequency deviation value
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description fDELTA = DELTAF[6:0]* fXTAL/8192
    */
    int get_deltaf(uint8_t* deltaf);

    /**
    * @brief Set frequency deviation from the space frequency for the mark frequency
    *
    * @param[in] deltaf_shape frequency deviation value
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description fDELTA = DELTAF_SHAPE[3:0]* fXTAL/81920
    */
    int set_deltaf_shape(uint8_t deltaf_shape);

    /**
    * @brief Gets frequency deviation from the space frequency for the mark frequency
    *
    * @param[in] deltaf_shape frequency deviation value
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description fDELTA = DELTAF_SHAPE[3:0]* fXTAL/81920
    */
    int get_deltaf_shape(uint8_t* deltaf_shape);

    /**
    * @brief Set Packet Length for I2C communication
    *
    * @param[in] pktlen values between 0x00 and 0x7FF
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_i2c_pktlen(uint16_t pktlen);

    /**
    * @brief Gets Packet Length for I2C communication
    *
    * @param[in] pktlen values between 0x00 and 0x7FF
    *
    * @returns 0 on success, negative error code on failure.
    */
    int get_i2c_pktlen(uint16_t* pktlen);

    /**
    * @brief Adjust baud rate
    *
    * @param[in] baud_rate preferred baud rate
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description It changes only the values of BCLK_PREDIV and BCLK_POSTDIV
    *              Baud_rate = f_clk/((1+BCLK_PREDIV)x2^(1+BCLK_POSTDIV))
    *              where f_clk = f_xtal/XOCLKDIV_ratio
    *              Note that to maintain the internal 3.2MHz time base,
    *              XOCLKDIV[1:0] (register CFG1, 0x00, bit 4) must be programmed,
    *              based on the crystal frequency
    */
    int adjust_baudrate(float rate);

    /**
	* @brief Gets baud rate
	*
	* @returns baud rate.
	*
	*/
	float get_baudrate();

    /**
    * @brief Adjust Manchester Bitrate
    *
    * @param[in] data_rate preferred data rate in (1-50)kbps
    *
    * @returns 0 on success, negative error code on failure.
    */
    int adjust_manchester_bitrate(char rate);

    /**
    * @brief Get Manchester Bitrate
    *
    * @returns data rate in (1-50)kbps
    */
    char get_manchester_bitrate();

    /**
    * @brief Configures the crystal frequency of the chip (Fxtal)
    *
    * @param[in] freq crystal frequency values between 12.8 MHz and 19.2 MHz
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_crystal_frequency(float freq);

    /**
    * @brief Get the crystal frequency of the chip (Fxtal)
    *
    * @returns crystal frequency values between 12.8 MHz and 19.2 MHz
    */
    float get_crystal_frequency();

    /**
    * @brief Adjust center/carrier frequency of the chip
    *
    * @param[in] freq center/carrier frequency value between 250 MHz and 950 MHz
    *
    * @returns 0 on success, negative error code on failure.
    */
    int set_center_frequency(float freq);

    /**
    * @brief Gets center/carrier frequency of the chip
    *
    * @returns center/carrier frequency value between 250 MHz and 950 MHz
    */
    float get_center_frequency();

    /**
    * @brief set the FSK deviation values (Delta_f)
    *
    * @param[in] deviation deviation value in in kHz baud rate
    *
    * @returns 0 on success, negative error code on failure.
    *
    * @description The mark frequency is defined by the space frequency
    *              plus a frequency deviation. If frequency shaping is
    *              disabled by setting FSKSHAPE = 0 (register CFG1, bit 2),
    *              the frequency deviation is defined by DELTAF[6:0]
    *              (register PLL6, bits 6:0).
    *              DELTAF[6 : 0] = (Delta_f * 8192)f_xtal
    *              If frequency shaping is enabled by setting FSKSHAPE = 1
    *              (register CFG1, bit 2), the frequency deviation is defined
    *              by DETLAF_SHAPE[3:0] (register PLL7, bits 3:0).
    *              DELTAF_SHAPE[3 : 0] = (Delta_f * 8192)/(f_xtal * 10)
    */
    int adjust_frequency_deviation(float deviation);

    /**
    * @brief Send data for selected Preset/I2C/SPI mode
    *
    * @param[in] data data pointer for data to be transferred
    * @param[in] length legth of data to be transferred
    *
    * @returns 0 on success, negative error code on failure.
    */
    int send_data(uint8_t *data, uint32_t length);
};


/** MAX41460 Device Class
 *
 * Hold configurations for the MAX41460
 */
class MAX41460 : public MAX4146X <max41460_reg_map_t>
{
    max41460_reg_map_t regmap;
public:
    MAX41460(SPI *spi, DigitalOut *cs) : MAX4146X<max41460_reg_map_t>(&regmap, spi, cs) {}

    MAX41460(SPI *spi) : MAX4146X<max41460_reg_map_t>(&regmap, spi) {}

    MAX41460(DigitalOut *cs) : MAX4146X(cs) {}

};

/** MAX41461 Device Class
 *
 * Hold configurations for the MAX41461
 */
class MAX41461 : public MAX4146X <max41461_2_reg_map_t>
{
    max41461_2_reg_map_t regmap;
public:
    MAX41461(I2C *i2c) : MAX4146X<max41461_2_reg_map_t>(&regmap, i2c) {}

    MAX41461(DigitalOut *cs) : MAX4146X(cs) {}
};

/** MAX41462 Device Class
 *
 * Hold configurations for the MAX41462
 */
class MAX41462 : public MAX41461
{
public:
    MAX41462(I2C *i2c) : MAX41461(i2c) {}

    MAX41462(DigitalOut *cs) : MAX41461(cs) {}

};

/** MAX41463 Device Class
 *
 * Hold configurations for the MAX41463
 */
class MAX41463 : public MAX4146X <max41463_4_reg_map_t>
{
    max41463_4_reg_map_t regmap;
public:
    MAX41463(I2C *i2c) : MAX4146X<max41463_4_reg_map_t>(&regmap, i2c) {}

    MAX41463(DigitalOut *cs) : MAX4146X(cs) {}

};

/** MAX41464 Device Class
 *
 * Hold configurations for the MAX41464
 */
class MAX41464 : public MAX41463
{
public:
    MAX41464(I2C *i2c) : MAX41463(i2c) {}

    MAX41464(DigitalOut *cs) : MAX41463(cs) {}

};


#endif /* MAX4146x_H_ */