Esempio n. 1
0
/*
 * Toggles out a single byte in master mode.
 *
 * Entry: SCL low, SDA any
 * Exit: SCL low, SDA high
 */
static int TwPut(uint8_t octet)
{
    int i;

    for (i = 0x80; i; i >>= 1) {
        /* Set the data bit. */
        if (octet & i) {
            SDA_HIGH();
        } else {
            SDA_LOW();
        }
        /* Wait for data to stabelize. */
        TwDelay(TWI_DELAY);
        /* Toggle the clock. */
        SCL_HIGH();
        TwDelay(2 * TWI_DELAY);
        SCL_LOW();
        TwDelay(TWI_DELAY);
    }

    /* Set data line high to receive the ACK bit. */
    SDA_HIGH();

    /* ACK should appear shortly after the clock's rising edge. */
    SCL_HIGH();
    TwDelay(2 * TWI_DELAY);
    if (SDA_STAT()) {
        i = -1;
    } else {
        i = 0;
    }
    SCL_LOW();

    return i;
}
static void TwAck(void)
{
    SDA_LOW();
    SCL_HIGH();
    TwDelay(2 * TWI_DELAY);
    SCL_LOW();
    SDA_HIGH();
}
Esempio n. 3
0
/*
 * Rising edge on the data line while the clock line is high indicates
 * a stop condition.
 *
 * Entry: SCL low, SDA any
 * Exit: SCL high, SDA high
 */
static void TwStop(void)
{
    SDA_LOW();
    TwDelay(TWI_DELAY);
    SCL_HIGH();
    TwDelay(2 * TWI_DELAY);
    SDA_HIGH();
    TwDelay(8 * TWI_DELAY);
}
Esempio n. 4
0
// SDA 0->1 while SCL=1
void i2c_stop(alt_u32 clk_base, alt_u32 data_base){
    // assume SCL = 0
    
    SDA_DIR_OUT(data_base);  // data output enabled
    SDA_LOW(data_base); // Data Low
    //SCL_DELAY; 
    SCL_HIGH(clk_base);  // clock high
    SCL_DELAY; // clock high long delay
    SDA_HIGH(data_base); // data high
    SCL_DELAY; // data high delay
}
Esempio n. 5
0
/*
 * Falling edge on the data line while the clock line is high indicates
 * a start condition.
 *
 * Entry: SCL any, SDA any
 * Exit: SCL low, SDA low
 */
static void TwStart(void)
{
    SDA_HIGH();
    TwDelay(TWI_DELAY);
    SCL_HIGH();
    TwDelay(TWI_DELAY);
    SDA_LOW();
    TwDelay(TWI_DELAY);
    SCL_LOW();
    TwDelay(TWI_DELAY);
}
Esempio n. 6
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;
}
Esempio n. 7
0
static bool twi_write_start(void) {
  SCL_HIGH();
  SDA_HIGH();
  if (SDA_READ() == 0) {
    return false;
  }
  twi_delay(twi_dcount);
  SDA_LOW();
  twi_delay(twi_dcount);
  return true;
}
Esempio n. 8
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;
}
Esempio n. 9
0
static bool ICACHE_FLASH_ATTR twi_write_start(void)
{
	SCL_HIGH();
	SDA_HIGH();
	if (SDA_READ() == 0) {
		serial_printf("twi write start sda read false\r\n");
		return false;
	}
	twi_delay(twi_dcount);
	SDA_LOW();
	twi_delay(twi_dcount);
	return true;
}
Esempio n. 10
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;
}
Esempio n. 11
0
void i2c_read(alt_u32 clk_base, alt_u32 data_base, alt_u8 *pData, bool bAck){ // return true if device response ack
    alt_u8 Data=0;
    int i;
    
    // assume SCL = low
    
    SDA_DIR_IN(data_base);  // set data read mode
    SCL_LOW(clk_base); // clock low
    SCL_DELAY; // clock low delay

    for(i=0;i<8;i++){
        Data <<= 1;
        SCL_HIGH(clk_base);  // clock high
        SCL_DELAY;
        if (SDA_READ(data_base))  // read data   
            Data |= 0x01;
        SCL_LOW(clk_base);  // clock log  
        SCL_DELAY;
    }
    
    // send ACK
    SCL_LOW(clk_base);  // new, make sure data change at clk low
    SDA_DIR_OUT(data_base);  // set data write mode
    if (bAck)
        SDA_LOW(data_base);
    else
        SDA_HIGH(data_base);
    SCL_HIGH(clk_base); // clock high
    SCL_DELAY; // clock high  delay
    SCL_LOW(clk_base); // clock low
    SCL_DELAY; // clock low delay
    SDA_LOW(data_base);  // data low
    SCL_DELAY; // data low delay
//    SDA_DIR_IN;  // set data read mode
    
    *pData = Data;
}
Esempio n. 12
0
//SDA 1->0 while SCL=1
void i2c_start(alt_u32 clk_base, alt_u32 data_base){
    
    // make sure it is in normal state
    SDA_DIR_OUT(data_base);  // data output enabled
    
    
    
    // start condition
    SDA_HIGH(data_base); // data high
    SCL_HIGH(clk_base);
    SCL_DELAY;
     
    SDA_LOW(data_base); // data low
    SCL_DELAY; 
    SCL_LOW(clk_base); // clock low
    SCL_DELAY;
}
Esempio n. 13
0
bool i2c_write(alt_u32 clk_base, alt_u32 data_base, alt_u8 Data){ // return true if device response ack
    alt_u8 Mask = 0x80;
    bool bAck;
    int i;
    
    // assume, SCL = 0
    
    SDA_DIR_OUT(data_base);  // data write mode
    
    for(i=0;i<8;i++){
        SCL_LOW(clk_base);  // new, make sure data change at clk low
        // output data on bus
        if (Data & Mask){ // there is a delay in this command
            SDA_HIGH(data_base);
        }else{    
            SDA_LOW(data_base);
        }
        Mask >>= 1; // there is a delay in this command
        // clock high
        SCL_HIGH(clk_base);
        SCL_DELAY;
        SCL_LOW(clk_base);
        SCL_DELAY;
    }
    
    //===== get ack
    SDA_DIR_IN(data_base);  // data read mode
    //SCL_DELAY;
    // clock high
    SCL_HIGH(clk_base);  // clock high
    SCL_DELAY;  // clock high delay
    bAck = SDA_READ(data_base)?FALSE:TRUE;  // get ack
    //SCL_DELAY;
    //SDA_DIR_OUT;
    SCL_LOW(clk_base); // clock low         
    SCL_DELAY; // clock low delay
    return bAck;
}    
Esempio n. 14
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;
	}
}
Esempio n. 15
0
void ICACHE_RAM_ATTR twi_onTwipEvent(uint8_t status)
{
  switch(status) {
    // Slave Receiver
    case TW_SR_SLA_ACK:   // addressed, returned ack
    case TW_SR_GCALL_ACK: // addressed generally, returned ack
    case TW_SR_ARB_LOST_SLA_ACK:   // lost arbitration, returned ack
    case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
      // enter slave receiver mode
      twi_state = TWI_SRX;
      // indicate that rx buffer can be overwritten and ack
      twi_rxBufferIndex = 0;
      twi_reply(1);
      break;
    case TW_SR_DATA_ACK:       // data received, returned ack
    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
      // if there is still room in the rx buffer
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        // put byte in buffer and ack
        twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
        twi_reply(1);
      }else{
        // otherwise nack
        twi_reply(0);
      }
      break;
    case TW_SR_STOP: // stop or repeated start condition received
      // put a null char after data if there's room
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        twi_rxBuffer[twi_rxBufferIndex] = '\0';
      }
      // callback to user-defined callback over event task to allow for non-RAM-residing code
	  //twi_rxBufferLock = true; // This may be necessary
	  ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_RX, twi_rxBufferIndex);

      // since we submit rx buffer to "wire" library, we can reset it
      twi_rxBufferIndex = 0;
      break;

    case TW_SR_DATA_NACK:       // data received, returned nack
    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
      // nack back at master
      twi_reply(0);
      break;

    // Slave Transmitter
    case TW_ST_SLA_ACK:          // addressed, returned ack
    case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
      // enter slave transmitter mode
      twi_state = TWI_STX;
      // ready the tx buffer index for iteration
      twi_txBufferIndex = 0;
      // set tx buffer length to be zero, to verify if user changes it
      twi_txBufferLength = 0;
      // callback to user-defined callback over event task to allow for non-RAM-residing code
      // request for txBuffer to be filled and length to be set
      // note: user must call twi_transmit(bytes, length) to do this
	  ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_TX, 0);
	  break;

	case TW_ST_DATA_ACK: // byte sent, ack returned
      // copy data to output register
      TWDR = twi_txBuffer[twi_txBufferIndex++];

	  bitCount = 8;
	  bitCount--;
	  (twi_data & 0x80) ? SDA_HIGH() : SDA_LOW();
	  twi_data <<= 1;

      // if there is more to send, ack, otherwise nack
      if(twi_txBufferIndex < twi_txBufferLength){
        twi_reply(1);
      }else{
        twi_reply(0);
      }
      break;
    case TW_ST_DATA_NACK: // received nack, we are done
    case TW_ST_LAST_DATA: // received ack, but we are done already!
      // leave slave receiver state
      twi_releaseBus();
      break;

    // All
    case TW_NO_INFO:   // no state information
      break;
    case TW_BUS_ERROR: // bus error, illegal stop/start
      twi_error = TW_BUS_ERROR;
      twi_stop();
      break;
  }
}