Ejemplo n.º 1
0
// Doc ID 13902 Rev 11 p 714/1072
// Transfer Sequence Diagram for Master Receiver for N=1
static inline enum STMI2CSubTransactionStatus stmi2c_read1(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // First Clear the ACK bit: after the next byte we do not want new bytes
    i2c_nack_current(i2c);
    i2c_disable_ack(i2c);

    // --- next to steps MUST be executed together to avoid missing the stop
    __I2C_REG_CRITICAL_ZONE_START;

    // Only after setting ACK, read SR2 to clear the ADDR (next byte will start arriving)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // Schedule a Stop
    PPRZ_I2C_SEND_STOP(i2c);

    __I2C_REG_CRITICAL_ZONE_STOP;
    // --- end of critical zone -----------

    // Enable the RXNE: it will trigger as soon as the 1 byte is received to get the result
    i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);

    // Document the current Status
    periph->status = I2CReadingLastByte;
  }
  // As soon as there is 1 byte ready to read, we have our byte
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    trans->buf[0] = I2C_DR(i2c);

    // We got all the results (stop condition might still be in progress but this is the last interrupt)
    trans->status = I2CTransSuccess;

    // Document the current Status:
    // -the stop was actually already requested in the previous step
    periph->status = I2CStopRequested;

    return STMI2C_SubTra_Ready_StopRequested;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
Ejemplo n.º 2
0
static inline void stmi2c_clear_pending_interrupts(uint32_t i2c)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Certainly do not wait for buffer interrupts:
  // -------------------------------------------
  i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);			// Disable TXE, RXNE

  // Error interrupts are handled separately:
  // ---------------------------------------

  // Clear Event interrupt conditions:
  // --------------------------------

  // Start Condition Was Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // SB: cleared by software when reading SR1 and writing to DR
    i2c_send_data(i2c, 0x00);
  }
  // Address Was Sent
  if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // ADDR: Cleared by software when reading SR1 and then SR2
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);
  }
  // Byte Transfer Finished
  if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // SB: cleared by software when reading SR1 and reading/writing to DR
    uint8_t dummy __attribute__ ((unused)) = i2c_get_data(i2c);
    i2c_send_data(i2c, 0x00);
  }

}
Ejemplo n.º 3
0
static inline void PPRZ_I2C_SEND_START(struct i2c_periph *periph)
{
  uint32_t i2c = (uint32_t) periph->reg_addr;

  // Reset the buffer pointer to the first byte
  periph->idx_buf = 0;

#ifdef I2C_DEBUG_LED
  LED_SHOW_ACTIVE_BITS(regs);

  LED2_ON();
  LED1_ON();
  LED1_OFF();
  LED1_ON();
  LED1_OFF();
  LED1_ON();
  LED1_OFF();
  LED2_OFF();
#endif

  // Enable Error IRQ, Event IRQ but disable Buffer IRQ
  i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
  i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
  i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);

  // Issue a new start
  i2c_nack_current(i2c);
  i2c_disable_ack(i2c);
  i2c_clear_stop(i2c);
  i2c_peripheral_enable(i2c);
  i2c_send_start(i2c);
  periph->status = I2CStartRequested;

}
Ejemplo n.º 4
0
void i2c3_ev_isr(void) {
  uint32_t i2c = (uint32_t) i2c3.reg_addr;
  i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
  i2c3.watchdog = 0; // restart watchdog
  i2c_irq(&i2c3);
  i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
}
Ejemplo n.º 5
0
void i2c2_er_isr(void) {
  uint32_t i2c = (uint32_t) i2c2.reg_addr;
  i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
  i2c2.watchdog = 0; // restart watchdog
  i2c_irq(&i2c2);
  i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
}
Ejemplo n.º 6
0
// Doc ID 13902 Rev 11 p 712/1072
// Transfer Sequence Diagram for Master Receiver for N>2
static inline enum STMI2CSubTransactionStatus stmi2c_readmany(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    // The first data byte will be acked in read many so the slave knows it should send more
    i2c_nack_current(i2c);
    i2c_enable_ack(i2c);
    // Clear the SB flag
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    periph->idx_buf = 0;

    // Enable RXNE: receive an interrupt any time a byte is available
    // only enable if MORE than 3 bytes need to be read
    if (periph->idx_buf < (trans->len_r - 3))
    {
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }

    // ACK is still on to get more DATA
    // Read SR2 to clear the ADDR (next byte will start arriving)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // Document the current Status
    periph->status = I2CReadingByte;
  }
  // one or more bytes are available AND we were interested in Buffer interrupts
  else if ( (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c)))  )
  {
    // read byte until 3 bytes remain to be read (e.g. len_r = 6, -> idx=3 means idx 3,4,5 = 3 remain to be read
    if (periph->idx_buf < (trans->len_r - 3))
    {
      trans->buf[periph->idx_buf] = I2C_DR(i2c);
      periph->idx_buf ++;
    }
    // from : 3bytes -> last byte: do nothing
    //
    // finally: this was the last byte
    else if (periph->idx_buf >= (trans->len_r - 1))
    {
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);

      // Last Value
      trans->buf[periph->idx_buf] = i2c_get_data(i2c);
      periph->idx_buf ++;

      // We got all the results
      trans->status = I2CTransSuccess;

      return STMI2C_SubTra_Ready_StopRequested;
    }

    // Check for end of transaction: start waiting for BTF instead of RXNE
    if (periph->idx_buf < (trans->len_r - 3))
    {
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }
    else // idx >= len-3: there are 3 bytes to be read
    {
      // We want to halt I2C to have sufficient time to clear ACK, so:
      // Stop listening to RXNE as it will be triggered infinitely since we did not empty the buffer
      // on the next (second in buffer) received byte BTF will be set (buffer full and I2C halted)
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }
  }
  // Buffer is full while this was not a RXNE interrupt
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // Now the shift register and data register contain data(n-2) and data(n-1)
    // And I2C is halted so we have time

    // --- Make absolutely sure the next 2 I2C actions are performed with no delay
    __I2C_REG_CRITICAL_ZONE_START;

    // First we clear the ACK while the SCL is held low by BTF
    i2c_disable_ack(i2c);

    // Now that ACK is cleared we read one byte: instantly the last byte is being clocked in...
    trans->buf[periph->idx_buf] = i2c_get_data(i2c);
    periph->idx_buf ++;

    // Now the last byte is being clocked. Stop in MUST be set BEFORE the transfer of the last byte is complete
    PPRZ_I2C_SEND_STOP(i2c);

    __I2C_REG_CRITICAL_ZONE_STOP;


    // --- end of critical zone -----------

    // Document the current Status
    periph->status = I2CStopRequested;

    // read the byte2 we had in the buffer (BTF means 2 bytes available)
    trans->buf[periph->idx_buf] = i2c_get_data(i2c);
    periph->idx_buf ++;

    // Ask for an interrupt to read the last byte (which is normally still busy now)
    // The last byte will be received with RXNE
    i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
Ejemplo n.º 7
0
// Doc ID 13902 Rev 11 p 713/1072
// Transfer Sequence Diagram for Master Receiver for N=2
static inline enum STMI2CSubTransactionStatus stmi2c_read2(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // according to the datasheet: instantly shedule a NAK on the second received byte:
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    i2c_enable_ack(i2c);
    i2c_nack_next(i2c);
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // --- make absolutely sure this command is not delayed too much after the previous:
    // --- the NAK bits must be set before the first byte arrived: allow other interrupts here
    __I2C_REG_CRITICAL_ZONE_START;

    //       if transfer of DR was finished already then we will get too many bytes
    // BEFORE clearing ACK, read SR2 to clear the ADDR (next byte will start arriving)
    // clearing ACK after the byte transfer has already started will NACK the next (2nd)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // NOT First Clear the ACK bit but only AFTER clearing ADDR
    i2c_disable_ack(i2c);

    // Disable the RXNE and wait for BTF
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);

    __I2C_REG_CRITICAL_ZONE_STOP;
    // --- end of critical zone -----------

    // We do not set the RxE but wait for both bytes to arrive using BTF

    // Document the current Status
    periph->status = I2CReadingByte;
  }
  // Receive buffer if full, master is halted: BTF
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // Stop condition MUST be set BEFORE reading the DR
    // otherwise since there is new buffer space a new byte will be read
    PPRZ_I2C_SEND_STOP(i2c);

    // Document the current Status
    periph->status = I2CStopRequested;

    trans->buf[0] = I2C_DR(i2c);
    trans->buf[1] = I2C_DR(i2c);

    // We got all the results
    trans->status = I2CTransSuccess;

    return STMI2C_SubTra_Ready_StopRequested;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
Ejemplo n.º 8
0
// Doc ID 13902 Rev 11 p 710/1072
// Transfer Sequence Diagram for Master Transmitter
static inline enum STMI2CSubTransactionStatus stmi2c_send(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // Disable buffer interrupt
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    // Send Slave address and wait for ADDR interrupt
    i2c_send_data(i2c, trans->slave_addr);
    // Document the current Status
    periph->status = I2CAddrWrSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // Now read SR2 to clear the ADDR status Bit
    uint16_t SR2  __attribute__ ((unused)) = I2C_SR2(i2c);

    // Maybe check we are transmitting (did not loose arbitration for instance)
    // if (! BIT_X_IS_SET_IN_REG(I2C_SR2_TRA, SR2)) { }
    // update: this should be caught by the ARLO error: so we will not arrive here

    // Send First max 2 bytes
    i2c_send_data(i2c, trans->buf[0]);
    if (trans->len_w > 1)
    {
      i2c_send_data(i2c, trans->buf[1]);
      periph->idx_buf = 2;
    }
    else
    {
      periph->idx_buf = 1;
    }

    // Enable buffer-space available interrupt
    // only if there is more to send: wait for TXE, no more to send: wait for BTF
    if ( periph->idx_buf < trans->len_w)
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);

    // Document the current Status
    periph->status = I2CSendingByte;
  }
  // The buffer is not full anymore AND we were not waiting for BTF
  else if ((BIT_X_IS_SET_IN_REG(I2C_SR1_TxE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c)))  )
  {
    // Send the next byte
    i2c_send_data(i2c, trans->buf[periph->idx_buf]);
    periph->idx_buf++;

    // All bytes Sent? Then wait for BTF instead
    if ( periph->idx_buf >= trans->len_w)
    {
      // Not interested anymore to know the buffer has space left
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
      // Next interrupt will be BTF (or error)
    }
  }
  // BTF: means last byte was sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    if (trans->type == I2CTransTx)
    {
      // Tell the driver we are ready
      trans->status = I2CTransSuccess;
    }
    // Otherwise we still need to do the receiving part

    return STMI2C_SubTra_Ready;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
Ejemplo n.º 9
0
static void i2c_wd_check(struct i2c_periph *periph) {
  uint32_t i2c = (uint32_t) periph->reg_addr;

  if (periph->watchdog > WD_DELAY) {
    if (periph->watchdog == WD_DELAY + 1) {

      i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
      i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);

      i2c_peripheral_disable(i2c);

#if USE_I2C1
      if (i2c == I2C1) {
        gpio_setup_output(I2C1_GPIO_PORT, I2C1_GPIO_SCL);
        gpio_setup_input(I2C1_GPIO_PORT, I2C1_GPIO_SDA);
      }
#endif
#if USE_I2C2
      if (i2c == I2C2) {
        gpio_setup_output(I2C2_GPIO_PORT, I2C2_GPIO_SCL);
        gpio_setup_input(I2C2_GPIO_PORT, I2C2_GPIO_SDA);
      }
#endif
#if USE_I2C3
      if (i2c == I2C3) {
        gpio_setup_output(I2C3_GPIO_PORT_SCL, I2C3_GPIO_SCL);
        gpio_setup_input(I2C3_GPIO_PORT_SDA,I2C3_GPIO_SDA);
      }
#endif

      i2c_scl_clear(i2c);
    }
    else if (periph->watchdog < WD_DELAY + WD_RECOVERY_TICKS) {
      if ((periph->watchdog - WD_DELAY) % 2)
        i2c_scl_clear(i2c);
      else
        i2c_scl_set(i2c);
    }
    else {
      i2c_scl_set(i2c);

      /* setup gpios for normal i2c operation again */
      i2c_setup_gpio(i2c);

      periph->trans_insert_idx = 0;
      periph->trans_extract_idx = 0;
      periph->status = I2CIdle;

      i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
      i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);

      i2c_peripheral_enable(i2c);
      periph->watchdog = 0; // restart watchdog

      periph->errors->timeout_tlow_cnt++;

      return;
    }
  }
  if (periph->watchdog >= 0)
    periph->watchdog++;
}
Ejemplo n.º 10
0
static void setup_i2c_port(enum I2C_FREQ I2C_speed)
{
	// Disable I2C if it happens to be enabled
	i2c_peripheral_disable(I2C_PORT);
	dma_channel_reset(I2C_TX_DMA, I2C_TX_DMA_CHANNEL);
	i2c_disable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN));
	DISABLE_I2C_INTERRUPT();
	reset_i2c_pins();

	// set: Source, Destination, and Amount (DMA channel must be disabled)
	dma_set_peripheral_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, (uint32_t)&I2C_DR(I2C_PORT));
	dma_set_memory_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0);
	dma_set_number_of_data(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0);
	// set the DMA Configuration (DMA_CCRx)
	//			 (BIT 14) mem2mem_mode disabled
	dma_set_priority(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PL_HIGH); // (BIT 12:13)
	dma_set_memory_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_MSIZE_8BIT); // (BIT 10:11)
	dma_set_peripheral_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PSIZE_8BIT); // (BIT 8:9)
	dma_enable_memory_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 7)
	dma_disable_peripheral_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 6)
	//			 (BIT 5) Circular mode is disabled
	dma_set_read_from_memory(I2C_TX_DMA, I2C_TX_DMA_CHANNEL);	// (BIT 4)
	dma_enable_transfer_error_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 3)
	dma_disable_half_transfer_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 2)
	dma_enable_transfer_complete_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 1)

	// This is the slave address when not transmitting data
	i2c_set_own_7bit_slave_address(I2C_PORT, 0x32);
	// do not respond to the specified slave address
	i2c_disable_ack(I2C_PORT);
	// Use DMA to send I2C data
	i2c_enable_dma(I2C_PORT);
	// set which interrupts I2C uses
	i2c_enable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN));
	// APB1 is running at 36MHz = T(PCLK1) = 1/36000000 sec.
	i2c_set_clock_frequency(I2C_PORT, I2C_CR2_FREQ_36MHZ);
	// Set up the hardware for the particular speed
	switch (I2C_speed) {
		// Values found on Internet for the I2C standard
		//   STANDARD : SCL max rise time = 1000ns = 1000/1000000000 sec
		//       FAST : SCL max rise time =  300ns =  300/1000000000 sec
		// 
		// DATASHEET Function:
		//   TRISE = (T(MAX_SCL_RISE) / T(PCLK1)) + 1
		// 
		// DATASHEET Functions:
		//   STANDARD :      
		//     T(high) =      CCR * T(PCLK1)
		//     T(low)  =      CCR * T(PCLK1)
		//   FAST (DUTY=I2C_CCR_DUTY_DIV2)
		//     T(high) =      CCR * T(PCLK1)
		//     T(low)  =  2 * CCR * T(PCLK1)
		//   FAST (DUTY=I2C_CCR_DUTY_16_DIV_9)   [To reach 400KHz]
		//     T(high) =  9 * CCR * T(PCLK1)
		//     T(low)  = 16 * CCR * T(PCLK1)
		// 
		// I2C PERIOD:
		//   STANDARD
		//     PERIOD = T(high) + T(low) = (2 * CCR * T(PCLK1))
		//   FAST (DUTY=I2C_CCR_DUTY_DIV2)
		//     PERIOD = T(high) + T(low) = (3 * CCR * T(PCLK1))
		//   FAST (DUTY=I2C_CCR_DUTY_16_DIV_9)
		//     PERIOD = T(high) + T(low) = (25 * CCR * T(PCLK1))
		case I2C_400KHz:
			// I2C PERIOD: 400KHz = 400000Hz = 1/400000 sec.
			i2c_set_fast_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_16_DIV_9);
			// CCR = PERIOD / (25 * T(PCLK1))
			// CCR = (1/400000) / (25/36000000) = 18/5 = 3.6
			// CCR = 4 => I2C PERIOD = 360kHz
			// CCR = 3 => I2C PERIOD = 480kHz
			i2c_set_ccr(I2C_PORT, 4);	// Only fast mode can have a value less than 0x04
			// TRISE = ( (300/1000000000) / (1/36000000) ) + 1 = 59/5 = 11.8
			// TRISE = 12 => SCL max rise time ~= 305.555ns
			// TRISE = 11 => SCL max rise time ~= 277.777ns
			i2c_set_trise(I2C_PORT, 11);
			break;
		case I2C_100KHz:
			// I2C PERIOD: 100KHz = 100000Hz = 1/100000 sec.
			i2c_set_standard_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2);
			// CCR = PERIOD / (2 * T(PCLK1))
			// CCR = (1/100000) / (2/36000000) = 180
			i2c_set_ccr(I2C_PORT, 180);
			// TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37
			i2c_set_trise(I2C_PORT, 37);
			break;
		case I2C_53KHz:
			// ~= 52.91kHz is the slowest I could get to work
			// CCR value of 341 works but not 342 or higher
		case I2C_50KHz:
		default:
			// I2C PERIOD: 50KHz = 50000Hz = 1/50000 sec.
			i2c_set_standard_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2);
			// CCR = PERIOD / (2 * T(PCLK1))
			// CCR = (1/50000) / (2/36000000) = 360
			//   (341 works but not 342 or higher)
			i2c_set_ccr(I2C_PORT, 341);
			// TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37
			i2c_set_trise(I2C_PORT, 37);
			break;
	}
	i2c_peripheral_enable(I2C_PORT);

	// set the priorities for the interrupts
	nvic_set_priority(I2C_EV_IRQ, IRQ_PRI_I2C);
	nvic_set_priority(I2C_ER_IRQ, IRQ_PRI_ER_I2C);
	nvic_set_priority(I2C_DMA_IRQ, IRQ_PRI_DMA_I2C);
}