diff options
-rw-r--r-- | CREDITS | 4 | ||||
-rw-r--r-- | libraries/Wire/HardWire.cpp | 66 | ||||
-rw-r--r-- | libraries/Wire/HardWire.h | 70 | ||||
-rw-r--r-- | libraries/Wire/README | 5 | ||||
-rw-r--r-- | libraries/Wire/Wire.cpp | 296 | ||||
-rw-r--r-- | libraries/Wire/Wire.h | 150 | ||||
-rw-r--r-- | libraries/Wire/WireBase.cpp | 140 | ||||
-rw-r--r-- | libraries/Wire/WireBase.h | 144 | ||||
-rw-r--r-- | libraries/Wire/rules.mk | 2 |
9 files changed, 626 insertions, 251 deletions
@@ -77,3 +77,7 @@ W: http://sarup.dk/index.html N: Andy Scott ("xttocs") E: andy.g.scott@gmail.com D: LiquidCrystal library + +N: Trystan Jones ("crenn") +E: crenn6977@gmail.com +D: New Wire library diff --git a/libraries/Wire/HardWire.cpp b/libraries/Wire/HardWire.cpp new file mode 100644 index 0000000..9176a87 --- /dev/null +++ b/libraries/Wire/HardWire.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file HardWire.cpp + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, uses the hardware I2C available in the Maple to + * interact with I2C slave devices. + */ + +/* + * Library created by crenn to use the new WireBase system and allow Arduino + * users easy interaction with the I2C Hardware in a familiar method. + */ + +#include "HardWire.h" + +uint8 HardWire::process() { + int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0); + if (res != 0) { + i2c_disable(sel_hard); + i2c_master_enable(sel_hard, (I2C_BUS_RESET | dev_flags)); + } + return 0; +} + +// TODO: Add in Error Handling if devsel is out of range for other Maples +HardWire::HardWire(uint8 dev_sel, uint8 flags) { + if (dev_sel == 1) { + sel_hard = I2C1; + } else if (dev_sel == 2) { + sel_hard = I2C2; + } else { + ASSERT(1); + } + dev_flags=flags; + i2c_master_enable(sel_hard, flags); +} + +HardWire::~HardWire() { + i2c_disable(sel_hard); + sel_hard = 0; +}
\ No newline at end of file diff --git a/libraries/Wire/HardWire.h b/libraries/Wire/HardWire.h new file mode 100644 index 0000000..91e141d --- /dev/null +++ b/libraries/Wire/HardWire.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file HardWire.h + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, uses the hardware I2C available in the Maple to + * interact with I2C slave devices. + */ + +/* + * Library created by crenn to use the new WireBase system and allow Arduino + * users easy interaction with the I2C Hardware in a familiar method. + */ + +#include "wirish.h" +#include "WireBase.h" + +#ifndef _HARDWIRE_H_ +#define _HARDWIRE_H_ + +#include "i2c.h" + +class HardWire : public WireBase { +private: + i2c_dev* sel_hard; + uint8 dev_flags; +protected: + /* + * Processes the incoming I2C message defined by WireBase to the hardware. If + * an error occured, restart the I2C device. + */ + uint8 process(); +public: + /* + * Check if devsel is within range and enable selected I2C interface with + * passed flags + */ + HardWire(uint8, uint8 = 0); + + /* + * Disables the I2C device and remove the device address. + */ + ~HardWire(); +}; + +#endif // _HARDWIRE_H_
\ No newline at end of file diff --git a/libraries/Wire/README b/libraries/Wire/README deleted file mode 100644 index 353d51a..0000000 --- a/libraries/Wire/README +++ /dev/null @@ -1,5 +0,0 @@ -Wirish soft (bit-banged) implementation of the Wire I2C library. - -This implementation is synchronous, and thus supports only a subset of -the full Wire interface. An asynchronous hardware version implemented -with DMA is expected for Maple IDE release 0.1.0. diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 8416525..9173234 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -25,236 +25,158 @@ *****************************************************************************/ /** - * @brief Wire library, ported from Arduino. Provides a simplistic - * interface to i2c. + * @file Wire.cpp + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, uses the WireBase to create the primary interface + * while keeping low level interactions invisible to the user. + */ + +/* + * Library updated by crenn to follow new Wire system. + * Code was derived from the original Wire for maple code by leaflabs and the + * modifications by gke and ala42. */ #include "Wire.h" +#define I2C_WRITE 0 +#define I2C_READ 1 + /* low level conventions: * - SDA/SCL idle high (expected high) * - always start with i2c_delay rather than end */ -uint32 i2c_delay = 1; -void i2c_start(Port port) { - I2C_DELAY; - digitalWrite(port.sda,LOW); - I2C_DELAY; - digitalWrite(port.scl,LOW); +void TwoWire::set_scl(bool state) { + I2C_DELAY(this->i2c_delay); + digitalWrite(this->scl_pin,state); + //Allow for clock stretching - dangerous currently + if (state == HIGH) { + while(digitalRead(this->scl_pin) == 0); + } +} + +void TwoWire::set_sda(bool state) { + I2C_DELAY(this->i2c_delay); + digitalWrite(this->sda_pin, state); } -void i2c_stop(Port port) { - I2C_DELAY; - digitalWrite(port.scl,HIGH); - I2C_DELAY; - digitalWrite(port.sda,HIGH); +void TwoWire::i2c_start() { + set_sda(LOW); + set_scl(LOW); } -boolean i2c_get_ack(Port port) { - I2C_DELAY; - digitalWrite(port.scl,LOW); - I2C_DELAY; - digitalWrite(port.sda,HIGH); - I2C_DELAY; - digitalWrite(port.scl,HIGH); - I2C_DELAY; +void TwoWire::i2c_stop() { + set_sda(LOW); + set_scl(HIGH); + set_sda(HIGH); +} - if (!digitalRead(port.sda)) { - I2C_DELAY; - digitalWrite(port.scl,LOW); - return true; - } else { - I2C_DELAY; - digitalWrite(port.scl,LOW); - return false; - } +bool TwoWire::i2c_get_ack() { + set_scl(LOW); + set_sda(HIGH); + set_scl(HIGH); + + bool ret = !digitalRead(this->sda_pin); + set_scl(LOW); + return ret; } -void i2c_send_ack(Port port) { - I2C_DELAY; - digitalWrite(port.sda,LOW); - I2C_DELAY; - digitalWrite(port.scl,HIGH); - I2C_DELAY; - digitalWrite(port.scl,LOW); +void TwoWire::i2c_send_ack() { + set_sda(LOW); + set_scl(HIGH); + set_scl(LOW); } -void i2c_send_nack(Port port) { - I2C_DELAY; - digitalWrite(port.sda,HIGH); - I2C_DELAY; - digitalWrite(port.scl,HIGH); +void TwoWire::i2c_send_nack() { + set_sda(HIGH); + set_scl(HIGH); + set_scl(LOW); } -uint8 i2c_shift_in(Port port) { +uint8 TwoWire::i2c_shift_in() { uint8 data = 0; + set_sda(HIGH); int i; - for (i=0;i<8;i++) { - I2C_DELAY; - digitalWrite(port.scl,HIGH); - I2C_DELAY; - data += digitalRead(port.sda) << (7-i); - I2C_DELAY; - digitalWrite(port.scl,LOW); + for (i = 0; i < 8; i++) { + set_scl(HIGH); + data |= digitalRead(this->sda_pin) << (7-i); + set_scl(LOW); } return data; } -void i2c_shift_out(Port port, uint8 val) { +void TwoWire::i2c_shift_out(uint8 val) { int i; - for (i=0;i<8;i++) { - I2C_DELAY; - digitalWrite(port.sda, !!(val & (1 << (7 - i)))); - I2C_DELAY; - digitalWrite(port.scl, HIGH); - I2C_DELAY; - digitalWrite(port.scl, LOW); + for (i = 0; i < 8; i++) { + set_sda(!!(val & (1 << (7 - i)) ) ); + set_scl(HIGH); + set_scl(LOW); } } -TwoWire::TwoWire() { - i2c_delay = 0; - rx_buf_idx = 0; - rx_buf_len = 0; - tx_addr = 0; - tx_buf_idx = 0; - tx_buf_overflow = false; -} - -/* - * Sets pins SDA and SCL to OUPTUT_OPEN_DRAIN, joining I2C bus as - * master. If you want them to be some other pins, use begin(uint8, - * uint8); - */ -void TwoWire::begin() { - begin(SDA, SCL); -} +uint8 TwoWire::process() { + itc_msg.xferred = 0; -/* - * Joins I2C bus as master on given SDA and SCL pins. - */ -void TwoWire::begin(uint8 sda, uint8 scl) { - port.sda = sda; - port.scl = scl; - pinMode(scl, OUTPUT_OPEN_DRAIN); - pinMode(sda, OUTPUT_OPEN_DRAIN); - digitalWrite(scl, HIGH); - digitalWrite(sda, HIGH); -} - -void TwoWire::beginTransmission(uint8 slave_address) { - tx_addr = slave_address; - tx_buf_idx = 0; - tx_buf_overflow = false; - rx_buf_idx = 0; - rx_buf_len = 0; -} - -void TwoWire::beginTransmission(int slave_address) { - beginTransmission((uint8)slave_address); -} - -uint8 TwoWire::endTransmission(void) { - if (tx_buf_overflow) return EDATA; - - i2c_start(port); - - i2c_shift_out(port, (tx_addr << 1) | I2C_WRITE); - if (!i2c_get_ack(port)) return ENACKADDR; - - // shift out the address we're transmitting to - for (uint8 i = 0; i < tx_buf_idx; i++) { - uint8 ret = writeOneByte(tx_buf[i]); - if (ret) return ret; // SUCCESS is 0 + uint8 sla_addr = (itc_msg.addr << 1); + if (itc_msg.flags == I2C_MSG_READ) { + sla_addr |= I2C_READ; } - - i2c_stop(port); - - tx_buf_idx = 0; - tx_buf_overflow = false; - return SUCCESS; -} - -uint8 TwoWire::requestFrom(uint8 address, int num_bytes) { - if (num_bytes > WIRE_BUFSIZ) num_bytes = WIRE_BUFSIZ; - - rx_buf_idx = 0; - rx_buf_len = 0; - while (rx_buf_len < num_bytes) { - if(!readOneByte(address, rx_buf + rx_buf_len)) rx_buf_len++; - else break; + i2c_start(); + // shift out the address we're transmitting to + i2c_shift_out(sla_addr); + if (!i2c_get_ack()) { + return ENACKADDR; } - return rx_buf_len; -} - -uint8 TwoWire::requestFrom(int address, int numBytes) { - return TwoWire::requestFrom((uint8)address, (uint8) numBytes); -} - -void TwoWire::send(uint8 value) { - if (tx_buf_idx == WIRE_BUFSIZ) { - tx_buf_overflow = true; - return; + // Recieving + if (itc_msg.flags == I2C_MSG_READ) { + while (itc_msg.xferred < itc_msg.length) { + itc_msg.data[itc_msg.xferred++] = i2c_shift_in(); + if (itc_msg.xferred < itc_msg.length) { + i2c_send_ack(); + } else { + i2c_send_nack(); + } + } } - - tx_buf[tx_buf_idx++] = value; -} - -void TwoWire::send(uint8* buf, int len) { - for (uint8 i = 0; i < len; i++) send(buf[i]); -} - -void TwoWire::send(int value) { - send((uint8)value); -} - -void TwoWire::send(int* buf, int len) { - send((uint8*)buf, (uint8)len); -} - -void TwoWire::send(char* buf) { - uint8 *ptr = (uint8*)buf; - while(*ptr) { - send(*ptr); - ptr++; + // Sending + else { + for (uint8 i = 0; i < itc_msg.length; i++) { + i2c_shift_out(itc_msg.data[i]); + if (!i2c_get_ack()) { + return ENACKTRNS; + } + itc_msg.xferred++; + } } + i2c_stop(); + return SUCCESS; } -uint8 TwoWire::available() { - return rx_buf_len - rx_buf_idx; -} - -uint8 TwoWire::receive() { - if (rx_buf_idx == rx_buf_len) return 0; - return rx_buf[rx_buf_idx++]; +// TODO: Add in Error Handling if pins is out of range for other Maples +// TODO: Make delays more capable +TwoWire::TwoWire(uint8 scl, uint8 sda, uint8 delay) : i2c_delay(delay) { + this->scl_pin=scl; + this->sda_pin=sda; } -// private methods - -uint8 TwoWire::writeOneByte(uint8 byte) { - i2c_shift_out(port, byte); - if (!i2c_get_ack(port)) return ENACKTRNS; - - return SUCCESS; +void TwoWire::begin(uint8 self_addr) { + tx_buf_idx = 0; + tx_buf_overflow = false; + rx_buf_idx = 0; + rx_buf_len = 0; + pinMode(this->scl_pin, OUTPUT_OPEN_DRAIN); + pinMode(this->sda_pin, OUTPUT_OPEN_DRAIN); + set_scl(HIGH); + set_sda(HIGH); } -uint8 TwoWire::readOneByte(uint8 address, uint8 *byte) { - i2c_start(port); - - i2c_shift_out(port, (address << 1) | I2C_READ); - if (!i2c_get_ack(port)) return ENACKADDR; - - *byte = i2c_shift_in(port); - - i2c_send_nack(port); - i2c_stop(port); - - return SUCCESS; // no real way of knowing, but be optimistic! +TwoWire::~TwoWire() { + this->scl_pin=0; + this->sda_pin=0; } // Declare the instance that the users of the library can use -TwoWire Wire; - +TwoWire Wire();
\ No newline at end of file diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index 0640c3b..7827e45 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -25,77 +25,111 @@ *****************************************************************************/ /** - * @brief Wire library, ported from Arduino. Provides a lean - * interface to I2C (two-wire) communication. + * @file Wire.h + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, uses the WireBase to create the primary interface + * while keeping low level interactions invisible to the user. */ +/* + * Library updated by crenn to follow new Wire system. + * Code was derived from the original Wire for maple code by leaflabs and the + * modifications by gke and ala42. + */ + +#include "wirish.h" +#include "WireBase.h" + #ifndef _WIRE_H_ #define _WIRE_H_ -#include <wirish/wirish.h> +/* + * On the Maple, let the default pins be in the same location as the Arduino + * pins + */ +#define SDA 19 +#define SCL 20 -typedef struct { - uint8 scl; - uint8 sda; -} Port; +//#define I2C_DELAY(x) {uint32 time=micros(); while(time>(micros()+x));} +#define I2C_DELAY(x) do{for(int i=0;i<x;i++) {asm volatile("nop");}}while(0) +#define SOFT_STANDARD 25 +#define SOFT_FAST 7 -/* You must update the online docs if you change this value. */ -#define WIRE_BUFSIZ 32 +class TwoWire : public WireBase { + private: + const uint8 i2c_delay; + uint8 scl_pin; + uint8 sda_pin; -/* return codes from endTransmission() */ -#define SUCCESS 0 /* transmission was successful */ -#define EDATA 1 /* too much data */ -#define ENACKADDR 2 /* received nack on transmit of address */ -#define ENACKTRNS 3 /* received nack on transmit of data */ -#define EOTHER 4 /* other error */ + /* + * Sets the SCL line to HIGH/LOW and allow for clock stretching by slave + * devices + */ + void set_scl(bool); -#define SDA 20 -#define SCL 21 + /* + * Sets the SDA line to HIGH/LOW + */ + void set_sda(bool); -#define I2C_WRITE 0 -#define I2C_READ 1 + /* + * Creates a Start condition on the bus + */ + void i2c_start(); -#define I2C_DELAY do{for(int i=0;i<50;i++) {asm volatile("nop");}}while(0) + /* + * Creates a Stop condition on the bus + */ + void i2c_stop(); -class TwoWire { - private: - uint8 rx_buf[WIRE_BUFSIZ]; /* receive buffer */ - uint8 rx_buf_idx; /* first unread idx in rx_buf */ - uint8 rx_buf_len; /* number of bytes read */ - - uint8 tx_addr; /* address transmitting to */ - uint8 tx_buf[WIRE_BUFSIZ]; /* transmit buffer */ - uint8 tx_buf_idx; /* next idx available in tx_buf, -1 overflow */ - boolean tx_buf_overflow; - Port port; - uint8 writeOneByte(uint8); - uint8 readOneByte(uint8, uint8*); + /* + * Gets an ACK condition from a slave device on the bus + */ + bool i2c_get_ack(); + + /* + * Creates a ACK condition on the bus + */ + void i2c_send_ack(); + + /* + * Creates a NACK condition on the bus + */ + void i2c_send_nack(); + + /* + * Shifts in the data through SDA and clocks SCL for the slave device + */ + uint8 i2c_shift_in(); + + /* + * Shifts out the data through SDA and clocks SCL for the slave device + */ + void i2c_shift_out(uint8); + protected: + /* + * Processes the incoming I2C message defined by WireBase + */ + uint8 process(); public: - TwoWire(); - void begin(); - void begin(uint8, uint8); - void beginTransmission(uint8); - void beginTransmission(int); - uint8 endTransmission(void); - uint8 requestFrom(uint8, int); - uint8 requestFrom(int, int); - void send(uint8); - void send(uint8*, int); - void send(int); - void send(int*, int); - void send(char*); - uint8 available(); - uint8 receive(); -}; + /* + * Accept pin numbers for SCL and SDA lines. Set the delay needed to create the + * timing for I2C's Standard Mode and Fast Mode. + */ + TwoWire(uint8 = SCL, uint8 = SDA, uint8 = SOFT_STANDARD); + + /* + * Sets pins SDA and SCL to OUPTUT_OPEN_DRAIN, joining I2C bus as master. This + * function overwrites the default behaviour of .begin(uint8) in WireBase + */ + void begin(uint8 = 0x00); -void i2c_start(Port port); -void i2c_stop(Port port); -boolean i2c_get_ack(Port port); -void i2c_send_ack(Port port); -void i2c_send_nack(Port port); -uint8 i2c_shift_in(Port port); -void i2c_shift_out(Port port, uint8 val); + /* + * If object is destroyed, set pin numbers to 0. + */ + ~TwoWire(); +}; -extern TwoWire Wire; +extern TwoWire Wire(); -#endif // _WIRE_H_ +#endif // _WIRE_H_
\ No newline at end of file diff --git a/libraries/Wire/WireBase.cpp b/libraries/Wire/WireBase.cpp new file mode 100644 index 0000000..00ca644 --- /dev/null +++ b/libraries/Wire/WireBase.cpp @@ -0,0 +1,140 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file WireBase.cpp + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, following the majority of the interface from Arduino. + * Provides a 'standard' interface to I2C (two-wire) communication for + * derived classes. + */ + +/* + * Library created by crenn to allow a system which would provide users the + * 'standardised' Arduino method for interfacing with I2C devices regardless of + * whether it is I2C hardware or emulating software. + */ + +#include "WireBase.h" +#include "wirish.h" + +void WireBase::begin(uint8 self_addr) { + tx_buf_idx = 0; + tx_buf_overflow = false; + rx_buf_idx = 0; + rx_buf_len = 0; +} + +void WireBase::beginTransmission(uint8 slave_address) { + itc_msg.addr = slave_address; + itc_msg.data = &tx_buf[tx_buf_idx]; + itc_msg.length = 0; + itc_msg.flags = 0; +} + +void WireBase::beginTransmission(int slave_address) { + beginTransmission((uint8)slave_address); +} + +uint8 WireBase::endTransmission(void) { + if (tx_buf_overflow) { + return EDATA; + } + process(); + tx_buf_idx = 0; + tx_buf_overflow = false; + return SUCCESS; +} + +//TODO: Add the ability to queue messages (adding a boolean to end of function +// call, allows for the Arduino style to stay while also giving the flexibility +// to bulk send +uint8 WireBase::requestFrom(uint8 address, int num_bytes) { + if (num_bytes > WIRE_BUFSIZ) { + num_bytes = WIRE_BUFSIZ; + } + itc_msg.addr = address; + itc_msg.flags = I2C_MSG_READ; + itc_msg.length = num_bytes; + itc_msg.data = &rx_buf[rx_buf_idx]; + process(); + rx_buf_len += itc_msg.xferred; + itc_msg.flags = 0; + return rx_buf_len; +} + +uint8 WireBase::requestFrom(int address, int numBytes) { + return WireBase::requestFrom((uint8)address, numBytes); +} + +void WireBase::send(uint8 value) { + if (tx_buf_idx == WIRE_BUFSIZ) { + tx_buf_overflow = true; + return; + } + tx_buf[tx_buf_idx++] = value; + itc_msg.length++; +} + +void WireBase::send(uint8* buf, int len) { + for (uint8 i = 0; i < len; i++) { + send(buf[i]); + } +} + +void WireBase::send(int value) { + send((uint8)value); +} + +void WireBase::send(int* buf, int len) { + send((uint8*)buf, (uint8)len); +} + +void WireBase::send(char* buf) { + uint8 *ptr = (uint8*)buf; + while (*ptr) { + send(*ptr); + ptr++; + } +} + +uint8 WireBase::available() { + return rx_buf_len - rx_buf_idx; +} + +uint8 WireBase::receive() { + if (rx_buf_idx == rx_buf_len) { + rx_buf_idx = 0; + rx_buf_len = 0; + return 0; + } else if (rx_buf_idx == (rx_buf_len-1)) { + uint8 temp = rx_buf[rx_buf_idx]; + rx_buf_idx = 0; + rx_buf_len = 0; + return temp; + } + return rx_buf[rx_buf_idx++]; +}
\ No newline at end of file diff --git a/libraries/Wire/WireBase.h b/libraries/Wire/WireBase.h new file mode 100644 index 0000000..555cbaf --- /dev/null +++ b/libraries/Wire/WireBase.h @@ -0,0 +1,144 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file WireBase.h + * @author Trystan Jones <crenn6977@gmail.com> + * @brief Wire library, following the majority of the interface from Arduino. + * Provides a 'standard' interface to I2C (two-wire) communication for + * derived classes. + */ + +/* + * Library created by crenn to allow a system which would provide users the + * 'standardised' Arduino method for interfacing with I2C devices regardless of + * whether it is I2C hardware or emulating software. + */ + +#include "wirish.h" + +#ifndef _WIREBASE_H_ +#define _WIREBASE_H_ + +#include "i2c.h" + +#define WIRE_BUFSIZ 32 + +/* return codes from endTransmission() */ +#define SUCCESS 0 /* transmission was successful */ +#define EDATA 1 /* too much data */ +#define ENACKADDR 2 /* received nack on transmit of address */ +#define ENACKTRNS 3 /* received nack on transmit of data */ +#define EOTHER 4 /* other error */ + +class WireBase { // Abstraction is awesome! +protected: + i2c_msg itc_msg; + uint8 rx_buf[WIRE_BUFSIZ]; /* receive buffer */ + uint8 rx_buf_idx; /* first unread idx in rx_buf */ + uint8 rx_buf_len; /* number of bytes read */ + + uint8 tx_buf[WIRE_BUFSIZ]; /* transmit buffer */ + uint8 tx_buf_idx; // next idx available in tx_buf, -1 overflow + boolean tx_buf_overflow; + + // Force derived classes to define process function + virtual uint8 process() = 0; +public: + WireBase() {} + ~WireBase() {} + + /* + * Initialises the class interface + */ + // Allow derived classes to overwrite begin function + virtual void begin(uint8 = 0x00); + + /* + * Sets up the transmission message to be processed + */ + void beginTransmission(uint8); + + /* + * Allow only 8 bit addresses to be used + */ + void beginTransmission(int); + + /* + * Call the process function to process the message if the TX buffer has not + * overflowed. + */ + uint8 endTransmission(void); + + /* + * Request bytes from a slave device and process the request, storing into the + * receiving buffer. + */ + uint8 requestFrom(uint8, int); + + /* + * Allow only 8 bit addresses to be used when requesting bytes + */ + uint8 requestFrom(int, int); + + /* + * Stack up bytes to be sent when transmitting + */ + void send(uint8); + + /* + * Stack up bytes from the array to be sent when transmitting + */ + void send(uint8*, int); + + /* + * Ensure that a sending data will only be 8-bit bytes + */ + void send(int); + + /* + * Ensure that an array sending data will only be 8-bit bytes + */ + void send(int*, int); + + /* + * Stack up bytes from a string to be sent when transmitting + */ + void send(char*); + + /* + * Return the amount of bytes that is currently in the receiving buffer + */ + uint8 available(); + + /* + * Return the value of byte in the receiving buffer that is currently being + * pointed to + */ + uint8 receive(); +}; + +#endif // _WIREBASE_H_
\ No newline at end of file diff --git a/libraries/Wire/rules.mk b/libraries/Wire/rules.mk index 71f5e75..e16f4db 100644 --- a/libraries/Wire/rules.mk +++ b/libraries/Wire/rules.mk @@ -10,7 +10,7 @@ CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES) # Local rules and targets cSRCS_$(d) := -cppSRCS_$(d) := Wire.cpp +cppSRCS_$(d) := WireBase.cpp HardWire.cpp Wire.cpp cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) |