/******************************************************************************
 * FunctionName : oled_write_reg
 * Description  : write the register of the i2c oled.
 * Parameters   : uint8_t reg_addr: the register address.
 * 				  uint8_t val: the write value.
 * Returns      : bool : the write result, 0:failed, 1:success.
*******************************************************************************/
static bool ICACHE_FLASH_ATTR
oled_write_reg(uint8_t reg_addr,uint8_t val)
{
  i2c_start();
  i2c_writeByte(OLED_ADDRESS);
  if(!i2c_check_ack())
  {
    i2c_stop();
    return 0;
  }
  i2c_writeByte(reg_addr);
  if(!i2c_check_ack())
  {
    i2c_stop();
    return 0;
  }
  i2c_writeByte(val&0xff);
  if(!i2c_check_ack())
  {
    i2c_stop();
    return 0;
  }
  i2c_stop();

  if(reg_addr==0x00)
  oledstat=true;

  return 1;
}
示例#2
0
static int ICACHE_FLASH_ATTR tcn75_set_cfg(int idx, uint8_t cfgval)
{
	uint8_t addr =  TCN_BASE_ADDR | idx;
	int rc = 0;
	// set in one shot mode
	i2c_start();
	i2c_writeByte(addr << 1);
	if (!i2c_check_ack()) {
		goto out_err;
	}
	i2c_writeByte(TCN_CFG);
	if (!i2c_check_ack()) {
		goto out_err;
	}
	// place all in powerdown mode
	i2c_writeByte(cfgval);
	if (!i2c_check_ack()) {
		goto out_err;
	}

	rc = 1;
out_err:
	i2c_stop();
	return rc;

}
示例#3
0
void write_to_register(i2c* bus, int address, int regAddr, int val)
{
  i2c_start(bus);
  i2c_writeByte(bus, address);
  i2c_writeByte(bus, regAddr);
  i2c_writeByte(bus, val);
  i2c_stop(bus);
}
/******************************************************************************
 * 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
peri_iaq_single_burst_read(uint8 addr, uint8 *pData, uint16 len)
{
    uint8 ack;
    uint16 i;

    i2c_start();
    i2c_writeByte(addr);
    ack = i2c_check_ack();
    PRINTF("the first ack is:%d\n",ack);
    if (ack==0) {
        os_printf("addr1 not ack when tx write cmd \n");
        i2c_stop();
        return false;
    }


      i2c_writeByte(0x52);
      ack = i2c_check_ack();
      PRINTF("the second ack is:%d\n",ack);

      if (ack==0) {
          os_printf("not ack when write 0x52 \n");
          i2c_stop();
          return false;
      }

    i2c_start();
    i2c_writeByte(addr + 1);
    ack = i2c_check_ack();
    PRINTF("the third ack is:%d\n",ack);
    if (ack==0) {
        os_printf("addr2 not ack when tx write cmd \n");
        i2c_stop();
        return false;
    }
    os_delay_us(1);
    for (i = 0; i < len; i++) {
        pData[i] = i2c_readByte();
        if(i==3)
            i2c_send_ack(0);
        else
        	i2c_send_ack(1);


        os_delay_us(1);
    	PRINTF("bytes_readed:%d\n", pData[i]);
    }

    i2c_stop();


    return true;
}
示例#5
0
unsigned short read_from_register(i2c* bus, int address, int regAddr)
{
  i2c_start(bus);
  i2c_writeByte(bus, address);
  i2c_writeByte(bus, regAddr);
  i2c_start(bus);
  i2c_writeByte(bus, address+1);

  unsigned short val = i2c_readByte(bus, 1);

  i2c_stop(bus);

  return val;
}
示例#6
0
/* Function sht21_writeCommand
 *
 * */
bool ICACHE_FLASH_ATTR sht21_writeCommand(uint8_t addr,  uint8_t cmd) {

	i2c_start();
	i2c_writeByte(addr);

	if(i2c_check_ack()){
		i2c_writeByte(cmd);
		if(i2c_check_ack()){
			i2c_stop();
			return TRUE;
		}
	} else {
		i2c_stop();
		return FALSE;
	}
	return FALSE;
}
示例#7
0
static void ICACHE_FLASH_ATTR tcn75_read_all(void *arg)
{
	int i;
	uint8 dtmp1, dtmp2;
	// set in one shot mode
	i2c_init();

	for (i=0; i < 8; i++) {
		uint8_t addr =  TCN_BASE_ADDR | i;

		if (!(present&(1<<i))) {
			continue;
		}

		i2c_start();
		i2c_writeByte(addr << 1);
		if (!i2c_check_ack()) {
			i2c_stop();
			data[i] |= INVALID_READING;
			continue;
		}
		i2c_writeByte(TCN_TA);
		if (!i2c_check_ack()) {
			i2c_stop();
			data[i] |= INVALID_READING;
			continue;
		}

		i2c_stop();
		i2c_start();
		// now read
		i2c_writeByte((addr<<1)|1); // i2c read
        	if (!i2c_check_ack()) {
   			i2c_stop();
			data[i] |= INVALID_READING;
			continue;
		}

	        dtmp1=i2c_readByte();   //read MSB
       		i2c_send_ack(1);
	        dtmp2 = i2c_readByte(); //read LSB
	       	i2c_send_ack(0);        //NACK READY FOR STOP
		data[i]= ((dtmp1<<8)|dtmp2);
		i2c_stop();
	}
}
示例#8
0
/* Function sht21_readCommand
 * TODO: Finish it!
 * */
uint32_t ICACHE_FLASH_ATTR sht21_readCommand(uint8_t addr) {
	while (!i2c_check_ack()) {
		i2c_start();
		i2c_writeByte(addr);
		if (!i2c_check_ack)
			i2c_stop();
	}
	return 0;
}
HUBTEXT int  i2c_in(i2c *bus, int i2cAddr, 
                     const unsigned char *regAddr, int regSize, 
                     unsigned char *data, int count)
{
  int n  = 0;
  i2cAddr &= -2;                                        // Clear i2cAddr.bit0 (write)
  i2c_start(bus);
  if(regSize) 
  {
    if(i2c_writeByte(bus, i2cAddr)) return n; else n++;
    n += i2c_writeData(bus, regAddr, regSize);
  }
  i2cAddr |= 1;                                       // Set i2cAddr.bit0 (read)
  i2c_start(bus);
  if(i2c_writeByte(bus, i2cAddr)) return n; else n++;
  n += i2c_readData(bus, data, count);
  i2c_stop(bus);
  return n;  
}
示例#10
0
bool ICACHE_FLASH_ATTR
SHT21_SoftReset()
{
  //Soft reset the SHT21
  i2c_start();
  i2c_writeByte(SHT21_ADDRESS);
  if (!i2c_check_ack()) {
    //os_printf("-%s-%s slave not ack... return \r\n", __FILE__, __func__);
    i2c_stop();
    return(0);
  }
  i2c_writeByte(SOFT_RESET);
  if (!i2c_check_ack()) {
    //os_printf("-%s-%s slave not ack... return \r\n", __FILE__, __func__);
    i2c_stop();
    return(0);
  }
  i2c_stop();
  return(1);
}
示例#11
0
unsigned short read_value(i2c* bus, int address, int regAddr, int sb)
{
  i2c_start(bus);
  i2c_writeByte(bus, address);
  i2c_writeByte(bus, regAddr);
  i2c_start(bus);
  i2c_writeByte(bus, address+1);

  char b1 = i2c_readByte(bus, 0);
  char b2 = i2c_readByte(bus, 1);

  unsigned short val;
  if (sb == 0)
    val = combine(b1, b2);
  else
    val = combine(b2, b1);

  i2c_stop(bus);

  return val;
}
示例#12
0
HUBTEXT int  i2c_in(i2c *busID, int i2cAddr, 
                     int memAddr, int memAddrCount, 
                     unsigned char *data, int dataCount)
{
  int n  = 0;
  i2cAddr <<= 1;
  i2cAddr &= -2;                                        // Clear i2cAddr.bit0 (write)
  i2c_start(busID);
  if(i2c_writeByte(busID, i2cAddr)) return n; else n++;
  if(memAddrCount) 
  {
    int m;
    if(memAddrCount)
    {
      if(memAddrCount > 0)
      {
        endianSwap(&m, &memAddr, memAddrCount);
      }  
      else 
      {
        m = memAddr;
        memAddrCount = - memAddrCount;
      }  
      n += i2c_writeData(busID, (unsigned char*) &m, memAddrCount);
    }  
  }  
  i2cAddr |= 1;                                       // Set i2cAddr.bit0 (read)
  i2c_start(busID);
  if(i2c_writeByte(busID, i2cAddr)) return n; else n++;
  n += i2c_readData(busID, data, abs(dataCount));
  i2c_stop(busID);
  if(dataCount < 0)
  {
    dataCount = -dataCount;
    char temp[dataCount];
    memcpy(temp, data, dataCount);
    endianSwap(data, temp, dataCount);
  }
  return n;  
}
示例#13
0
HUBTEXT int  i2c_out(i2c *bus, int i2cAddr, 
                     const unsigned char *regAddr, int regSize, 
                     const unsigned char *data, int count)
{
  int n  = 0;
  i2cAddr &= -2;                                       // Clear i2cAddr.bit0
  i2c_start(bus);
  if(i2c_writeByte(bus, i2cAddr)) return n; else n++;
  if(regSize) 
  {
    n += i2c_writeData(bus, regAddr, regSize);
  }
  n += i2c_writeData(bus, data, count);
  i2c_stop(bus);
  return n;  
}
示例#14
0
文件: i2cbus.c 项目: tslator/ArloBot
uint16_t I2C_ReadADC(uint8_t write_addr, uint8_t read_addr, uint8_t channel)
{
    uint8_t a2d_val_high;
    uint8_t a2d_val_low;
    
    int ack;
    
    lockset(lock);
    ack = i2c_startpoll(&i2c_bus, write_addr);    
    ack = i2c_writeByte(&i2c_bus, ADC_CHANNEL[channel]);
    ack = i2c_startpoll(&i2c_bus, read_addr);    
    a2d_val_high = i2c_readByte(&i2c_bus, 0);
    a2d_val_low = i2c_readByte(&i2c_bus, 1);
    i2c_stop(&i2c_bus);
    lockclr(lock);
        
    return (((uint16_t) a2d_val_high) << 8) | (uint16_t) a2d_val_low;
}
示例#15
0
HUBTEXT int  i2c_out(i2c *busID, int i2cAddr, 
                     int memAddr, int memAddrCount, 
                     const unsigned char *data, int dataCount)
{
  int n  = 0;
  i2cAddr <<= 1;
  i2cAddr &= -2;
  i2c_start(busID);
  if(i2c_writeByte(busID, i2cAddr)) return n; else n++;
  int m;
  if(memAddrCount)
  {
    if(memAddrCount > 0)
    {
      endianSwap(&m, &memAddr, memAddrCount);
    }  
    else 
    {
      m = memAddr;
      memAddrCount = - memAddrCount;
    }  
    n += i2c_writeData(busID, (unsigned char*) &m, memAddrCount);
  }  
  if(dataCount)
  {
    if(dataCount > 0)
      n += i2c_writeData(busID, data, dataCount);
    else  
    {
      dataCount = -dataCount;
      unsigned char temp[dataCount];
      endianSwap(temp, (void*) data, dataCount);
      n += i2c_writeData(busID, temp, dataCount);
    }        
  }  
  i2c_stop(busID);
  return n;  
}
示例#16
0
void main(void)
{
  stop_watchdog();
  set_clk_8MHz();


  interrupts_enable();
  lcd_init();

  uart_init();
  uart_tx_string("Register Value:");

  unsigned char i2creceive[8];
  i2c_master_init();
  unsigned char data[1] = {0x6F};
  lcd_goto(1,0);
  lcd_print("R: ");
  lcd_print(int2HEXcharArray(*data));
  lcd_goto(2,0);
  lcd_print("V: ");
  i2c_writeByte(1,data,0x50);
  __delay_cycles(300);  // delay some time to get a better view on the signals on the scope
  unsigned char rx_byte = i2c_receiveSingleByte(0x50);
  __delay_cycles(300);
  uart_tx_string(int2HEXcharArray(rx_byte));
  lcd_print(int2HEXcharArray(rx_byte));

  __delay_cycles(300);
  uart_tx_string("\n");


  for (;;)
  {

  }
}
示例#17
0
void main(void)
{
  stop_watchdog();
  set_clk_8MHz();

  //interrupts_enable();

  lcd_init();
  uart_init();


  /*
   * Read a regiser (data[1]) and print register and value on the display
   * */
  unsigned char i2creceive[8];
  i2c_master_init();
  unsigned char data[1] = {0x6F};
  lcd_goto(1,0);
  lcd_print("R: ");
  lcd_print(int2HEXcharArray(*data));
  lcd_goto(2,0);
  lcd_print("V: ");
  i2c_writeByte(1,data,0x50);
  __delay_cycles(300);  // delay some time to get a better view on the signals
  unsigned char rx_byte = i2c_receiveSingleByte(0x50);
  __delay_cycles(300);
  lcd_print(int2HEXcharArray(rx_byte));


  /*
   * receive 256 register values via UART and write them to the EEPROM (incrementing address from 0x00 to 0xFF)
   * */

  ///*
  unsigned char write_byte[2];
  unsigned int write_counter = 0;

  while(write_counter < 255) {
	  lcd_goto(2,0);
	  write_byte[0] = write_counter;
	  write_byte[1] = uart_rx_char();
	  lcd_print(int2HEXcharArray(write_byte[1]));
	  i2c_writeByte(2,write_byte,0x50);
	  write_counter = write_counter + 1;
  }
  //*/


  /*
   * Read out a register value and print it on the display to verify the write process
   * */
  lcd_goto(2,0);
  lcd_print("V: ");
  i2c_writeByte(1,data,0x50);
  rx_byte = i2c_receiveSingleByte(0x50);
  __delay_cycles(300);
  lcd_print(int2HEXcharArray(rx_byte));
  __delay_cycles(300);

  for (;;)
  {

  }
}
示例#18
0
void mpu6050_setup()
{
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_SMPLRT_DIV, 0x00); //Insert sample rate divider: SampleRate = GyroOutputRate/(1 + SMPLRT_DIV), GyroOutputRate = 8000 Hz if DLPF disabled, else 1000 Hz
	
	//Disable FSync, 256Hz DLPF
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_CONFIG, 0x00);
	
	#define XG_ST 7
	#define YG_ST 6
	#define ZG_ST 5
	#define FS_SEL1 4
	#define FS_SEL0 3
	//XG_ST,... activates self test, FS_SEL chooses range: FS_SEL = 0: +-250°/s, FS_SEL = 1: +-500°/s, FS_SEL = 2: +-1000°/s, FS_SEL = 3: +-2000°/s
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_GYRO_CONFIG, 0 << XG_ST | 0 << YG_ST | 0 << ZG_ST | 1 << FS_SEL1 | 1 << FS_SEL0);
	
	
	#define XA_ST 7
	#define YA_ST 6
	#define ZA_ST 5
	#define AFS_SEL1 4
	#define AFS_SEL0 3
	//XA_ST,... activates self test, AFS_SEL chooses range: FS_SEL = 0: +-2g, FS_SEL = 1: +-4g, FS_SEL = 2: +-8g, FS_SEL = 3: +-16g
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_ACCEL_CONFIG, 0 << XA_ST | 0 << YA_ST | 0 << ZA_ST | 0 << AFS_SEL1 | 1 << AFS_SEL0);
	
	//Freefall threshold of |0mg|
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_FF_THR, 0x00);
	//Freefall duration limit of 0
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_FF_DUR, 0x00);
	//Motion threshold of 0mg
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_MOT_THR, 0x00);
	//Motion duration of 0s
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_MOT_DUR, 0x00);
	//Zero motion threshold
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_ZRMOT_THR, 0x00);
	//Zero motion duration threshold
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_ZRMOT_DUR, 0x00);
	//Disable sensor output to FIFO buffer
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_FIFO_EN, 0x00);
	
	//AUX I2C setup
	//Sets AUX I2C to single master control, plus other config
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_MST_CTRL, 0x00);
	//Setup AUX I2C slaves
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_ADDR, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_REG, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_CTRL, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_ADDR, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_REG, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_CTRL, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_ADDR, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_REG, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_CTRL, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_ADDR, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_REG, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_CTRL, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_ADDR, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_REG, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_DO, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_CTRL, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_DI, 0x00);
	
	#define INT_LEVEL 7	//When this bit is equal to 0, the logic level for the INT pin is active high and vice versa
	#define INT_OPEN 6 //When this bit is equal to 0, the INT pin is configured as push-pull; if it is equal to 1, the INT pin is configured as open drain
	#define LATCH_INT_EN 5 //When this bit is equal to 0, the INT pin emits a 50us long pulse; if it is equal to 1, the INT pin is held high until the interrupt is cleared
	#define INT_RD_CLEAR 4 //When this bit is equal to 0, interrupt status bits are cleared only by reading INT_STATUS; if it is equal to 1, interrupt status bits are cleared on any read operation
	#define FSYNC_INT_LEVEL 3 //When this bit is equal to 0, the logic level for the FSYNC pin (when used as an interrupt to the host processor) is active high; otherwise active low
	#define FSYNC_INT_EN 2 //When equal to 0, this bit disables the FSYNC pin from causing an interrupt to the host processor; otherwise enables the FSYNC pin to be used as an interrupt pin
	#define I2C_BYPASS_EN 1 //When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to 0, the host application processor will be able to directly access the auxiliary I2C-bus
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_INT_PIN_CFG, 0 << INT_LEVEL | 0 << INT_OPEN | 1 << LATCH_INT_EN | 1 << INT_RD_CLEAR | 0 << FSYNC_INT_LEVEL | 0 << FSYNC_INT_EN | 0 << I2C_BYPASS_EN);
	
	
	#define MOT_EN 6 //When set to 1, this bit enables Motion detection to generate an interrupt
	#define FIFO_OFLOW_EN 4 //When set to 1, this bit enables a FIFO buffer overflow to generate an interrupt
	#define I2C_MST_INT_EN 3 //When set to 1, this bit enables any of the I2C-master interrupt sources to generate an interrupt
	#define DATA_RDY_EN 0 //When set to 1, this bit enables the Data Ready interrupt, which occurs each time a write operation to all of the sensor registers has been completed
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_INT_ENABLE, 0 << MOT_EN | 0 << FIFO_OFLOW_EN | 0 << I2C_MST_INT_EN | 1 << DATA_RDY_EN );
	//Slave out, dont care
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_DO, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_DO, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_DO, 0x00);
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_DO, 0x00);
	//More slave config
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x00);
	//Reset sensor signal paths
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_SIGNAL_PATH_RESET, 0x00);
	//Motion detection control
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_MOT_DETECT_CTRL, 0x00);
	//Disables FIFO, AUX I2C, FIFO and I2C reset bits to 0
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_USER_CTRL, 0x00);
	//Sets clock source to gyro reference w/ PLL
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_PWR_MGMT_1, 0b00000010);
	//Controls frequency of wakeups in accel low power mode plus the sensor standby modes
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_PWR_MGMT_2, 0x00);
	//MPU6050_RA_BANK_SEL            //Not in datasheet
	//MPU6050_RA_MEM_START_ADDR        //Not in datasheet
	//MPU6050_RA_MEM_R_W            //Not in datasheet
	//MPU6050_RA_DMP_CFG_1            //Not in datasheet
	//MPU6050_RA_DMP_CFG_2            //Not in datasheet
	//Data transfer to and from the FIFO buffer
	i2c_writeByte(MPU6050_ADDRESS, MPU6050_RA_FIFO_R_W, 0x00);
	return;
}
示例#19
0
int16_t ICACHE_FLASH_ATTR
SHT21_GetVal(uint8 mode)
{
  i2c_start(); //Start i2c
  i2c_writeByte(SHT21_ADDRESS);
  if (!i2c_check_ack()) {
    //os_printf("-%s-%s slave not ack... return \r\n", __FILE__, __func__);
    i2c_stop();
    return(0);
  }

  if (mode==GET_SHT_TEMPERATURE)
    i2c_writeByte(TRIGGER_TEMP_MEASURE_NOHOLD);
  else if (mode==GET_SHT_HUMIDITY)
    i2c_writeByte(TRIGGER_HUMD_MEASURE_NOHOLD);
  else
    return 0;
    
  if (!i2c_check_ack()) {
    //os_printf("-%s-%s slave not ack... return \r\n", __FILE__, __func__);
    i2c_stop();
    return(0);
  }
  
  os_delay_us(20);
  
  i2c_stop();
  
  os_delay_us(70000);
  
  uint8 ack = 0;
  while (!ack) {
    i2c_start();
    i2c_writeByte(SHT21_ADDRESS+1);
    ack = i2c_check_ack();
    if (!ack) i2c_stop();
  }
  //os_printf("-%s-%s get ack \r\n", __FILE__, __func__);

  uint8 msb = i2c_readByte();
  i2c_send_ack(1);
  uint8 lsb = i2c_readByte();
  i2c_send_ack(0);
  i2c_stop();
     
  uint16_t _rv = msb << 8;
  _rv += lsb;
  _rv &= ~0x0003; 
 
  //os_printf("-%s-%s RAW:%d \r\n", __FILE__, __func__,_rv);

  float rv = _rv;
  
  if (mode==GET_SHT_TEMPERATURE) {
    rv *= 175.72;
    rv /= 65536;
    rv -= 46.85;
  } else if (mode==GET_SHT_HUMIDITY) {
    rv *= 125.0;
    rv /= 65536;
    rv -= 6.0; 
  }
  
  return (int16_t)(rv*10);
}