Browse Source

Don't use static variables

main
PaulStoffregen 7 years ago
parent
commit
9ed2f188dc
2 changed files with 119 additions and 106 deletions
  1. +35
    -47
      WireKinetis.cpp
  2. +84
    -59
      WireKinetis.h

+ 35
- 47
WireKinetis.cpp View File

@@ -26,30 +26,23 @@
#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::txBuffer[BUFFER_LENGTH+1];
uint8_t TwoWire::txBufferIndex = 0;
uint8_t TwoWire::txBufferLength = 0;
uint8_t TwoWire::transmitting = 0;
uint8_t TwoWire::sda_pin_num = 18;
uint8_t TwoWire::scl_pin_num = 19;
void (*TwoWire::user_onRequest)(void) = NULL;
void (*TwoWire::user_onReceive)(int) = NULL;

void sda_rising_isr(void);

TwoWire::TwoWire()
{
rxBufferIndex = 0;
rxBufferLength = 0;
txBufferIndex = 0;
txBufferLength = 0;
transmitting = 0;
sda_pin_num = 18;
scl_pin_num = 19;
user_onRequest = NULL;
user_onReceive = NULL;
}

static uint8_t slave_mode = 0;
static uint8_t irqcount=0;


void TwoWire::begin(void)
{
//serial_begin(BAUD2DIV(115200));
@@ -255,7 +248,7 @@ void TwoWire::setClock(uint32_t frequency)
I2C0_F = 0x00; // 100 kHz
I2C0_FLT = 1;
#else
#error "F_BUS must be 120, 108, 96, 9, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 16, 8, 4 or 2 MHz"
#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
}

@@ -383,7 +376,7 @@ void i2c0_isr(void)
// Arbitration Lost
I2C0_S = I2C_S_ARBL;
//serial_print("a");
if (receiving && TwoWire::rxBufferLength > 0) {
if (receiving && Wire.rxBufferLength > 0) {
// TODO: does this detect the STOP condition in slave receive mode?


@@ -397,25 +390,25 @@ void i2c0_isr(void)
//serial_print("T");
// Begin Slave Transmit
receiving = 0;
TwoWire::txBufferLength = 0;
if (TwoWire::user_onRequest != NULL) {
TwoWire::user_onRequest();
Wire.txBufferLength = 0;
if (Wire.user_onRequest != NULL) {
Wire.user_onRequest();
}
if (TwoWire::txBufferLength == 0) {
if (Wire.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;
Wire.txBufferLength = 1;
Wire.txBuffer[0] = 0;
}
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX;
I2C0_D = TwoWire::txBuffer[0];
TwoWire::txBufferIndex = 1;
I2C0_D = Wire.txBuffer[0];
Wire.txBufferIndex = 1;
} else {
// Begin Slave Receive
//serial_print("R");
receiving = 1;
TwoWire::rxBufferLength = 0;
Wire.rxBufferLength = 0;
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE;
data = I2C0_D;
}
@@ -426,9 +419,9 @@ void i2c0_isr(void)
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);
if (Wire.user_onReceive != NULL) {
Wire.rxBufferIndex = 0;
Wire.user_onReceive(Wire.rxBufferLength);
}
}
#endif
@@ -439,8 +432,8 @@ void i2c0_isr(void)
if ((status & I2C_S_RXAK) == 0) {
//serial_print(".");
// Master ACK'd previous byte
if (TwoWire::txBufferIndex < TwoWire::txBufferLength) {
I2C0_D = TwoWire::txBuffer[TwoWire::txBufferIndex++];
if (Wire.txBufferIndex < Wire.txBufferLength) {
I2C0_D = Wire.txBuffer[Wire.txBufferIndex++];
} else {
I2C0_D = 0;
}
@@ -453,17 +446,17 @@ void i2c0_isr(void)
}
} else {
// Continue Slave Receive
irqcount = 0;
Wire.irqcount = 0;
#if defined(KINETISK)
attachInterrupt(18, TwoWire::sda_rising_isr, RISING);
attachInterrupt(18, 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;
if (Wire.rxBufferLength < BUFFER_LENGTH && receiving) {
Wire.rxBuffer[Wire.rxBufferLength++] = data;
}
//digitalWriteFast(4, LOW);
}
@@ -473,18 +466,18 @@ void i2c0_isr(void)
// 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)
void sda_rising_isr(void)
{
//digitalWrite(3, HIGH);
if (!(I2C0_S & I2C_S_BUSY)) {
detachInterrupt(18);
if (user_onReceive != NULL) {
rxBufferIndex = 0;
user_onReceive(rxBufferLength);
if (Wire.user_onReceive != NULL) {
Wire.rxBufferIndex = 0;
Wire.user_onReceive(Wire.rxBufferLength);
}
//delayMicroseconds(100);
} else {
if (++irqcount >= 2 || !slave_mode) {
if (++Wire.irqcount >= 2 || !Wire.slave_mode) {
detachInterrupt(18);
}
}
@@ -760,11 +753,6 @@ 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;

+ 84
- 59
WireKinetis.h View File

@@ -32,68 +32,93 @@ extern "C" void i2c0_isr(void);
#define BUFFER_LENGTH 32
#define WIRE_HAS_END 1

#if defined(__MKL26Z64__)
#define WIRE_HAS_STOP_INTERRUPT 1
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define WIRE_HAS_START_INTERRUPT 1
#define WIRE_HAS_STOP_INTERRUPT 1
#endif

class TwoWire : public Stream
{
private:
static uint8_t rxBuffer[];
static uint8_t rxBufferIndex;
static uint8_t rxBufferLength;

static uint8_t txAddress;
static uint8_t txBuffer[];
static uint8_t txBufferIndex;
static uint8_t txBufferLength;

static uint8_t transmitting;
static void onRequestService(void);
static void onReceiveService(uint8_t*, int);
static void (*user_onRequest)(void);
static void (*user_onReceive)(int);
static void sda_rising_isr(void);
static uint8_t sda_pin_num;
static uint8_t scl_pin_num;
friend void i2c0_isr(void);
public:
TwoWire();
void begin();
void begin(uint8_t);
void begin(int);
void end();
void setClock(uint32_t);
void setSDA(uint8_t);
void setSCL(uint8_t);
void beginTransmission(uint8_t);
void beginTransmission(int);
uint8_t endTransmission(void);
uint8_t endTransmission(uint8_t);
uint8_t requestFrom(uint8_t, uint8_t);
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
uint8_t requestFrom(int, int);
uint8_t requestFrom(int, int, int);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *, size_t);
virtual int available(void);
virtual int read(void);
virtual int peek(void);
public:
TwoWire();
void begin();
void begin(uint8_t address);
void begin(int address) {
begin((uint8_t)address);
}
void end();
void setClock(uint32_t);
void setSDA(uint8_t);
void setSCL(uint8_t);
void beginTransmission(uint8_t);
void beginTransmission(int);
uint8_t endTransmission(void);
uint8_t endTransmission(uint8_t);
uint8_t requestFrom(uint8_t, uint8_t);
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
uint8_t requestFrom(int, int);
uint8_t requestFrom(int, int, int);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *, size_t);
virtual int available(void);
virtual int read(void);
virtual int peek(void);
virtual void flush(void);
void onReceive( void (*)(int) );
void onRequest( void (*)(void) );
// added by Teensyduino installer, for compatibility
// with pre-1.0 sketches and libraries
void send(uint8_t b) { write(b); }
void send(uint8_t *s, uint8_t n) { write(s, n); }
void send(int n) { write((uint8_t)n); }
void send(char *s) { write(s); }
uint8_t receive(void) {
int c = read();
if (c < 0) return 0;
return c;
}
inline size_t write(unsigned long n) { return write((uint8_t)n); }
inline size_t write(long n) { return write((uint8_t)n); }
inline size_t write(unsigned int n) { return write((uint8_t)n); }
inline size_t write(int n) { return write((uint8_t)n); }
using Print::write;
void onReceive(void (*function)(int));
void onRequest(void (*function)(void));
// send() for compatibility with very old sketches and libraries
void send(uint8_t b) {
write(b);
}
void send(uint8_t *s, uint8_t n) {
write(s, n);
}
void send(int n) {
write((uint8_t)n);
}
void send(char *s) {
write(s);
}
uint8_t receive(void) {
int c = read();
if (c < 0) return 0;
return c;
}
size_t write(unsigned long n) {
return write((uint8_t)n);
}
size_t write(long n) {
return write((uint8_t)n);
}
size_t write(unsigned int n) {
return write((uint8_t)n);
}
size_t write(int n) {
return write((uint8_t)n);
}
using Print::write;
private:
uint8_t rxBuffer[BUFFER_LENGTH];
uint8_t rxBufferIndex;
uint8_t rxBufferLength;
uint8_t txAddress;
uint8_t txBuffer[BUFFER_LENGTH+1];
uint8_t txBufferIndex;
uint8_t txBufferLength;
uint8_t transmitting;
uint8_t slave_mode;
uint8_t irqcount;
void onRequestService(void);
void onReceiveService(uint8_t*, int);
void (*user_onRequest)(void);
void (*user_onReceive)(int);
void sda_rising_isr(void);
uint8_t sda_pin_num;
uint8_t scl_pin_num;
friend void i2c0_isr(void);
friend void sda_rising_isr(void);
};

extern TwoWire Wire;

Loading…
Cancel
Save