Example #1
0
/**
 * \brief Set the I2C bus speed in conjunction with the clock frequency.
 *
 * \param p_twihs Pointer to a TWIHS instance.
 * \param ul_speed The desired I2C bus speed (in Hz).
 * \param ul_mck Main clock of the device (in Hz).
 *
 * \retval PASS New speed setting is accepted.
 * \retval FAIL New speed setting is rejected.
 */
uint32_t twihs_set_speed(Twihs *p_twihs, uint32_t ul_speed, uint32_t ul_mck)
{
	uint32_t ckdiv = 0;
	uint32_t c_lh_div;
	uint32_t cldiv, chdiv;

	/* High-Speed can be only used in slave mode, 400k is the max speed allowed for master */
	if (ul_speed > I2C_FAST_MODE_SPEED) {
		return FAIL;
	}

	/* Low level time not less than 1.3us of I2C Fast Mode. */
	if (ul_speed > LOW_LEVEL_TIME_LIMIT) {
		/* Low level of time fixed for 1.3us. */
		cldiv = ul_mck / (LOW_LEVEL_TIME_LIMIT * TWIHS_CLK_DIVIDER) - TWIHS_CLK_CALC_ARGU;
		chdiv = ul_mck / ((ul_speed + (ul_speed - LOW_LEVEL_TIME_LIMIT)) * TWIHS_CLK_DIVIDER) - TWIHS_CLK_CALC_ARGU;
		
		/* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */
		while ((cldiv > TWIHS_CLK_DIV_MAX) && (ckdiv < TWIHS_CLK_DIV_MIN)) {
			/* Increase clock divider */
			ckdiv++;
			/* Divide cldiv value */
			cldiv /= TWIHS_CLK_DIVIDER;
		}
		/* chdiv must fit in 8 bits, ckdiv must fit in 3 bits */
		while ((chdiv > TWIHS_CLK_DIV_MAX) && (ckdiv < TWIHS_CLK_DIV_MIN)) {
			/* Increase clock divider */
			ckdiv++;
			/* Divide cldiv value */
			chdiv /= TWIHS_CLK_DIVIDER;
		}

		/* set clock waveform generator register */
		p_twihs->TWIHS_CWGR =
				TWIHS_CWGR_CLDIV(cldiv) | TWIHS_CWGR_CHDIV(chdiv) |
				TWIHS_CWGR_CKDIV(ckdiv);
	} else {
		c_lh_div = ul_mck / (ul_speed * TWIHS_CLK_DIVIDER) - TWIHS_CLK_CALC_ARGU;

		/* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */
		while ((c_lh_div > TWIHS_CLK_DIV_MAX) && (ckdiv < TWIHS_CLK_DIV_MIN)) {
			/* Increase clock divider */
			ckdiv++;
			/* Divide cldiv value */
			c_lh_div /= TWIHS_CLK_DIVIDER;
		}

		/* set clock waveform generator register */
		p_twihs->TWIHS_CWGR =
				TWIHS_CWGR_CLDIV(c_lh_div) | TWIHS_CWGR_CHDIV(c_lh_div) |
				TWIHS_CWGR_CKDIV(ckdiv);
	}

	return PASS;
}
Example #2
0
/**
 * \brief Set the I2C bus speed in conjunction with the clock frequency.
 *
 * \param p_twihs Pointer to a TWIHS instance.
 * \param ul_speed The desired I2C bus speed (in Hz).
 * \param ul_mck Main clock of the device (in Hz).
 *
 * \retval PASS New speed setting is accepted.
 * \retval FAIL New speed setting is rejected.
 */
uint32_t twihs_set_speed(Twihs *p_twihs, uint32_t ul_speed, uint32_t ul_mck)
{
	uint32_t ckdiv = 0;
	uint32_t c_lh_div;

	/* High-Speed can be only used in slave mode, 400k is the max speed allowed for master */
	if (ul_speed > I2C_FAST_MODE_SPEED) {
		return FAIL;
	}

	c_lh_div = ul_mck / (ul_speed * TWIHS_CLK_DIVIDER) - TWIHS_CLK_CALC_ARGU;

	/* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */
	while ((c_lh_div > TWIHS_CLK_DIV_MAX) && (ckdiv < TWIHS_CLK_DIV_MIN)) {
		/* Increase clock divider */
		ckdiv++;
		/* Divide cldiv value */
		c_lh_div /= TWIHS_CLK_DIVIDER;
	}

	/* set clock waveform generator register */
	p_twihs->TWIHS_CWGR =
			TWIHS_CWGR_CLDIV(c_lh_div) | TWIHS_CWGR_CHDIV(c_lh_div) |
			TWIHS_CWGR_CKDIV(ckdiv);

	return PASS;
}
Example #3
0
bool i2c_init(void *i2c)
{
    Twihs *twi = (Twihs *)i2c;
    if (twi != TWIHS0)
    {
        printf("ahh unknown TWI peripheral\r\n");
        return false;
    }
    PMC->PMC_PCER0 |= (1 << ID_TWIHS0);
    pin_set_mux(PIOA, 3, PERIPH_A); // sdc0
    pin_set_mux(PIOA, 4, PERIPH_A); // sda0
    // set up 400 kHz i2c timing on our 144 MHz system clock
    //twi->TWIHS_CWGR = TWIHS_CWGR_CHDIV(86) | TWIHS_CWGR_CLDIV(187) | TWIHS_CWGR_CKDIV(2);
    // hmm...this board doesn't have any i2c pullups, so let's do 100 kHz i2c
    twi->TWIHS_CWGR =
        TWIHS_CWGR_CHDIV(170) |
        TWIHS_CWGR_CLDIV(170) |
        TWIHS_CWGR_HOLD(0x1f) | // todo: need to solder on physical pullups
        TWIHS_CWGR_CKDIV(2);
    twi->TWIHS_CR = TWIHS_CR_SVDIS; // disable slave mode. ONCE I WAS THE LEARNER
    twi->TWIHS_CR = TWIHS_CR_MSEN;  // enable master mode. NOW I AM THE MASTER
    printf("twi init complete\r\n");

    return true;
}