![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
max4146x_comp
Diff: max4146x/Max4146x.cpp
- Revision:
- 0:0061165683ee
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/max4146x/Max4146x.cpp Sun Oct 25 20:10:02 2020 +0000 @@ -0,0 +1,1212 @@ +/******************************************************************************* +* 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. +******************************************************************************* +*/ + +#include "Max4146x.h" +#include <iostream> + +using namespace std; + +const uint8_t default_register_value_0[17] = {0x90, 0x81, 0x03, 0x00, 0x00, 0x04, 0x80, 0x80, 0x60, 0x00, + 0x00, 0xC4, 0xDE, 0x98, 0x28, 0x04, 0x02}; +const uint8_t default_register_value_1[20] = {0x90, 0x81, 0x03, 0x00, 0x00, 0x04, 0x80, 0x80, 0x60, 0x00, + 0x00, 0xC4, 0xDE, 0x98, 0x28, 0x04, 0x04, 0x00, 0xFF, 0x00}; + +template <class REG> +MAX4146X<REG>::MAX4146X(REG *reg, SPI *spi, DigitalOut *cs) +{ + operation_mode = UNINITIALIZED; + + if (reg == NULL) { + return; + } + + if (cs == NULL) { + return; + } + + this->reg = reg; + ssel = cs; + + if (spi == NULL) { + return; + } + + spi_handler = spi; + i2c_handler = NULL; + preset_mode = 0; + + if (initial_programming() < 0) { + return; + } + + this->crystal_frequency = 16.0; + this->center_frequency = 315.0; + this->baud_rate = 5000.0; //5 kHz + + operation_mode = INITIALIZED; +} + +template <class REG> +MAX4146X<REG>::MAX4146X(REG *reg, SPI *spi) +{ + operation_mode = UNINITIALIZED; + + if (reg == NULL) { + return; + } + + this->reg = reg; + + if (spi == NULL) { + return; + } + + spi_handler = spi; + i2c_handler = NULL; + ssel = NULL; + preset_mode = 0; + + if (initial_programming() < 0) { + return; + } + + this->crystal_frequency = 16.0; + this->center_frequency = 315.0; + this->baud_rate = 5000.0; //5 kHz + + operation_mode = INITIALIZED; +} + +template <class REG> +MAX4146X<REG>::MAX4146X(REG *reg, I2C *i2c) +{ + operation_mode = UNINITIALIZED; + + if (reg == NULL) { + return; + } + + this->reg = reg; + + if (i2c == NULL) { + return; + } + + i2c_handler = i2c; + spi_handler = NULL; + ssel = NULL; + preset_mode = 0; + + if (initial_programming() < 0) { + return; + } + + this->crystal_frequency = 16.0; + this->center_frequency = 315.0; + this->baud_rate = 5000.0; //5 kHz + + operation_mode = INITIALIZED; +} + +template <class REG> +MAX4146X<REG>::MAX4146X(DigitalOut *cs) +{ + operation_mode = UNINITIALIZED; + + if (cs == NULL) { + return; + } + + data_sent = cs; + + data_rate = 5; + + this->reg = NULL; + this->ssel = NULL; + spi_handler = NULL; + i2c_handler = NULL; + preset_mode = 1; + + operation_mode = INITIALIZED; +} + +template <> +int MAX4146X<max41460_reg_map_t>::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 (ssel != NULL) { + *ssel = 0; + } + spi_handler->write((uint8_t)0x80 | reg); + for (uint8_t i = 0; i < len; i++) { + *(value++) = spi_handler->write(0x00); // read back data bytes + } + if (ssel != NULL) { + *ssel = 1; + } + return 0; +} + +template <class REG> +int MAX4146X<REG>::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; + } + + rtn_val = i2c_handler->write(I2C_ADDRESS, (const char *)®, 1, true); + if (rtn_val != 0) { + return -1; + } + + rtn_val = i2c_handler->read(I2C_ADDRESS, (char *) value, len, false); + if (rtn_val < 0) { + return rtn_val; + } + + return 0; +} + +template <> +int MAX4146X<max41460_reg_map_t>::write_register(uint8_t reg, const uint8_t *value, uint8_t len) +{ + int rtn_val = -1; + uint8_t local_data[1 + len]; + + if (value == NULL) { + return -1; + } + + memcpy(&local_data[0], value, len); + + rtn_val = spi_handler->write(0x7F & reg); // write mode and adress send + for (int i = 0; i < len; i++) { + rtn_val = spi_handler->write(local_data[i]); // write adress + } + if (rtn_val != 0) { + return rtn_val; + } + + return 0; +} + +template <class REG> +int MAX4146X<REG>::write_register(uint8_t reg, const uint8_t *value, uint8_t len) +{ + int rtn_val = -1; + uint8_t local_data[1 + len]; + + if (value == NULL) { + return -1; + } + + local_data[0] = reg; + + memcpy(&local_data[1], value, len); + + rtn_val = i2c_handler->write(I2C_ADDRESS, (const char *)local_data, + sizeof(local_data)); + if (rtn_val != 0) { + return -1; + } + + return 0; +} + +#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; \ + } + +template <class REG> +int MAX4146X<REG>::set_crystal_frequency(float freq) +{ + if (freq < 250 || freq > 950) { + return -1; + } + this->crystal_frequency = freq; + + return 0; +} + +template <class REG> +float MAX4146X<REG>::get_crystal_frequency() +{ + return this->crystal_frequency; +} + +template <class REG> +int MAX4146X<REG>::set_center_frequency(float freq) +{ + if (freq < 250 || freq > 950) { + return -1; + } + + this->center_frequency = freq; + + uint32_t value = (uint32_t)((65536 * freq) / this->crystal_frequency); //65536 is constant defined in the datasheet + + return this->set_frequency(value); +} + +template <class REG> +float MAX4146X<REG>::get_center_frequency() +{ + return this->center_frequency; +} + +template <class REG> +int MAX4146X<REG>::adjust_baudrate(float rate) +{ + if (rate < 195.3 || rate > 200000.0) { + return -1; + } + + if (this->preset_mode == 1) { + this->baud_rate = rate; + } + + int error = 0; + uint8_t prediv = 3; + + if (rate < 12500.0) { + error = this->set_bclk_postdiv(this->BCLK_POSTDIV_BY_5); + prediv = (uint8_t)((50000.0 / rate) - 1); + } else if (rate < 25000.0) { + error = this->set_bclk_postdiv(this->BCLK_POSTDIV_BY_4); + prediv = (uint8_t)((100000.0 / rate) - 1); + } else if (rate < 50000.0) { + error = this->set_bclk_postdiv(this->BCLK_POSTDIV_BY_3); + prediv = (uint8_t)((200000.0 / rate) - 1); + } else if (rate < 100000.0) { + error = this->set_bclk_postdiv(this->BCLK_POSTDIV_BY_2); + prediv = (uint8_t)((400000.0 / rate) - 1); + } else { + error = this->set_bclk_postdiv(this->BCLK_POSTDIV_BY_1); + prediv = (uint8_t)((800000.0 / rate) - 1); + } + + if (error < 0) { + return -1; + } + + return this->set_bclk_prediv(prediv); +} + +template <class REG> +float MAX4146X<REG>::get_baudrate() +{ + return this->baud_rate; +} + +template <class REG> +int MAX4146X<REG>::adjust_frequency_deviation(float deviation) +{ + uint8_t dev = 0; + + if (this->read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1) < 0) { + return -1; + } + + if (this->reg->reg_cfg1.bits.fskshape == 0) { + dev = (uint8_t)(deviation * 8.192 / crystal_frequency); + if (dev < 127) { + return this->set_deltaf(dev); + } + } else { + dev = (uint8_t)(deviation * 81.92 / crystal_frequency); // crystal_frequency in MHz form + if (dev < 15) { + return this->set_deltaf_shape(dev); + } + } + + return -1; +} + +template <class REG> +int MAX4146X<REG>::adjust_manchester_bitrate(char rate) +{ + this->data_rate = rate; + + return 0; +} + +template <class REG> +char MAX4146X<REG>::get_manchester_bitrate() +{ + return this->data_rate; +} + +template <> +int MAX4146X<max41460_reg_map_t>::send_data(uint8_t *data, uint32_t length) +{ + if (this->preset_mode == 0) { + + if (ssel != NULL) { + *ssel = 0; + } + + spi_handler->write(0x7F & 0x0A); /*write mode and adress send*/ + + spi_handler->write(0x01); /*write data SPI_EN1 clear*/ + + + if (ssel != NULL) { + *ssel = 1; + } + + wait_us(300); /* for waiting another SPI operation*/ + + if (ssel != NULL) { + *ssel = 0; + } + + spi_handler->write(0x7F & 0x10); /*write mode and adress send*/ + + spi_handler->write(0x03); /*write data SPI_EN2 set*/ + + if (ssel != NULL) { + *ssel = 0; + } + + wait_us(300); /* for waiting another SPI operation*/ + + } + + return this->io_write(data, length); +} + +template <class REG> +int MAX4146X<REG>::send_data(uint8_t *data, uint32_t length) +{ + if (this->preset_mode == 0) { + if (length > 32767) { + return -100; + } + + this->adjust_baudrate(this->baud_rate); + +// this->set_i2c_txen1(I2C_TXEN1_DISABLE); + + char * value = (char *)malloc(17 * sizeof(char)); + + if (value == NULL) { + return -99; + } + + int rtn_val = i2c_handler->write(I2C_ADDRESS, (char *) 0x00, 1, true); + rtn_val = i2c_handler->read(I2C_ADDRESS, value, length, true); + if (rtn_val != 0) { + return rtn_val; + } + + free(value); + + uint8_t local_data[4+length]; + + local_data[0] = CFG7_ADDR; + local_data[1] = 0x04; + local_data[2] = (uint8_t)((length >> 8) | 0x80); + local_data[3] = (uint8_t)((length) & 0x0FF); + + memcpy(&local_data[4], data, length); + + i2c_handler->write(I2C_ADDRESS, (const char *)local_data, sizeof(local_data), false); + + } else { + this->io_write(data, length); + } + + return 0; +} + +template <class REG> +int MAX4146X<REG>::io_write(uint8_t *data, uint32_t length) +{ + //manchester array + manchester_bit_array = new unsigned char[length * 2 * 8]; + + //bit array + bits_array = new unsigned char[length * 8]; + + //byte to bit conversion + for (int i = 0; i < length; i++) { + for (int j = 0; j < 8; j++) { + // Mask each bit in the byte and store it + if (data[i] & (mask << j)) { + bits_array[i * 8 + j] = 1; + } else { + bits_array[i * 8 + j] = 0; + } + } + } + + //manchester encode + for (int i = 0; i < length * 8; i++) { + if (bits_array[i] == 0) { + //falling edge + manchester_bit_array[2 * i] = 1; + manchester_bit_array[2 * i + 1] = 0; + } else { + //rising edge + manchester_bit_array[2 * i] = 0; + manchester_bit_array[2 * i + 1] = 1; + } + } + + delete[] bits_array; //delete bit array anymore not used + + float result = (500.0 / data_rate); + + bool rxFinished = false; + Timer t; + core_util_critical_section_enter(); + *this->data_sent = 0; + wait_us(100); + *this->data_sent = 1; + wait_us(350); + *this->data_sent = 0; + wait_us(10); + t.start(); + int manch_bit_counter = 0; + do { + if (t.read_us() >= (result * manch_bit_counter)) { + if (manchester_bit_array[manch_bit_counter] == 0) { + *this->data_sent = 0; + } else { + *this->data_sent = 1; + } + + manch_bit_counter++; + + if (manch_bit_counter >= (length * 2 * 8)) { + rxFinished = true; + t.stop(); + if (this->ssel != NULL) { + *this->ssel = 1; + } + } + + } + } while (!rxFinished); + *this->data_sent = 0; + core_util_critical_section_exit(); + + delete[] manchester_bit_array; //manchester array clean + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_softreset(softreset_t softreset) +{ + SET_BIT_FIELD(CFG8_ADDR, this->reg->reg_cfg8, this->reg->reg_cfg8.bits.softreset, softreset); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_xoclkdelay(xoclkdelay_t delay) +{ + SET_BIT_FIELD(CFG1_ADDR, this->reg->reg_cfg1, this->reg->reg_cfg1.bits.xoclkdelay, delay); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_xoclkdelay(xoclkdelay_t *delay) +{ + int ret; + + ret = read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1); + if (ret < 0) { + return ret; + } + + *delay = (xoclkdelay_t)this->reg->reg_cfg1.bits.xoclkdelay; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_fifo_flags(uint8_t *fifo_flags) +{ + return read_register(I2C6_ADDR, fifo_flags, 1); +} + +template <class REG> +int MAX4146X<REG>::get_pktcomplete(uint8_t *pktcomplete) +{ + int ret; + + ret = read_register(I2C4_ADDR, (uint8_t *) & (this->reg->reg_i2c4), 1); + if (ret < 0) { + return ret; + } + + *pktcomplete = (uint8_t)this->reg->reg_i2c4.bits.pktcomplete; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_tx_pktlen(uint16_t *pktlen) +{ + int ret; + + ret = read_register(I2C4_ADDR, (uint8_t *) & (this->reg->reg_i2c4), 2); + if (ret < 0) { + return ret; + } + + *pktlen = (uint16_t)(((this->reg->reg_i2c4.bits.tx_pktlen_14_to_8) << 8) + (this->reg->reg_i2c5.raw)) ; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_xoclkdiv(xoclkdiv_t div) +{ + SET_BIT_FIELD(CFG1_ADDR, this->reg->reg_cfg1, this->reg->reg_cfg1.bits.xoclkdiv, div); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_xoclkdiv(xoclkdiv_t* div) +{ + int ret; + + ret = read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1); + if (ret < 0) { + return ret; + } + + *div = (xoclkdiv_t)this->reg->reg_cfg1.bits.xoclkdiv; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_fskshape(fskshape_t shape) +{ + SET_BIT_FIELD(CFG1_ADDR, this->reg->reg_cfg1, this->reg->reg_cfg1.bits.fskshape, shape); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_fskshape(fskshape_t* shape) +{ + int ret; + + ret = read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1); + if (ret < 0) { + return ret; + } + + *shape = (fskshape_t)this->reg->reg_cfg1.bits.fskshape; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_sync(sync_t state) +{ + SET_BIT_FIELD(CFG1_ADDR, this->reg->reg_cfg1, this->reg->reg_cfg1.bits.sync, state); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_sync(sync_t* state) +{ + int ret; + + ret = read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1); + if (ret < 0) { + return ret; + } + + *state = (sync_t)this->reg->reg_cfg1.bits.sync; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_modmode(modmode_t mode) +{ + SET_BIT_FIELD(CFG1_ADDR, this->reg->reg_cfg1, this->reg->reg_cfg1.bits.modmode, mode); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_modmode(modmode_t* mode) +{ + int ret; + + ret = read_register(CFG1_ADDR, (uint8_t *) & (this->reg->reg_cfg1), 1); + if (ret < 0) { + return ret; + } + + *mode = (modmode_t)this->reg->reg_cfg1.bits.modmode; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_clkout_delay(clkout_delay_t delay) +{ + SET_BIT_FIELD(CFG2_ADDR, this->reg->reg_cfg2, this->reg->reg_cfg2.bits.clkout_delay, delay); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_clkout_delay(clkout_delay_t* delay) +{ + int ret; + + ret = read_register(CFG2_ADDR, (uint8_t *) & (this->reg->reg_cfg2), 1); + if (ret < 0) { + return ret; + } + + *delay = (clkout_delay_t)this->reg->reg_cfg2.bits.clkout_delay; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_bclk_postdiv(bclk_postdiv_t div) +{ + SET_BIT_FIELD(CFG2_ADDR, this->reg->reg_cfg2, this->reg->reg_cfg2.bits.bclk_postdiv, div); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_bclk_postdiv(bclk_postdiv_t* div) +{ + int ret; + + ret = read_register(CFG2_ADDR, (uint8_t *) & (this->reg->reg_cfg2), 1); + if (ret < 0) { + return ret; + } + + *div = (bclk_postdiv_t)this->reg->reg_cfg2.bits.bclk_postdiv; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_bclk_prediv(uint8_t prediv) +{ + if (prediv < 3) { + return -1; + } + + SET_BIT_FIELD(CFG3_ADDR, this->reg->reg_cfg3, this->reg->reg_cfg3.bits.bclk_prediv, prediv); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_bclk_prediv(uint8_t* prediv) +{ + int ret; + + ret = read_register(CFG3_ADDR, (uint8_t *) & (this->reg->reg_cfg3), 1); + if (ret < 0) { + return ret; + } + + *prediv = (uint8_t)this->reg->reg_cfg3.bits.bclk_prediv; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_pwdn_mode(pwdn_mode_t pwdn_mode) +{ + SET_BIT_FIELD(CFG4_ADDR, this->reg->reg_cfg4, this->reg->reg_cfg4.bits.pwdn_mode, pwdn_mode); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_pwdn_mode(pwdn_mode_t* pwdn_mode) +{ + int ret; + + ret = read_register(CFG4_ADDR, (uint8_t *) & (this->reg->reg_cfg4), 1); + if (ret < 0) { + return ret; + } + + *pwdn_mode = (pwdn_mode_t)this->reg->reg_cfg4.bits.pwdn_mode; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_tstep(uint8_t tstep) +{ + SET_BIT_FIELD(CFG5_ADDR, this->reg->reg_cfg5, this->reg->reg_cfg5.bits.tstep, tstep); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_tstep(uint8_t* tstep) +{ + int ret; + + ret = read_register(CFG5_ADDR, (uint8_t *) & (this->reg->reg_cfg5), 1); + if (ret < 0) { + return ret; + } + + *tstep = (uint8_t)this->reg->reg_cfg5.bits.tstep; + + return 0; +} +/*sdivarci*/ +template <class REG> +int MAX4146X<REG>::set_i2c_txen1(i2c_txen1_t setting) +{ + SET_BIT_FIELD(CFG6_ADDR, this->reg->reg_cfg6, this->reg->reg_cfg6.bits.i2c_txen1, setting); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_i2c_txen2(i2c_txen2_t setting) +{ + SET_BIT_FIELD(CFG7_ADDR, this->reg->reg_cfg7, this->reg->reg_cfg7.bits.i2c_txen2, setting); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_i2c_data(uint8_t setting) +{ + return write_register(I2C3_ADDR, (uint8_t *)&setting, 1); +} + + + + +template <class REG> +int MAX4146X<REG>::set_pa_boost(pa_boost_t pa_boost) +{ + SET_BIT_FIELD(SHDN_ADDR, this->reg->reg_shdn, this->reg->reg_shdn.bits.pa_boost, pa_boost); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_pa_boost(pa_boost_t* pa_boost) +{ + int ret; + + ret = read_register(CFG5_ADDR, (uint8_t *) & (this->reg->reg_shdn), 1); + if (ret < 0) { + return ret; + } + + *pa_boost = (pa_boost_t)this->reg->reg_shdn.bits.pa_boost; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_papwr(papwr_t papwr) +{ + SET_BIT_FIELD(PA1_ADDR, this->reg->reg_pa1, this->reg->reg_pa1.bits.papwr, papwr); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_papwr(papwr_t* papwr) +{ + int ret; + + ret = read_register(PA1_ADDR, (uint8_t *) & (this->reg->reg_pa1), 1); + if (ret < 0) { + return ret; + } + + *papwr = (papwr_t)this->reg->reg_pa1.bits.papwr; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_pacap(pacap_t pacap) +{ + SET_BIT_FIELD(PA2_ADDR, this->reg->reg_pa2, this->reg->reg_pa2.bits.pacap, pacap); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_pacap(pacap_t* pacap) +{ + int ret; + + ret = read_register(CFG5_ADDR, (uint8_t *) & (this->reg->reg_pa2), 1); + if (ret < 0) { + return ret; + } + + *pacap = (pacap_t)this->reg->reg_pa2.bits.pacap; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_cplin(cplin_t cplin) +{ + SET_BIT_FIELD(PLL1_ADDR, this->reg->reg_pll1, this->reg->reg_pll1.bits.cplin, cplin); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_cplin(cplin_t* cplin) +{ + int ret; + + ret = read_register(PLL1_ADDR, (uint8_t *) & (this->reg->reg_pll1), 1); + if (ret < 0) { + return ret; + } + + *cplin = (cplin_t)this->reg->reg_pll1.bits.cplin; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_fracmode(fracmode_t fracmode) +{ + SET_BIT_FIELD(PLL1_ADDR, this->reg->reg_pll1, this->reg->reg_pll1.bits.fracmode, fracmode); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_fracmode(fracmode_t* fracmode) +{ + int ret; + + ret = read_register(PLL1_ADDR, (uint8_t *) & (this->reg->reg_pll1), 1); + if (ret < 0) { + return ret; + } + + *fracmode = (fracmode_t)this->reg->reg_pll1.bits.fracmode; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_lodiv(lodiv_t lodiv) +{ + SET_BIT_FIELD(PLL1_ADDR, this->reg->reg_pll1, this->reg->reg_pll1.bits.lodiv, lodiv); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_lodiv(lodiv_t* lodiv) +{ + int ret; + + ret = read_register(PLL1_ADDR, (uint8_t *) & (this->reg->reg_pll1), 1); + if (ret < 0) { + return ret; + } + + *lodiv = (lodiv_t)this->reg->reg_pll1.bits.lodiv; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_lomode(lomode_t lomode) +{ + SET_BIT_FIELD(PLL1_ADDR, this->reg->reg_pll1, this->reg->reg_pll1.bits.lomode, lomode); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_lomode(lomode_t* lomode) +{ + int ret; + + ret = read_register(PLL1_ADDR, (uint8_t *) & (this->reg->reg_pll1), 1); + if (ret < 0) { + return ret; + } + + *lomode = (lomode_t)this->reg->reg_pll1.bits.lomode; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_cpval(cpval_t cpval) +{ + + SET_BIT_FIELD(PLL2_ADDR, this->reg->reg_pll2, this->reg->reg_pll2.bits.cpval, cpval); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_cpval(cpval_t* cpval) +{ + int ret; + + ret = read_register(PLL2_ADDR, (uint8_t *) & (this->reg->reg_pll2), 1); + if (ret < 0) { + return ret; + } + + *cpval = (cpval_t)this->reg->reg_pll2.bits.cpval; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_frequency(uint32_t freq) +{ + uint8_t value[3] = {(uint8_t)(freq >> 16), (uint8_t)(freq >> 8), (uint8_t)freq}; + + return write_register(PLL3_ADDR, (uint8_t *)&value, 3); + +} + +template <class REG> +int MAX4146X<REG>::get_frequency(uint32_t* freq) +{ + int ret; + + uint8_t value[3]; + + ret = read_register(PLL3_ADDR, (uint8_t *)&value, 3); + if (ret < 0) { + return ret; + } + + *freq = (uint32_t)((value[0] << 16) + (value[1] << 8) + value[2]); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_deltaf(uint8_t deltaf) +{ + if (deltaf > 127) { + return -1; + } + + SET_BIT_FIELD(PLL6_ADDR, this->reg->reg_pll6, this->reg->reg_pll6.bits.deltaf, deltaf); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_deltaf(uint8_t* deltaf) +{ + int ret; + + ret = read_register(PLL6_ADDR, (uint8_t *) & (this->reg->reg_pll6), 1); + if (ret < 0) { + return ret; + } + + *deltaf = (uint8_t)this->reg->reg_pll6.bits.deltaf; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_deltaf_shape(uint8_t deltaf_shape) +{ + if (deltaf_shape > 15) { + return -1; + } + + SET_BIT_FIELD(PLL7_ADDR, this->reg->reg_pll7, this->reg->reg_pll7.bits.deltaf_shape, deltaf_shape); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_deltaf_shape(uint8_t* deltaf_shape) +{ + int ret; + + ret = read_register(PLL7_ADDR, (uint8_t *) & (this->reg->reg_pll7), 1); + if (ret < 0) { + return ret; + } + + *deltaf_shape = (uint8_t)this->reg->reg_pll7.bits.deltaf_shape; + + return 0; +} + +template <class REG> +int MAX4146X<REG>::set_pktlen_mode(pktlen_mode_t pktlen_mode) +{ + SET_BIT_FIELD(I2C1_ADDR, this->reg->reg_i2c1, this->reg->reg_i2c1.bits.pktlen_mode, pktlen_mode); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::get_pktlen_mode(pktlen_mode_t* pktlen_mode) +{ + int ret; + + ret = read_register(I2C1_ADDR, (uint8_t *) & (this->reg->reg_i2c1), 1); + if (ret < 0) { + return ret; + } + + *pktlen_mode = (pktlen_mode_t)this->reg->reg_i2c1.bits.pktlen_mode; + + return 0; +} + + +template <class REG> +int MAX4146X<REG>::set_i2c_pktlen(uint16_t pktlen) +{ + if (pktlen > 0x7FF) { + return -1; + } + + SET_BIT_FIELD(I2C1_ADDR, this->reg->reg_i2c1, this->reg->reg_i2c1.bits.pktlen_14_to_8, (uint8_t)((pktlen >> 8) & 0x07)); + + uint8_t value = (uint8_t)(pktlen & 0xFF); + + return write_register(I2C2_ADDR, (uint8_t *)&value, 1); +} + +template <class REG> +int MAX4146X<REG>::get_i2c_pktlen(uint16_t* pktlen) +{ + int ret; + + ret = read_register(I2C1_ADDR, (uint8_t *) & (this->reg->reg_i2c1), 1); + if (ret < 0) { + return ret; + } + + ret = read_register(I2C2_ADDR, (uint8_t *) & (this->reg->reg_i2c2), 1); + if (ret < 0) { + return ret; + } + + *pktlen = (uint16_t)(((this->reg->reg_i2c1.raw & 0x7F)<<8) + (this->reg->reg_i2c2.raw &0x7F)); + + return 0; +} + +template <class REG> +int MAX4146X<REG>::initial_programming(void) +{ + uint8_t value = 0x80; + write_register(ADDL2_ADDR, (uint8_t *)&value, 1); + + return write_register(CFG1_ADDR, default_register_value_1, 20); +} + +template <> +int MAX4146X<max41460_reg_map_t>::initial_programming(void) +{ + if (this->ssel != NULL){ + *this->ssel = 0; + wait_us(100); + } + + int rtn = write_register(CFG1_ADDR, default_register_value_0, 17); + + if (this->ssel != NULL){ + wait_us(90); + *this->ssel = 1; + } + + return rtn; +} + + +template class MAX4146X<max41460_reg_map_t>; +template class MAX4146X<max41461_2_reg_map_t>; +template class MAX4146X<max41463_4_reg_map_t>; + +