MBED driver for Max1471.
Diff: MAX1471.cpp
- Revision:
- 0:99e9397112f0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX1471.cpp Fri Oct 04 15:15:06 2019 +0300 @@ -0,0 +1,715 @@ +/* + * 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; +} + + + + + + +