MBED driver for Max1471.

MAX1471.cpp

Committer:
Abdullah.Turan@IST-LT-37344.maxim-ic.internal
Date:
2019-10-04
Revision:
0:99e9397112f0

File content as of revision 0:99e9397112f0:

/*
 * MAX1471.cpp
 *
 *  Created on: Dec 17, 2018
 */

#include <limits.h>
#include "spim.h"
#include "max32630fthr.h"
#include "MAX1471.h"
#include "tmr.h"
#include "gpio.h"


#define GPIO_P3_IN          (uint32_t)0x4000A18C

using namespace std;

#define BITBAND(reg, bit)               ((0xf0000000 & (uint32_t)(reg)) + 0x2000000 + \
                                            (((uint32_t)(reg) & 0x0fffffff) << 5) + ((bit) << 2))

#define MXC_CLRBIT(reg, bit)            (*(volatile uint32_t *)BITBAND(reg, bit) = 0)
#define MXC_SETBIT(reg, bit)            (*(volatile uint32_t *)BITBAND(reg, bit) = 1)
#define MXC_GETBIT(reg, bit)            (*(volatile uint32_t *)BITBAND(reg, bit))

#define SET_BIT_FIELD(address, reg_name, bit_field_name, value) {                            \
                int ret;                                                                    \
                ret = read_register(address, (uint8_t *)&(reg_name), 1);                    \
                if (ret) {                                                                  \
                    return ret;                                                             \
                }                                                                           \
                bit_field_name = value;                                                     \
                ret = write_register(address, (uint8_t *)&(reg_name), 1);                   \
                if (ret) {                                                                  \
                    return ret;                                                             \
                }}

//Constructors

int MAX1471::ASKPeakDetectorEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.askpd_en, enable );

	return 0;
}

int MAX1471::FSKPeakDetectorEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.fskpd_en, enable );

	return 0;
}

int MAX1471::ASKBaseBandReceiverEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.askbb_en, enable );

	return 0;
}

int MAX1471::FSKBaseBandReceiverEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.fskbb_en, enable );

	return 0;
}

int MAX1471::RFMixerEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.mixer_en, enable );

	return 0;
}

int MAX1471::AGCEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.agc_en, enable );

	return 0;
}

int MAX1471::LNAEnable(bool enable)
{
	SET_BIT_FIELD( PWR_CFG_ADDR, this -> reg->reg_pwr_cfg, this -> reg->reg_pwr_cfg.bits.lna_en, enable );

	return 0;
}

int MAX1471::DRXEnable(bool enable)
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this -> reg->reg_cfg.bits.drx_mode, enable );

	return 0;
}


int MAX1471::SetFDATAasDOUTPin(bool enable)
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.dout_fsk, enable );

	return 0;
}

int MAX1471::SetADATAasDOUTPin(bool enable)
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.dout_ask, enable );

	return 0;
}

int MAX1471::LongerFSKCalibrationEnable(bool enable)
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.fskcallsb, enable );

	return 0;
}

int MAX1471::LNAGainState(bool isHighGain)
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.gainset, isHighGain );

	return 0;
}

int MAX1471::FSKCalibrationDone(bool enable)
{
	SET_BIT_FIELD( CTRL_ADDR, this -> reg->reg_ctrl, this->reg->reg_ctrl.bits.fsk_cal_en, enable );

	return 0;
}

int MAX1471::PollTimerCalibrationEnable(bool enable)
{
	SET_BIT_FIELD( CTRL_ADDR, this -> reg->reg_ctrl, this->reg->reg_ctrl.bits.pol_cal_en, enable );

	return 0;
}

int MAX1471::ASKPeakDetectorTrackEnable(bool enable)
{
	SET_BIT_FIELD( CTRL_ADDR, this -> reg->reg_ctrl, this->reg->reg_ctrl.bits.asktrk_en, enable );

	return 0;
}

int MAX1471::FSKPeakDetectorTrackEnable(bool enable)
{
	SET_BIT_FIELD( CTRL_ADDR, this -> reg->reg_ctrl, this->reg->reg_ctrl.bits.fsktrk_en, enable );

	return 0;
}

int MAX1471::LockAGCCurrentState()
{
	SET_BIT_FIELD( CTRL_ADDR, this -> reg->reg_ctrl, this->reg->reg_ctrl.bits.agclock, 1 );

	return 0;
}

int MAX1471::GetPollTimerCalibrationDoneStatus( unsigned char *valuePtr )
{
	read_register( STAT_ADDR, &this -> reg->reg_stat.raw, 1 );

	*valuePtr = this -> reg->reg_stat.bits.pol_cal_done;

	return 0;
}

int MAX1471::GetFSKCalibrationDoneStatus( unsigned char *valuePtr )
{
	read_register( STAT_ADDR, &this -> reg->reg_stat.raw, 1 );

	*valuePtr = this -> reg->reg_stat.bits.fsk_cal_done;

	return 0;
}

int MAX1471::GetClockAliveStatus( unsigned char *valuePtr )
{
	read_register( STAT_ADDR, &this -> reg->reg_stat.raw, 1 );

	*valuePtr = this -> reg->reg_stat.bits.clkalive;

	return 0;
}

int MAX1471::GetAGCStatus( unsigned char *valuePtr )
{
	read_register( STAT_ADDR, &this -> reg->reg_stat.raw, 1 );

	*valuePtr = this -> reg->reg_stat.bits.agcst;

	return 0;
}

int MAX1471::GetPLLLockStatus( unsigned char *valuePtr )
{
	read_register( STAT_ADDR, &this -> reg->reg_stat.raw, 1 );

	*valuePtr = this -> reg->reg_stat.bits.lockdet;

	return 0;
}

int MAX1471::GetOffTimerPrescale( unsigned char *valuePtr )
{
	read_register( CFG_ADDR, &this -> reg->reg_cfg.raw, 1 );

	*valuePtr =  this->reg->reg_cfg.bits.toff_ps1;
	*valuePtr =  ( *valuePtr << 1 ) | this->reg->reg_cfg.bits.toff_ps0;

	return 0;
}

int MAX1471::SetOffTimerPrescale( unsigned char value )
{
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.toff_ps0, value & 0x01 );
	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.toff_ps1, !!( value & 0x02 ) );

	return 0;
}

int MAX1471::GetAGCDwellTimer( unsigned char *valuePtr )
{
	return read_register( AGC_DWL_TMR_ADDR, valuePtr, 1 );
}

int MAX1471::SetAGCDwellTimer( unsigned char value )
{
	return write_register( AGC_DWL_TMR_ADDR, value & 0x1F, 1);
}

int MAX1471::SetRFSettleTimer( unsigned short int value )
{
	write_register( RF_ST_UP_ADDR, ( value >> 8 ), 1 );
	write_register( RF_ST_DWN_ADDR, ( value & 0x00FF ), 1 );

	return 0;
}

int MAX1471::GetRFSettleTimer( unsigned short int *valuePtr )
{
	unsigned char *valueUint8Ptr;


	valueUint8Ptr = ( unsigned char * )valuePtr;

	read_register( RF_ST_UP_ADDR, &valueUint8Ptr[1], 1 );
	read_register( RF_ST_DWN_ADDR, &valueUint8Ptr[0], 1 );

	return 0;
}

int MAX1471::SetOFFTimer( unsigned short int value )
{
	write_register( OFF_TMR_UP_ADDR, ( value >> 8 ), 1 );

	return write_register( OFF_TMR_DWN_ADDR, ( value & 0x00FF ), 1 );;
}

int MAX1471::GetOFFTimer( unsigned short int *valuePtr )
{
	unsigned char *valueUint8Ptr;


	valueUint8Ptr = ( unsigned char * )valuePtr;

	read_register( OFF_TMR_UP_ADDR, &valueUint8Ptr[1], 1 );

	return read_register( OFF_TMR_DWN_ADDR, &valueUint8Ptr[0], 1 );;
}

int MAX1471::SetCPURecoveryTimer( unsigned char value )
{
	return write_register( CPU_REC_ADDR, value, 1 );;
}

int MAX1471::GetCPURecoveryTimer( unsigned char *valuePtr )
{
	return read_register( CPU_REC_ADDR, valuePtr, 1 );
}

int MAX1471::SetRFOscillatorFreq( float frequency )
{
	if( frequency >= 9.0406 && frequency <= 13.7281 )
	{
		unsigned char regValue = ( unsigned char )( ( frequency * 10 ) + 0.5 );
		oscFrequency = frequency;
		return write_register( OSC_FREQ_ADDR, regValue, 1 );
	}

	return -1;
}

int MAX1471::GetRFOscillatorFreq( float *freqPtr )
{
	*freqPtr = oscFrequency;
	return 0;
}

MAX1471::MAX1471(DigitalOut *cs)
{
	modulation = ASK; /*!< Current modulation mode */
	oscFrequency = 0; /*!< Extern oscillator frequency */
#if defined(TARGET_MAX32630FTHR)
	this->spi_handler =  new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
#endif

#if defined(TARGET_MAX32625PICO)
	this->spi_handler =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
#endif

	this->spi_handler->format(8,0);
	this->spi_handler->frequency(100000);

	this->ssel = cs;
	*(this->ssel) = 1;

	this->spi_mode = 0;

	this->reg = new max1471_reg_map_t();

	this->set_spi_type(0);
}

int MAX1471::read_register(uint8_t reg, uint8_t *value, uint8_t len)
{
	int rtn_val = -1;

    if (value == NULL) {
        return -1;
    }

    if (this->reg == NULL) {
        return -1;
    }

#if defined(TARGET_MAX32630FTHR)
	SPI *spi = new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
	mxc_spim_regs_t *MAX1471_SPI = MXC_SPIM2;
#endif

#if defined(TARGET_MAX32625PICO)
	SPI *spi =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
	mxc_spim_regs_t *MAX1471_SPI = MXC_SPIM0;
#endif

	spi->format(8,0);
	spi->frequency(400000);

    if (ssel != NULL) {
        *ssel = 0;
    }

    spi->write((uint8_t)0x20 | reg);
    spi->write(0x00);     // dummy write command for waiting data read

    if (ssel != NULL) {
        *ssel = 1;
    }

    wait_us(1);

    if (ssel != NULL) {
        *ssel = 0;
    }

	if (this->spi_mode == 0) {

		MAX1471_SPI->mstr_cfg |= MXC_F_SPIM_MSTR_CFG_THREE_WIRE_MODE;

		// Disable SPI for General Control Configuration
		MAX1471_SPI->gen_ctrl = 0;
		MAX1471_SPI->gen_ctrl |= (MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE | (1 << MXC_F_SPIM_GEN_CTRL_SIMPLE_MODE_POS)); // simple header

		MAX1471_SPI->simple_headers &= 0x0000FFFF;
		MAX1471_SPI->simple_headers |= 0x2016<<16;
		MAX1471_SPI->gen_ctrl |=MXC_F_SPIM_GEN_CTRL_START_RX_ONLY;

		// Enable the SPI
		MAX1471_SPI->gen_ctrl |= MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN;

		volatile mxc_spim_fifo_regs_t *fifo;

		fifo = MXC_SPIM_GET_SPIM_FIFO(MXC_SPIM_GET_IDX(MAX1471_SPI));

		int avail = ((MAX1471_SPI->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >> MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);

		Timer t;

		t.start();

		while (avail < 1) {
			if (t.read_ms() > 1000) {
				break;
			} else {
				avail = ((MAX1471_SPI->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >> MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);
			}
		}

		t.stop();

		for (int i = 0; i < avail; i++) {
			*(value++) = fifo->rslts_8[i];
		}

		while (MAX1471_SPI->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) {
			fifo->rslts_8[0];
		}

		MAX1471_SPI->gen_ctrl = 0;
		MAX1471_SPI->gen_ctrl |= (MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE | (0 << MXC_F_SPIM_GEN_CTRL_SIMPLE_MODE_POS)); // simple header

		MAX1471_SPI->gen_ctrl |= MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN;

	} else {
		MAX1471_SPI->mstr_cfg &= ~MXC_F_SPIM_MSTR_CFG_THREE_WIRE_MODE;

		for (uint8_t i = 0; i < len; i++) {
        *(value++) = spi->write(0x00);     // read back  data bytes
		}
	}

    if (ssel != NULL) {
        *ssel = 1;
    }

	delete spi;

    return 0;
}

int MAX1471::write_register(uint8_t reg, const uint8_t *value, uint8_t len)
{
    int rtn_val = -1;

    if (value == NULL) {
        return -1;
    }

#if defined(TARGET_MAX32630FTHR)
	SPI *spi = new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
#endif

#if defined(TARGET_MAX32625PICO)
	SPI *spi =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
#endif

	spi->format(8,0);
	spi->frequency(100000);

    if (ssel != NULL) {
        *ssel = 0;
    }

    rtn_val = spi->write(0x10 | reg); // write mode and adress send

    rtn_val = spi->write((int)*value); // write adress


    if (ssel != NULL) {
        *ssel = 1;
    }

    delete spi;

    if (rtn_val != 0) {
        return rtn_val;
    }

    return 0;
}

int MAX1471::write_register(uint8_t reg, const uint8_t value, uint8_t len)
{
    int rtn_val = -1;


#if defined(TARGET_MAX32630FTHR)
	SPI *spi = new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
#endif

#if defined(TARGET_MAX32625PICO)
	SPI *spi =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
#endif

	spi->format(8,0);
	spi->frequency(100000);

    if (ssel != NULL) {
        *ssel = 0;
    }

    rtn_val = spi->write(0x10 | reg); // write mode and adress send

    rtn_val = spi->write((int)value); // write adress


    if (ssel != NULL) {
        *ssel = 1;
    }

    delete spi;

    if (rtn_val != 0) {
        return rtn_val;
    }

    return 0;
}

int MAX1471::set_spi_type(uint8_t type)
{
	/*
	 *  0 -> 3-Wire Default
	 *  1 -> 4-Wire (DOUT_FSK) enabled
	 *  2 -> 4-Wire (DOUT_ASK) enabled
	 */

	switch (type)
	{
		case 0:
			this->reg->reg_cfg.bits.dout_ask = 0;
			this->reg->reg_cfg.bits.dout_fsk = 0;
			break;
		case 1:
			this->reg->reg_cfg.bits.dout_ask = 0;
			this->reg->reg_cfg.bits.dout_fsk = 1;
			break;
		case 2:
			this->reg->reg_cfg.bits.dout_ask = 1;
			this->reg->reg_cfg.bits.dout_fsk = 0;
			break;
		default:
			break;
	}

	if (this->write_register(CFG_ADDR, (uint8_t *)&this->reg->reg_cfg.raw, 1) == 0) {
		spi_mode = type;
	}

	return 0;
}

int MAX1471::reset()
{
#if defined(TARGET_MAX32630FTHR)
	SPI *spi = new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
#endif

#if defined(TARGET_MAX32625PICO)
	SPI *spi =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
#endif

	spi->format(8,0);
	spi->frequency(100000);

    if (ssel != NULL) {
        *ssel = 0;
    }

	int rtrn = spi->write(0x30); // write mode and adress send

    if (ssel != NULL) {
        *ssel = 1;
    }

    delete spi;

    return rtrn;

}

int MAX1471::nop()
{
#if defined(TARGET_MAX32630FTHR)
	SPI *spi = new SPI(P5_1, P5_2, P5_0); /* mosi, miso, sclk */
#endif

#if defined(TARGET_MAX32625PICO)
	SPI *spi =  new SPI(P0_5, P0_6, P0_4); /* mosi, miso, sclk */
#endif

	spi->format(8,0);
	spi->frequency(100000);

    if (ssel != NULL) {
        *ssel = 0;
    }

	int rtrn = spi->write(0x00); // write mode and adress send

    if (ssel != NULL) {
        *ssel = 1;
    }

    delete spi;

    return rtrn;

}

int MAX1471::InitMAX1471()
{
	// Write 0x3000 to reset the part
	this->reset();
	// wait for 100ms
	Thread::wait(100);
	// Write 0x10FE to enable all RF and baseband sections.
	uint8_t value = 0xF4;
	this->write_register(PWR_CFG_ADDR, &value, 1);

	// Write 0x135F to set the oscillator frequency register to work with a 315MHz crystal.
	// Write 0x1384 to set the oscillator frequency register to work with a 433.92MHz crystal.
	value = 0x84;
	this->write_register(OSC_FREQ_ADDR, &value, 1);

	return 0;
}


int MAX1471::PrepMAX1471RX( modulation_type_t modType ) {
	uint8_t value = 0x20;
	uint8_t *readValue = &value;


	if( modType == ASK ){
		this->ASKBaseBandReceiverEnable(true);
		this->ASKPeakDetectorEnable(true);
		this->RFMixerEnable(true);

		this->LNAEnable(true);

		this->AGCEnable(true);
		this->LNAGainState(true);
		this->AGCEnable(false);
	}
	else if( modType == FSK ){
		this->FSKBaseBandReceiverEnable(true);
		this->FSKPeakDetectorEnable(true);

		this->RFMixerEnable(true);

		this->LNAEnable(true);

		this->LongerFSKCalibrationEnable(true);

		this->AGCEnable(true);
		this->LNAGainState(true);
		this->AGCEnable(false);

		this->FSKCalibrationDone(true);

		uint8_t *readValue = &value;

		*readValue = 0;

		while (*readValue == 0) {
			this->GetFSKCalibrationDoneStatus( readValue );
		}
	}
	else{
		this->PrepMAX1471RX();
	}

	return 0;

}

int MAX1471::PrepMAX1471RX() {
	uint8_t value;

	this->ASKBaseBandReceiverEnable(true);
	this->ASKPeakDetectorEnable(true);

	this->FSKBaseBandReceiverEnable(true);
	this->FSKPeakDetectorEnable(true);

	this->RFMixerEnable(true);

	this->LNAEnable(true);

	this->LongerFSKCalibrationEnable(true);

	this->AGCEnable(true);
	this->LNAGainState(true);
	this->AGCEnable(false);

	this->FSKCalibrationDone(true);

	uint8_t *readValue = &value;

	*readValue = 0;

	while (*readValue == 0) {
		this->GetFSKCalibrationDoneStatus( readValue );
	}

  return 0;
}

int MAX1471::PrepMAX1471Sleep(bool enable) {
	/* This routine is used to prepare the MAX7032 for sleep mode */

	SET_BIT_FIELD( CFG_ADDR, this -> reg->reg_cfg, this->reg->reg_cfg.bits.toff_ps0, enable );

	return 0;
}