コード例 #1
0
/******************************************************************************
 * FunctionName : i2c_master_readByte
 * Description  : read Byte from i2c bus
 * Parameters   : NONE
 * Returns	  : uint8 - readed value
*******************************************************************************/
uint8 i2c_master_readByte(void)
{
	uint8 retVal = 0;
	uint8 k, i;

	i2c_master_setDC(1, m_nLastSCL);

	for (i = 0; i < 8; i++) {
		i2c_master_wait(I2C_SLEEP_TIME);
		i2c_master_setDC(1, 0);
		i2c_master_wait(I2C_SLEEP_TIME);// sda 1, scl 0
		i2c_master_setDC(1, 1);
		while(i2c_master_getCL()==0)
			;		// clock stretch
		i2c_master_wait(I2C_SLEEP_TIME);// sda 1, scl 1

		k = i2c_master_getDC();
		i2c_master_wait(I2C_SLEEP_TIME);

		//if (i == 7) {
		//	i2c_master_wait(5);   ////
		//}

		k <<= (7 - i);
		retVal |= k;
	}

	i2c_master_setDC(m_nLastSDA, 0);
	i2c_master_wait(I2C_SLEEP_TIME);// sda 1, scl 0

	return retVal;
}
コード例 #2
0
/******************************************************************************
 * FunctionName : i2c_master_writeByte
 * Description  : write wrdata value(one byte) into i2c
 * Parameters   : uint8 wrdata - write value
 * Returns	  : NONE
*******************************************************************************/
void i2c_master_writeByte(uint8 wrdata)
{
	uint8 dat;
	sint8 i;
/*
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(m_nLastSDA, 0);
*/
	i2c_master_wait(I2C_SLEEP_TIME);

	for (i = 7; i >= 0; i--) {
		dat = wrdata >> i;
		i2c_master_setDC(dat, 0);
		i2c_master_wait(I2C_SLEEP_TIME);
		i2c_master_setDC(dat, 1);
		i2c_master_wait(I2C_SLEEP_TIME);
/*
		if (i == 0) {
			i2c_master_wait(5);   ////
		}
*/
		i2c_master_setDC(dat, 0);
		i2c_master_wait(I2C_SLEEP_TIME);
	}
}
コード例 #3
0
ファイル: i2c_master.c プロジェクト: modSwap/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_readByte
 * Description  : read Byte from i2c bus
 * Parameters   : NONE
 * Returns	    : uint8 - readed value
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_readByte(void)
{
	uint8 retVal = 0;
	uint8 k, i;
	
	i2c_master_wait(I2C_DELAY);
	i2c_master_setDC(m_nLastSDA, 0); // sda 1, scl 0
	
	for (i = 0; i < 8; i++) {
		i2c_master_wait(I2C_DELAY);
		i2c_master_setDC(1, 0); // sda 1, scl 0
		i2c_master_setDC(1, 1); // sda 1, scl 1

		k = i2c_master_getDC();

		if (i == 7) {
			i2c_master_wait(I2C_DELAY);   // extra delay
		}
		
		k <<= (7 - i);
		retVal |= k;
	}
	
	i2c_master_setDC(1, 0); // sda 1, scl 0
	
	return retVal;
}
コード例 #4
0
ファイル: i2c_master.c プロジェクト: Daven005/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_init
 * Description  : initilize I2C bus to enable i2c operations
 * Parameters   : NONE
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_init(void)
{
    uint8 i;

    i2c_master_setDC(1, 0);
    i2c_master_wait(5);

    // when SCL = 0, toggle SDA to clear up
    i2c_master_setDC(0, 0) ;
    i2c_master_wait(5);
    i2c_master_setDC(1, 0) ;
    i2c_master_wait(5);

    // set data_cnt to max value
    for (i = 0; i < 28; i++) {
        i2c_master_setDC(1, 0);
        i2c_master_wait(5);	// sda 1, scl 0
        i2c_master_setDC(1, 1);
        i2c_master_wait(5);	// sda 1, scl 1
    }

    // reset all
    i2c_master_stop();
    return;
}
コード例 #5
0
/******************************************************************************
 * FunctionName : i2c_master_start
 * Description  : set i2c to send state
 * Parameters   : NONE
 * Returns	  : NONE
*******************************************************************************/
void i2c_master_start(void)
{
	i2c_master_setDC(1, m_nLastSCL);
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(1, 1);
	i2c_master_wait(I2C_SLEEP_TIME);// sda 1, scl 1
	i2c_master_setDC(0, 1);
	i2c_master_wait(I2C_SLEEP_TIME);// sda 0, scl 1
}
コード例 #6
0
ファイル: i2c_master.c プロジェクト: Daven005/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_start
 * Description  : set i2c to send state
 * Parameters   : NONE
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(void)
{
    i2c_master_setDC(1, m_nLastSCL);
    i2c_master_wait(5);
    i2c_master_setDC(1, 1);
    i2c_master_wait(5);	// sda 1, scl 1
    i2c_master_setDC(0, 1);
    i2c_master_wait(5);	// sda 0, scl 1
}
コード例 #7
0
ファイル: led_i2c_master.c プロジェクト: hcheung92/WiFiYaala
/******************************************************************************
 * FunctionName : i2c_master_stop
 * Description  : set i2c to stop sending state
 * Parameters   : NONE
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_stop(void)
{
    i2c_master_wait(I2C_DELAY_FULL);

    i2c_master_setDC(0, m_nLastSCL);
    i2c_master_wait(I2C_DELAY_FULL);	// sda 0
    i2c_master_setDC(0, 1);
    i2c_master_wait(I2C_DELAY_FULL);	// sda 0, scl 1
    i2c_master_setDC(1, 1);
    i2c_master_wait(I2C_DELAY_FULL);	// sda 1, scl 1
}
コード例 #8
0
ファイル: i2c_master.c プロジェクト: RobinLin/Espruino
/******************************************************************************
 * FunctionName : i2c_master_stop
 * Description  : set i2c to stop sending state
 * Parameters   : NONE
 * Returns      : NONE
*******************************************************************************/
void ICACHE_RAM_ATTR
i2c_master_stop(void)
{
    i2c_master_wait(5);

    i2c_master_setDC(0, m_nLastSCL);
    i2c_master_wait(5);	// sda 0
    i2c_master_setDC(0, 1);
    i2c_master_wait(5);	// sda 0, scl 1
    i2c_master_setDC(1, 1);
    i2c_master_wait(5);	// sda 1, scl 1
}
コード例 #9
0
ファイル: i2c_master.c プロジェクト: nkolban/Espruino
/******************************************************************************
 * FunctionName : i2c_master_setAck
 * Description  : set ack to i2c bus as level value
 * Parameters   : uint8 level - 0 or 1
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)
{
    i2c_master_setDC(level, 0);
    i2c_master_wait(2);	// sda level, scl 0
    i2c_master_setDC(level, 1);
    i2c_master_wait(4);	// sda level, scl 1
    i2c_master_setDC(level, 0);
    i2c_master_wait(2);	// sda level, scl 0
    i2c_master_setDC(1, 0);
    i2c_master_wait(2);
}
コード例 #10
0
/******************************************************************************
 * FunctionName : i2c_master_setAck
 * Description  : set ack to i2c bus as level value
 * Parameters   : uint8 level - 0 or 1
 * Returns	  : NONE
*******************************************************************************/
void i2c_master_setAck(uint8 level)
{
	i2c_master_setDC(m_nLastSDA, 0);
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(level, 0);
	i2c_master_wait(I2C_SLEEP_TIME);// sda level, scl 0
	i2c_master_setDC(level, 1);
	i2c_master_wait(8);// sda level, scl 1
	i2c_master_setDC(level, 0);
	i2c_master_wait(I2C_SLEEP_TIME);// sda level, scl 0
	i2c_master_setDC(1, 0);
	i2c_master_wait(I2C_SLEEP_TIME);
}
コード例 #11
0
ファイル: i2c_master.c プロジェクト: nkolban/Espruino
/******************************************************************************
 * FunctionName : i2c_master_getAck
 * Description  : confirm if peer send ack
 * Parameters   : NONE
 * Returns      : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)
{
    uint8 retVal;
    i2c_master_setDC(1, 0);
    i2c_master_wait(2);
    i2c_master_setDC(1, 1);
    i2c_master_wait(4);
    retVal = i2c_master_getDC();
    i2c_master_setDC(1, 0);
    i2c_master_wait(2);

    return !retVal; // 0->true->ACK, 1->false->NACK
}
コード例 #12
0
ファイル: led_i2c_master.c プロジェクト: hcheung92/WiFiYaala
/******************************************************************************
 * FunctionName : i2c_master_setAck
 * Description  : set ack to i2c bus as level value
 * Parameters   : uint8 level - 0 or 1
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)
{
    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(I2C_DELAY_FULL);
    i2c_master_setDC(level, 0);
    i2c_master_wait(I2C_DELAY_FULL);	// sda level, scl 0
    i2c_master_setDC(level, 1);
    i2c_master_wait(I2C_DELAY_LONG);	// sda level, scl 1
    i2c_master_setDC(level, 0);
    i2c_master_wait(I2C_DELAY_FULL);	// sda level, scl 0
    i2c_master_setDC(1, 0);
    i2c_master_wait(I2C_DELAY_FULL);
}
コード例 #13
0
ファイル: i2c_master.c プロジェクト: Daven005/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_setAck
 * Description  : set ack to i2c bus as level value
 * Parameters   : uint8 level - 0 or 1
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)
{
    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(5);
    i2c_master_setDC(level, 0);
    i2c_master_wait(5);	// sda level, scl 0
    i2c_master_setDC(level, 1);
    i2c_master_wait(8);	// sda level, scl 1
    i2c_master_setDC(level, 0);
    i2c_master_wait(5);	// sda level, scl 0
    i2c_master_setDC(1, 0);
    i2c_master_wait(5);
}
コード例 #14
0
ファイル: user_main.c プロジェクト: alonewolfx2/esp8266-sdk
LOCAL void ICACHE_FLASH_ATTR
read_cb(void)
{
	uint8_t ack, low, high;
	wdt_feed();
	os_printf("Time=%ld\n", system_get_time());
	i2c_master_start();
	i2c_master_writeByte(BH1750_ADDR);
	ack = i2c_master_getAck();
	if (ack)
	{
		os_printf("I2C:No ack after sending address\n");
		i2c_master_stop();
		return;
	}
	i2c_master_stop();
    i2c_master_wait(40000); // why?

    i2c_master_start();
    i2c_master_writeByte(BH1750_ADDR + 1);
    ack = i2c_master_getAck();
	if (ack)
	{
		os_printf("I2C:No ack after write command\n");
		i2c_master_stop();
		return;
	}
	low = i2c_master_readByte();
	high = i2c_master_readByte();
	i2c_master_setAck(1);
    i2c_master_stop();
	os_printf("I2C:read(L/H)=(0x%02x/0x%02x)\n", low, high);
}
コード例 #15
0
ファイル: i2c_master.c プロジェクト: modSwap/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_getDC
 * Description  : Internal used function -
 *					get i2c SDA bit value
 * Parameters   : NONE
 * Returns	  : uint8 - SDA bit value
*******************************************************************************/
LOCAL uint8 ICACHE_FLASH_ATTR
i2c_master_getDC(void)
{
	uint8 sda_out;
	sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
	i2c_master_wait(I2C_DELAY);
	return sda_out;
}
コード例 #16
0
/******************************************************************************
 * FunctionName : i2c_master_getAck
 * Description  : confirm if peer send ack
 * Parameters   : NONE
 * Returns	  : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 i2c_master_getAck(void)
{
	uint8 retVal;
	i2c_master_setDC(m_nLastSDA, 0);
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(1, 0);
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(1, 1);
	i2c_master_wait(I2C_SLEEP_TIME);

	retVal = i2c_master_getDC();
	i2c_master_wait(I2C_SLEEP_TIME);
	i2c_master_setDC(1, 0);
	i2c_master_wait(I2C_SLEEP_TIME);

	return retVal;
}
コード例 #17
0
ファイル: i2c_master.c プロジェクト: Daven005/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_getAck
 * Description  : confirm if peer send ack
 * Parameters   : NONE
 * Returns      : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)
{
    uint8 retVal;
    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(5);
    i2c_master_setDC(1, 0);
    i2c_master_wait(5);
    i2c_master_setDC(1, 1);
    i2c_master_wait(5);

    retVal = i2c_master_getDC();
    i2c_master_wait(5);
    i2c_master_setDC(1, 0);
    i2c_master_wait(5);

    return retVal;
}
コード例 #18
0
ファイル: i2c_master.c プロジェクト: nkolban/Espruino
/******************************************************************************
 * FunctionName : i2c_master_writeByte
 * Description  : write wrdata value(one byte) into i2c
 * Parameters   : uint8 wrdata - write value
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)
{
    uint8 dat;
    sint8 i;

    i2c_master_wait(2);
    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(4);

    for (i = 7; i >= 0; i--) {
        dat = wrdata >> i;
        i2c_master_setDC(dat, 0);
        i2c_master_wait(1);
        i2c_master_setDC(dat, 1);
        i2c_master_wait(5);
        i2c_master_setDC(dat, 0);
        i2c_master_wait(2);
    }
}
コード例 #19
0
ファイル: led_i2c_master.c プロジェクト: hcheung92/WiFiYaala
/******************************************************************************
 * FunctionName : i2c_master_writeByte
 * Description  : write wrdata value(one byte) into i2c
 * Parameters   : uint8 wrdata - write value
 * Returns      : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)
{
    uint8 dat;
    sint8 i;

    i2c_master_wait(I2C_DELAY_FULL);

    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(I2C_DELAY_FULL);

    for (i = 7; i >= 0; i--) {
        dat = wrdata >> i;
        i2c_master_setDC(dat, 0);
        i2c_master_wait(I2C_DELAY_FULL);
        i2c_master_setDC(dat, 1);
        i2c_master_wait(I2C_DELAY_FULL);

        if (i == 0) {
            i2c_master_wait(I2C_DELAY_HALF);   ////
        }

        i2c_master_setDC(dat, 0);
        i2c_master_wait(I2C_DELAY_FULL);
    }
}
コード例 #20
0
ファイル: i2c_master.c プロジェクト: nkolban/Espruino
/******************************************************************************
 * FunctionName : i2c_master_readByte
 * Description  : read Byte from i2c bus
 * Parameters   : NONE
 * Returns      : uint8 - readed value
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_readByte(void)
{
    uint8 retVal = 0;
    uint8 i;

    i2c_master_wait(2);
    i2c_master_setDC(m_nLastSDA, 0);
    i2c_master_wait(4);	// sda 1, scl 0

    for (i = 0; i < 8; i++) {
        i2c_master_setDC(1, 0);
        i2c_master_wait(4);	// sda 1, scl 0
        i2c_master_setDC(1, 1);
        i2c_master_wait(3);	// sda 1, scl 1
        retVal = (retVal<<1) | (i2c_master_getDC()&1);
    }

    i2c_master_setDC(1, 0);
    i2c_master_wait(2);	// sda 1, scl 0

    return retVal;
}
コード例 #21
0
ファイル: i2c_master.c プロジェクト: modSwap/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_getAck
 * Description  : confirm if peer send ack
 * Parameters   : NONE
 * Returns	  : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)
{
	uint8 retVal;
	i2c_master_setDC(m_nLastSDA, 0);
	i2c_master_setDC(1, 0);
	i2c_master_wait(I2C_DELAY); // extra delay
	i2c_master_setDC(1, 1);

	retVal = i2c_master_getDC();
	
	i2c_master_setDC(1, 0);
	
	return retVal;
}
コード例 #22
0
bool i2c_master_readBytes(uint8 address, uint8 *values, uint8 length)
{
	if(values[0] > 0){
		if(!i2c_master_writeBytes(address, values, 1)){
			return false;
		}
	}

	uint8 timeout = 100;
	do{
		i2c_master_start();
		i2c_master_writeByte(address+1);
		if(!i2c_master_checkAck()){
			i2c_master_stop();
			i2c_master_wait(1000);
			continue;
		}
		break;
	}while(--timeout>0);

	if(timeout == 0){
		return false;
	}

#ifdef CONFIG_I2C_MASTER_DEBUG
	console_printf("Read: ");
#endif
	uint8 readed = 0;
	while((readed < length) && (--timeout>0)){
		uint8 byte = i2c_master_readByte();
		values[readed++] = byte;
		i2c_master_setAck((readed == length));	// send the ACK or NAK as applicable
		i2c_master_setDC(1, 0); // release SDA
#ifdef CONFIG_I2C_MASTER_DEBUG
		console_printf("%d ", byte);
#endif
	}
#ifdef CONFIG_I2C_MASTER_DEBUG
	console_printf("\n");
#endif
	i2c_master_stop();
	return true;
}
コード例 #23
0
ファイル: user_sensor.c プロジェクト: alonewolfx2/esp8266-sdk
/******************************************************************************
 * FunctionName : user_mvh3004_burst_read
 * Description  : burst read mvh3004's internal data
 * Parameters   : uint8 addr - mvh3004's address
 *                uint8 *pData - data point to put read data
 *                uint16 len - read length
 * Returns      : bool - true or false
*******************************************************************************/
LOCAL bool ICACHE_FLASH_ATTR
user_mvh3004_burst_read(uint8 addr, uint8 *pData, uint16 len)
{
    uint8 ack;
    uint16 i;

    i2c_master_start();
    i2c_master_writeByte(addr);
    ack = i2c_master_getAck();

    if (ack) {
        os_printf("addr not ack when tx write cmd \n");
        i2c_master_stop();
        return false;
    }

    i2c_master_stop();
    i2c_master_wait(40000);

    i2c_master_start();
    i2c_master_writeByte(addr + 1);
    ack = i2c_master_getAck();

    if (ack) {
        os_printf("addr not ack when tx write cmd \n");
        i2c_master_stop();
        return false;
    }

    for (i = 0; i < len; i++) {
        pData[i] = i2c_master_readByte();

        i2c_master_setAck((i == (len - 1)) ? 1 : 0);
    }

    i2c_master_stop();

    return true;
}
コード例 #24
0
ファイル: i2c_master.c プロジェクト: modSwap/ESP8266
/******************************************************************************
 * FunctionName : i2c_master_setDC
 * Description  : Internal used function -
 *					set i2c SDA and SCL bit value for half clk cycle
 * Parameters   : uint8 SDA
 *				uint8 SCL
 * Returns	  : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
i2c_master_setDC(uint8 SDA, uint8 SCL)
{
	SDA	&= 0x01;
	SCL	&= 0x01;
	m_nLastSDA = SDA;
	m_nLastSCL = SCL;

	if ((0 == SDA) && (0 == SCL)) {
		I2C_MASTER_SDA_LOW_SCL_LOW();
	} else if ((0 == SDA) && (1 == SCL)) {
		do {
			I2C_MASTER_SDA_LOW_SCL_HIGH();
		} while (GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)) == 0);
	} else if ((1 == SDA) && (0 == SCL)) {
		I2C_MASTER_SDA_HIGH_SCL_LOW();
	} else {
		do {
			I2C_MASTER_SDA_HIGH_SCL_HIGH();
		} while (GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)) == 0);
	}
	i2c_master_wait(I2C_DELAY);
}
コード例 #25
0
ファイル: i2c.c プロジェクト: espressif/ESP8266_RTOS_SDK
static void i2c_master_cmd_begin_static(i2c_port_t i2c_num)
{
    i2c_obj_t *p_i2c = p_i2c_obj[i2c_num];
    i2c_cmd_t *cmd;
    uint8_t dat;
    uint8_t len;
    int8_t i, k;
    uint8_t retVal;

    // This should never happen
    if (p_i2c->mode != I2C_MODE_MASTER) {
        return;
    }

    while (p_i2c->cmd_link.head) {
        cmd = &p_i2c->cmd_link.head->cmd;

        switch (cmd->op_code) {
            case (I2C_CMD_RESTART): {
                i2c_master_set_dc(i2c_num, 1, i2c_last_state[i2c_num]->scl);
                i2c_master_set_dc(i2c_num, 1, 1);
                i2c_master_wait(1);     // sda 1, scl 1
                i2c_master_set_dc(i2c_num, 0, 1);
                i2c_master_wait(1);     // sda 0, scl 1
            }
            break;

            case (I2C_CMD_WRITE): {
                p_i2c->status = I2C_STATUS_WRITE;

                for (len = 0; len < cmd->byte_num; len++) {
                    dat = 0;
                    retVal = 0;
                    i2c_master_set_dc(i2c_num, i2c_last_state[i2c_num]->sda, 0);

                    for (i = 7; i >= 0; i--) {
                        if (cmd->byte_num == 1 && cmd->data == NULL) {
                            dat = (cmd->byte_cmd) >> i;
                        } else {
                            dat = ((uint8_t) * (cmd->data + len)) >> i;
                        }

                        i2c_master_set_dc(i2c_num, dat, 0);
                        i2c_master_wait(1);
                        i2c_master_set_dc(i2c_num, dat, 1);
                        i2c_master_wait(2);

                        if (i == 0) {
                            i2c_master_wait(1);   // wait slaver ack
                        }

                        i2c_master_set_dc(i2c_num, dat, 0);
                    }

                    i2c_master_set_dc(i2c_num, i2c_last_state[i2c_num]->sda, 0);
                    i2c_master_set_dc(i2c_num, 1, 0);
                    i2c_master_set_dc(i2c_num, 1, 1);
                    i2c_master_wait(1);
                    retVal = i2c_master_get_dc(i2c_num);
                    i2c_master_wait(1);
                    i2c_master_set_dc(i2c_num, 1, 0);

                    if (cmd->ack.en == 1) {
                        if ((retVal & 0x01) != cmd->ack.exp) {
                            p_i2c->status = I2C_STATUS_ACK_ERROR;
                            return ;
                        }
                    }
                }
            }
            break;

            case (I2C_CMD_READ): {
                p_i2c->status = I2C_STATUS_READ;

                for (len = 0; len < cmd->byte_num; len++) {
                    retVal = 0;
                    i2c_master_set_dc(i2c_num, i2c_last_state[i2c_num]->sda, 0);

                    for (i = 0; i < 8; i++) {
                        i2c_master_set_dc(i2c_num, 1, 0);
                        i2c_master_wait(2);
                        i2c_master_set_dc(i2c_num, 1, 1);
                        i2c_master_wait(1);     // sda 1, scl 1
                        k = i2c_master_get_dc(i2c_num);
                        i2c_master_wait(1);

                        if (i == 7) {
                            i2c_master_wait(1);
                        }

                        k <<= (7 - i);
                        retVal |= k;
                    }

                    i2c_master_set_dc(i2c_num, 1, 0);
                    memcpy((uint8_t *)(cmd->data + len), (uint8_t *)&retVal, 1);
                    i2c_master_set_dc(i2c_num, i2c_last_state[i2c_num]->sda, 0);
                    i2c_master_set_dc(i2c_num, cmd->ack.val, 0);
                    i2c_master_set_dc(i2c_num, cmd->ack.val, 1);
                    i2c_master_wait(4);     // sda level, scl 1
                    i2c_master_set_dc(i2c_num, cmd->ack.val, 0);
                    i2c_master_set_dc(i2c_num, 1, 0);
                    i2c_master_wait(1);
                }
            }
            break;

            case (I2C_CMD_STOP): {
                i2c_master_wait(1);
                i2c_master_set_dc(i2c_num, 0, i2c_last_state[i2c_num]->scl);
                i2c_master_set_dc(i2c_num, 0, 1);
                i2c_master_wait(2);     // sda 0, scl 1
                i2c_master_set_dc(i2c_num, 1, 1);
                i2c_master_wait(2);     // sda 1, scl 1
            }
            break;
        }