void TwoWire::onService(void) { if ( sercom->isSlaveWIRE() ) { if(sercom->isStopDetectedWIRE() || (sercom->isAddressMatch() && sercom->isRestartDetectedWIRE() && !sercom->isMasterReadOperationWIRE())) //Stop or Restart detected { sercom->prepareAckBitWIRE(); sercom->prepareCommandBitsWire(0x03); //Calling onReceiveCallback, if exists if(onReceiveCallback) { onReceiveCallback(available()); } rxBuffer.clear(); } else if(sercom->isAddressMatch()) //Address Match { sercom->prepareAckBitWIRE(); sercom->prepareCommandBitsWire(0x03); if(sercom->isMasterReadOperationWIRE()) //Is a request ? { // wait for data ready flag, // before calling request callback while(!sercom->isDataReadyWIRE()); //Calling onRequestCallback, if exists if(onRequestCallback) { onRequestCallback(); } } } else if(sercom->isDataReadyWIRE()) //Received data { if (rxBuffer.isFull()) { sercom->prepareNackBitWIRE(); } else { //Store data rxBuffer.store_char(sercom->readDataWIRE()); sercom->prepareAckBitWIRE(); } sercom->prepareCommandBitsWire(0x03); } } }
void TwoWire::onService(void) { if (I2C_GetITStatus(twi, I2C_IT_ADDR) == SET) { I2C_ITConfig(twi, I2C_IT_RXI | I2C_IT_TXI | I2C_IT_STOPI, ENABLE); srvBufferLength = 0; srvBufferIndex = 0; if (twi->ISR & (1 << 16)) { status = SLAVE_SEND; if (onRequestCallback) onRequestCallback(); } else { status = SLAVE_RECV; } I2C_ClearITPendingBit(twi, I2C_IT_ADDR); } if (I2C_GetITStatus(twi, I2C_IT_TXIS) == SET) { uint8_t c = 'x'; if (srvBufferIndex < srvBufferLength) c = srvBuffer[srvBufferIndex++]; I2C_SendData(twi, c); } if (I2C_GetITStatus(twi, I2C_IT_RXNE) == SET) { if (srvBufferLength < BUFFER_LENGTH) srvBuffer[srvBufferLength++] = I2C_ReceiveData(twi); } if (I2C_GetITStatus(twi, I2C_IT_STOPF) == SET) { if (status == SLAVE_RECV && onReceiveCallback) { // Copy data into rxBuffer // (allows to receive another packet while the // user program reads actual data) for (uint8_t i = 0; i < srvBufferLength; ++i) rxBuffer[i] = srvBuffer[i]; rxBufferIndex = 0; rxBufferLength = srvBufferLength; // Alert calling program onReceiveCallback( rxBufferLength); } I2C_ITConfig(twi, I2C_IT_ADDRI, ENABLE); I2C_ITConfig(twi, I2C_IT_RXI | I2C_IT_TXI | I2C_IT_STOPI, DISABLE); I2C_ClearITPendingBit(twi, I2C_IT_STOPF); } }
void TwoWire::onService(void) { if ( sercom->isSlaveWIRE() ) { //Received data if(sercom->isDataReadyWIRE()) { //Store data rxBuffer.store_char(sercom->readDataWIRE()); //Stop or Restart detected if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE()) { //Calling onReceiveCallback, if exists if(onReceiveCallback) { onReceiveCallback(available()); } } } //Address Match if(sercom->isAddressMatch()) { //Is a request ? if(sercom->isMasterReadOperationWIRE()) { //Calling onRequestCallback, if exists if(onRequestCallback) { onRequestCallback(); } } } } }
void TwoWire::onService(void) { // Retrieve interrupt status uint32_t sr = TWI_GetStatus(twi); if (status == SLAVE_IDLE && TWI_STATUS_SVACC(sr)) { TWI_DisableIt(twi, TWI_IDR_SVACC); TWI_EnableIt(twi, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS | TWI_IER_TXCOMP); srvBufferLength = 0; srvBufferIndex = 0; // Detect if we should go into RECV or SEND status // SVREAD==1 means *master* reading -> SLAVE_SEND if (!TWI_STATUS_SVREAD(sr)) { status = SLAVE_RECV; } else { status = SLAVE_SEND; // Alert calling program to generate a response ASAP if (onRequestCallback) onRequestCallback(); else // create a default 1-byte response write((uint8_t) 0); } } if (status != SLAVE_IDLE) { if (TWI_STATUS_TXCOMP(sr) && TWI_STATUS_EOSACC(sr)) { if (status == SLAVE_RECV && onReceiveCallback) { // Copy data into rxBuffer // (allows to receive another packet while the // user program reads actual data) for (uint8_t i = 0; i < srvBufferLength; ++i) rxBuffer[i] = srvBuffer[i]; rxBufferIndex = 0; rxBufferLength = srvBufferLength; // Alert calling program onReceiveCallback( rxBufferLength); } // Transfer completed TWI_EnableIt(twi, TWI_SR_SVACC); TWI_DisableIt(twi, TWI_IDR_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK | TWI_IDR_EOSACC | TWI_IDR_SCL_WS | TWI_IER_TXCOMP); status = SLAVE_IDLE; } } if (status == SLAVE_RECV) { if (TWI_STATUS_RXRDY(sr)) { if (srvBufferLength < BUFFER_LENGTH) srvBuffer[srvBufferLength++] = TWI_ReadByte(twi); } } if (status == SLAVE_SEND) { if (TWI_STATUS_TXRDY(sr) && !TWI_STATUS_NACK(sr)) { uint8_t c = 'x'; if (srvBufferIndex < srvBufferLength) c = srvBuffer[srvBufferIndex++]; TWI_WriteByte(twi, c); } } }
void TwoWire::onService(void) { //interrupt handler uint8_t i2cData = 0x00; bool wasArbLost = I2C_HAL_GetStatusFlag(instance, kI2CArbitrationLost); bool addressed = I2C_HAL_GetStatusFlag(instance, kI2CAddressAsSlave); bool stopIntEnabled = false; bool startDetected = I2C_HAL_GetStartFlag(instance); bool startIntEnabled = I2C_HAL_GetStartStopIntCmd(instance); bool stopDetected = I2C_HAL_GetStopFlag(instance); stopIntEnabled = startIntEnabled; /* Get current slave transfer direction */ i2c_direction_t direction = I2C_HAL_GetDirMode(instance); /*--------------- Handle START, STOP or REPEAT START ------------------*/ if (stopIntEnabled && (startDetected || stopDetected)) { if(startDetected) I2C_HAL_ClearStartFlag(instance); if(stopDetected) I2C_HAL_ClearStopFlag(instance); I2C_HAL_ClearInt(instance); if(slaveBufferLength) { if(onReceiveCallback) { receiving_slave = true; onReceiveCallback(slaveBufferLength); receiving_slave = false; } slaveBufferIndex = 0; slaveBufferLength = 0; } return; } /* Clear I2C IRQ.*/ I2C_HAL_ClearInt(instance); if (wasArbLost) { I2C_HAL_ClearArbitrationLost(instance); if (!addressed) { master_state = MASTER_STATE_ARB_LOST; return; } } if(I2C_HAL_IsMaster(instance)) { if (direction == kI2CSend) { //check for NAK /* Check whether we got an ACK or NAK from the former byte we sent */ if (I2C_HAL_GetStatusFlag(instance, kI2CReceivedNak)) { master_state = MASTER_STATE_TX_NAK; } else if(transmitting_master) { /* Continue send if still have data. TxSize/txBuff index need * increment first because one byte is already sent in order * to trigger interrupt */ if (txBufferIndex < txBufferLength) { /* Transmit next byte and update buffer index */ I2C_HAL_WriteByte(instance, txBuffer[txBufferIndex++]); } else { /* Finish send data, send STOP, disable interrupt */ master_state = MASTER_STATE_COMPLETE; } } else { master_state = MASTER_STATE_READ_READY; //address sent for a read } } else { switch (--rxBufferQuantity) { case 0x0U: /* Finish receive data, send STOP, disable interrupt */ master_state = MASTER_STATE_COMPLETE; if(master_send_stop) I2C_HAL_SendStop(instance); else I2C_HAL_SendStart(instance); break; case 0x1U: /* For the byte before last, we need to set NAK */ I2C_HAL_SendNak(instance); break; default : I2C_HAL_SendAck(instance); break; } rxBuffer[rxBufferLength++] = I2C_HAL_ReadByte(instance); } return; } /*--------------- Handle Address ------------------*/ /* Addressed only happens when receiving address. */ if (addressed) /* Slave is addressed. */ { /* Master read from Slave. Slave transmit.*/ if (I2C_HAL_GetStatusFlag(instance, kI2CSlaveTransmit)) { /* Switch to TX mode*/ I2C_HAL_SetDirMode(instance, kI2CSend); transmitting_slave = true; slaveBufferIndex = 0; slaveBufferLength = 0; if (onRequestCallback) onRequestCallback(); //this needs to load the transmit buffer else // create a default 1-byte response write((uint8_t) 0); } else /* Master write to Slave. Slave receive.*/ { /* Switch to RX mode.*/ I2C_HAL_SetDirMode(instance, kI2CReceive); I2C_HAL_SendAck(instance); /* Read dummy character.*/ I2C_HAL_ReadByte(instance); slaveBufferIndex = 0; slaveBufferLength = 0; } } /*--------------- Handle Transfer ------------------*/ else { /* Handle transmit */ if (direction == kI2CSend) { if (I2C_HAL_GetStatusFlag(instance, kI2CReceivedNak)) { /* Switch to RX mode.*/ I2C_HAL_SetDirMode(instance, kI2CReceive); /* Read dummy character to release bus */ I2C_HAL_ReadByte(instance); transmitting_slave = false; slaveBufferIndex = 0; slaveBufferLength = 0; } else /* ACK from receiver.*/ { transmitting_slave = true; } } /* Handle receive */ else { /* Get byte from data register */ I2C_HAL_SendAck(instance); i2cData = I2C_HAL_ReadByte(instance); if(slaveBufferLength < BUFFER_LENGTH) slaveBuffer[slaveBufferLength++] = i2cData; } } if (transmitting_slave) { /* Send byte to data register */ if (slaveBufferIndex < slaveBufferLength) { I2C_HAL_WriteByte(instance, slaveBuffer[slaveBufferIndex++]); if (slaveBufferIndex >= slaveBufferLength) { slaveBufferIndex = 0; slaveBufferLength = 0; transmitting_slave = false; } } else transmitting_slave = false; } }
void TwoWire::I2C_SlaveTRx(uint32_t u32Status) { if(u32Status == 0x60) /* Own SLA+W has been receive; ACK has been return */ { status = SLAVE_RECV; srvBufferLength = 0; I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } else if(u32Status == 0x80 || u32Status==0x10) /* Previously address with own SLA address Data has been received; ACK has been returned*/ { srvBuffer[srvBufferLength] = (unsigned char) I2C_GET_DATA(i2c); srvBufferLength++; I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } else if(u32Status == 0xA8) /* Own SLA+R has been receive; ACK has been return */ { // Alert calling program to generate a response ASAP if (onRequestCallback && status != SLAVE_SEND) { srvBufferLength = 0; srvBufferIndex = 0; onRequestCallback(); } status = SLAVE_SEND; if (srvBufferIndex < srvBufferLength) { //Serial.print("==============>"); //Serial.println((char)srvBuffer[srvBufferIndex]); I2C_SET_DATA(i2c, srvBuffer[srvBufferIndex++]); I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } if (srvBufferIndex == srvBufferLength) status = SLAVE_IDLE; }else if(u32Status == 0xB8) { if (srvBufferIndex < srvBufferLength){ //Serial.print("==============>"); //Serial.println((char)srvBuffer[srvBufferIndex]); I2C_SET_DATA(i2c, srvBuffer[srvBufferIndex++]); I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } if (srvBufferIndex == srvBufferLength) status = SLAVE_IDLE; } else if(u32Status == 0xC0) /* Data byte or last data in I2CDAT has been transmitted Not ACK has been received */ { I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } else if(u32Status == 0x88) /* Previously addressed with own SLA address; NOT ACK has been returned */ { srvBufferLength = 0; I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); } else if(u32Status == 0xA0) /* A STOP or repeated START has been received while still addressed as Slave/Receiver*/ { srvBufferIndex = 0; I2C_SET_CONTROL_REG(i2c, I2C_SI_AA); if (status != SLAVE_IDLE) { for (uint8_t i = 0; i < srvBufferLength; ++i) rxBuffer[i] = srvBuffer[i]; rxBufferIndex = 0; rxBufferLength = srvBufferLength; onReceiveCallback( rxBufferLength); // Alert calling program status = SLAVE_IDLE; } } }
void TwoWire::onService(void) { if ( sercom->isSlaveWIRE() ) { if(sercom->isStopDetectedWIRE() || (sercom->isAddressMatch() && sercom->isRestartDetectedWIRE() && !sercom->isMasterReadOperationWIRE())) //Stop or Restart detected { sercom->prepareAckBitWIRE(); sercom->prepareCommandBitsWire(0x03); //Calling onReceiveCallback, if exists if(onReceiveCallback) { onReceiveCallback(available()); } rxBuffer.clear(); } else if(sercom->isAddressMatch()) //Address Match { sercom->prepareAckBitWIRE(); sercom->prepareCommandBitsWire(0x03); if(sercom->isMasterReadOperationWIRE()) //Is a request ? { txBuffer.clear(); transmissionBegun = true; //Calling onRequestCallback, if exists if(onRequestCallback) { onRequestCallback(); } } } else if(sercom->isDataReadyWIRE()) { if (sercom->isMasterReadOperationWIRE()) { uint8_t c = 0xff; if( txBuffer.available() ) { c = txBuffer.read_char(); } transmissionBegun = sercom->sendDataSlaveWIRE(c); } else { //Received data if (rxBuffer.isFull()) { sercom->prepareNackBitWIRE(); } else { //Store data rxBuffer.store_char(sercom->readDataWIRE()); sercom->prepareAckBitWIRE(); } sercom->prepareCommandBitsWire(0x03); } } } }