|
|
@@ -19,6 +19,507 @@ |
|
|
|
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts |
|
|
|
*/ |
|
|
|
|
|
|
|
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__) |
|
|
|
|
|
|
|
#include "kinetis.h" |
|
|
|
#include <string.h> // for memcpy |
|
|
|
#include "core_pins.h" |
|
|
|
//#include "HardwareSerial.h" |
|
|
|
#include "Wire.h" |
|
|
|
|
|
|
|
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; |
|
|
|
uint8_t TwoWire::rxBufferIndex = 0; |
|
|
|
uint8_t TwoWire::rxBufferLength = 0; |
|
|
|
//uint8_t TwoWire::txAddress = 0; |
|
|
|
uint8_t TwoWire::txBuffer[BUFFER_LENGTH+1]; |
|
|
|
uint8_t TwoWire::txBufferIndex = 0; |
|
|
|
uint8_t TwoWire::txBufferLength = 0; |
|
|
|
uint8_t TwoWire::transmitting = 0; |
|
|
|
void (*TwoWire::user_onRequest)(void) = NULL; |
|
|
|
void (*TwoWire::user_onReceive)(int) = NULL; |
|
|
|
|
|
|
|
|
|
|
|
TwoWire::TwoWire() |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
static uint8_t slave_mode = 0; |
|
|
|
static uint8_t irqcount=0; |
|
|
|
|
|
|
|
|
|
|
|
void TwoWire::begin(void) |
|
|
|
{ |
|
|
|
//serial_begin(BAUD2DIV(115200)); |
|
|
|
//serial_print("\nWire Begin\n"); |
|
|
|
|
|
|
|
slave_mode = 0; |
|
|
|
SIM_SCGC4 |= SIM_SCGC4_I2C0; // TODO: use bitband |
|
|
|
I2C0_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 |
|
|
|
// It might seem like setting PORT_PCR_PE & PORT_PCR_PS |
|
|
|
// would enable pullup resistors. However, there seems |
|
|
|
// to be a bug in chip while I2C is enabled, where setting |
|
|
|
// those causes the port to be driven strongly high. |
|
|
|
CORE_PIN18_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE; |
|
|
|
CORE_PIN19_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE; |
|
|
|
setClock(100000); |
|
|
|
I2C0_C2 = I2C_C2_HDRS; |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
//pinMode(3, OUTPUT); |
|
|
|
//pinMode(4, OUTPUT); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::setClock(uint32_t frequency) |
|
|
|
{ |
|
|
|
#if F_BUS == 60000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x2C; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1C; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x12; // 938 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
#elif F_BUS == 56000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x2B; // 109 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1C; // 389 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0E; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
#elif F_BUS == 48000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x27; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x1A; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0D; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 4; |
|
|
|
#elif F_BUS == 40000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x29; // 104 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x19; // 416 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0B; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 3; |
|
|
|
#elif F_BUS == 36000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x28; // 113 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x19; // 375 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x0A; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 3; |
|
|
|
#elif F_BUS == 24000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x1F; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x12; // 375 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x02; // 1 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 2; |
|
|
|
#elif F_BUS == 16000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x20; // 100 kHz |
|
|
|
} else if (frequency < 1000000) { |
|
|
|
I2C0_F = 0x07; // 400 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 800 MHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
#elif F_BUS == 8000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x14; // 100 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 400 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
#elif F_BUS == 4000000 |
|
|
|
if (frequency < 400000) { |
|
|
|
I2C0_F = 0x07; // 100 kHz |
|
|
|
} else { |
|
|
|
I2C0_F = 0x00; // 200 kHz |
|
|
|
} |
|
|
|
I2C0_FLT = 1; |
|
|
|
#elif F_BUS == 2000000 |
|
|
|
I2C0_F = 0x00; // 100 kHz |
|
|
|
I2C0_FLT = 1; |
|
|
|
#else |
|
|
|
#error "F_BUS must be 60, 56, 48, 40, 36, 24, 16, 8, 4 or 2 MHz" |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::begin(uint8_t address) |
|
|
|
{ |
|
|
|
begin(); |
|
|
|
I2C0_A1 = address << 1; |
|
|
|
slave_mode = 1; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
NVIC_ENABLE_IRQ(IRQ_I2C0); |
|
|
|
} |
|
|
|
|
|
|
|
void i2c0_isr(void) |
|
|
|
{ |
|
|
|
uint8_t status, c1, data; |
|
|
|
static uint8_t receiving=0; |
|
|
|
|
|
|
|
status = I2C0_S; |
|
|
|
//serial_print("."); |
|
|
|
if (status & I2C_S_ARBL) { |
|
|
|
// Arbitration Lost |
|
|
|
I2C0_S = I2C_S_ARBL; |
|
|
|
//serial_print("a"); |
|
|
|
if (receiving && TwoWire::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; |
|
|
|
TwoWire::txBufferLength = 0; |
|
|
|
if (TwoWire::user_onRequest != NULL) { |
|
|
|
TwoWire::user_onRequest(); |
|
|
|
} |
|
|
|
if (TwoWire::txBufferLength == 0) { |
|
|
|
// is this correct, transmitting a single zero |
|
|
|
// when we should send nothing? Arduino's AVR |
|
|
|
// implementation does this, but is it ok? |
|
|
|
TwoWire::txBufferLength = 1; |
|
|
|
TwoWire::txBuffer[0] = 0; |
|
|
|
} |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; |
|
|
|
I2C0_D = TwoWire::txBuffer[0]; |
|
|
|
TwoWire::txBufferIndex = 1; |
|
|
|
} else { |
|
|
|
// Begin Slave Receive |
|
|
|
//serial_print("R"); |
|
|
|
receiving = 1; |
|
|
|
TwoWire::rxBufferLength = 0; |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; |
|
|
|
data = I2C0_D; |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
return; |
|
|
|
} |
|
|
|
#if defined(KINETISL) |
|
|
|
c1 = I2C0_FLT; |
|
|
|
if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) { |
|
|
|
I2C0_FLT = c1 & ~I2C_FLT_STOPIE; |
|
|
|
if (TwoWire::user_onReceive != NULL) { |
|
|
|
TwoWire::rxBufferIndex = 0; |
|
|
|
TwoWire::user_onReceive(TwoWire::rxBufferLength); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
c1 = I2C0_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 (TwoWire::txBufferIndex < TwoWire::txBufferLength) { |
|
|
|
I2C0_D = TwoWire::txBuffer[TwoWire::txBufferIndex++]; |
|
|
|
} else { |
|
|
|
I2C0_D = 0; |
|
|
|
} |
|
|
|
I2C0_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; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// Continue Slave Receive |
|
|
|
irqcount = 0; |
|
|
|
#if defined(KINETISK) |
|
|
|
attachInterrupt(18, TwoWire::sda_rising_isr, RISING); |
|
|
|
#elif defined(KINETISL) |
|
|
|
I2C0_FLT |= I2C_FLT_STOPIE; |
|
|
|
#endif |
|
|
|
//digitalWriteFast(4, HIGH); |
|
|
|
data = I2C0_D; |
|
|
|
//serial_phex(data); |
|
|
|
if (TwoWire::rxBufferLength < BUFFER_LENGTH && receiving) { |
|
|
|
TwoWire::rxBuffer[TwoWire::rxBufferLength++] = data; |
|
|
|
} |
|
|
|
//digitalWriteFast(4, LOW); |
|
|
|
} |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
} |
|
|
|
|
|
|
|
// Detects the stop condition that terminates a slave receive transfer. |
|
|
|
// Sadly, the I2C in Kinetis K series lacks the stop detect interrupt |
|
|
|
// This pin change interrupt hack is needed to detect the stop condition |
|
|
|
void TwoWire::sda_rising_isr(void) |
|
|
|
{ |
|
|
|
//digitalWrite(3, HIGH); |
|
|
|
if (!(I2C0_S & I2C_S_BUSY)) { |
|
|
|
detachInterrupt(18); |
|
|
|
if (user_onReceive != NULL) { |
|
|
|
rxBufferIndex = 0; |
|
|
|
user_onReceive(rxBufferLength); |
|
|
|
} |
|
|
|
//delayMicroseconds(100); |
|
|
|
} else { |
|
|
|
if (++irqcount >= 2 || !slave_mode) { |
|
|
|
detachInterrupt(18); |
|
|
|
} |
|
|
|
} |
|
|
|
//digitalWrite(3, LOW); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Chapter 44: Inter-Integrated Circuit (I2C) - Page 1012 |
|
|
|
// I2C0_A1 // I2C Address Register 1 |
|
|
|
// I2C0_F // I2C Frequency Divider register |
|
|
|
// I2C0_C1 // I2C Control Register 1 |
|
|
|
// I2C0_S // I2C Status register |
|
|
|
// I2C0_D // I2C Data I/O register |
|
|
|
// I2C0_C2 // I2C Control Register 2 |
|
|
|
// I2C0_FLT // I2C Programmable Input Glitch Filter register |
|
|
|
|
|
|
|
|
|
|
|
static void i2c_wait(void) |
|
|
|
{ |
|
|
|
while (!(I2C0_S & I2C_S_IICIF)) ; // wait |
|
|
|
I2C0_S = I2C_S_IICIF; |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::beginTransmission(uint8_t address) |
|
|
|
{ |
|
|
|
txBuffer[0] = (address << 1); |
|
|
|
transmitting = 1; |
|
|
|
txBufferLength = 1; |
|
|
|
} |
|
|
|
|
|
|
|
size_t TwoWire::write(uint8_t data) |
|
|
|
{ |
|
|
|
if (transmitting || slave_mode) { |
|
|
|
if (txBufferLength >= BUFFER_LENGTH+1) { |
|
|
|
setWriteError(); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
txBuffer[txBufferLength++] = data; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
size_t TwoWire::write(const uint8_t *data, size_t quantity) |
|
|
|
{ |
|
|
|
if (transmitting || slave_mode) { |
|
|
|
size_t avail = BUFFER_LENGTH+1 - txBufferLength; |
|
|
|
if (quantity > avail) { |
|
|
|
quantity = avail; |
|
|
|
setWriteError(); |
|
|
|
} |
|
|
|
memcpy(txBuffer + txBufferLength, data, quantity); |
|
|
|
txBufferLength += quantity; |
|
|
|
return quantity; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::flush(void) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
// now take control of the bus... |
|
|
|
if (I2C0_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; |
|
|
|
} else { |
|
|
|
// we are not currently the bus master, so wait for bus ready |
|
|
|
while (I2C0_S & 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; |
|
|
|
} |
|
|
|
// transmit the address and data |
|
|
|
for (i=0; i < txBufferLength; i++) { |
|
|
|
I2C0_D = txBuffer[i]; |
|
|
|
i2c_wait(); |
|
|
|
status = I2C0_S; |
|
|
|
if (status & I2C_S_RXAK) { |
|
|
|
// the slave device did not acknowledge |
|
|
|
if (i == 0) { |
|
|
|
ret = 2; // 2:received NACK on transmit of address |
|
|
|
} else { |
|
|
|
ret = 3; // 3:received NACK on transmit of data |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
if ((status & I2C_S_ARBL)) { |
|
|
|
// we lost bus arbitration to another master |
|
|
|
// TODO: what is the proper thing to do here?? |
|
|
|
ret = 4; // 4:other error |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (sendStop) { |
|
|
|
// send the stop condition |
|
|
|
I2C0_C1 = I2C_C1_IICEN; |
|
|
|
// TODO: do we wait for this somehow? |
|
|
|
} |
|
|
|
transmitting = 0; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop) |
|
|
|
{ |
|
|
|
uint8_t tmp __attribute__((unused)); |
|
|
|
uint8_t status, count=0; |
|
|
|
|
|
|
|
rxBufferIndex = 0; |
|
|
|
rxBufferLength = 0; |
|
|
|
//serial_print("requestFrom\n"); |
|
|
|
// clear the status flags |
|
|
|
I2C0_S = I2C_S_IICIF | I2C_S_ARBL; |
|
|
|
// now take control of the bus... |
|
|
|
if (I2C0_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; |
|
|
|
} else { |
|
|
|
// we are not currently the bus master, so wait for bus ready |
|
|
|
while (I2C0_S & 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; |
|
|
|
} |
|
|
|
// send the address |
|
|
|
I2C0_D = (address << 1) | 1; |
|
|
|
i2c_wait(); |
|
|
|
status = I2C0_S; |
|
|
|
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; |
|
|
|
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); |
|
|
|
return 0; |
|
|
|
} else if (length == 1) { |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; |
|
|
|
} else { |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST; |
|
|
|
} |
|
|
|
tmp = I2C0_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; |
|
|
|
rxBuffer[count++] = I2C0_D; |
|
|
|
} |
|
|
|
i2c_wait(); |
|
|
|
I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; |
|
|
|
rxBuffer[count++] = I2C0_D; |
|
|
|
if (sendStop) I2C0_C1 = I2C_C1_IICEN; |
|
|
|
rxBufferLength = count; |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
int TwoWire::available(void) |
|
|
|
{ |
|
|
|
return rxBufferLength - rxBufferIndex; |
|
|
|
} |
|
|
|
|
|
|
|
int TwoWire::read(void) |
|
|
|
{ |
|
|
|
if (rxBufferIndex >= rxBufferLength) return -1; |
|
|
|
return rxBuffer[rxBufferIndex++]; |
|
|
|
} |
|
|
|
|
|
|
|
int TwoWire::peek(void) |
|
|
|
{ |
|
|
|
if (rxBufferIndex >= rxBufferLength) return -1; |
|
|
|
return rxBuffer[rxBufferIndex]; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// alternate function prototypes |
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) |
|
|
|
{ |
|
|
|
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(int address, int quantity) |
|
|
|
{ |
|
|
|
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) |
|
|
|
{ |
|
|
|
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::beginTransmission(int address) |
|
|
|
{ |
|
|
|
beginTransmission((uint8_t)address); |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t TwoWire::endTransmission(void) |
|
|
|
{ |
|
|
|
return endTransmission(true); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::begin(int address) |
|
|
|
{ |
|
|
|
begin((uint8_t)address); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::onReceive( void (*function)(int) ) |
|
|
|
{ |
|
|
|
user_onReceive = function; |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::onRequest( void (*function)(void) ) |
|
|
|
{ |
|
|
|
user_onRequest = function; |
|
|
|
} |
|
|
|
|
|
|
|
//TwoWire Wire = TwoWire(); |
|
|
|
TwoWire Wire; |
|
|
|
|
|
|
|
|
|
|
|
#endif // __MK20DX128__ || __MK20DX256__ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__AVR__) |
|
|
|
|
|
|
|
extern "C" { |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
@@ -75,6 +576,11 @@ void TwoWire::begin(int address) |
|
|
|
begin((uint8_t)address); |
|
|
|
} |
|
|
|
|
|
|
|
void TwoWire::setClock(uint32_t frequency) |
|
|
|
{ |
|
|
|
TWBR = ((F_CPU / frequency) - 16) / 2; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) |
|
|
|
{ |
|
|
|
// clamp to buffer length |
|
|
@@ -296,3 +802,4 @@ void TwoWire::onRequest( void (*function)(void) ) |
|
|
|
|
|
|
|
TwoWire Wire = TwoWire(); |
|
|
|
|
|
|
|
#endif // __AVR__ |