Exemple #1
0
uint8_t twi_status() {
    if (SCL_READ() == 0)
      return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover

    int clockCount = 20;
    while (SDA_READ() == 0 && clockCount-- > 0) { // if SDA low, read the bits slaves have to sent to a max
        twi_read_bit();
        if (SCL_READ() == 0) {
          return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time
        }
    }
    if (SDA_READ() == 0)
      return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits.
    
    if (!twi_write_start())
      return I2C_SDA_HELD_LOW_AFTER_INIT;  // line busy. SDA again held low by another device. 2nd master?

    return I2C_OK;
}
Exemple #2
0
static bool twi_read_bit(void) {
  uint32_t i = 0;
  SCL_LOW();
  SDA_HIGH();
  twi_delay(twi_dcount+2);
  SCL_HIGH();
  while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
  bool bit = SDA_READ();
  twi_delay(twi_dcount);
  return bit;
}
Exemple #3
0
static bool twi_write_bit(bool bit) {
  uint32_t i = 0;
  SCL_LOW();
  if (bit) SDA_HIGH();
  else SDA_LOW();
  twi_delay(twi_dcount+1);
  SCL_HIGH();
  while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
  twi_delay(twi_dcount);
  return true;
}
Exemple #4
0
static bool ICACHE_FLASH_ATTR twi_read_bit()
{
	unsigned int i = 0;
	SCL_LOW();
	SDA_HIGH();
	twi_delay(twi_dcount + 2);
	SCL_HIGH();
	while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);	// Clock stretching
	bool bit = SDA_READ();
	twi_delay(twi_dcount);
	return bit;
}
Exemple #5
0
static bool twi_write_stop(void){
  uint32_t i = 0;
  SCL_LOW();
  SDA_LOW();
  twi_delay(twi_dcount);
  SCL_HIGH();
  while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit); // Clock stretching
  twi_delay(twi_dcount);
  SDA_HIGH();
  twi_delay(twi_dcount);
  return true;
}
Exemple #6
0
static bool ICACHE_FLASH_ATTR twi_write_stop(void)
{
	unsigned int i = 0;
	SCL_LOW();
	SDA_LOW();
	twi_delay(twi_dcount);
	SCL_HIGH();
	while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);	// Clock stretching
	twi_delay(twi_dcount);
	SDA_HIGH();
	twi_delay(twi_dcount);

	return true;
}
Exemple #7
0
unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop){
  unsigned int i;
  if(!twi_write_start()) return 4;//line busy
  if(!twi_write_byte(((address << 1) | 1) & 0xFF)) {
    if (sendStop) twi_write_stop();
    return 2;//received NACK on transmit of address
  }
  for(i=0; i<(len-1); i++) buf[i] = twi_read_byte(false);
  buf[len-1] = twi_read_byte(true);
  if(sendStop) twi_write_stop();
  i = 0;
  while(SDA_READ() == 0 && (i++) < 10){
    SCL_LOW();
    twi_delay(twi_dcount);
    SCL_HIGH();
    unsigned int t=0; while(SCL_READ()==0 && (t++)<twi_clockStretchLimit); // twi_clockStretchLimit
    twi_delay(twi_dcount);
  }
  return 0;
}
Exemple #8
0
unsigned char twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop){
  unsigned int i;
  if(!twi_write_start()) return 4;//line busy
  if(!twi_write_byte(((address << 1) | 0) & 0xFF)) {
    if (sendStop) twi_write_stop();
    return 2; //received NACK on transmit of address
  }
  for(i=0; i<len; i++) {
    if(!twi_write_byte(buf[i])) {
      if (sendStop) twi_write_stop();
      return 3;//received NACK on transmit of data
    }
  }
  if(sendStop) twi_write_stop();
  i = 0;
  while(SDA_READ() == 0 && (i++) < 10){
    SCL_LOW();
    twi_delay(twi_dcount);
    SCL_HIGH();
    unsigned int t=0; while(SCL_READ()==0 && (t++)<twi_clockStretchLimit); // twi_clockStretchLimit
    twi_delay(twi_dcount);
  }
  return 0;
}
Exemple #9
0
void ICACHE_RAM_ATTR onSdaChange(void)
{
	static uint8_t sda;
	static uint8_t scl;
	sda	= SDA_READ();
	scl = SCL_READ();

	switch (twip_state)
	{
		case TWIP_IDLE:
			if (!scl) {
				// DATA - ignore
			} else if (sda) {
				// STOP - ignore
			} else {
				// START
				bitCount = 8;
				twip_state = TWIP_START;
				ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms
			}
			break;

		case TWIP_START:
		case TWIP_REP_START:
		case TWIP_SEND_ACK:
		case TWIP_WAIT_ACK:
		case TWIP_SLA_R:
		case TWIP_REC_ACK:
		case TWIP_READ_ACK:
		case TWIP_RWAIT_ACK:
		case TWIP_WRITE:
			if (!scl) {
				// DATA - ignore
			} else {
				// START or STOP
				SDA_HIGH();	 // Should not be necessary
				twip_status = TW_BUS_ERROR;
				twi_onTwipEvent(twip_status);
				twip_mode = TWIPM_WAIT;
				twip_state = TWIP_BUS_ERR;
			}
			break;

		case TWIP_WAIT_STOP:
		case TWIP_BUS_ERR:
			if (!scl) {
				// DATA - ignore
			} else {
				if (sda) {
					// STOP
					SCL_LOW();	// clock stretching
					ets_timer_disarm(&timer);
					twip_state = TWIP_IDLE;
					twip_mode = TWIPM_IDLE;
					SCL_HIGH();
				} else {
					// START
					if (twip_state == TWIP_BUS_ERR) {
						// ignore
					} else {
						bitCount = 8;
						twip_state = TWIP_REP_START;
						ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms
					}
				}
			}
			break;

		case TWIP_SLA_W:
		case TWIP_READ:
			if (!scl) {
				// DATA - ignore
			} else {
				// START or STOP
				if (bitCount != 7) {
					// inside byte transfer - error
					twip_status = TW_BUS_ERROR;
					twi_onTwipEvent(twip_status);
					twip_mode = TWIPM_WAIT;
					twip_state = TWIP_BUS_ERR;
				} else {
					// during first bit in byte transfer - ok
					SCL_LOW();	// clock stretching
					twip_status = TW_SR_STOP;
					twi_onTwipEvent(twip_status);
					if (sda) {
						// STOP
						ets_timer_disarm(&timer);
						twip_state = TWIP_IDLE;
						twip_mode = TWIPM_IDLE;
					} else {
						// START
						bitCount = 8;
						ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms
						twip_state = TWIP_REP_START;
						twip_mode = TWIPM_IDLE;
					}
				}
			}
			break;

		default:
			break;
	}
}
Exemple #10
0
void ICACHE_RAM_ATTR onSclChange(void)
{
	static uint8_t sda;
	static uint8_t scl;

	sda	= SDA_READ();
	scl = SCL_READ();

	twip_status = 0xF8;		// reset TWI status

	switch (twip_state)
	{
		case TWIP_IDLE:
		case TWIP_WAIT_STOP:
		case TWIP_BUS_ERR:
			// ignore
			break;

		case TWIP_START:
		case TWIP_REP_START:
		case TWIP_SLA_W:
		case TWIP_READ:
			if (!scl) {
				// ignore
			} else {
				bitCount--;
				twi_data <<= 1;
				twi_data |= sda;

				if (bitCount != 0) {
					// continue
				} else {
					twip_state = TWIP_SEND_ACK;
				}
			}
			break;

		case TWIP_SEND_ACK:
			if (scl) {
				// ignore
			} else {
				if (twip_mode == TWIPM_IDLE) {
					if ((twi_data & 0xFE) != twi_addr) {
						// ignore
					} else {
						SDA_LOW();
					}
				} else {
					if (!twi_ack) {
						// ignore
					} else {
						SDA_LOW();
					}
				}
				twip_state = TWIP_WAIT_ACK;
			}
			break;

		case TWIP_WAIT_ACK:
			if (scl) {
				// ignore
			} else {
				if (twip_mode == TWIPM_IDLE) {
					if ((twi_data & 0xFE) != twi_addr) {
						SDA_HIGH();
						twip_state = TWIP_WAIT_STOP;
					} else {
						SCL_LOW();	// clock stretching
						SDA_HIGH();
						twip_mode = TWIPM_ADDRESSED;
						if (!(twi_data & 0x01)) {
							twip_status = TW_SR_SLA_ACK;
							twi_onTwipEvent(twip_status);
							bitCount = 8;
							twip_state = TWIP_SLA_W;
						} else {
							twip_status = TW_ST_SLA_ACK;
							twi_onTwipEvent(twip_status);
							twip_state = TWIP_SLA_R;
						}
					}
				} else {
					SCL_LOW();	// clock stretching
					SDA_HIGH();
					if (!twi_ack) {
						twip_status = TW_SR_DATA_NACK;
						twi_onTwipEvent(twip_status);
						twip_mode = TWIPM_WAIT;
						twip_state = TWIP_WAIT_STOP;
					} else {
						twip_status = TW_SR_DATA_ACK;
						twi_onTwipEvent(twip_status);
						bitCount = 8;
						twip_state = TWIP_READ;
					}
				}
			}
			break;

		case TWIP_SLA_R:
		case TWIP_WRITE:
			if (scl) {
				// ignore
			} else {
				bitCount--;
				(twi_data & 0x80) ? SDA_HIGH() : SDA_LOW();
				twi_data <<= 1;

				if (bitCount != 0) {
					// continue
				} else {
					twip_state = TWIP_REC_ACK;
				}
			}
			break;

		case TWIP_REC_ACK:
			if (scl) {
				// ignore
			} else {
				SDA_HIGH();
				twip_state = TWIP_READ_ACK;
			}
			break;

		case TWIP_READ_ACK:
			if (!scl) {
				// ignore
			} else {
				twi_ack_rec = !sda;
				twip_state = TWIP_RWAIT_ACK;
			}
			break;

		case TWIP_RWAIT_ACK:
			if (scl) {
				// ignore
			} else {
				SCL_LOW();	// clock stretching
				if (twi_ack && twi_ack_rec) {
					twip_status = TW_ST_DATA_ACK;
					twi_onTwipEvent(twip_status);
					twip_state = TWIP_WRITE;
				} else {
					// we have no more data to send and/or the master doesn't want anymore
					twip_status = twi_ack_rec ? TW_ST_LAST_DATA : TW_ST_DATA_NACK;
					twi_onTwipEvent(twip_status);
					twip_mode = TWIPM_WAIT;
					twip_state = TWIP_WAIT_STOP;
				}
			}
			break;

		default:
			break;
	}
}