software/src/ASF/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master.c
/**
 * \internal Sets configurations to module
 *
 * \param[out] module  Pointer to software module structure
 * \param[in]  config  Configuration structure with configurations to set
 *
 * \return Status of setting configuration.
 * \retval STATUS_OK                        If module was configured correctly
 * \retval STATUS_ERR_ALREADY_INITIALIZED   If setting other GCLK generator than
 *                                          previously set
 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE  If given baudrate is not compatible
 *                                          with set GCLK frequency
 */
\internal Sets configurations to module
\param[out] module  Pointer to software module structure
\param[in]  config  Configuration structure with configurations to set

\return Status of setting configuration.
\retval STATUS_OK                        If module was configured correctly
\retval STATUS_ERR_ALREADY_INITIALIZED   If setting other GCLK generator than
previously set
\retval STATUS_ERR_BAUDRATE_UNAVAILABLE  If given baudrate is not compatible
with set GCLK frequency
\ internal Sets configurations to module \ param [ out ] module Pointer to software module structure \ param [ in ] config Configuration structure with configurations to set \ return Status of setting configuration . \ retval STATUS_OK If module was configured correctly \ retval STATUS_ERR_ALREADY_INITIALIZED If setting other GCLK generator than previously set \ retval STATUS_ERR_BAUDRATE_UNAVAILABLE If given baudrate is not compatible with set GCLK frequency
static enum status_code _i2c_master_set_config(
		struct i2c_master_module *const module,
		const struct i2c_master_config *const config)
{
	Assert(module);
	Assert(module->hw);
	Assert(config);
	uint32_t tmp_ctrla;
	int32_t tmp_baud = 0;
	int32_t tmp_baud_hs = 0;
	int32_t tmp_baudlow_hs = 0;
	enum status_code tmp_status_code = STATUS_OK;
	SercomI2cm *const i2c_module = &(module->hw->I2CM);
	Sercom *const sercom_hw = module->hw;
	uint8_t sercom_index = _sercom_get_sercom_inst_index(sercom_hw);
	struct system_pinmux_config pin_conf;
	system_pinmux_get_config_defaults(&pin_conf);
	uint32_t pad0 = config->pinmux_pad0;
	uint32_t pad1 = config->pinmux_pad1;
	if (pad0 == PINMUX_DEFAULT) {
		pad0 = _sercom_get_default_pad(sercom_hw, 0);
	}
	pin_conf.mux_position = pad0 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);
	if (pad1 == PINMUX_DEFAULT) {
		pad1 = _sercom_get_default_pad(sercom_hw, 1);
	}
	pin_conf.mux_position = pad1 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);
	module->unknown_bus_state_timeout = config->unknown_bus_state_timeout;
	module->buffer_timeout = config->buffer_timeout;
	if (config->run_in_standby || system_is_debugger_present()) {
		tmp_ctrla = SERCOM_I2CM_CTRLA_RUNSTDBY;
	} else {
		tmp_ctrla = 0;
	}
	if (config->start_hold_time != I2C_MASTER_START_HOLD_TIME_DISABLED) {
		tmp_ctrla |= config->start_hold_time;
	}
	tmp_ctrla |= config->transfer_speed;
	if (config->scl_low_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_LOWTOUTEN;
	}
	if (config->inactive_timeout != I2C_MASTER_INACTIVE_TIMEOUT_DISABLED) {
		tmp_ctrla |= config->inactive_timeout;
	}
	if (config->scl_stretch_only_after_ack_bit || (config->transfer_speed == I2C_MASTER_SPEED_HIGH_SPEED)) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_SCLSM;
	}
	if (config->slave_scl_low_extend_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_SEXTTOEN;
	}
	if (config->master_scl_low_extend_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_MEXTTOEN;
	}
	i2c_module->CTRLA.reg |= tmp_ctrla;
	i2c_module->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
	uint32_t fgclk       = system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index);
	uint32_t fscl        = 1000 * config->baud_rate;
	uint32_t fscl_hs     = 1000 * config->baud_rate_high_speed;
	uint32_t trise       = config->sda_scl_rise_time_ns;
	tmp_baud = (int32_t)(div_ceil(
			fgclk - fscl * (10 + (fgclk * 0.000000001)* trise), 2 * fscl));
	if (config->transfer_speed == I2C_MASTER_SPEED_HIGH_SPEED) {
		tmp_baudlow_hs = (int32_t)((fgclk * 2.0) / (3.0 * fscl_hs) - 1);
		if (tmp_baudlow_hs) {
			tmp_baud_hs = (int32_t)(fgclk / fscl_hs) - 2 - tmp_baudlow_hs;
		} else {
			tmp_baud_hs = (int32_t)(div_ceil(fgclk, 2 * fscl_hs)) - 1;
		}
	}
	if (tmp_baud > 255 || tmp_baud < 0 || tmp_baud_hs > 255 || tmp_baud_hs < 0) {
		tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
	}
	if (tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE) {
		i2c_module->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud) |
			SERCOM_I2CM_BAUD_HSBAUD(tmp_baud_hs) | SERCOM_I2CM_BAUD_HSBAUDLOW(tmp_baudlow_hs);
	}
	return tmp_status_code;
}
static enum status_code _i2c_master_set_config ( struct i2c_master_module * const module , const struct i2c_master_config * const config ) { Assert ( module ) ; Assert ( module -> hw ) ; Assert ( config ) ; uint32_t tmp_ctrla ; int32_t tmp_baud = 0 ; int32_t tmp_baud_hs = 0 ; int32_t tmp_baudlow_hs = 0 ; enum status_code tmp_status_code = STATUS_OK ; SercomI2cm * const i2c_module = & ( module -> hw -> I2CM ) ; Sercom * const sercom_hw = module -> hw ; uint8_t sercom_index = _sercom_get_sercom_inst_index ( sercom_hw ) ; struct system_pinmux_config pin_conf ; system_pinmux_get_config_defaults ( & pin_conf ) ; uint32_t pad0 = config -> pinmux_pad0 ; uint32_t pad1 = config -> pinmux_pad1 ; if ( pad0 == PINMUX_DEFAULT ) { pad0 = _sercom_get_default_pad ( sercom_hw , 0 ) ; } pin_conf . mux_position = pad0 & 0xFFFF ; pin_conf . direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK ; system_pinmux_pin_set_config ( pad0 >> 16 , & pin_conf ) ; if ( pad1 == PINMUX_DEFAULT ) { pad1 = _sercom_get_default_pad ( sercom_hw , 1 ) ; } pin_conf . mux_position = pad1 & 0xFFFF ; pin_conf . direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK ; system_pinmux_pin_set_config ( pad1 >> 16 , & pin_conf ) ; module -> unknown_bus_state_timeout = config -> unknown_bus_state_timeout ; module -> buffer_timeout = config -> buffer_timeout ; if ( config -> run_in_standby || system_is_debugger_present ( ) ) { tmp_ctrla = SERCOM_I2CM_CTRLA_RUNSTDBY ; } else { tmp_ctrla = 0 ; } if ( config -> start_hold_time != I2C_MASTER_START_HOLD_TIME_DISABLED ) { tmp_ctrla |= config -> start_hold_time ; } tmp_ctrla |= config -> transfer_speed ; if ( config -> scl_low_timeout ) { tmp_ctrla |= SERCOM_I2CM_CTRLA_LOWTOUTEN ; } if ( config -> inactive_timeout != I2C_MASTER_INACTIVE_TIMEOUT_DISABLED ) { tmp_ctrla |= config -> inactive_timeout ; } if ( config -> scl_stretch_only_after_ack_bit || ( config -> transfer_speed == I2C_MASTER_SPEED_HIGH_SPEED ) ) { tmp_ctrla |= SERCOM_I2CM_CTRLA_SCLSM ; } if ( config -> slave_scl_low_extend_timeout ) { tmp_ctrla |= SERCOM_I2CM_CTRLA_SEXTTOEN ; } if ( config -> master_scl_low_extend_timeout ) { tmp_ctrla |= SERCOM_I2CM_CTRLA_MEXTTOEN ; } i2c_module -> CTRLA . reg |= tmp_ctrla ; i2c_module -> CTRLB . reg = SERCOM_I2CM_CTRLB_SMEN ; uint32_t fgclk = system_gclk_chan_get_hz ( SERCOM0_GCLK_ID_CORE + sercom_index ) ; uint32_t fscl = 1000 * config -> baud_rate ; uint32_t fscl_hs = 1000 * config -> baud_rate_high_speed ; uint32_t trise = config -> sda_scl_rise_time_ns ; tmp_baud = ( int32_t ) ( div_ceil ( fgclk - fscl * ( 10 + ( fgclk * 0.000000001 ) * trise ) , 2 * fscl ) ) ; if ( config -> transfer_speed == I2C_MASTER_SPEED_HIGH_SPEED ) { tmp_baudlow_hs = ( int32_t ) ( ( fgclk * 2.0 ) / ( 3.0 * fscl_hs ) - 1 ) ; if ( tmp_baudlow_hs ) { tmp_baud_hs = ( int32_t ) ( fgclk / fscl_hs ) - 2 - tmp_baudlow_hs ; } else { tmp_baud_hs = ( int32_t ) ( div_ceil ( fgclk , 2 * fscl_hs ) ) - 1 ; } } if ( tmp_baud > 255 || tmp_baud < 0 || tmp_baud_hs > 255 || tmp_baud_hs < 0 ) { tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE ; } if ( tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE ) { i2c_module -> BAUD . reg = SERCOM_I2CM_BAUD_BAUD ( tmp_baud ) | SERCOM_I2CM_BAUD_HSBAUD ( tmp_baud_hs ) | SERCOM_I2CM_BAUD_HSBAUDLOW ( tmp_baudlow_hs ) ; } return tmp_status_code ; }
\internal Sets configurations to module
 \param[out] module  Pointer to software module structure
 \param[in]  config  Configuration structure with configurations to set
\ internal Sets configurations to module \ param [ out ] module Pointer to software module structure \ param [ in ] config Configuration structure with configurations to set
/* Sanity check arguments. */ /* Temporary variables. */ /* Pin configuration */ /* SERCOM PAD0 - SDA */ /* SERCOM PAD1 - SCL */ /* Save timeout on unknown bus state in software module. */ /* Save timeout on buffer write. */ /* Set whether module should run in standby. */ /* Check and set start data hold timeout. */ /* Check and set transfer speed */ /* Check and set SCL low timeout. */ /* Check and set inactive bus timeout. */ /* Check and set SCL clock stretch mode. */ /* Check and set slave SCL low extend timeout. */ /* Check and set master SCL low extend timeout. */ /* Write config to register CTRLA. */ /* Set configurations in CTRLB. */ /* Find and set baudrate, considering sda/scl rise time */ /* For High speed mode, set the SCL ratio of high:low to 1:2. */ /* Check that baudrate is supported at current speed. */ /* Baud rate not supported. */ /* Baud rate acceptable. */