Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Library for MAX41460, MAX41461, MAX41462, MAX41463, MAX41464 RF Transmitter ICs.
Diff: Max4146x.cpp
- Revision:
- 0:4040347d719c
- Child:
- 1:ccf0e1d28860
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max4146x.cpp Thu May 02 12:51:33 2019 +0300 @@ -0,0 +1,1185 @@ +/******************************************************************************* + * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * 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; +} + +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>; + +