|
|
@@ -28,9 +28,23 @@ |
|
|
|
#include "core_pins.h" |
|
|
|
#include "Wire.h" |
|
|
|
|
|
|
|
// undefine these, so we can't accidentally access the hardware directly. |
|
|
|
#undef I2C0_A1 |
|
|
|
#undef I2C0_F |
|
|
|
#undef I2C0_C1 |
|
|
|
#undef I2C0_S |
|
|
|
#undef I2C0_D |
|
|
|
#undef I2C0_C2 |
|
|
|
#undef I2C0_FLT |
|
|
|
#undef I2C0_RA |
|
|
|
#undef I2C0_SMB |
|
|
|
#undef I2C0_A2 |
|
|
|
#undef I2C0_SLTH |
|
|
|
#undef I2C0_SLTL |
|
|
|
|
|
|
|
void sda_rising_isr(void); |
|
|
|
|
|
|
|
TwoWire::TwoWire() |
|
|
|
TwoWire::TwoWire(KINETIS_I2C_t &myport) : port(myport) |
|
|
|
{ |
|
|
|
rxBufferIndex = 0; |
|
|
|
rxBufferLength = 0; |
|
|
@@ -50,7 +64,7 @@ void TwoWire::begin(void) |
|
|
|
|
|
|
|
slave_mode = 0; |
|
|
|
SIM_SCGC4 |= SIM_SCGC4_I2C0; // TODO: use bitband |
|
|
|
I2C0_C1 = 0; |
|
|
|
port.C1 = 0; |
|
|
|
// On Teensy 3.0 external pullup resistors *MUST* be used |
|
|
|
// the PORT_PCR_PE bit is ignored when in I2C mode |
|
|
|
// I2C will not work at all without pullup resistors |
|
|
@@ -85,8 +99,8 @@ void TwoWire::begin(void) |
|
|
|
#endif |
|
|
|
} |
|
|
|
setClock(100000); |
|
|
|
I2C0_C2 = I2C_C2_HDRS; |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
port.C2 = I2C_C2_HDRS; |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
//pinMode(3, OUTPUT); |
|
|
|
//pinMode(4, OUTPUT); |
|
|
|
} |
|
|
@@ -97,156 +111,156 @@ void TwoWire::setClock(uint32_t frequency) |
|
|
|
|
|
|
|
#if F_BUS == 120000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV1152; // 104 kHz |
|
|
|
port.F = I2C_F_DIV1152; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV288; // 416 kHz |
|
|
|
port.F = I2C_F_DIV288; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV128; // 0.94 MHz |
|
|
|
port.F = I2C_F_DIV128; // 0.94 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 108000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV1024; // 105 kHz |
|
|
|
port.F = I2C_F_DIV1024; // 105 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV256; // 422 kHz |
|
|
|
port.F = I2C_F_DIV256; // 422 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV112; // 0.96 MHz |
|
|
|
port.F = I2C_F_DIV112; // 0.96 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 96000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV960; // 100 kHz |
|
|
|
port.F = I2C_F_DIV960; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV240; // 400 kHz |
|
|
|
port.F = I2C_F_DIV240; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV96; // 1.0 MHz |
|
|
|
port.F = I2C_F_DIV96; // 1.0 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 90000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV896; // 100 kHz |
|
|
|
port.F = I2C_F_DIV896; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV224; // 402 kHz |
|
|
|
port.F = I2C_F_DIV224; // 402 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV88; // 1.02 MHz |
|
|
|
port.F = I2C_F_DIV88; // 1.02 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 80000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV768; // 104 kHz |
|
|
|
port.F = I2C_F_DIV768; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV192; // 416 kHz |
|
|
|
port.F = I2C_F_DIV192; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV80; // 1.0 MHz |
|
|
|
port.F = I2C_F_DIV80; // 1.0 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 72000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV640; // 112 kHz |
|
|
|
port.F = I2C_F_DIV640; // 112 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV192; // 375 kHz |
|
|
|
port.F = I2C_F_DIV192; // 375 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV72; // 1.0 MHz |
|
|
|
port.F = I2C_F_DIV72; // 1.0 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 64000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV640; // 100 kHz |
|
|
|
port.F = I2C_F_DIV640; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV160; // 400 kHz |
|
|
|
port.F = I2C_F_DIV160; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV64; // 1.0 MHz |
|
|
|
port.F = I2C_F_DIV64; // 1.0 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 60000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x2C; // 104 kHz |
|
|
|
port.F = 0x2C; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1C; // 416 kHz |
|
|
|
port.F = 0x1C; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x12; // 938 kHz |
|
|
|
port.F = 0x12; // 938 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 56000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x2B; // 109 kHz |
|
|
|
port.F = 0x2B; // 109 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1C; // 389 kHz |
|
|
|
port.F = 0x1C; // 389 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0E; // 1 MHz |
|
|
|
port.F = 0x0E; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 54000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = I2C_F_DIV512; // 105 kHz |
|
|
|
port.F = I2C_F_DIV512; // 105 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = I2C_F_DIV128; // 422 kHz |
|
|
|
port.F = I2C_F_DIV128; // 422 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = I2C_F_DIV56; // 0.96 MHz |
|
|
|
port.F = I2C_F_DIV56; // 0.96 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 48000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x27; // 100 kHz |
|
|
|
port.F = 0x27; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1A; // 400 kHz |
|
|
|
port.F = 0x1A; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0D; // 1 MHz |
|
|
|
port.F = 0x0D; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
port.FLT = 4; |
|
|
|
#elif F_BUS == 40000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x29; // 104 kHz |
|
|
|
port.F = 0x29; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x19; // 416 kHz |
|
|
|
port.F = 0x19; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0B; // 1 MHz |
|
|
|
port.F = 0x0B; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 3; |
|
|
|
port.FLT = 3; |
|
|
|
#elif F_BUS == 36000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x28; // 113 kHz |
|
|
|
port.F = 0x28; // 113 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x19; // 375 kHz |
|
|
|
port.F = 0x19; // 375 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0A; // 1 MHz |
|
|
|
port.F = 0x0A; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 3; |
|
|
|
port.FLT = 3; |
|
|
|
#elif F_BUS == 24000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x1F; // 100 kHz |
|
|
|
port.F = 0x1F; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x12; // 375 kHz |
|
|
|
port.F = 0x12; // 375 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x02; // 1 MHz |
|
|
|
port.F = 0x02; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 2; |
|
|
|
port.FLT = 2; |
|
|
|
#elif F_BUS == 16000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x20; // 100 kHz |
|
|
|
port.F = 0x20; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x07; // 400 kHz |
|
|
|
port.F = 0x07; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 800 MHz |
|
|
|
port.F = 0x00; // 800 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
port.FLT = 1; |
|
|
|
#elif F_BUS == 8000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x14; // 100 kHz |
|
|
|
port.F = 0x14; // 100 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 400 kHz |
|
|
|
port.F = 0x00; // 400 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
port.FLT = 1; |
|
|
|
#elif F_BUS == 4000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x07; // 100 kHz |
|
|
|
port.F = 0x07; // 100 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 200 kHz |
|
|
|
port.F = 0x00; // 200 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
port.FLT = 1; |
|
|
|
#elif F_BUS == 2000000 |
|
|
|
I2C0_F = 0x00; // 100 kHz |
|
|
|
I2C0_FLT = 1; |
|
|
|
port.F = 0x00; // 100 kHz |
|
|
|
port.FLT = 1; |
|
|
|
#else |
|
|
|
#error "F_BUS must be 120, 108, 96, 90, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 16, 8, 4 or 2 MHz" |
|
|
|
#endif |
|
|
@@ -325,9 +339,9 @@ void TwoWire::setSCL(uint8_t pin) |
|
|
|
void TwoWire::begin(uint8_t address) |
|
|
|
{ |
|
|
|
begin(); |
|
|
|
I2C0_A1 = address << 1; |
|
|
|
port.A1 = address << 1; |
|
|
|
slave_mode = 1; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
NVIC_ENABLE_IRQ(IRQ_I2C0); |
|
|
|
} |
|
|
|
|
|
|
@@ -335,7 +349,7 @@ void TwoWire::end() |
|
|
|
{ |
|
|
|
if (!(SIM_SCGC4 & SIM_SCGC4_I2C0)) return; |
|
|
|
NVIC_DISABLE_IRQ(IRQ_I2C0); |
|
|
|
I2C0_C1 = 0; |
|
|
|
port.C1 = 0; |
|
|
|
if (sda_pin_num == 18) { |
|
|
|
CORE_PIN18_CONFIG = 0; |
|
|
|
} else if (sda_pin_num == 17) { |
|
|
@@ -370,11 +384,11 @@ void i2c0_isr(void) |
|
|
|
uint8_t status, c1, data; |
|
|
|
static uint8_t receiving=0; |
|
|
|
|
|
|
|
status = I2C0_S; |
|
|
|
status = Wire.port.S; |
|
|
|
//serial_print("."); |
|
|
|
if (status & I2C_S_ARBL) { |
|
|
|
// Arbitration Lost |
|
|
|
I2C0_S = I2C_S_ARBL; |
|
|
|
Wire.port.S = I2C_S_ARBL; |
|
|
|
//serial_print("a"); |
|
|
|
if (receiving && Wire.rxBufferLength > 0) { |
|
|
|
// TODO: does this detect the STOP condition in slave receive mode? |
|
|
@@ -401,31 +415,31 @@ void i2c0_isr(void) |
|
|
|
Wire.txBufferLength = 1; |
|
|
|
Wire.txBuffer[0] = 0; |
|
|
|
} |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
I2C0_D = Wire.txBuffer[0]; |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
Wire.port.D = Wire.txBuffer[0]; |
|
|
|
Wire.txBufferIndex = 1; |
|
|
|
} else { |
|
|
|
// Begin Slave Receive |
|
|
|
//serial_print("R"); |
|
|
|
receiving = 1; |
|
|
|
Wire.rxBufferLength = 0; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = I2C0_D; |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = Wire.port.D; |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
Wire.port.S = I2C_S_IICIF; |
|
|
|
return; |
|
|
|
} |
|
|
|
#if defined(KINETISL) |
|
|
|
c1 = I2C0_FLT; |
|
|
|
c1 = Wire.port.FLT; |
|
|
|
if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) { |
|
|
|
I2C0_FLT = c1 & ~I2C_FLT_STOPIE; |
|
|
|
Wire.port.FLT = c1 & ~I2C_FLT_STOPIE; |
|
|
|
if (Wire.user_onReceive != NULL) { |
|
|
|
Wire.rxBufferIndex = 0; |
|
|
|
Wire.user_onReceive(Wire.rxBufferLength); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
c1 = I2C0_C1; |
|
|
|
c1 = Wire.port.C1; |
|
|
|
if (c1 & I2C_C1_TX) { |
|
|
|
// Continue Slave Transmit |
|
|
|
//serial_print("t"); |
|
|
@@ -433,16 +447,16 @@ void i2c0_isr(void) |
|
|
|
//serial_print("."); |
|
|
|
// Master ACK'd previous byte |
|
|
|
if (Wire.txBufferIndex < Wire.txBufferLength) { |
|
|
|
I2C0_D = Wire.txBuffer[Wire.txBufferIndex++]; |
|
|
|
Wire.port.D = Wire.txBuffer[Wire.txBufferIndex++]; |
|
|
|
} else { |
|
|
|
I2C0_D = 0; |
|
|
|
Wire.port.D = 0; |
|
|
|
} |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
} else { |
|
|
|
//serial_print("*"); |
|
|
|
// Master did not ACK previous byte |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = I2C0_D; |
|
|
|
Wire.port.C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = Wire.port.D; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// Continue Slave Receive |
|
|
@@ -450,17 +464,17 @@ void i2c0_isr(void) |
|
|
|
#if defined(KINETISK) |
|
|
|
attachInterrupt(18, sda_rising_isr, RISING); |
|
|
|
#elif defined(KINETISL) |
|
|
|
I2C0_FLT |= I2C_FLT_STOPIE; |
|
|
|
Wire.port.FLT |= I2C_FLT_STOPIE; |
|
|
|
#endif |
|
|
|
//digitalWriteFast(4, HIGH); |
|
|
|
data = I2C0_D; |
|
|
|
data = Wire.port.D; |
|
|
|
//serial_phex(data); |
|
|
|
if (Wire.rxBufferLength < BUFFER_LENGTH && receiving) { |
|
|
|
Wire.rxBuffer[Wire.rxBufferLength++] = data; |
|
|
|
} |
|
|
|
//digitalWriteFast(4, LOW); |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
Wire.port.S = I2C_S_IICIF; |
|
|
|
} |
|
|
|
|
|
|
|
// Detects the stop condition that terminates a slave receive transfer. |
|
|
@@ -469,7 +483,7 @@ void i2c0_isr(void) |
|
|
|
void sda_rising_isr(void) |
|
|
|
{ |
|
|
|
//digitalWrite(3, HIGH); |
|
|
|
if (!(I2C0_S & I2C_S_BUSY)) { |
|
|
|
if (!(Wire.port.S & I2C_S_BUSY)) { |
|
|
|
detachInterrupt(18); |
|
|
|
if (Wire.user_onReceive != NULL) { |
|
|
|
Wire.rxBufferIndex = 0; |
|
|
@@ -494,30 +508,6 @@ void sda_rising_isr(void) |
|
|
|
// I2C0_C2 // I2C Control Register 2 |
|
|
|
// I2C0_FLT // I2C Programmable Input Glitch Filter register |
|
|
|
|
|
|
|
static uint8_t i2c_status(void) |
|
|
|
{ |
|
|
|
static uint32_t p=0xFFFF; |
|
|
|
uint32_t s = I2C0_S; |
|
|
|
if (s != p) { |
|
|
|
//Serial.printf("(%02X)", s); |
|
|
|
p = s; |
|
|
|
} |
|
|
|
return s; |
|
|
|
} |
|
|
|
|
|
|
|
static void i2c_wait(void) |
|
|
|
{ |
|
|
|
#if 0 |
|
|
|
while (!(I2C0_S & I2C_S_IICIF)) ; // wait |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
#endif |
|
|
|
//Serial.write('^'); |
|
|
|
while (1) { |
|
|
|
if ((i2c_status() & I2C_S_IICIF)) break; |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
} |
|
|
|
|
|
|
|
size_t TwoWire::write(uint8_t data) |
|
|
|
{ |
|
|
|
if (transmitting || slave_mode) { |
|
|
@@ -552,12 +542,12 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) |
|
|
|
uint8_t i, status, ret=0; |
|
|
|
|
|
|
|
// clear the status flags |
|
|
|
I2C0_S = I2C_S_IICIF | I2C_S_ARBL; |
|
|
|
port.S = I2C_S_IICIF | I2C_S_ARBL; |
|
|
|
// now take control of the bus... |
|
|
|
if (I2C0_C1 & I2C_C1_MST) { |
|
|
|
if (port.C1 & I2C_C1_MST) { |
|
|
|
// we are already the bus master, so send a repeated start |
|
|
|
//Serial.print("rstart:"); |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; |
|
|
|
} else { |
|
|
|
// we are not currently the bus master, so wait for bus ready |
|
|
|
//Serial.print("busy:"); |
|
|
@@ -566,15 +556,15 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) |
|
|
|
//Serial.write('.') ; |
|
|
|
if (millis() - wait_begin > 15) { |
|
|
|
// bus stuck busy too long |
|
|
|
I2C0_C1 = 0; |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
port.C1 = 0; |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
//Serial.println("abort"); |
|
|
|
return 4; |
|
|
|
} |
|
|
|
} |
|
|
|
// become the bus master in transmit mode (send start) |
|
|
|
slave_mode = 0; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
} |
|
|
|
// wait until start condition establishes control of the bus |
|
|
|
while (1) { |
|
|
@@ -583,27 +573,27 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) |
|
|
|
} |
|
|
|
// transmit the address and data |
|
|
|
for (i=0; i < txBufferLength; i++) { |
|
|
|
I2C0_D = txBuffer[i]; |
|
|
|
port.D = txBuffer[i]; |
|
|
|
//Serial.write('^'); |
|
|
|
while (1) { |
|
|
|
status = i2c_status(); |
|
|
|
if ((status & I2C_S_IICIF)) break; |
|
|
|
if (!(status & I2C_S_BUSY)) break; |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
port.S = I2C_S_IICIF; |
|
|
|
//Serial.write('$'); |
|
|
|
status = i2c_status(); |
|
|
|
if ((status & I2C_S_ARBL)) { |
|
|
|
// we lost bus arbitration to another master |
|
|
|
// TODO: what is the proper thing to do here?? |
|
|
|
//Serial.printf(" c1=%02X ", I2C0_C1); |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
//Serial.printf(" c1=%02X ", port.C1); |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
ret = 4; // 4:other error |
|
|
|
break; |
|
|
|
} |
|
|
|
if (!(status & I2C_S_BUSY)) { |
|
|
|
// suddenly lost control of the bus! |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
ret = 4; // 4:other error |
|
|
|
break; |
|
|
|
} |
|
|
@@ -620,7 +610,7 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) |
|
|
|
} |
|
|
|
if (sendStop) { |
|
|
|
// send the stop condition |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
// TODO: do we wait for this somehow? |
|
|
|
} |
|
|
|
transmitting = 0; |
|
|
@@ -639,64 +629,64 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop) |
|
|
|
rxBufferLength = 0; |
|
|
|
//serial_print("requestFrom\n"); |
|
|
|
// clear the status flags |
|
|
|
I2C0_S = I2C_S_IICIF | I2C_S_ARBL; |
|
|
|
port.S = I2C_S_IICIF | I2C_S_ARBL; |
|
|
|
// now take control of the bus... |
|
|
|
if (I2C0_C1 & I2C_C1_MST) { |
|
|
|
if (port.C1 & I2C_C1_MST) { |
|
|
|
// we are already the bus master, so send a repeated start |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; |
|
|
|
} else { |
|
|
|
// we are not currently the bus master, so wait for bus ready |
|
|
|
while (i2c_status() & I2C_S_BUSY) ; |
|
|
|
// become the bus master in transmit mode (send start) |
|
|
|
slave_mode = 0; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
} |
|
|
|
// send the address |
|
|
|
I2C0_D = (address << 1) | 1; |
|
|
|
port.D = (address << 1) | 1; |
|
|
|
i2c_wait(); |
|
|
|
status = i2c_status(); |
|
|
|
if ((status & I2C_S_RXAK) || (status & I2C_S_ARBL)) { |
|
|
|
// the slave device did not acknowledge |
|
|
|
// or we lost bus arbitration to another master |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
port.C1 = I2C_C1_IICEN; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
if (length == 0) { |
|
|
|
// TODO: does anybody really do zero length reads? |
|
|
|
// if so, does this code really work? |
|
|
|
I2C0_C1 = I2C_C1_IICEN | (sendStop ? 0 : I2C_C1_MST); |
|
|
|
port.C1 = I2C_C1_IICEN | (sendStop ? 0 : I2C_C1_MST); |
|
|
|
return 0; |
|
|
|
} else if (length == 1) { |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; |
|
|
|
} else { |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST; |
|
|
|
} |
|
|
|
tmp = I2C0_D; // initiate the first receive |
|
|
|
tmp = port.D; // initiate the first receive |
|
|
|
while (length > 1) { |
|
|
|
i2c_wait(); |
|
|
|
length--; |
|
|
|
if (length == 1) I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; |
|
|
|
if (length == 1) port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; |
|
|
|
if (count < BUFFER_LENGTH) { |
|
|
|
rxBuffer[count++] = I2C0_D; |
|
|
|
rxBuffer[count++] = port.D; |
|
|
|
} else { |
|
|
|
tmp = I2C0_D; |
|
|
|
tmp = port.D; |
|
|
|
} |
|
|
|
} |
|
|
|
i2c_wait(); |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
if (count < BUFFER_LENGTH) { |
|
|
|
rxBuffer[count++] = I2C0_D; |
|
|
|
rxBuffer[count++] = port.D; |
|
|
|
} else { |
|
|
|
tmp = I2C0_D; |
|
|
|
tmp = port.D; |
|
|
|
} |
|
|
|
if (sendStop) I2C0_C1 = I2C_C1_IICEN; |
|
|
|
if (sendStop) port.C1 = I2C_C1_IICEN; |
|
|
|
rxBufferLength = count; |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TwoWire Wire; |
|
|
|
TwoWire Wire(KINETIS_I2C0); |
|
|
|
|
|
|
|
|
|
|
|
|