Ejemplo n.º 1
0
/* i2c_read_byte
   Read a byte from I2C bus
   => ack = acknowlege bit to send after read
   <= returns data read from the bus
*/
unsigned char i2c_read_byte(unsigned char ack)
{
   unsigned char loop, byte;
   
   i2c_set_sda();
   
   /* read data msb first */
   for(loop = 0; loop < 8; loop++)
   {
      byte = byte << 1;
      i2c_set_scl();
      i2c_delay();
      if(i2c_read_sda()) byte = byte | 1;
      i2c_clear_scl();
   }
   
   /* send ack bit */
   if(ack)
      i2c_set_sda();
   else
      i2c_clear_sda();
   i2c_set_scl();
   i2c_delay();
   i2c_clear_scl();
   i2c_set_sda();
   
   return byte;
}
Ejemplo n.º 2
0
/* i2c_write_byte
   Write a byte to I2C bus
   => byte = data to write out
   <= return 0 if acknowleged by the slave
*/
unsigned char i2c_write_byte(unsigned char byte)
{
   unsigned char loop, ack, original_byte = byte;
   
   /* send data, msb first */
   for(loop = 0; loop < 8; loop++)
   {
      if(byte & 0x80)
         i2c_set_sda();
      else
         i2c_clear_sda();
      i2c_set_scl();
      i2c_delay();
      i2c_clear_scl();
      byte = byte << 1;
   }
   
   /* read ack bit from slave */
   i2c_set_sda();
   i2c_set_scl();
   i2c_delay();
   ack = i2c_read_sda();
   i2c_clear_scl();
   
   return ack;
}
Ejemplo n.º 3
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_start
 *#
 *# DESCRIPTION  : generate i2c start condition
 *#
 *# PARAMETERS   : none
 *#
 *# RETURN       : EI2CNOERRORS if OK, EI2CSTRTCOND otherwise
 *#
 *#---------------------------------------------------------------------------
 */
int i2c_start( void )
{
  /* Set SCL=1, SDA=1 */
  i2c_sda_dir_out();
  i2c_set_sda( SDA_HIGH );
  i2c_delay( WAITONEUS );
  i2c_set_scl( SCL_HIGH );
  i2c_delay( WAITONEUS );
  
  /* Set SCL=1, SDA=0 */
  i2c_set_sda( SDA_LOW );
  i2c_delay( THDSTA );
  
  /* Set SCL=0, SDA=0 */
  i2c_set_scl( SCL_LOW );
  /* We can take 1 us less than defined in spec (5 us), since the next action
   * will be to set the dataline high or low and this action is 1 us
   * before the clock is put high, so that makes our 5 us.
   */
  i2c_delay( TLOW - WAITONEUS );
  
  if ( i2c_sda_is_high() || i2c_scl_is_high() )
    {
      printk( KERN_DEBUG "I2C: EI2CSTRTCOND\n" );
      return ( EI2CSTRTCOND );
    }
  
  return ( EI2CNOERRORS );
}   /* i2c_start */
Ejemplo n.º 4
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_sendnack
 *#
 *# DESCRIPTION  : sends NACK on received data
 *#
 *# PARAMETERS   : none
 *#
 *# RETURN       : none
 *#
 *#---------------------------------------------------------------------------
 */
void i2c_sendnack( void )
{
#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    int n=MAXSCLRETRIES;
#endif

    /* make sure the SDA line is set high prior to activation of the output.
     * this way, you avoid an unnecessary peak to ground when a NACK has to
     * be created.
     */
    /* set data high */
    i2c_set_sda( SDA_HIGH );
    /* enable output */
    i2c_sda_dir_out();

    /* generate clock pulse */
    i2c_delay( TSUDAT );

#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    i2c_scl_dir_in();
    /* wait for clock to rise (n=MAXSCLRETRIES) */
    for( ; n>0; n-- )
    {
	if( i2c_scl_is_high() )
            break;
	i2c_delay( THIGH );
    }

    i2c_set_scl( SCL_HIGH );
    i2c_scl_dir_out();
    i2c_delay( THIGH );
#else
    i2c_set_scl( SCL_HIGH );

    i2c_delay( THIGH );
#endif
    i2c_set_scl( SCL_LOW );
    i2c_delay( TSUDAT );
    i2c_set_sda( SDA_LOW );
    i2c_delay( TLOW - TSUDAT );

    /* There's no need to change the direction of SDA to "in" again,
     * since a NACK is always followed by a stop condition.
     * A STOP condition will put the direction of SDA back to "out"
     * resulting in a useless SDA "dip" on the line...
     */
    /* i2c_sda_dir_in(); */
}   /* i2c_sendnack */
Ejemplo n.º 5
0
int i2c_wait_nack() {
	i2c_clr_scl();
	i2c_set_sda();
	i2c_set_scl();
	while(i2c_get_scl() == 0); /* wait for scl = 1 (clock stretching) */
	return (i2c_get_sda() == 1);
}
Ejemplo n.º 6
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_stop
 *#
 *# DESCRIPTION  : generate i2c stop condition
 *#
 *# PARAMETERS   : none
 *#
 *# RETURN       : none
 *#
 *#---------------------------------------------------------------------------
 */
int i2c_stop( void )
{
#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    int n=MAXSCLRETRIES;
#endif
    i2c_sda_dir_out();
    
    /* Set SCL=0, SDA=0 */
    /* Don't change order, otherwise you might generate a start condition! */
    i2c_set_scl( SCL_LOW );
    i2c_delay( WAITONEUS );
    i2c_set_sda( SDA_LOW );
    i2c_delay( WAITONEUS );
    
    /* Set SCL=1, SDA=0 */
    
#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    i2c_set_scl( SCL_HIGH );
    i2c_scl_dir_in();
    for( ; n>0; n-- )
      {
	if( i2c_scl_is_high() )
	  break;
	i2c_delay( TSUSTO );
      }
    
    i2c_scl_dir_out();
#else
    i2c_set_scl( SCL_HIGH );
#endif
    i2c_delay( TSUSTO );
    
    /* Set SCL=1, SDA=1 */
    i2c_set_sda( SDA_HIGH );
    i2c_delay( TBUF );
    
    i2c_sda_dir_in();
    
    if ( !i2c_sda_is_high() || !i2c_scl_is_high() )
      {
	return ( EI2CSTOPCOND );
      }
    
    return ( EI2CNOERRORS );
}   /* i2c_stop */
Ejemplo n.º 7
0
void i2c_stop_condition() {
	i2c_clr_scl();
	i2c_clr_sda();
	while(i2c_get_sda() == 1); /* wait for SDA = 0 */
	i2c_set_scl();
	while(i2c_get_scl() == 0); /* wait for SCL = 1 */
	i2c_set_sda();
	while(i2c_get_sda() == 0); /* wait for SDA = 1 */
}
Ejemplo n.º 8
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_sendack
 *#
 *# DESCRIPTION  : sends ACK on received data
 *#
 *# PARAMETERS   : none
 *#
 *# RETURN       : none
 *#
 *#---------------------------------------------------------------------------
 */
void i2c_sendack( void )
{
#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    int n=MAXSCLRETRIES;
#endif

    /* enable output */
    /* Clock has been set to TLOW already at end of i2c_inbyte()
     * and i2c_outbyte(), so no need to do it again.
     */
    i2c_sda_dir_out();
    /* set ack pulse low */
    i2c_set_sda( SDA_LOW );
    /* generate clock pulse */
    i2c_delay( TSUDAT );

#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    i2c_scl_dir_in();
    /* wait for clock to rise (n=MAXSCLRETRIES) */
    for( ; n>0; n-- )
    {
	if( i2c_scl_is_high() )
            break;
	i2c_delay( THIGH );
    }

    i2c_set_scl( SCL_HIGH );
    i2c_scl_dir_out();
    i2c_delay( THIGH );
#else
    i2c_set_scl( SCL_HIGH );

    i2c_delay( THIGH );
#endif
    i2c_set_scl( SCL_LOW );
    i2c_delay( THDDAT );
    /* reset data out */
    i2c_set_sda( SDA_HIGH );
    /* Subtract time spend already when waited to put SDA high */
    i2c_delay( TLOW - THDDAT );

    /* release the SDA line */
    i2c_sda_dir_in();
}   /* i2c_sendack */
Ejemplo n.º 9
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_outbyte
 *#
 *# DESCRIPTION  : write a byte to the i2c interface
 *#
 *# PARAMETERS   : x: byte to be sent on the I2C bus
 *#
 *# RETURN       : none
 *#
 *#---------------------------------------------------------------------------
 */
int i2c_outbyte( unsigned char x )
{
    int i;

    i2c_sda_dir_out();

    for ( i = 0; i < 8; i++ )
    {
        if ( x & 0x80 )
        {
            i2c_set_sda( SDA_HIGH );
        }
        else
        {
            i2c_set_sda( SDA_LOW );
        }

        i2c_delay( TSUDAT );
        i2c_set_scl( SCL_HIGH );
        i2c_delay( THIGH );
        i2c_set_scl( SCL_LOW );
        i2c_delay( TSUDAT );
        i2c_set_sda( SDA_LOW );
        /* There should be only 5 us between falling edge and new rising
         * edge of clock pulse.
         * Since we spend already 1 us since clock edge was low, there are
         * only ( TLOW - TSUDAT ) us left.
         * Next to this, since the data line will be set up 1 us before the
         * clock line is set up, we can reduce the delay with another us.
         */
        i2c_delay( TLOW - TSUDAT - WAITONEUS );
        x <<= 1;
    }

    /* enable input */
    i2c_sda_dir_in();

    if ( !i2c_getack() )
      {
        return( EI2CNOACKNLD );
      }

    return ( EI2CNOERRORS );
}   /* i2c_outbyte */
Ejemplo n.º 10
0
void s_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start
//           _____         ________
// I2CDAT:        |_______|
//               ___     ___
// I2C_SCL : ___|   |___|   |______
{
	i2c_set_sda(1);
	i2c_set_scl(1);
	i2c_set_sda(0);
	i2c_set_scl(0);

	i2c_set_scl(0);
	i2c_set_scl(1);
	i2c_set_sda(1);
	i2c_set_scl(0);
	i2c_set_scl(0);
    if(i2c_test_sda() == 0) hmioerr++;
}
Ejemplo n.º 11
0
void i2c_send_char(unsigned char data) {
	unsigned char mask = 0x80;
	int i, x;
	for(i=0;i<8;++i) {
		x = (data & mask);
		i2c_clr_scl();
		if(x) i2c_set_sda();
		else i2c_clr_sda();
		i2c_set_scl();
		mask >>= 1;
	}
}
Ejemplo n.º 12
0
char i2c_read_char() {
	int i;
	char acc = 0;
	
	i2c_clr_scl();
	i2c_set_sda();
	for(i=0;i<8;++i) {
		i2c_clr_scl();
		i2c_set_scl();
		acc = (acc << 1) | i2c_get_sda();
	}
	
	return acc;
}
Ejemplo n.º 13
0
void i2c_send_stop(void)
{   
   /* set SDA to 0 */
   i2c_clear_sda();
   i2c_delay();
   
   /* bring the clock line high */
   i2c_set_scl();
   i2c_delay();
   
   /* and set SDA back to 1 */
   i2c_set_sda();
   i2c_delay();
}
Ejemplo n.º 14
0
void i2c_send_start(void)
{   
   /* take data and clock high, then toggle */
   i2c_set_sda();
   i2c_delay();
   
   i2c_set_scl();
   i2c_delay();
   
   i2c_clear_sda();
   i2c_delay();
   
   i2c_clear_scl();
   i2c_delay();
}
Ejemplo n.º 15
0
void i2c_send_nack() {
		i2c_clr_scl();
		i2c_set_sda();
		i2c_set_scl();
}
Ejemplo n.º 16
0
Archivo: i2c_gvc.c Proyecto: 7LK/McWRT
/*#---------------------------------------------------------------------------
 *#
 *# FUNCTION NAME: i2c_getack
 *#
 *# DESCRIPTION  : checks if ack was received from ic2
 *#
 *# PARAMETERS   : none
 *#
 *# RETURN       : returns the ack state of the I2C device
 *#
 *#---------------------------------------------------------------------------
 */
int i2c_getack( void )
{
    int ack = 1;
#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    int n=MAXSCLRETRIES;
#endif

    /* generate ACK clock pulse */
    i2c_set_scl( SCL_HIGH );

    /* switch off I2C */
    i2c_disable();

#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
    /* set clock low */
    i2c_set_scl( SCL_LOW );

    /* now wait for ack */
    i2c_delay( THIGH );

    /* set clock as input */
    i2c_scl_dir_in();

    /* wait for clock to rise (n=MAXSCLRETRIES) */
    for( ; n>0; n-- )
    {
	if( i2c_scl_is_high() )
            break;
	i2c_delay( THIGH );
    }

    i2c_set_scl( SCL_HIGH );

    i2c_scl_dir_out();

    i2c_delay( THIGH );
#else
    /* now wait for ack */
    i2c_delay( THIGH );
#endif

    /* check for ack: if SDA is high, then NACK, else ACK */
    if ( i2c_sda_is_high() )
    {
        ack = 0;
    }
    else
    {
        ack = 1;
    }

    /* end clock pulse */
    i2c_enable();
    i2c_set_scl( SCL_LOW );
    i2c_sda_dir_out();
    i2c_set_sda( SDA_LOW );

    /* Since we "lost" already THDDAT time, we can subtract it here... */
    i2c_delay( TLOW  - THDDAT );

    return ( ack );
}   /* i2c_getack */
Ejemplo n.º 17
0
/* i2c_read_sda
 Return data line's state */
unsigned char i2c_read_sda(void)
{   
   i2c_set_sda();
   /* the sda state is in bit 1 of the control reg */
   return !!(CHIPSET_REG32(REG_SB_CONTROL) & BIT_SDA);
}