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; }