|
|
@@ -314,17 +314,22 @@ void TwoWire::end() |
|
|
|
} |
|
|
|
|
|
|
|
void i2c0_isr(void) |
|
|
|
{ |
|
|
|
Wire.isr(); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::isr(void) |
|
|
|
{ |
|
|
|
uint8_t status, c1, data; |
|
|
|
static uint8_t receiving=0; |
|
|
|
|
|
|
|
status = Wire.port.S; |
|
|
|
status = port.S; |
|
|
|
//serial_print("."); |
|
|
|
if (status & I2C_S_ARBL) { |
|
|
|
// Arbitration Lost |
|
|
|
Wire.port.S = I2C_S_ARBL; |
|
|
|
port.S = I2C_S_ARBL; |
|
|
|
//serial_print("a"); |
|
|
|
if (receiving && Wire.rxBufferLength > 0) { |
|
|
|
if (receiving && rxBufferLength > 0) { |
|
|
|
// TODO: does this detect the STOP condition in slave receive mode? |
|
|
|
|
|
|
|
|
|
|
@@ -338,77 +343,77 @@ void i2c0_isr(void) |
|
|
|
//serial_print("T"); |
|
|
|
// Begin Slave Transmit |
|
|
|
receiving = 0; |
|
|
|
Wire.txBufferLength = 0; |
|
|
|
if (Wire.user_onRequest != NULL) { |
|
|
|
Wire.user_onRequest(); |
|
|
|
txBufferLength = 0; |
|
|
|
if (user_onRequest != NULL) { |
|
|
|
user_onRequest(); |
|
|
|
} |
|
|
|
if (Wire.txBufferLength == 0) { |
|
|
|
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? |
|
|
|
Wire.txBufferLength = 1; |
|
|
|
Wire.txBuffer[0] = 0; |
|
|
|
txBufferLength = 1; |
|
|
|
txBuffer[0] = 0; |
|
|
|
} |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
Wire.port.D = Wire.txBuffer[0]; |
|
|
|
Wire.txBufferIndex = 1; |
|
|
|
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; |
|
|
|
Wire.rxBufferLength = 0; |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = Wire.port.D; |
|
|
|
rxBufferLength = 0; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = port.D; |
|
|
|
} |
|
|
|
Wire.port.S = I2C_S_IICIF; |
|
|
|
port.S = I2C_S_IICIF; |
|
|
|
return; |
|
|
|
} |
|
|
|
#if defined(KINETISL) |
|
|
|
c1 = Wire.port.FLT; |
|
|
|
c1 = port.FLT; |
|
|
|
if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) { |
|
|
|
Wire.port.FLT = c1 & ~I2C_FLT_STOPIE; |
|
|
|
if (Wire.user_onReceive != NULL) { |
|
|
|
Wire.rxBufferIndex = 0; |
|
|
|
Wire.user_onReceive(Wire.rxBufferLength); |
|
|
|
port.FLT = c1 & ~I2C_FLT_STOPIE; |
|
|
|
if (user_onReceive != NULL) { |
|
|
|
rxBufferIndex = 0; |
|
|
|
user_onReceive(rxBufferLength); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
c1 = Wire.port.C1; |
|
|
|
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 (Wire.txBufferIndex < Wire.txBufferLength) { |
|
|
|
Wire.port.D = Wire.txBuffer[Wire.txBufferIndex++]; |
|
|
|
if (txBufferIndex < txBufferLength) { |
|
|
|
port.D = txBuffer[txBufferIndex++]; |
|
|
|
} else { |
|
|
|
Wire.port.D = 0; |
|
|
|
port.D = 0; |
|
|
|
} |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
} else { |
|
|
|
//serial_print("*"); |
|
|
|
// Master did not ACK previous byte |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = Wire.port.D; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = port.D; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// Continue Slave Receive |
|
|
|
Wire.irqcount = 0; |
|
|
|
irqcount = 0; |
|
|
|
#if defined(KINETISK) |
|
|
|
attachInterrupt(18, sda_rising_isr, RISING); |
|
|
|
attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr, RISING); |
|
|
|
#elif defined(KINETISL) |
|
|
|
Wire.port.FLT |= I2C_FLT_STOPIE; |
|
|
|
port.FLT |= I2C_FLT_STOPIE; |
|
|
|
#endif |
|
|
|
//digitalWriteFast(4, HIGH); |
|
|
|
data = Wire.port.D; |
|
|
|
data = port.D; |
|
|
|
//serial_phex(data); |
|
|
|
if (Wire.rxBufferLength < BUFFER_LENGTH && receiving) { |
|
|
|
Wire.rxBuffer[Wire.rxBufferLength++] = data; |
|
|
|
if (rxBufferLength < BUFFER_LENGTH && receiving) { |
|
|
|
rxBuffer[rxBufferLength++] = data; |
|
|
|
} |
|
|
|
//digitalWriteFast(4, LOW); |
|
|
|
} |
|
|
|
Wire.port.S = I2C_S_IICIF; |
|
|
|
port.S = I2C_S_IICIF; |
|
|
|
} |
|
|
|
|
|
|
|
// Detects the stop condition that terminates a slave receive transfer. |
|
|
@@ -418,7 +423,7 @@ void sda_rising_isr(void) |
|
|
|
{ |
|
|
|
//digitalWrite(3, HIGH); |
|
|
|
if (!(Wire.port.S & I2C_S_BUSY)) { |
|
|
|
detachInterrupt(18); |
|
|
|
detachInterrupt(Wire.hardware.sda_pin[Wire.sda_pin_index]); |
|
|
|
if (Wire.user_onReceive != NULL) { |
|
|
|
Wire.rxBufferIndex = 0; |
|
|
|
Wire.user_onReceive(Wire.rxBufferLength); |
|
|
@@ -426,7 +431,7 @@ void sda_rising_isr(void) |
|
|
|
//delayMicroseconds(100); |
|
|
|
} else { |
|
|
|
if (++Wire.irqcount >= 2 || !Wire.slave_mode) { |
|
|
|
detachInterrupt(18); |
|
|
|
detachInterrupt(Wire.hardware.sda_pin[Wire.sda_pin_index]); |
|
|
|
} |
|
|
|
} |
|
|
|
//digitalWrite(3, LOW); |
|
|
@@ -618,6 +623,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop) |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef WIRE_IMPLEMENT_WIRE |
|
|
|
|
|
|
|
const TwoWire::I2C_Hardware_t TwoWire::i2c0_hardware = { |
|
|
|
SIM_SCGC4, SIM_SCGC4_I2C0, |
|
|
@@ -634,6 +640,13 @@ const TwoWire::I2C_Hardware_t TwoWire::i2c0_hardware = { |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
TwoWire Wire(KINETIS_I2C0, TwoWire::i2c0_hardware); |
|
|
|
|
|
|
|
#endif // WIRE_IMPLEMENT_WIRE |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIRE_IMPLEMENT_WIRE1 |
|
|
|
|
|
|
|
const TwoWire::I2C_Hardware_t TwoWire::i2c1_hardware = { |
|
|
|
SIM_SCGC4, SIM_SCGC4_I2C1, |
|
|
|
#if defined(__MKL26Z64__) |
|
|
@@ -651,14 +664,16 @@ const TwoWire::I2C_Hardware_t TwoWire::i2c1_hardware = { |
|
|
|
2, 0, 0, 0, 0, |
|
|
|
37, 255, 255, 255, 255, |
|
|
|
2, 0, 0, 0, 0, |
|
|
|
#else |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
TwoWire Wire1(KINETIS_I2C1, TwoWire::i2c1_hardware); |
|
|
|
|
|
|
|
#endif // WIRE_IMPLEMENT_WIRE1 |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIRE_IMPLEMENT_WIRE2 |
|
|
|
|
|
|
|
const TwoWire::I2C_Hardware_t TwoWire::i2c2_hardware = { |
|
|
|
SIM_SCGC1, SIM_SCGC1_I2C2, |
|
|
|
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) |
|
|
@@ -666,14 +681,14 @@ const TwoWire::I2C_Hardware_t TwoWire::i2c2_hardware = { |
|
|
|
5, 0, 0, 0, 0, |
|
|
|
3, 26, 255, 255, 255, |
|
|
|
5, 5, 0, 0, 0, |
|
|
|
#else |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
#endif // WIRE_IMPLEMENT_WIRE2 |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIRE_IMPLEMENT_WIRE3 |
|
|
|
|
|
|
|
const TwoWire::I2C_Hardware_t TwoWire::i2c3_hardware = { |
|
|
|
SIM_SCGC1, SIM_SCGC1_I2C3, |
|
|
|
#if defined(__MK66FX1M0__) |
|
|
@@ -681,18 +696,10 @@ const TwoWire::I2C_Hardware_t TwoWire::i2c3_hardware = { |
|
|
|
2, 0, 0, 0, 0, |
|
|
|
57, 255, 255, 255, 255, |
|
|
|
2, 0, 0, 0, 0, |
|
|
|
#else |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
255, 255, 255, 255, 255, |
|
|
|
0, 0, 0, 0, 0, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
TwoWire Wire(KINETIS_I2C0, TwoWire::i2c0_hardware); |
|
|
|
TwoWire Wire1(KINETIS_I2C1, TwoWire::i2c1_hardware); |
|
|
|
|
|
|
|
#endif // WIRE_IMPLEMENT_WIRE3 |
|
|
|
|
|
|
|
|
|
|
|
#endif // __arm__ && TEENSYDUINO |