Ver código fonte

Don't use static variables

main
PaulStoffregen 8 anos atrás
pai
commit
9ed2f188dc
2 arquivos alterados com 119 adições e 106 exclusões
  1. +35
    -47
      WireKinetis.cpp
  2. +84
    -59
      WireKinetis.h

+ 35
- 47
WireKinetis.cpp Ver arquivo

#include "kinetis.h" #include "kinetis.h"
#include <string.h> // for memcpy #include <string.h> // for memcpy
#include "core_pins.h" #include "core_pins.h"
//#include "HardwareSerial.h"
#include "Wire.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() 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) void TwoWire::begin(void)
{ {
//serial_begin(BAUD2DIV(115200)); //serial_begin(BAUD2DIV(115200));
I2C0_F = 0x00; // 100 kHz I2C0_F = 0x00; // 100 kHz
I2C0_FLT = 1; I2C0_FLT = 1;
#else #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 #endif
} }


// Arbitration Lost // Arbitration Lost
I2C0_S = I2C_S_ARBL; I2C0_S = I2C_S_ARBL;
//serial_print("a"); //serial_print("a");
if (receiving && TwoWire::rxBufferLength > 0) {
if (receiving && Wire.rxBufferLength > 0) {
// TODO: does this detect the STOP condition in slave receive mode? // TODO: does this detect the STOP condition in slave receive mode?




//serial_print("T"); //serial_print("T");
// Begin Slave Transmit // Begin Slave Transmit
receiving = 0; 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 // is this correct, transmitting a single zero
// when we should send nothing? Arduino's AVR // when we should send nothing? Arduino's AVR
// implementation does this, but is it ok? // 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_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 { } else {
// Begin Slave Receive // Begin Slave Receive
//serial_print("R"); //serial_print("R");
receiving = 1; receiving = 1;
TwoWire::rxBufferLength = 0;
Wire.rxBufferLength = 0;
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE; I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE;
data = I2C0_D; data = I2C0_D;
} }
c1 = I2C0_FLT; c1 = I2C0_FLT;
if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) { if ((c1 & I2C_FLT_STOPF) && (c1 & I2C_FLT_STOPIE)) {
I2C0_FLT = 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 #endif
if ((status & I2C_S_RXAK) == 0) { if ((status & I2C_S_RXAK) == 0) {
//serial_print("."); //serial_print(".");
// Master ACK'd previous byte // 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 { } else {
I2C0_D = 0; I2C0_D = 0;
} }
} }
} else { } else {
// Continue Slave Receive // Continue Slave Receive
irqcount = 0;
Wire.irqcount = 0;
#if defined(KINETISK) #if defined(KINETISK)
attachInterrupt(18, TwoWire::sda_rising_isr, RISING);
attachInterrupt(18, sda_rising_isr, RISING);
#elif defined(KINETISL) #elif defined(KINETISL)
I2C0_FLT |= I2C_FLT_STOPIE; I2C0_FLT |= I2C_FLT_STOPIE;
#endif #endif
//digitalWriteFast(4, HIGH); //digitalWriteFast(4, HIGH);
data = I2C0_D; data = I2C0_D;
//serial_phex(data); //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); //digitalWriteFast(4, LOW);
} }
// Detects the stop condition that terminates a slave receive transfer. // Detects the stop condition that terminates a slave receive transfer.
// Sadly, the I2C in Kinetis K series lacks the stop detect interrupt // Sadly, the I2C in Kinetis K series lacks the stop detect interrupt
// This pin change interrupt hack is needed to detect the stop condition // 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); //digitalWrite(3, HIGH);
if (!(I2C0_S & I2C_S_BUSY)) { if (!(I2C0_S & I2C_S_BUSY)) {
detachInterrupt(18); 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); //delayMicroseconds(100);
} else { } else {
if (++irqcount >= 2 || !slave_mode) {
if (++Wire.irqcount >= 2 || !Wire.slave_mode) {
detachInterrupt(18); detachInterrupt(18);
} }
} }
return endTransmission(true); return endTransmission(true);
} }


void TwoWire::begin(int address)
{
begin((uint8_t)address);
}

void TwoWire::onReceive( void (*function)(int) ) void TwoWire::onReceive( void (*function)(int) )
{ {
user_onReceive = function; user_onReceive = function;

+ 84
- 59
WireKinetis.h Ver arquivo

#define BUFFER_LENGTH 32 #define BUFFER_LENGTH 32
#define WIRE_HAS_END 1 #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 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); 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; extern TwoWire Wire;

Carregando…
Cancelar
Salvar