/** * Handle a request ISL as a slave */ void DWire::_handleRequestSlave( void ) { // Check whether a user interrupt has been set if ( !user_onRequest ) return; // If no message has been set, then call the user interrupt to set if (!(*pTxBufferIndex)) { user_onRequest( ); *pTxBufferSize = *pTxBufferIndex - 1; *pTxBufferIndex = 0; } // If we've transmitted the entire message, then reset the tx buffer if (*pTxBufferIndex > *pTxBufferSize) { *pTxBufferIndex = 0; *pTxBufferSize = 0; } else { // Transmit a byte MAP_I2C_slavePutData( module, pTxBuffer[*pTxBufferIndex] ); (*pTxBufferIndex)++; } }
// behind the scenes function that is called when data is requested void TwoWire::onRequestService(void) { // don't bother if user hasn't registered a callback if(!user_onRequest){ return; } // alert user program user_onRequest(); }
// behind the scenes function that is called when data is requested void WireClass::onRequestService(void){ // don't bother if user hasn't registered a callback if(!user_onRequest){ return; } // reset tx buffer iterator vars // !!! this will kill any pending pre-master sendTo() activity txBufferIndex = 0; txBufferLength = 0; // alert user program user_onRequest(); }
void TwoWire::I2CIntHandler(void) { //clear data interrupt HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_DATAIC; uint8_t startDetected = 0; uint8_t stopDetected = 0; if(HWREG(SLAVE_BASE + I2C_O_SRIS) & I2C_SLAVE_INT_START) { startDetected = 1; //clear raw start interrupt HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_STARTIC; } else if(HWREG(SLAVE_BASE + I2C_O_SRIS) & I2C_SLAVE_INT_STOP) { stopDetected = 1; HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_STOPIC; } switch(I2CSlaveStatus(SLAVE_BASE) & (I2C_SCSR_TREQ | I2C_SCSR_RREQ)) { case(I2C_SLAVE_ACT_RREQ)://data received if(I2CSlaveStatus(SLAVE_BASE) & I2C_SCSR_FBR) currentState = SLAVE_RX; if(!RX_BUFFER_FULL) { rxBuffer[rxWriteIndex] = I2CSlaveDataGet(SLAVE_BASE); rxWriteIndex = (rxWriteIndex + 1) % BUFFER_LENGTH; } break; case(I2C_SLAVE_ACT_TREQ)://data requested if(startDetected) { uint8_t oldWriteIndex = txWriteIndex; user_onRequest(); // // send data if onRequest() wrote data that has // yet to be sent // if(oldWriteIndex != txWriteIndex) { I2CSlaveDataPut(SLAVE_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } } else if(!TX_BUFFER_EMPTY) { I2CSlaveDataPut(SLAVE_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } else I2CSlaveDataPut(SLAVE_BASE, 0); break; default: break; } if(stopDetected && currentState == SLAVE_RX) { int avail = available(); user_onReceive(avail); currentState = IDLE; } }
void TwoWire::isr(void) { uint8_t status, c1, data; static uint8_t receiving=0; status = port().S; //serial_print("."); if (status & I2C_S_ARBL) { // Arbitration Lost port().S = I2C_S_ARBL; //serial_print("a"); if (receiving && rxBufferLength > 0) { // TODO: does this detect the STOP condition in slave receive mode? } if (!(status & I2C_S_IAAS)) return; } if (status & I2C_S_IAAS) { //serial_print("\n"); // Addressed As A Slave if (status & I2C_S_SRW) { //serial_print("T"); // Begin Slave Transmit receiving = 0; txBufferLength = 0; if (user_onRequest != NULL) { user_onRequest(); } if (txBufferLength == 0) { // is this correct, transmitting a single zero // when we should send nothing? Arduino's AVR // implementation does this, but is it ok? txBufferLength = 1; txBuffer[0] = 0; } port().C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; port().D = txBuffer[0]; txBufferIndex = 1; } else { // Begin Slave Receive //serial_print("R"); receiving = 1; rxBufferLength = 0; port().C1 = I2C_C1_IICEN | I2C_C1_IICIE; data = port().D; } port().S = I2C_S_IICIF; return; } #if defined(WIRE_HAS_STOP_INTERRUPT) c1 = port().FLT; if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) { port().FLT = c1 & ~I2C_FLT_STOPIE; if (user_onReceive != NULL) { rxBufferIndex = 0; user_onReceive(rxBufferLength); } } #endif c1 = port().C1; if (c1 & I2C_C1_TX) { // Continue Slave Transmit //serial_print("t"); if ((status & I2C_S_RXAK) == 0) { //serial_print("."); // Master ACK'd previous byte if (txBufferIndex < txBufferLength) { port().D = txBuffer[txBufferIndex++]; } else { port().D = 0; } port().C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; } else { //serial_print("*"); // Master did not ACK previous byte port().C1 = I2C_C1_IICEN | I2C_C1_IICIE; data = port().D; } } else { // Continue Slave Receive irqcount = 0; #ifdef WIRE_HAS_STOP_INTERRUPT port().FLT |= I2C_FLT_STOPIE; #else #if defined(WIRE_IMPLEMENT_WIRE) && !defined(WIRE_IMPLEMENT_WIRE1) attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING); #elif !defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1) attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING); #elif defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1) if (this == &Wire) { attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING); } else if (this == &Wire1) { attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING); } #endif #endif // WIRE_HAS_STOP_INTERRUPT //digitalWriteFast(4, HIGH); data = port().D; //serial_phex(data); if (rxBufferLength < BUFFER_LENGTH && receiving) { rxBuffer[rxBufferLength++] = data; } //digitalWriteFast(4, LOW); } port().S = I2C_S_IICIF; }