diff options
Diffstat (limited to 'libraries')
| -rw-r--r-- | libraries/LiquidCrystal/LiquidCrystal.cpp | 324 | ||||
| -rw-r--r-- | libraries/LiquidCrystal/LiquidCrystal.h | 105 | ||||
| -rw-r--r-- | libraries/LiquidCrystal/rules.mk | 29 | ||||
| -rw-r--r-- | libraries/Servo/Servo.cpp | 4 | ||||
| -rw-r--r-- | libraries/Servo/Servo.h | 2 | ||||
| -rw-r--r-- | libraries/Wire/README | 5 | ||||
| -rw-r--r-- | libraries/Wire/Wire.cpp | 259 | ||||
| -rw-r--r-- | libraries/Wire/Wire.h | 99 | ||||
| -rw-r--r-- | libraries/Wire/rules.mk | 29 | 
9 files changed, 853 insertions, 3 deletions
diff --git a/libraries/LiquidCrystal/LiquidCrystal.cpp b/libraries/LiquidCrystal/LiquidCrystal.cpp new file mode 100644 index 0000000..52f0308 --- /dev/null +++ b/libraries/LiquidCrystal/LiquidCrystal.cpp @@ -0,0 +1,324 @@ +#include "LiquidCrystal.h" + +#include <stdio.h> +#include <string.h> +#include "WProgram.h" + +// When the display powers up, it is configured as follows: +// +// 1. Display clear +// 2. Function set: +//    DL = 1; 8-bit interface data +//    N = 0; 1-line display +//    F = 0; 5x8 dot character font +// 3. Display on/off control: +//    D = 0; Display off +//    C = 0; Cursor off +//    B = 0; Blinking off +// 4. Entry mode set: +//    I/D = 1; Increment by 1 +//    S = 0; No shift +// +// Note, however, that resetting the Arduino doesn't reset the LCD, so we +// can't assume that its in that state when a sketch starts (and the +// LiquidCrystal constructor is called). + +// This library has been modified to be compatible with the LeafLabs Maple; +// very conservative timing is used due to problems with delayMicroseconds() +// that should be fixed in the 0.0.7 release of the libmaple. [bnewbold] + +LiquidCrystal::LiquidCrystal(uint8 rs, uint8 rw, uint8 enable, +                             uint8 d0, uint8 d1, uint8 d2, uint8 d3, +                             uint8 d4, uint8 d5, uint8 d6, uint8 d7) +{ +  init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); +} + +LiquidCrystal::LiquidCrystal(uint8 rs, uint8 enable, +                             uint8 d0, uint8 d1, uint8 d2, uint8 d3, +                             uint8 d4, uint8 d5, uint8 d6, uint8 d7) +{ +  init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); +} + +LiquidCrystal::LiquidCrystal(uint8 rs, uint8 rw, uint8 enable, +                             uint8 d0, uint8 d1, uint8 d2, uint8 d3) +{ +  init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); +} + +LiquidCrystal::LiquidCrystal(uint8 rs,  uint8 enable, +                             uint8 d0, uint8 d1, uint8 d2, uint8 d3) +{ +  init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); +} + +void LiquidCrystal::init(uint8 fourbitmode, uint8 rs, uint8 rw, uint8 enable, +                         uint8 d0, uint8 d1, uint8 d2, uint8 d3, +                         uint8 d4, uint8 d5, uint8 d6, uint8 d7) +{ +  _rs_pin = rs; +  _rw_pin = rw; +  _enable_pin = enable; + +  _data_pins[0] = d0; +  _data_pins[1] = d1; +  _data_pins[2] = d2; +  _data_pins[3] = d3; +  _data_pins[4] = d4; +  _data_pins[5] = d5; +  _data_pins[6] = d6; +  _data_pins[7] = d7; + +  pinMode(_rs_pin, OUTPUT); +  // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# +  if (_rw_pin != 255) { +    pinMode(_rw_pin, OUTPUT); +  } +  pinMode(_enable_pin, OUTPUT); + +  if (fourbitmode) +    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; +  else +    _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; + +  // TODO: bnewbold, re-enable this? +  begin(16, 1); +} + +void LiquidCrystal::begin(uint8 cols, uint8 lines, uint8 dotsize) { +  if (lines > 1) { +    _displayfunction |= LCD_2LINE; +  } +  _numlines = lines; +  _currline = 0; + +  // for some 1 line displays you can select a 10 pixel high font +  if ((dotsize != 0) && (lines == 1)) { +    _displayfunction |= LCD_5x10DOTS; +  } + +  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! +  // according to datasheet, we need at least 40ms after power rises above 2.7V +  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 +  delay(50);    // Maple mod +  //delayMicroseconds(50000); +  // Now we pull both RS and R/W low to begin commands +  digitalWrite(_rs_pin, LOW); +  digitalWrite(_enable_pin, LOW); +  if (_rw_pin != 255) { +    digitalWrite(_rw_pin, LOW); +  } + +  //put the LCD into 4 bit or 8 bit mode +  if (! (_displayfunction & LCD_8BITMODE)) { +    // this is according to the hitachi HD44780 datasheet +    // figure 24, pg 46 + +    // we start in 8bit mode, try to set 4 bit mode +    write4bits(0x03); +    delay(5);   // Maple mod +    //delayMicroseconds(4500); // wait min 4.1ms + +    // second try +    write4bits(0x03); +    delay(5);   // Maple mod +    //delayMicroseconds(4500); // wait min 4.1ms + +    // third go! +    write4bits(0x03); +    delay(1);   // Maple mod +    //delayMicroseconds(150); + +    // finally, set to 8-bit interface +    write4bits(0x02); +  } else { +    // this is according to the hitachi HD44780 datasheet +    // page 45 figure 23 + +    // Send function set command sequence +    command(LCD_FUNCTIONSET | _displayfunction); +    delay(5);   // Maple mod +    //delayMicroseconds(4500);  // wait more than 4.1ms + +    // second try +    command(LCD_FUNCTIONSET | _displayfunction); +    delay(1);   // Maple mod +    //delayMicroseconds(150); + +    // third go +    command(LCD_FUNCTIONSET | _displayfunction); +  } + +  // finally, set # lines, font size, etc. +  command(LCD_FUNCTIONSET | _displayfunction); + +  // turn the display on with no cursor or blinking default +  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; +  display(); + +  // clear it off +  clear(); + +  // Initialize to default text direction (for romance languages) +  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; +  // set the entry mode +  command(LCD_ENTRYMODESET | _displaymode); + +} + +/********** high level commands, for the user! */ +void LiquidCrystal::clear() +{ +  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero +  delay(2);     // Maple mod +  //delayMicroseconds(2000);  // this command takes a long time! +} + +void LiquidCrystal::home() +{ +  command(LCD_RETURNHOME);  // set cursor position to zero +  delay(2);     // Maple mod +  //delayMicroseconds(2000);  // this command takes a long time! +} + +void LiquidCrystal::setCursor(uint8 col, uint8 row) +{ +  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; +  if ( row > _numlines ) { +    row = _numlines-1;    // we count rows starting w/0 +  } + +  command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + +// Turn the display on/off (quickly) +void LiquidCrystal::noDisplay() { +  _displaycontrol &= ~LCD_DISPLAYON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LiquidCrystal::display() { +  _displaycontrol |= LCD_DISPLAYON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns the underline cursor on/off +void LiquidCrystal::noCursor() { +  _displaycontrol &= ~LCD_CURSORON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LiquidCrystal::cursor() { +  _displaycontrol |= LCD_CURSORON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turn on and off the blinking cursor +void LiquidCrystal::noBlink() { +  _displaycontrol &= ~LCD_BLINKON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LiquidCrystal::blink() { +  _displaycontrol |= LCD_BLINKON; +  command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM +void LiquidCrystal::scrollDisplayLeft(void) { +  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} +void LiquidCrystal::scrollDisplayRight(void) { +  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +// This is for text that flows Left to Right +void LiquidCrystal::leftToRight(void) { +  _displaymode |= LCD_ENTRYLEFT; +  command(LCD_ENTRYMODESET | _displaymode); +} + +// This is for text that flows Right to Left +void LiquidCrystal::rightToLeft(void) { +  _displaymode &= ~LCD_ENTRYLEFT; +  command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'right justify' text from the cursor +void LiquidCrystal::autoscroll(void) { +  _displaymode |= LCD_ENTRYSHIFTINCREMENT; +  command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'left justify' text from the cursor +void LiquidCrystal::noAutoscroll(void) { +  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; +  command(LCD_ENTRYMODESET | _displaymode); +} + +// Allows us to fill the first 8 CGRAM locations +// with custom characters +void LiquidCrystal::createChar(uint8 location, uint8 charmap[]) { +  location &= 0x7; // we only have 8 locations 0-7 +  command(LCD_SETCGRAMADDR | (location << 3)); +  for (int i=0; i<8; i++) { +    write(charmap[i]); +  } +} + +/*********** mid level commands, for sending data/cmds */ + +inline void LiquidCrystal::command(uint8 value) { +  send(value, LOW); +} + +inline void LiquidCrystal::write(uint8 value) { +  send(value, HIGH); +} + +/************ low level data pushing commands **********/ + +// write either command or data, with automatic 4/8-bit selection +void LiquidCrystal::send(uint8 value, uint8 mode) { +  digitalWrite(_rs_pin, mode); + +  // if there is a RW pin indicated, set it low to Write +  if (_rw_pin != 255) { +    digitalWrite(_rw_pin, LOW); +  } + +  if (_displayfunction & LCD_8BITMODE) { +    write8bits(value); +  } else { +    write4bits(value>>4); +    write4bits(value); +  } +} + +void LiquidCrystal::pulseEnable(void) { +  digitalWrite(_enable_pin, LOW); +  delay(1);     // Maple mod +  //delayMicroseconds(1); +  digitalWrite(_enable_pin, HIGH); +  delay(1);     // Maple mod +  //delayMicroseconds(1);    // enable pulse must be >450ns +  digitalWrite(_enable_pin, LOW); +  delay(1);     // Maple mod +  //delayMicroseconds(100);   // commands need > 37us to settle +} + +void LiquidCrystal::write4bits(uint8 value) { +  for (int i = 0; i < 4; i++) { +    pinMode(_data_pins[i], OUTPUT); +    digitalWrite(_data_pins[i], (value >> i) & 0x01); +  } + +  pulseEnable(); +} + +void LiquidCrystal::write8bits(uint8 value) { +  for (int i = 0; i < 8; i++) { +    pinMode(_data_pins[i], OUTPUT); +    digitalWrite(_data_pins[i], (value >> i) & 0x01); +  } + +  pulseEnable(); +} diff --git a/libraries/LiquidCrystal/LiquidCrystal.h b/libraries/LiquidCrystal/LiquidCrystal.h new file mode 100644 index 0000000..0baf543 --- /dev/null +++ b/libraries/LiquidCrystal/LiquidCrystal.h @@ -0,0 +1,105 @@ +#ifndef LiquidCrystal_h +#define LiquidCrystal_h + +//#include <inttypes.h> +#include "wirish.h" +#include "Print.h" + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +class LiquidCrystal : public Print { +public: +  LiquidCrystal(uint8 rs, uint8 enable, +                uint8 d0, uint8 d1, uint8 d2, uint8 d3, +                uint8 d4, uint8 d5, uint8 d6, uint8 d7); +  LiquidCrystal(uint8 rs, uint8 rw, uint8 enable, +                uint8 d0, uint8 d1, uint8 d2, uint8 d3, +                uint8 d4, uint8 d5, uint8 d6, uint8 d7); +  LiquidCrystal(uint8 rs, uint8 rw, uint8 enable, +                uint8 d0, uint8 d1, uint8 d2, uint8 d3); +  LiquidCrystal(uint8 rs, uint8 enable, +                uint8 d0, uint8 d1, uint8 d2, uint8 d3); + +  void init(uint8 fourbitmode, uint8 rs, uint8 rw, uint8 enable, +            uint8 d0, uint8 d1, uint8 d2, uint8 d3, +            uint8 d4, uint8 d5, uint8 d6, uint8 d7); + +  void begin(uint8 cols, uint8 rows, uint8 charsize = LCD_5x8DOTS); + +  void clear(); +  void home(); + +  void noDisplay(); +  void display(); +  void noBlink(); +  void blink(); +  void noCursor(); +  void cursor(); +  void scrollDisplayLeft(); +  void scrollDisplayRight(); +  void leftToRight(); +  void rightToLeft(); +  void autoscroll(); +  void noAutoscroll(); + +  void createChar(uint8, uint8[]); +  void setCursor(uint8, uint8); +  virtual void write(uint8); +  void command(uint8); +private: +  void send(uint8, uint8); +  void write4bits(uint8); +  void write8bits(uint8); +  void pulseEnable(); + +  uint8 _rs_pin; // LOW: command.  HIGH: character. +  uint8 _rw_pin; // LOW: write to LCD.  HIGH: read from LCD. +  uint8 _enable_pin; // activated by a HIGH pulse. +  uint8 _data_pins[8]; + +  uint8 _displayfunction; +  uint8 _displaycontrol; +  uint8 _displaymode; + +  uint8 _initialized; + +  uint8 _numlines,_currline; +}; + +#endif diff --git a/libraries/LiquidCrystal/rules.mk b/libraries/LiquidCrystal/rules.mk new file mode 100644 index 0000000..7b18203 --- /dev/null +++ b/libraries/LiquidCrystal/rules.mk @@ -0,0 +1,29 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES) + +# Local rules and targets +cSRCS_$(d) := + +cppSRCS_$(d) := LiquidCrystal.cpp + +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ +                 $(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp))
\ No newline at end of file diff --git a/libraries/Servo/Servo.cpp b/libraries/Servo/Servo.cpp index 4f60fbe..ae87b63 100644 --- a/libraries/Servo/Servo.cpp +++ b/libraries/Servo/Servo.cpp @@ -22,13 +22,13 @@   * THE SOFTWARE.   *****************************************************************************/ +#include "Servo.h" +  #include "boards.h"  #include "io.h"  #include "pwm.h"  #include "wirish_math.h" -#include "Servo.h" -  // Configure prescaler and overflow for a 20msec period (could just  // use HardwareTimer::setPeriod(), but this lets conversions below  // happen more statically, in combination with an inlined map() -- a diff --git a/libraries/Servo/Servo.h b/libraries/Servo/Servo.h index d35572a..1c75618 100644 --- a/libraries/Servo/Servo.h +++ b/libraries/Servo/Servo.h @@ -27,7 +27,7 @@  #include <stdint.h> -#include "HardwareTimer.h" +#include "wirish.h"             /* hack for IDE compile */  /* Note on Arduino compatibility: diff --git a/libraries/Wire/README b/libraries/Wire/README new file mode 100644 index 0000000..353d51a --- /dev/null +++ b/libraries/Wire/README @@ -0,0 +1,5 @@ +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 new file mode 100644 index 0000000..736bd25 --- /dev/null +++ b/libraries/Wire/Wire.cpp @@ -0,0 +1,259 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + *  @brief Wire library, ported from Arduino. Provides a simplistic + *  interface to i2c. + */ + +#include "Wire.h" +#include "wirish.h" + +/* 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 i2c_stop(Port port) { +    I2C_DELAY; +    digitalWrite(port.scl,HIGH); +    I2C_DELAY; +    digitalWrite(port.sda,HIGH); +} + +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; + +    if (!digitalRead(port.sda)) { +      I2C_DELAY; +      digitalWrite(port.scl,LOW); +      return true; +    } else { +      I2C_DELAY; +      digitalWrite(port.scl,LOW); +      return false; +    } +} + +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 i2c_send_nack(Port port) { +    I2C_DELAY; +    digitalWrite(port.sda,HIGH); +    I2C_DELAY; +    digitalWrite(port.scl,HIGH); +} + +uint8 i2c_shift_in(Port port) { +    uint8 data = 0; + +    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); +    } + +    return data; +} + +void i2c_shift_out(Port port, 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); +    } +} + +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); +} + +/* + * 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 +    } + +    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; +    } +    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; +    } + +    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++; +    } +} + +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++]; +} + +// private methods + +uint8 TwoWire::writeOneByte(uint8 byte) { +    i2c_shift_out(port, byte); +    if (!i2c_get_ack(port)) return ENACKTRNS; + +    return SUCCESS; +} + +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! +} + +// Declare the instance that the users of the library can use +TwoWire Wire; + diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h new file mode 100644 index 0000000..62e37bd --- /dev/null +++ b/libraries/Wire/Wire.h @@ -0,0 +1,99 @@ +/* ***************************************************************************** + * 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. + * ****************************************************************************/ + +/** + *  @brief Wire library, ported from Arduino. Provides a lean + *  interface to I2C (two-wire) communication. + */ + +#include "wirish.h" + +#ifndef _WIRE_H_ +#define _WIRE_H_ + +typedef struct { +  uint8 scl; +  uint8 sda; +} Port; + +/* You must update the online docs if you change this value. */ +#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 */ + +#define SDA 20 +#define SCL 21 + +#define I2C_WRITE 0 +#define I2C_READ  1 + +#define I2C_DELAY do{for(int i=0;i<50;i++) {asm volatile("nop");}}while(0) + +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*); + 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(); +}; + +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); + +extern TwoWire Wire; + +#endif // _WIRE_H_ diff --git a/libraries/Wire/rules.mk b/libraries/Wire/rules.mk new file mode 100644 index 0000000..71f5e75 --- /dev/null +++ b/libraries/Wire/rules.mk @@ -0,0 +1,29 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES) + +# Local rules and targets +cSRCS_$(d) := + +cppSRCS_$(d) := Wire.cpp + +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ +                 $(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp))
\ No newline at end of file  | 
