diff options
Diffstat (limited to 'libraries')
31 files changed, 2967 insertions, 0 deletions
diff --git a/libraries/EEPROM/EEPROM.cpp b/libraries/EEPROM/EEPROM.cpp new file mode 100644 index 0000000..dfa1deb --- /dev/null +++ b/libraries/EEPROM/EEPROM.cpp @@ -0,0 +1,50 @@ +/* +  EEPROM.cpp - EEPROM library +  Copyright (c) 2006 David A. Mellis.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +/****************************************************************************** + * Includes + ******************************************************************************/ + +#include <avr/eeprom.h> +#include "Arduino.h" +#include "EEPROM.h" + +/****************************************************************************** + * Definitions + ******************************************************************************/ + +/****************************************************************************** + * Constructors + ******************************************************************************/ + +/****************************************************************************** + * User API + ******************************************************************************/ + +uint8_t EEPROMClass::read(int address) +{ +	return eeprom_read_byte((unsigned char *) address); +} + +void EEPROMClass::write(int address, uint8_t value) +{ +	eeprom_write_byte((unsigned char *) address, value); +} + +EEPROMClass EEPROM; diff --git a/libraries/EEPROM/EEPROM.h b/libraries/EEPROM/EEPROM.h new file mode 100644 index 0000000..aa2b577 --- /dev/null +++ b/libraries/EEPROM/EEPROM.h @@ -0,0 +1,35 @@ +/* +  EEPROM.h - EEPROM library +  Copyright (c) 2006 David A. Mellis.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +#ifndef EEPROM_h +#define EEPROM_h + +#include <inttypes.h> + +class EEPROMClass +{ +  public: +    uint8_t read(int); +    void write(int, uint8_t); +}; + +extern EEPROMClass EEPROM; + +#endif + diff --git a/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino b/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino new file mode 100644 index 0000000..b18ff2c --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino @@ -0,0 +1,23 @@ +/* + * EEPROM Clear + * + * Sets all of the bytes of the EEPROM to 0. + * This example code is in the public domain. + + */ + +#include <EEPROM.h> + +void setup() +{ +  // write a 0 to all 512 bytes of the EEPROM +  for (int i = 0; i < 512; i++) +    EEPROM.write(i, 0); + +  // turn the LED on when we're done +  digitalWrite(13, HIGH); +} + +void loop() +{ +} diff --git a/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino b/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino new file mode 100644 index 0000000..ebf79d6 --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino @@ -0,0 +1,43 @@ +/* + * EEPROM Read + * + * Reads the value of each byte of the EEPROM and prints it + * to the computer. + * This example code is in the public domain. + */ + +#include <EEPROM.h> + +// start reading from the first byte (address 0) of the EEPROM +int address = 0; +byte value; + +void setup() +{ +  // initialize serial and wait for port to open: +  Serial.begin(9600); +  while (!Serial) { +    ; // wait for serial port to connect. Needed for Leonardo only +  } +} + +void loop() +{ +  // read a byte from the current address of the EEPROM +  value = EEPROM.read(address); + +  Serial.print(address); +  Serial.print("\t"); +  Serial.print(value, DEC); +  Serial.println(); + +  // advance to the next address of the EEPROM +  address = address + 1; + +  // there are only 512 bytes of EEPROM, from 0 to 511, so if we're +  // on address 512, wrap around to address 0 +  if (address == 512) +    address = 0; + +  delay(500); +} diff --git a/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino b/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino new file mode 100644 index 0000000..c047887 --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino @@ -0,0 +1,38 @@ +/* + * EEPROM Write + * + * Stores values read from analog input 0 into the EEPROM. + * These values will stay in the EEPROM when the board is + * turned off and may be retrieved later by another sketch. + */ + +#include <EEPROM.h> + +// the current address in the EEPROM (i.e. which byte +// we're going to write to next) +int addr = 0; + +void setup() +{ +} + +void loop() +{ +  // need to divide by 4 because analog inputs range from +  // 0 to 1023 and each byte of the EEPROM can only hold a +  // value from 0 to 255. +  int val = analogRead(0) / 4; + +  // write the value to the appropriate byte of the EEPROM. +  // these values will remain there when the board is +  // turned off. +  EEPROM.write(addr, val); + +  // advance to the next address.  there are 512 bytes in +  // the EEPROM, so go back to 0 when we hit 512. +  addr = addr + 1; +  if (addr == 512) +    addr = 0; + +  delay(100); +} diff --git a/libraries/EEPROM/keywords.txt b/libraries/EEPROM/keywords.txt new file mode 100644 index 0000000..d3218fe --- /dev/null +++ b/libraries/EEPROM/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +EEPROM	KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/EEPROM/library.properties b/libraries/EEPROM/library.properties new file mode 100644 index 0000000..796f7cb --- /dev/null +++ b/libraries/EEPROM/library.properties @@ -0,0 +1,8 @@ +name=EEPROM +version=1.0 +author=Arduino +maintainer=Arduino <info@arduino.cc> +sentence=Enables reading and writing to the permanent board storage. For all Arduino boards BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/EEPROM +architectures=avr diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp new file mode 100644 index 0000000..9a7a400 --- /dev/null +++ b/libraries/SPI/SPI.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> + * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "SPI.h" +#include "pins_arduino.h" + +SPIClass SPI; + +uint8_t SPIClass::interruptMode = 0; +uint8_t SPIClass::interruptMask = 0; +uint8_t SPIClass::interruptSave = 0; +#ifdef SPI_TRANSACTION_MISMATCH_LED +uint8_t SPIClass::inTransactionFlag = 0; +#endif + +void SPIClass::begin() +{ +  // Set SS to high so a connected chip will be "deselected" by default +  digitalWrite(SS, HIGH); + +  // When the SS pin is set as OUTPUT, it can be used as +  // a general purpose output port (it doesn't influence +  // SPI operations). +  pinMode(SS, OUTPUT); + +  // Warning: if the SS pin ever becomes a LOW INPUT then SPI +  // automatically switches to Slave, so the data direction of +  // the SS pin MUST be kept as OUTPUT. +  SPCR |= _BV(MSTR); +  SPCR |= _BV(SPE); + +  // Set direction register for SCK and MOSI pin. +  // MISO pin automatically overrides to INPUT. +  // By doing this AFTER enabling SPI, we avoid accidentally +  // clocking in a single bit since the lines go directly +  // from "input" to SPI control.   +  // http://code.google.com/p/arduino/issues/detail?id=888 +  pinMode(SCK, OUTPUT); +  pinMode(MOSI, OUTPUT); +} + +void SPIClass::end() { +  SPCR &= ~_BV(SPE); +} + +// mapping of interrupt numbers to bits within SPI_AVR_EIMSK +#if defined(__AVR_ATmega32U4__) +  #define SPI_INT0_MASK  (1<<INT0) +  #define SPI_INT1_MASK  (1<<INT1) +  #define SPI_INT2_MASK  (1<<INT2) +  #define SPI_INT3_MASK  (1<<INT3) +  #define SPI_INT4_MASK  (1<<INT6) +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +  #define SPI_INT0_MASK  (1<<INT0) +  #define SPI_INT1_MASK  (1<<INT1) +  #define SPI_INT2_MASK  (1<<INT2) +  #define SPI_INT3_MASK  (1<<INT3) +  #define SPI_INT4_MASK  (1<<INT4) +  #define SPI_INT5_MASK  (1<<INT5) +  #define SPI_INT6_MASK  (1<<INT6) +  #define SPI_INT7_MASK  (1<<INT7) +#elif defined(EICRA) && defined(EICRB) && defined(EIMSK) +  #define SPI_INT0_MASK  (1<<INT4) +  #define SPI_INT1_MASK  (1<<INT5) +  #define SPI_INT2_MASK  (1<<INT0) +  #define SPI_INT3_MASK  (1<<INT1) +  #define SPI_INT4_MASK  (1<<INT2) +  #define SPI_INT5_MASK  (1<<INT3) +  #define SPI_INT6_MASK  (1<<INT6) +  #define SPI_INT7_MASK  (1<<INT7) +#else +  #ifdef INT0 +  #define SPI_INT0_MASK  (1<<INT0) +  #endif +  #ifdef INT1 +  #define SPI_INT1_MASK  (1<<INT1) +  #endif +  #ifdef INT2 +  #define SPI_INT2_MASK  (1<<INT2) +  #endif +#endif + +void SPIClass::usingInterrupt(uint8_t interruptNumber) +{ +  uint8_t mask; + +  if (interruptMode > 1) return; + +  noInterrupts(); +  switch (interruptNumber) { +  #ifdef SPI_INT0_MASK +  case 0: mask = SPI_INT0_MASK; break; +  #endif +  #ifdef SPI_INT1_MASK +  case 1: mask = SPI_INT1_MASK; break; +  #endif +  #ifdef SPI_INT2_MASK +  case 2: mask = SPI_INT2_MASK; break; +  #endif +  #ifdef SPI_INT3_MASK +  case 3: mask = SPI_INT3_MASK; break; +  #endif +  #ifdef SPI_INT4_MASK +  case 4: mask = SPI_INT4_MASK; break; +  #endif +  #ifdef SPI_INT5_MASK +  case 5: mask = SPI_INT5_MASK; break; +  #endif +  #ifdef SPI_INT6_MASK +  case 6: mask = SPI_INT6_MASK; break; +  #endif +  #ifdef SPI_INT7_MASK +  case 7: mask = SPI_INT7_MASK; break; +  #endif +  default: +    interruptMode = 2; +    interrupts(); +    return; +  } +  interruptMode = 1; +  interruptMask |= mask; +  interrupts(); +} + diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h new file mode 100644 index 0000000..962100b --- /dev/null +++ b/libraries/SPI/SPI.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> + * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include <Arduino.h> + +// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), +// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) +#define SPI_HAS_TRANSACTION 1 + +// Uncomment this line to add detection of mismatched begin/end transactions. +// A mismatch occurs if other libraries fail to use SPI.endTransaction() for +// each SPI.beginTransaction().  Connect a LED to this pin.  The LED will turn +// on if any mismatch is ever detected. +//#define SPI_TRANSACTION_MISMATCH_LED 5 + +#ifndef LSBFIRST +#define LSBFIRST 0 +#endif +#ifndef MSBFIRST +#define MSBFIRST 1 +#endif + +#define SPI_CLOCK_DIV4 0x00 +#define SPI_CLOCK_DIV16 0x01 +#define SPI_CLOCK_DIV64 0x02 +#define SPI_CLOCK_DIV128 0x03 +#define SPI_CLOCK_DIV2 0x04 +#define SPI_CLOCK_DIV8 0x05 +#define SPI_CLOCK_DIV32 0x06 + +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x04 +#define SPI_MODE2 0x08 +#define SPI_MODE3 0x0C + +#define SPI_MODE_MASK 0x0C  // CPOL = bit 3, CPHA = bit 2 on SPCR +#define SPI_CLOCK_MASK 0x03  // SPR1 = bit 1, SPR0 = bit 0 on SPCR +#define SPI_2XCLOCK_MASK 0x01  // SPI2X = bit 0 on SPSR + +// define SPI_AVR_EIMSK for AVR boards with external interrupt pins +#if defined(EIMSK) +  #define SPI_AVR_EIMSK  EIMSK +#elif defined(GICR) +  #define SPI_AVR_EIMSK  GICR +#elif defined(GIMSK) +  #define SPI_AVR_EIMSK  GIMSK +#endif + +class SPISettings { +public: +  SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { +    if (__builtin_constant_p(clock)) { +      init_AlwaysInline(clock, bitOrder, dataMode); +    } else { +      init_MightInline(clock, bitOrder, dataMode); +    } +  } +  SPISettings() { +    init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); +  } +private: +  void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { +    init_AlwaysInline(clock, bitOrder, dataMode); +  } +  void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) +    __attribute__((__always_inline__)) { +    // Clock settings are defined as follows. Note that this shows SPI2X +    // inverted, so the bits form increasing numbers. Also note that +    // fosc/64 appears twice +    // SPR1 SPR0 ~SPI2X Freq +    //   0    0     0   fosc/2 +    //   0    0     1   fosc/4 +    //   0    1     0   fosc/8 +    //   0    1     1   fosc/16 +    //   1    0     0   fosc/32 +    //   1    0     1   fosc/64 +    //   1    1     0   fosc/64 +    //   1    1     1   fosc/128 + +    // We find the fastest clock that is less than or equal to the +    // given clock rate. The clock divider that results in clock_setting +    // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the +    // slowest (128 == 2 ^^ 7, so clock_div = 6). +    uint8_t clockDiv; + +    // When the clock is known at compiletime, use this if-then-else +    // cascade, which the compiler knows how to completely optimize +    // away. When clock is not known, use a loop instead, which generates +    // shorter code. +    if (__builtin_constant_p(clock)) { +      if (clock >= F_CPU / 2) { +        clockDiv = 0; +      } else if (clock >= F_CPU / 4) { +        clockDiv = 1; +      } else if (clock >= F_CPU / 8) { +        clockDiv = 2; +      } else if (clock >= F_CPU / 16) { +        clockDiv = 3; +      } else if (clock >= F_CPU / 32) { +        clockDiv = 4; +      } else if (clock >= F_CPU / 64) { +        clockDiv = 5; +      } else { +        clockDiv = 6; +      } +    } else { +      uint32_t clockSetting = F_CPU / 2; +      clockDiv = 0; +      while (clockDiv < 6 && clock < clockSetting) { +        clockSetting /= 2; +        clockDiv++; +      } +    } + +    // Compensate for the duplicate fosc/64 +    if (clockDiv == 6) +    clockDiv = 7; + +    // Invert the SPI2X bit +    clockDiv ^= 0x1; + +    // Pack into the SPISettings class +    spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | +      (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); +    spsr = clockDiv & SPI_2XCLOCK_MASK; +  } +  uint8_t spcr; +  uint8_t spsr; +  friend class SPIClass; +}; + + +class SPIClass { +public: +  // Initialize the SPI library +  static void begin(); + +  // If SPI is to used from within an interrupt, this function registers +  // that interrupt with the SPI library, so beginTransaction() can +  // prevent conflicts.  The input interruptNumber is the number used +  // with attachInterrupt.  If SPI is used from a different interrupt +  // (eg, a timer), interruptNumber should be 255. +  static void usingInterrupt(uint8_t interruptNumber); + +  // Before using SPI.transfer() or asserting chip select pins, +  // this function is used to gain exclusive access to the SPI bus +  // and configure the correct settings. +  inline static void beginTransaction(SPISettings settings) { +    if (interruptMode > 0) { +      #ifdef SPI_AVR_EIMSK +      if (interruptMode == 1) { +        interruptSave = SPI_AVR_EIMSK; +        SPI_AVR_EIMSK &= ~interruptMask; +      } else +      #endif +      { +        interruptSave = SREG; +        cli(); +      } +    } +    #ifdef SPI_TRANSACTION_MISMATCH_LED +    if (inTransactionFlag) { +      pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); +      digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); +    } +    inTransactionFlag = 1; +    #endif +    SPCR = settings.spcr; +    SPSR = settings.spsr; +  } + +  // Write to the SPI bus (MOSI pin) and also receive (MISO pin) +  inline static uint8_t transfer(uint8_t data) { +    SPDR = data; +    asm volatile("nop"); +    while (!(SPSR & _BV(SPIF))) ; // wait +    return SPDR; +  } +  inline static uint16_t transfer16(uint16_t data) { +    union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; +    in.val = data; +    if (!(SPCR & _BV(DORD))) { +      SPDR = in.msb; +      while (!(SPSR & _BV(SPIF))) ; +      out.msb = SPDR; +      SPDR = in.lsb; +      while (!(SPSR & _BV(SPIF))) ; +      out.lsb = SPDR; +    } else { +      SPDR = in.lsb; +      while (!(SPSR & _BV(SPIF))) ; +      out.lsb = SPDR; +      SPDR = in.msb; +      while (!(SPSR & _BV(SPIF))) ; +      out.msb = SPDR; +    } +    return out.val; +  } +  inline static void transfer(void *buf, size_t count) { +    if (count == 0) return; +    uint8_t *p = (uint8_t *)buf; +    SPDR = *p; +    while (--count > 0) { +      uint8_t out = *(p + 1); +      while (!(SPSR & _BV(SPIF))) ; +      uint8_t in = SPDR; +      SPDR = out; +      *p++ = in; +    } +    while (!(SPSR & _BV(SPIF))) ; +    *p = SPDR; +  } +  // After performing a group of transfers and releasing the chip select +  // signal, this function allows others to access the SPI bus +  inline static void endTransaction(void) { +    #ifdef SPI_TRANSACTION_MISMATCH_LED +    if (!inTransactionFlag) { +      pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); +      digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); +    } +    inTransactionFlag = 0; +    #endif +    if (interruptMode > 0) { +      #ifdef SPI_AVR_EIMSK +      if (interruptMode == 1) { +        SPI_AVR_EIMSK = interruptSave; +      } else +      #endif +      { +        SREG = interruptSave; +      } +    } +  } + +  // Disable the SPI bus +  static void end(); + +  // This function is deprecated.  New applications should use +  // beginTransaction() to configure SPI settings. +  inline static void setBitOrder(uint8_t bitOrder) { +    if (bitOrder == LSBFIRST) SPCR |= _BV(DORD); +    else SPCR &= ~(_BV(DORD)); +  } +  // This function is deprecated.  New applications should use +  // beginTransaction() to configure SPI settings. +  inline static void setDataMode(uint8_t dataMode) { +    SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode; +  } +  // This function is deprecated.  New applications should use +  // beginTransaction() to configure SPI settings. +  inline static void setClockDivider(uint8_t clockDiv) { +    SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK); +    SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK); +  } +  // These undocumented functions should not be used.  SPI.transfer() +  // polls the hardware flag which is automatically cleared as the +  // AVR responds to SPI's interrupt +  inline static void attachInterrupt() { SPCR |= _BV(SPIE); } +  inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); } + +private: +  static uint8_t interruptMode; // 0=none, 1=mask, 2=global +  static uint8_t interruptMask; // which interrupts to mask +  static uint8_t interruptSave; // temp storage, to restore state +  #ifdef SPI_TRANSACTION_MISMATCH_LED +  static uint8_t inTransactionFlag; +  #endif +}; + +extern SPIClass SPI; + +#endif diff --git a/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino new file mode 100644 index 0000000..8104fcb --- /dev/null +++ b/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino @@ -0,0 +1,143 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Shows the output of a Barometric Pressure Sensor on a + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6, 7, 10 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + modified 14 August 2010 + by Tom Igoe + */ + +// the sensor communicates using SPI, so include the library: +#include <SPI.h> + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F;      //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20;  //16 least significant bits of pressure +const int TEMPERATURE = 0x21;   //16 bit temperature reading +const byte READ = 0b11111100;     // SCP1000's read command +const byte WRITE = 0b00000010;   // SCP1000's write command + +// pins used for the connection with the sensor +// the other you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +void setup() { +  Serial.begin(9600); + +  // start the SPI library: +  SPI.begin(); + +  // initalize the  data ready and chip select pins: +  pinMode(dataReadyPin, INPUT); +  pinMode(chipSelectPin, OUTPUT); + +  //Configure SCP1000 for low noise configuration: +  writeRegister(0x02, 0x2D); +  writeRegister(0x01, 0x03); +  writeRegister(0x03, 0x02); +  // give the sensor time to set up: +  delay(100); +} + +void loop() { +  //Select High Resolution Mode +  writeRegister(0x03, 0x0A); + +  // don't do anything until the data ready pin is high: +  if (digitalRead(dataReadyPin) == HIGH) { +    //Read the temperature data +    int tempData = readRegister(0x21, 2); + +    // convert the temperature to celsius and display it: +    float realTemp = (float)tempData / 20.0; +    Serial.print("Temp[C]="); +    Serial.print(realTemp); + + +    //Read the pressure data highest 3 bits: +    byte  pressure_data_high = readRegister(0x1F, 1); +    pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 + +    //Read the pressure data lower 16 bits: +    unsigned int pressure_data_low = readRegister(0x20, 2); +    //combine the two parts into one 19-bit number: +    long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; + +    // display the temperature: +    Serial.println("\tPressure [Pa]=" + String(pressure)); +  } +} + +//Read from or write to register from the SCP1000: +unsigned int readRegister(byte thisRegister, int bytesToRead ) { +  byte inByte = 0;           // incoming byte from the SPI +  unsigned int result = 0;   // result to return +  Serial.print(thisRegister, BIN); +  Serial.print("\t"); +  // SCP1000 expects the register name in the upper 6 bits +  // of the byte. So shift the bits left by two bits: +  thisRegister = thisRegister << 2; +  // now combine the address and the command into one byte +  byte dataToSend = thisRegister & READ; +  Serial.println(thisRegister, BIN); +  // take the chip select low to select the device: +  digitalWrite(chipSelectPin, LOW); +  // send the device the register you want to read: +  SPI.transfer(dataToSend); +  // send a value of 0 to read the first byte returned: +  result = SPI.transfer(0x00); +  // decrement the number of bytes left to read: +  bytesToRead--; +  // if you still have another byte to read: +  if (bytesToRead > 0) { +    // shift the first byte left, then get the second byte: +    result = result << 8; +    inByte = SPI.transfer(0x00); +    // combine the byte you just got with the previous one: +    result = result | inByte; +    // decrement the number of bytes left to read: +    bytesToRead--; +  } +  // take the chip select high to de-select: +  digitalWrite(chipSelectPin, HIGH); +  // return the result: +  return(result); +} + + +//Sends a write command to SCP1000 + +void writeRegister(byte thisRegister, byte thisValue) { + +  // SCP1000 expects the register address in the upper 6 bits +  // of the byte. So shift the bits left by two bits: +  thisRegister = thisRegister << 2; +  // now combine the register address and the command into one byte: +  byte dataToSend = thisRegister | WRITE; + +  // take the chip select low to select the device: +  digitalWrite(chipSelectPin, LOW); + +  SPI.transfer(dataToSend); //Send register location +  SPI.transfer(thisValue);  //Send value to record into register + +  // take the chip select high to de-select: +  digitalWrite(chipSelectPin, HIGH); +} + diff --git a/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino new file mode 100644 index 0000000..b135a74 --- /dev/null +++ b/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino @@ -0,0 +1,71 @@ +/* +  Digital Pot Control + +  This example controls an Analog Devices AD5206 digital potentiometer. +  The AD5206 has 6 potentiometer channels. Each channel's pins are labeled +  A - connect this to voltage +  W - this is the pot's wiper, which changes when you set it +  B - connect this to ground. + + The AD5206 is SPI-compatible,and to command it, you send two bytes, + one with the channel number (0 - 5) and one with the resistance value for the + channel (0 - 255). + + The circuit: +  * All A pins  of AD5206 connected to +5V +  * All B pins of AD5206 connected to ground +  * An LED and a 220-ohm resisor in series connected from each W pin to ground +  * CS - to digital pin 10  (SS pin) +  * SDI - to digital pin 11 (MOSI pin) +  * CLK - to digital pin 13 (SCK pin) + + created 10 Aug 2010 + by Tom Igoe + + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 + +*/ + + +// inslude the SPI library: +#include <SPI.h> + + +// set pin 10 as the slave select for the digital pot: +const int slaveSelectPin = 10; + +void setup() { +  // set the slaveSelectPin as an output: +  pinMode (slaveSelectPin, OUTPUT); +  // initialize SPI: +  SPI.begin(); +} + +void loop() { +  // go through the six channels of the digital pot: +  for (int channel = 0; channel < 6; channel++) { +    // change the resistance on this channel from min to max: +    for (int level = 0; level < 255; level++) { +      digitalPotWrite(channel, level); +      delay(10); +    } +    // wait a second at the top: +    delay(100); +    // change the resistance on this channel from max to min: +    for (int level = 0; level < 255; level++) { +      digitalPotWrite(channel, 255 - level); +      delay(10); +    } +  } + +} + +void digitalPotWrite(int address, int value) { +  // take the SS pin low to select the chip: +  digitalWrite(slaveSelectPin, LOW); +  //  send in the address and value via SPI: +  SPI.transfer(address); +  SPI.transfer(value); +  // take the SS pin high to de-select the chip: +  digitalWrite(slaveSelectPin, HIGH); +} diff --git a/libraries/SPI/keywords.txt b/libraries/SPI/keywords.txt new file mode 100644 index 0000000..fa76165 --- /dev/null +++ b/libraries/SPI/keywords.txt @@ -0,0 +1,36 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI	KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin	KEYWORD2 +end	KEYWORD2 +transfer	KEYWORD2 +setBitOrder	KEYWORD2 +setDataMode	KEYWORD2 +setClockDivider	KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_CLOCK_DIV4	LITERAL1 +SPI_CLOCK_DIV16	LITERAL1 +SPI_CLOCK_DIV64	LITERAL1 +SPI_CLOCK_DIV128	LITERAL1 +SPI_CLOCK_DIV2	LITERAL1 +SPI_CLOCK_DIV8	LITERAL1 +SPI_CLOCK_DIV32	LITERAL1 +SPI_CLOCK_DIV64	LITERAL1 +SPI_MODE0	LITERAL1 +SPI_MODE1	LITERAL1 +SPI_MODE2	LITERAL1 +SPI_MODE3	LITERAL1
\ No newline at end of file diff --git a/libraries/SPI/library.properties b/libraries/SPI/library.properties new file mode 100644 index 0000000..6f1ae20 --- /dev/null +++ b/libraries/SPI/library.properties @@ -0,0 +1,8 @@ +name=SPI +version=1.0 +author=Arduino +maintainer=Arduino <info@arduino.cc> +sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE.  +paragraph= +url=http://arduino.cc/en/Reference/SPI +architectures=avr diff --git a/libraries/SoftwareSerial/SoftwareSerial.cpp b/libraries/SoftwareSerial/SoftwareSerial.cpp new file mode 100644 index 0000000..d1f6c92 --- /dev/null +++ b/libraries/SoftwareSerial/SoftwareSerial.cpp @@ -0,0 +1,518 @@ +/*
 +SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - 
 +Multi-instance software serial library for Arduino/Wiring
 +-- Interrupt-driven receive and other improvements by ladyada
 +   (http://ladyada.net)
 +-- Tuning, circular buffer, derivation from class Print/Stream,
 +   multi-instance support, porting to 8MHz processors,
 +   various optimizations, PROGMEM delay tables, inverse logic and 
 +   direct port writing by Mikal Hart (http://www.arduiniana.org)
 +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
 +-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
 +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
 +
 +This library is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Lesser General Public
 +License as published by the Free Software Foundation; either
 +version 2.1 of the License, or (at your option) any later version.
 +
 +This library is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +Lesser General Public License for more details.
 +
 +You should have received a copy of the GNU Lesser General Public
 +License along with this library; if not, write to the Free Software
 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 +
 +The latest version of this library can always be found at
 +http://arduiniana.org.
 +*/
 +
 +// When set, _DEBUG co-opts pins 11 and 13 for debugging with an
 +// oscilloscope or logic analyzer.  Beware: it also slightly modifies
 +// the bit times, so don't rely on it too much at high baud rates
 +#define _DEBUG 0
 +#define _DEBUG_PIN1 11
 +#define _DEBUG_PIN2 13
 +// 
 +// Includes
 +// 
 +#include <avr/interrupt.h>
 +#include <avr/pgmspace.h>
 +#include <Arduino.h>
 +#include <SoftwareSerial.h>
 +//
 +// Lookup table
 +//
 +typedef struct _DELAY_TABLE
 +{
 +  long baud;
 +  unsigned short rx_delay_centering;
 +  unsigned short rx_delay_intrabit;
 +  unsigned short rx_delay_stopbit;
 +  unsigned short tx_delay;
 +} DELAY_TABLE;
 +
 +#if F_CPU == 16000000
 +
 +static const DELAY_TABLE PROGMEM table[] = 
 +{
 +  //  baud    rxcenter   rxintra    rxstop    tx
 +  { 115200,   1,         17,        17,       12,    },
 +  { 57600,    10,        37,        37,       33,    },
 +  { 38400,    25,        57,        57,       54,    },
 +  { 31250,    31,        70,        70,       68,    },
 +  { 28800,    34,        77,        77,       74,    },
 +  { 19200,    54,        117,       117,      114,   },
 +  { 14400,    74,        156,       156,      153,   },
 +  { 9600,     114,       236,       236,      233,   },
 +  { 4800,     233,       474,       474,      471,   },
 +  { 2400,     471,       950,       950,      947,   },
 +  { 1200,     947,       1902,      1902,     1899,  },
 +  { 600,      1902,      3804,      3804,     3800,  },
 +  { 300,      3804,      7617,      7617,     7614,  },
 +};
 +
 +const int XMIT_START_ADJUSTMENT = 5;
 +
 +#elif F_CPU == 8000000
 +
 +static const DELAY_TABLE table[] PROGMEM = 
 +{
 +  //  baud    rxcenter    rxintra    rxstop  tx
 +  { 115200,   1,          5,         5,      3,      },
 +  { 57600,    1,          15,        15,     13,     },
 +  { 38400,    2,          25,        26,     23,     },
 +  { 31250,    7,          32,        33,     29,     },
 +  { 28800,    11,         35,        35,     32,     },
 +  { 19200,    20,         55,        55,     52,     },
 +  { 14400,    30,         75,        75,     72,     },
 +  { 9600,     50,         114,       114,    112,    },
 +  { 4800,     110,        233,       233,    230,    },
 +  { 2400,     229,        472,       472,    469,    },
 +  { 1200,     467,        948,       948,    945,    },
 +  { 600,      948,        1895,      1895,   1890,   },
 +  { 300,      1895,       3805,      3805,   3802,   },
 +};
 +
 +const int XMIT_START_ADJUSTMENT = 4;
 +
 +#elif F_CPU == 20000000
 +
 +// 20MHz support courtesy of the good people at macegr.com.
 +// Thanks, Garrett!
 +
 +static const DELAY_TABLE PROGMEM table[] =
 +{
 +  //  baud    rxcenter    rxintra    rxstop  tx
 +  { 115200,   3,          21,        21,     18,     },
 +  { 57600,    20,         43,        43,     41,     },
 +  { 38400,    37,         73,        73,     70,     },
 +  { 31250,    45,         89,        89,     88,     },
 +  { 28800,    46,         98,        98,     95,     },
 +  { 19200,    71,         148,       148,    145,    },
 +  { 14400,    96,         197,       197,    194,    },
 +  { 9600,     146,        297,       297,    294,    },
 +  { 4800,     296,        595,       595,    592,    },
 +  { 2400,     592,        1189,      1189,   1186,   },
 +  { 1200,     1187,       2379,      2379,   2376,   },
 +  { 600,      2379,       4759,      4759,   4755,   },
 +  { 300,      4759,       9523,      9523,   9520,   },
 +};
 +
 +const int XMIT_START_ADJUSTMENT = 6;
 +
 +#else
 +
 +#error This version of SoftwareSerial supports only 20, 16 and 8MHz processors
 +
 +#endif
 +
 +//
 +// Statics
 +//
 +SoftwareSerial *SoftwareSerial::active_object = 0;
 +char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; 
 +volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
 +volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
 +
 +//
 +// Debugging
 +//
 +// This function generates a brief pulse
 +// for debugging or measuring on an oscilloscope.
 +inline void DebugPulse(uint8_t pin, uint8_t count)
 +{
 +#if _DEBUG
 +  volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
 +
 +  uint8_t val = *pport;
 +  while (count--)
 +  {
 +    *pport = val | digitalPinToBitMask(pin);
 +    *pport = val;
 +  }
 +#endif
 +}
 +
 +//
 +// Private methods
 +//
 +
 +/* static */ 
 +inline void SoftwareSerial::tunedDelay(uint16_t delay) { 
 +  uint8_t tmp=0;
 +
 +  asm volatile("sbiw    %0, 0x01 \n\t"
 +    "ldi %1, 0xFF \n\t"
 +    "cpi %A0, 0xFF \n\t"
 +    "cpc %B0, %1 \n\t"
 +    "brne .-10 \n\t"
 +    : "+r" (delay), "+a" (tmp)
 +    : "0" (delay)
 +    );
 +}
 +
 +// This function sets the current object as the "listening"
 +// one and returns true if it replaces another 
 +bool SoftwareSerial::listen()
 +{
 +  if (active_object != this)
 +  {
 +    _buffer_overflow = false;
 +    uint8_t oldSREG = SREG;
 +    cli();
 +    _receive_buffer_head = _receive_buffer_tail = 0;
 +    active_object = this;
 +    SREG = oldSREG;
 +    return true;
 +  }
 +
 +  return false;
 +}
 +
 +//
 +// The receive routine called by the interrupt handler
 +//
 +void SoftwareSerial::recv()
 +{
 +
 +#if GCC_VERSION < 40302
 +// Work-around for avr-gcc 4.3.0 OSX version bug
 +// Preserve the registers that the compiler misses
 +// (courtesy of Arduino forum user *etracer*)
 +  asm volatile(
 +    "push r18 \n\t"
 +    "push r19 \n\t"
 +    "push r20 \n\t"
 +    "push r21 \n\t"
 +    "push r22 \n\t"
 +    "push r23 \n\t"
 +    "push r26 \n\t"
 +    "push r27 \n\t"
 +    ::);
 +#endif  
 +
 +  uint8_t d = 0;
 +
 +  // If RX line is high, then we don't see any start bit
 +  // so interrupt is probably not for us
 +  if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
 +  {
 +    // Wait approximately 1/2 of a bit width to "center" the sample
 +    tunedDelay(_rx_delay_centering);
 +    DebugPulse(_DEBUG_PIN2, 1);
 +
 +    // Read each of the 8 bits
 +    for (uint8_t i=0x1; i; i <<= 1)
 +    {
 +      tunedDelay(_rx_delay_intrabit);
 +      DebugPulse(_DEBUG_PIN2, 1);
 +      uint8_t noti = ~i;
 +      if (rx_pin_read())
 +        d |= i;
 +      else // else clause added to ensure function timing is ~balanced
 +        d &= noti;
 +    }
 +
 +    // skip the stop bit
 +    tunedDelay(_rx_delay_stopbit);
 +    DebugPulse(_DEBUG_PIN2, 1);
 +
 +    if (_inverse_logic)
 +      d = ~d;
 +
 +    // if buffer full, set the overflow flag and return
 +    if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) 
 +    {
 +      // save new data in buffer: tail points to where byte goes
 +      _receive_buffer[_receive_buffer_tail] = d; // save new byte
 +      _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
 +    } 
 +    else 
 +    {
 +#if _DEBUG // for scope: pulse pin as overflow indictator
 +      DebugPulse(_DEBUG_PIN1, 1);
 +#endif
 +      _buffer_overflow = true;
 +    }
 +  }
 +
 +#if GCC_VERSION < 40302
 +// Work-around for avr-gcc 4.3.0 OSX version bug
 +// Restore the registers that the compiler misses
 +  asm volatile(
 +    "pop r27 \n\t"
 +    "pop r26 \n\t"
 +    "pop r23 \n\t"
 +    "pop r22 \n\t"
 +    "pop r21 \n\t"
 +    "pop r20 \n\t"
 +    "pop r19 \n\t"
 +    "pop r18 \n\t"
 +    ::);
 +#endif
 +}
 +
 +void SoftwareSerial::tx_pin_write(uint8_t pin_state)
 +{
 +  if (pin_state == LOW)
 +    *_transmitPortRegister &= ~_transmitBitMask;
 +  else
 +    *_transmitPortRegister |= _transmitBitMask;
 +}
 +
 +uint8_t SoftwareSerial::rx_pin_read()
 +{
 +  return *_receivePortRegister & _receiveBitMask;
 +}
 +
 +//
 +// Interrupt handling
 +//
 +
 +/* static */
 +inline void SoftwareSerial::handle_interrupt()
 +{
 +  if (active_object)
 +  {
 +    active_object->recv();
 +  }
 +}
 +
 +#if defined(PCINT0_vect)
 +ISR(PCINT0_vect)
 +{
 +  SoftwareSerial::handle_interrupt();
 +}
 +#endif
 +
 +#if defined(PCINT1_vect)
 +ISR(PCINT1_vect)
 +{
 +  SoftwareSerial::handle_interrupt();
 +}
 +#endif
 +
 +#if defined(PCINT2_vect)
 +ISR(PCINT2_vect)
 +{
 +  SoftwareSerial::handle_interrupt();
 +}
 +#endif
 +
 +#if defined(PCINT3_vect)
 +ISR(PCINT3_vect)
 +{
 +  SoftwareSerial::handle_interrupt();
 +}
 +#endif
 +
 +//
 +// Constructor
 +//
 +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : 
 +  _rx_delay_centering(0),
 +  _rx_delay_intrabit(0),
 +  _rx_delay_stopbit(0),
 +  _tx_delay(0),
 +  _buffer_overflow(false),
 +  _inverse_logic(inverse_logic)
 +{
 +  setTX(transmitPin);
 +  setRX(receivePin);
 +}
 +
 +//
 +// Destructor
 +//
 +SoftwareSerial::~SoftwareSerial()
 +{
 +  end();
 +}
 +
 +void SoftwareSerial::setTX(uint8_t tx)
 +{
 +  pinMode(tx, OUTPUT);
 +  digitalWrite(tx, _inverse_logic ? LOW : HIGH);
 +  _transmitBitMask = digitalPinToBitMask(tx);
 +  uint8_t port = digitalPinToPort(tx);
 +  _transmitPortRegister = portOutputRegister(port);
 +}
 +
 +void SoftwareSerial::setRX(uint8_t rx)
 +{
 +  pinMode(rx, INPUT);
 +  if (!_inverse_logic)
 +    digitalWrite(rx, HIGH);  // pullup for normal logic!
 +  _receivePin = rx;
 +  _receiveBitMask = digitalPinToBitMask(rx);
 +  uint8_t port = digitalPinToPort(rx);
 +  _receivePortRegister = portInputRegister(port);
 +}
 +
 +//
 +// Public methods
 +//
 +
 +void SoftwareSerial::begin(long speed)
 +{
 +  _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
 +
 +  for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
 +  {
 +    long baud = pgm_read_dword(&table[i].baud);
 +    if (baud == speed)
 +    {
 +      _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
 +      _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
 +      _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
 +      _tx_delay = pgm_read_word(&table[i].tx_delay);
 +      break;
 +    }
 +  }
 +
 +  // Set up RX interrupts, but only if we have a valid RX baud rate
 +  if (_rx_delay_stopbit)
 +  {
 +    if (digitalPinToPCICR(_receivePin))
 +    {
 +      *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
 +      *digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin));
 +    }
 +    tunedDelay(_tx_delay); // if we were low this establishes the end
 +  }
 +
 +#if _DEBUG
 +  pinMode(_DEBUG_PIN1, OUTPUT);
 +  pinMode(_DEBUG_PIN2, OUTPUT);
 +#endif
 +
 +  listen();
 +}
 +
 +void SoftwareSerial::end()
 +{
 +  if (digitalPinToPCMSK(_receivePin))
 +    *digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
 +}
 +
 +
 +// Read data from buffer
 +int SoftwareSerial::read()
 +{
 +  if (!isListening())
 +    return -1;
 +
 +  // Empty buffer?
 +  if (_receive_buffer_head == _receive_buffer_tail)
 +    return -1;
 +
 +  // Read from "head"
 +  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
 +  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
 +  return d;
 +}
 +
 +int SoftwareSerial::available()
 +{
 +  if (!isListening())
 +    return 0;
 +
 +  return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
 +}
 +
 +size_t SoftwareSerial::write(uint8_t b)
 +{
 +  if (_tx_delay == 0) {
 +    setWriteError();
 +    return 0;
 +  }
 +
 +  uint8_t oldSREG = SREG;
 +  cli();  // turn off interrupts for a clean txmit
 +
 +  // Write the start bit
 +  tx_pin_write(_inverse_logic ? HIGH : LOW);
 +  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
 +
 +  // Write each of the 8 bits
 +  if (_inverse_logic)
 +  {
 +    for (byte mask = 0x01; mask; mask <<= 1)
 +    {
 +      if (b & mask) // choose bit
 +        tx_pin_write(LOW); // send 1
 +      else
 +        tx_pin_write(HIGH); // send 0
 +    
 +      tunedDelay(_tx_delay);
 +    }
 +
 +    tx_pin_write(LOW); // restore pin to natural state
 +  }
 +  else
 +  {
 +    for (byte mask = 0x01; mask; mask <<= 1)
 +    {
 +      if (b & mask) // choose bit
 +        tx_pin_write(HIGH); // send 1
 +      else
 +        tx_pin_write(LOW); // send 0
 +    
 +      tunedDelay(_tx_delay);
 +    }
 +
 +    tx_pin_write(HIGH); // restore pin to natural state
 +  }
 +
 +  SREG = oldSREG; // turn interrupts back on
 +  tunedDelay(_tx_delay);
 +  
 +  return 1;
 +}
 +
 +void SoftwareSerial::flush()
 +{
 +  if (!isListening())
 +    return;
 +
 +  uint8_t oldSREG = SREG;
 +  cli();
 +  _receive_buffer_head = _receive_buffer_tail = 0;
 +  SREG = oldSREG;
 +}
 +
 +int SoftwareSerial::peek()
 +{
 +  if (!isListening())
 +    return -1;
 +
 +  // Empty buffer?
 +  if (_receive_buffer_head == _receive_buffer_tail)
 +    return -1;
 +
 +  // Read from "head"
 +  return _receive_buffer[_receive_buffer_head];
 +}
 diff --git a/libraries/SoftwareSerial/SoftwareSerial.h b/libraries/SoftwareSerial/SoftwareSerial.h new file mode 100644 index 0000000..a6a60b5 --- /dev/null +++ b/libraries/SoftwareSerial/SoftwareSerial.h @@ -0,0 +1,112 @@ +/*
 +SoftwareSerial.h (formerly NewSoftSerial.h) - 
 +Multi-instance software serial library for Arduino/Wiring
 +-- Interrupt-driven receive and other improvements by ladyada
 +   (http://ladyada.net)
 +-- Tuning, circular buffer, derivation from class Print/Stream,
 +   multi-instance support, porting to 8MHz processors,
 +   various optimizations, PROGMEM delay tables, inverse logic and 
 +   direct port writing by Mikal Hart (http://www.arduiniana.org)
 +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
 +-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
 +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
 +
 +This library is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Lesser General Public
 +License as published by the Free Software Foundation; either
 +version 2.1 of the License, or (at your option) any later version.
 +
 +This library is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +Lesser General Public License for more details.
 +
 +You should have received a copy of the GNU Lesser General Public
 +License along with this library; if not, write to the Free Software
 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 +
 +The latest version of this library can always be found at
 +http://arduiniana.org.
 +*/
 +
 +#ifndef SoftwareSerial_h
 +#define SoftwareSerial_h
 +
 +#include <inttypes.h>
 +#include <Stream.h>
 +
 +/******************************************************************************
 +* Definitions
 +******************************************************************************/
 +
 +#define _SS_MAX_RX_BUFF 64 // RX buffer size
 +#ifndef GCC_VERSION
 +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
 +#endif
 +
 +class SoftwareSerial : public Stream
 +{
 +private:
 +  // per object data
 +  uint8_t _receivePin;
 +  uint8_t _receiveBitMask;
 +  volatile uint8_t *_receivePortRegister;
 +  uint8_t _transmitBitMask;
 +  volatile uint8_t *_transmitPortRegister;
 +
 +  uint16_t _rx_delay_centering;
 +  uint16_t _rx_delay_intrabit;
 +  uint16_t _rx_delay_stopbit;
 +  uint16_t _tx_delay;
 +
 +  uint16_t _buffer_overflow:1;
 +  uint16_t _inverse_logic:1;
 +
 +  // static data
 +  static char _receive_buffer[_SS_MAX_RX_BUFF]; 
 +  static volatile uint8_t _receive_buffer_tail;
 +  static volatile uint8_t _receive_buffer_head;
 +  static SoftwareSerial *active_object;
 +
 +  // private methods
 +  void recv();
 +  uint8_t rx_pin_read();
 +  void tx_pin_write(uint8_t pin_state);
 +  void setTX(uint8_t transmitPin);
 +  void setRX(uint8_t receivePin);
 +
 +  // private static method for timing
 +  static inline void tunedDelay(uint16_t delay);
 +
 +public:
 +  // public methods
 +  SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
 +  ~SoftwareSerial();
 +  void begin(long speed);
 +  bool listen();
 +  void end();
 +  bool isListening() { return this == active_object; }
 +  bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; }
 +  int peek();
 +
 +  virtual size_t write(uint8_t byte);
 +  virtual int read();
 +  virtual int available();
 +  virtual void flush();
 +  
 +  using Print::write;
 +
 +  // public only for easy access by interrupt handlers
 +  static inline void handle_interrupt();
 +};
 +
 +// Arduino 0012 workaround
 +#undef int
 +#undef char
 +#undef long
 +#undef byte
 +#undef float
 +#undef abs
 +#undef round
 +
 +#endif
 diff --git a/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino b/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino new file mode 100644 index 0000000..f659133 --- /dev/null +++ b/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino @@ -0,0 +1,55 @@ +/* +  Software serial multple serial test + + Receives from the hardware serial, sends to software serial. + Receives from software serial, sends to hardware serial. + + The circuit: + * RX is digital pin 10 (connect to TX of other device) + * TX is digital pin 11 (connect to RX of other device) + + Note: + Not all pins on the Mega and Mega 2560 support change interrupts, + so only the following can be used for RX: + 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 + + Not all pins on the Leonardo support change interrupts, + so only the following can be used for RX: + 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). + + created back in the mists of time + modified 25 May 2012 + by Tom Igoe + based on Mikal Hart's example + + This example code is in the public domain. + + */ +#include <SoftwareSerial.h> + +SoftwareSerial mySerial(10, 11); // RX, TX + +void setup() +{ +  // Open serial communications and wait for port to open: +  Serial.begin(57600); +  while (!Serial) { +    ; // wait for serial port to connect. Needed for Leonardo only +  } + + +  Serial.println("Goodnight moon!"); + +  // set the data rate for the SoftwareSerial port +  mySerial.begin(4800); +  mySerial.println("Hello, world?"); +} + +void loop() // run over and over +{ +  if (mySerial.available()) +    Serial.write(mySerial.read()); +  if (Serial.available()) +    mySerial.write(Serial.read()); +} + diff --git a/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino new file mode 100644 index 0000000..95881a6 --- /dev/null +++ b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino @@ -0,0 +1,93 @@ +/* +  Software serial multple serial test + + Receives from the two software serial ports, + sends to the hardware serial port. + + In order to listen on a software port, you call port.listen(). + When using two software serial ports, you have to switch ports + by listen()ing on each one in turn. Pick a logical time to switch + ports, like the end of an expected transmission, or when the + buffer is empty. This example switches ports when there is nothing + more to read from a port + + The circuit: + Two devices which communicate serially are needed. + * First serial device's TX attached to digital pin 2, RX to pin 3 + * Second serial device's TX attached to digital pin 4, RX to pin 5 + + Note: + Not all pins on the Mega and Mega 2560 support change interrupts, + so only the following can be used for RX: + 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 + + Not all pins on the Leonardo support change interrupts, + so only the following can be used for RX: + 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). + + created 18 Apr. 2011 + modified 25 May 2012 + by Tom Igoe + based on Mikal Hart's twoPortRXExample + + This example code is in the public domain. + + */ + +#include <SoftwareSerial.h> +// software serial #1: TX = digital pin 10, RX = digital pin 11 +SoftwareSerial portOne(10, 11); + +// software serial #2: TX = digital pin 8, RX = digital pin 9 +// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega +SoftwareSerial portTwo(8, 9); + +void setup() +{ +  // Open serial communications and wait for port to open: +  Serial.begin(9600); +  while (!Serial) { +    ; // wait for serial port to connect. Needed for Leonardo only +  } + + +  // Start each software serial port +  portOne.begin(9600); +  portTwo.begin(9600); +} + +void loop() +{ +  // By default, the last intialized port is listening. +  // when you want to listen on a port, explicitly select it: +  portOne.listen(); +  Serial.println("Data from port one:"); +  // while there is data coming in, read it +  // and send to the hardware serial port: +  while (portOne.available() > 0) { +    char inByte = portOne.read(); +    Serial.write(inByte); +  } + +  // blank line to separate data from the two ports: +  Serial.println(); + +  // Now listen on the second port +  portTwo.listen(); +  // while there is data coming in, read it +  // and send to the hardware serial port: +  Serial.println("Data from port two:"); +  while (portTwo.available() > 0) { +    char inByte = portTwo.read(); +    Serial.write(inByte); +  } + +  // blank line to separate data from the two ports: +  Serial.println(); +} + + + + + + diff --git a/libraries/SoftwareSerial/keywords.txt b/libraries/SoftwareSerial/keywords.txt new file mode 100644 index 0000000..aaea17c --- /dev/null +++ b/libraries/SoftwareSerial/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map for SoftwareSerial +# (formerly NewSoftSerial) +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SoftwareSerial	KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin	KEYWORD2 +end	KEYWORD2 +read	KEYWORD2 +write	KEYWORD2 +available	KEYWORD2 +isListening	KEYWORD2 +overflow	KEYWORD2 +flush	KEYWORD2 +listen	KEYWORD2 +peek	KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/SoftwareSerial/library.properties b/libraries/SoftwareSerial/library.properties new file mode 100644 index 0000000..a69b54d --- /dev/null +++ b/libraries/SoftwareSerial/library.properties @@ -0,0 +1,8 @@ +name=SoftwareSerial +version=1.0 +author=Arduino +maintainer=Arduino <info@arduino.cc> +sentence=Enables serial communication on digital pins. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/SoftwareSerial +architectures=avr diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp new file mode 100644 index 0000000..553add7 --- /dev/null +++ b/libraries/Wire/Wire.cpp @@ -0,0 +1,303 @@ +/* +  TwoWire.cpp - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +  +  Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +extern "C" { +  #include <stdlib.h> +  #include <string.h> +  #include <inttypes.h> +  #include "twi.h" +} + +#include "Wire.h" + +// Initialize Class Variables ////////////////////////////////////////////////// + +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]; +uint8_t TwoWire::txBufferIndex = 0; +uint8_t TwoWire::txBufferLength = 0; + +uint8_t TwoWire::transmitting = 0; +void (*TwoWire::user_onRequest)(void); +void (*TwoWire::user_onReceive)(int); + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire() +{ +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) +{ +  rxBufferIndex = 0; +  rxBufferLength = 0; + +  txBufferIndex = 0; +  txBufferLength = 0; + +  twi_init(); +} + +void TwoWire::begin(uint8_t address) +{ +  twi_setAddress(address); +  twi_attachSlaveTxEvent(onRequestService); +  twi_attachSlaveRxEvent(onReceiveService); +  begin(); +} + +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 +  if(quantity > BUFFER_LENGTH){ +    quantity = BUFFER_LENGTH; +  } +  // perform blocking read into buffer +  uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); +  // set rx buffer iterator vars +  rxBufferIndex = 0; +  rxBufferLength = read; + +  return read; +} + +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(uint8_t address) +{ +  // indicate that we are transmitting +  transmitting = 1; +  // set address of targeted slave +  txAddress = address; +  // reset tx buffer iterator vars +  txBufferIndex = 0; +  txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) +{ +  beginTransmission((uint8_t)address); +} + +// +//	Originally, 'endTransmission' was an f(void) function. +//	It has been modified to take one parameter indicating +//	whether or not a STOP should be performed on the bus. +//	Calling endTransmission(false) allows a sketch to  +//	perform a repeated start.  +// +//	WARNING: Nothing in the library keeps track of whether +//	the bus tenure has been properly ended with a STOP. It +//	is very possible to leave the bus in a hung state if +//	no call to endTransmission(true) is made. Some I2C +//	devices will behave oddly if they do not see a STOP. +// +uint8_t TwoWire::endTransmission(uint8_t sendStop) +{ +  // transmit buffer (blocking) +  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); +  // reset tx buffer iterator vars +  txBufferIndex = 0; +  txBufferLength = 0; +  // indicate that we are done transmitting +  transmitting = 0; +  return ret; +} + +//	This provides backwards compatibility with the original +//	definition, and expected behaviour, of endTransmission +// +uint8_t TwoWire::endTransmission(void) +{ +  return endTransmission(true); +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(uint8_t data) +{ +  if(transmitting){ +  // in master transmitter mode +    // don't bother if buffer is full +    if(txBufferLength >= BUFFER_LENGTH){ +      setWriteError(); +      return 0; +    } +    // put byte in tx buffer +    txBuffer[txBufferIndex] = data; +    ++txBufferIndex; +    // update amount in buffer    +    txBufferLength = txBufferIndex; +  }else{ +  // in slave send mode +    // reply to master +    twi_transmit(&data, 1); +  } +  return 1; +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(const uint8_t *data, size_t quantity) +{ +  if(transmitting){ +  // in master transmitter mode +    for(size_t i = 0; i < quantity; ++i){ +      write(data[i]); +    } +  }else{ +  // in slave send mode +    // reply to master +    twi_transmit(data, quantity); +  } +  return quantity; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::available(void) +{ +  return rxBufferLength - rxBufferIndex; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::read(void) +{ +  int value = -1; +   +  // get each successive byte on each call +  if(rxBufferIndex < rxBufferLength){ +    value = rxBuffer[rxBufferIndex]; +    ++rxBufferIndex; +  } + +  return value; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::peek(void) +{ +  int value = -1; +   +  if(rxBufferIndex < rxBufferLength){ +    value = rxBuffer[rxBufferIndex]; +  } + +  return value; +} + +void TwoWire::flush(void) +{ +  // XXX: to be implemented. +} + +// behind the scenes function that is called when data is received +void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) +{ +  // don't bother if user hasn't registered a callback +  if(!user_onReceive){ +    return; +  } +  // don't bother if rx buffer is in use by a master requestFrom() op +  // i know this drops data, but it allows for slight stupidity +  // meaning, they may not have read all the master requestFrom() data yet +  if(rxBufferIndex < rxBufferLength){ +    return; +  } +  // copy twi rx buffer into local read buffer +  // this enables new reads to happen in parallel +  for(uint8_t i = 0; i < numBytes; ++i){ +    rxBuffer[i] = inBytes[i];     +  } +  // set rx iterator vars +  rxBufferIndex = 0; +  rxBufferLength = numBytes; +  // alert user program +  user_onReceive(numBytes); +} + +// behind the scenes function that is called when data is requested +void TwoWire::onRequestService(void) +{ +  // don't bother if user hasn't registered a callback +  if(!user_onRequest){ +    return; +  } +  // reset tx buffer iterator vars +  // !!! this will kill any pending pre-master sendTo() activity +  txBufferIndex = 0; +  txBufferLength = 0; +  // alert user program +  user_onRequest(); +} + +// sets function called on slave write +void TwoWire::onReceive( void (*function)(int) ) +{ +  user_onReceive = function; +} + +// sets function called on slave read +void TwoWire::onRequest( void (*function)(void) ) +{ +  user_onRequest = function; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +TwoWire Wire = TwoWire(); + diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h new file mode 100644 index 0000000..732bdc3 --- /dev/null +++ b/libraries/Wire/Wire.h @@ -0,0 +1,80 @@ +/* +  TwoWire.h - TWI/I2C library for Arduino & Wiring +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + +  Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +#ifndef TwoWire_h +#define TwoWire_h + +#include <inttypes.h> +#include "Stream.h" + +#define BUFFER_LENGTH 32 + +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 (*user_onRequest)(void); +    static void (*user_onReceive)(int); +    static void onRequestService(void); +    static void onReceiveService(uint8_t*, int); +  public: +    TwoWire(); +    void begin(); +    void begin(uint8_t); +    void begin(int); +    void setClock(uint32_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) ); + +    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; +}; + +extern TwoWire Wire; + +#endif + diff --git a/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino b/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino new file mode 100644 index 0000000..d97a9e3 --- /dev/null +++ b/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino @@ -0,0 +1,87 @@ +// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder +// by Nicholas Zambetti <http://www.zambetti.com> +// and James Tichenor <http://www.jamestichenor.net> + +// Demonstrates use of the Wire library reading data from the +// Devantech Utrasonic Rangers SFR08 and SFR10 + +// Created 29 April 2006 + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin();                // join i2c bus (address optional for master) +  Serial.begin(9600);          // start serial communication at 9600bps +} + +int reading = 0; + +void loop() +{ +  // step 1: instruct sensor to read echoes +  Wire.beginTransmission(112); // transmit to device #112 (0x70) +  // the address specified in the datasheet is 224 (0xE0) +  // but i2c adressing uses the high 7 bits so it's 112 +  Wire.write(byte(0x00));      // sets register pointer to the command register (0x00) +  Wire.write(byte(0x50));      // command sensor to measure in "inches" (0x50) +  // use 0x51 for centimeters +  // use 0x52 for ping microseconds +  Wire.endTransmission();      // stop transmitting + +  // step 2: wait for readings to happen +  delay(70);                   // datasheet suggests at least 65 milliseconds + +  // step 3: instruct sensor to return a particular echo reading +  Wire.beginTransmission(112); // transmit to device #112 +  Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02) +  Wire.endTransmission();      // stop transmitting + +  // step 4: request reading from sensor +  Wire.requestFrom(112, 2);    // request 2 bytes from slave device #112 + +  // step 5: receive reading from sensor +  if (2 <= Wire.available())   // if two bytes were received +  { +    reading = Wire.read();  // receive high byte (overwrites previous reading) +    reading = reading << 8;    // shift high byte to be high 8 bits +    reading |= Wire.read(); // receive low byte as lower 8 bits +    Serial.println(reading);   // print the reading +  } + +  delay(250);                  // wait a bit since people have to read the output :) +} + + +/* + +// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) +// usage: changeAddress(0x70, 0xE6); + +void changeAddress(byte oldAddress, byte newAddress) +{ +  Wire.beginTransmission(oldAddress); +  Wire.write(byte(0x00)); +  Wire.write(byte(0xA0)); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.write(byte(0x00)); +  Wire.write(byte(0xAA)); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.write(byte(0x00)); +  Wire.write(byte(0xA5)); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.write(byte(0x00)); +  Wire.write(newAddress); +  Wire.endTransmission(); +} + +*/ diff --git a/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino b/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino new file mode 100644 index 0000000..4d1580a --- /dev/null +++ b/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino @@ -0,0 +1,39 @@ +// I2C Digital Potentiometer +// by Nicholas Zambetti <http://www.zambetti.com> +// and Shawn Bonkowski <http://people.interaction-ivrea.it/s.bonkowski/> + +// Demonstrates use of the Wire library +// Controls AD5171 digital potentiometer via I2C/TWI + +// Created 31 March 2006 + +// This example code is in the public domain. + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin(); // join i2c bus (address optional for master) +} + +byte val = 0; + +void loop() +{ +  Wire.beginTransmission(44); // transmit to device #44 (0x2c) +  // device address is specified in datasheet +  Wire.write(byte(0x00));            // sends instruction byte +  Wire.write(val);             // sends potentiometer value byte +  Wire.endTransmission();     // stop transmitting + +  val++;        // increment value +  if (val == 64) // if reached 64th position (max) +  { +    val = 0;    // start over from lowest value +  } +  delay(500); +} + diff --git a/libraries/Wire/examples/master_reader/master_reader.ino b/libraries/Wire/examples/master_reader/master_reader.ino new file mode 100644 index 0000000..74f0155 --- /dev/null +++ b/libraries/Wire/examples/master_reader/master_reader.ino @@ -0,0 +1,32 @@ +// Wire Master Reader +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin();        // join i2c bus (address optional for master) +  Serial.begin(9600);  // start serial for output +} + +void loop() +{ +  Wire.requestFrom(2, 6);    // request 6 bytes from slave device #2 + +  while (Wire.available())   // slave may send less than requested +  { +    char c = Wire.read(); // receive a byte as character +    Serial.print(c);         // print the character +  } + +  delay(500); +} diff --git a/libraries/Wire/examples/master_writer/master_writer.ino b/libraries/Wire/examples/master_writer/master_writer.ino new file mode 100644 index 0000000..482e922 --- /dev/null +++ b/libraries/Wire/examples/master_writer/master_writer.ino @@ -0,0 +1,31 @@ +// Wire Master Writer +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin(); // join i2c bus (address optional for master) +} + +byte x = 0; + +void loop() +{ +  Wire.beginTransmission(4); // transmit to device #4 +  Wire.write("x is ");        // sends five bytes +  Wire.write(x);              // sends one byte +  Wire.endTransmission();    // stop transmitting + +  x++; +  delay(500); +} diff --git a/libraries/Wire/examples/slave_receiver/slave_receiver.ino b/libraries/Wire/examples/slave_receiver/slave_receiver.ino new file mode 100644 index 0000000..15eff9a --- /dev/null +++ b/libraries/Wire/examples/slave_receiver/slave_receiver.ino @@ -0,0 +1,38 @@ +// Wire Slave Receiver +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin(4);                // join i2c bus with address #4 +  Wire.onReceive(receiveEvent); // register event +  Serial.begin(9600);           // start serial for output +} + +void loop() +{ +  delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +void receiveEvent(int howMany) +{ +  while (1 < Wire.available()) // loop through all but the last +  { +    char c = Wire.read(); // receive byte as a character +    Serial.print(c);         // print the character +  } +  int x = Wire.read();    // receive byte as an integer +  Serial.println(x);         // print the integer +} diff --git a/libraries/Wire/examples/slave_sender/slave_sender.ino b/libraries/Wire/examples/slave_sender/slave_sender.ino new file mode 100644 index 0000000..4437ab1 --- /dev/null +++ b/libraries/Wire/examples/slave_sender/slave_sender.ino @@ -0,0 +1,32 @@ +// Wire Slave Sender +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include <Wire.h> + +void setup() +{ +  Wire.begin(2);                // join i2c bus with address #2 +  Wire.onRequest(requestEvent); // register event +} + +void loop() +{ +  delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() +{ +  Wire.write("hello "); // respond with message of 6 bytes +  // as expected by master +} diff --git a/libraries/Wire/keywords.txt b/libraries/Wire/keywords.txt new file mode 100644 index 0000000..ff31475 --- /dev/null +++ b/libraries/Wire/keywords.txt @@ -0,0 +1,32 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin	KEYWORD2 +setClock	KEYWORD2 +beginTransmission	KEYWORD2 +endTransmission	KEYWORD2 +requestFrom	KEYWORD2 +send	KEYWORD2 +receive	KEYWORD2 +onReceive	KEYWORD2 +onRequest	KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire	KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/Wire/library.properties b/libraries/Wire/library.properties new file mode 100644 index 0000000..3246a75 --- /dev/null +++ b/libraries/Wire/library.properties @@ -0,0 +1,8 @@ +name=Wire +version=1.0 +author=Arduino +maintainer=Arduino <info@arduino.cc> +sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For all Arduino boards, BUT Arduino DUE.  +paragraph= +url=http://arduino.cc/en/Reference/Wire +architectures=avr diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c new file mode 100644 index 0000000..201d7d1 --- /dev/null +++ b/libraries/Wire/utility/twi.c @@ -0,0 +1,527 @@ +/* +  twi.c - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + +  Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +#include <math.h> +#include <stdlib.h> +#include <inttypes.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <compat/twi.h> +#include "Arduino.h" // for digitalWrite + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif + +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#include "pins_arduino.h" +#include "twi.h" + +static volatile uint8_t twi_state; +static volatile uint8_t twi_slarw; +static volatile uint8_t twi_sendStop;			// should the transaction end with a stop +static volatile uint8_t twi_inRepStart;			// in the middle of a repeated start + +static void (*twi_onSlaveTransmit)(void); +static void (*twi_onSlaveReceive)(uint8_t*, int); + +static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_masterBufferIndex; +static volatile uint8_t twi_masterBufferLength; + +static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_txBufferIndex; +static volatile uint8_t twi_txBufferLength; + +static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_rxBufferIndex; + +static volatile uint8_t twi_error; + +/*  + * Function twi_init + * Desc     readys twi pins and sets twi bitrate + * Input    none + * Output   none + */ +void twi_init(void) +{ +  // initialize state +  twi_state = TWI_READY; +  twi_sendStop = true;		// default value +  twi_inRepStart = false; +   +  // activate internal pullups for twi. +  digitalWrite(SDA, 1); +  digitalWrite(SCL, 1); + +  // initialize twi prescaler and bit rate +  cbi(TWSR, TWPS0); +  cbi(TWSR, TWPS1); +  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; + +  /* twi bit rate formula from atmega128 manual pg 204 +  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) +  note: TWBR should be 10 or higher for master mode +  It is 72 for a 16mhz Wiring board with 100kHz TWI */ + +  // enable twi module, acks, and twi interrupt +  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +} + +/*  + * Function twi_slaveInit + * Desc     sets slave address and enables interrupt + * Input    none + * Output   none + */ +void twi_setAddress(uint8_t address) +{ +  // set twi slave address (skip over TWGCE bit) +  TWAR = address << 1; +} + +/*  + * Function twi_readFrom + * Desc     attempts to become twi bus master and read a + *          series of bytes from a device on the bus + * Input    address: 7bit i2c device address + *          data: pointer to byte array + *          length: number of bytes to read into array + *          sendStop: Boolean indicating whether to send a stop at the end + * Output   number of bytes read + */ +uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 0; +  } + +  // wait until twi is ready, become master receiver +  while(TWI_READY != twi_state){ +    continue; +  } +  twi_state = TWI_MRX; +  twi_sendStop = sendStop; +  // reset error state (0xFF.. no error occured) +  twi_error = 0xFF; + +  // initialize buffer iteration vars +  twi_masterBufferIndex = 0; +  twi_masterBufferLength = length-1;  // This is not intuitive, read on... +  // On receive, the previously configured ACK/NACK setting is transmitted in +  // response to the received byte before the interrupt is signalled.  +  // Therefor we must actually set NACK when the _next_ to last byte is +  // received, causing that NACK to be sent in response to receiving the last +  // expected byte of data. + +  // build sla+w, slave device address + w bit +  twi_slarw = TW_READ; +  twi_slarw |= address << 1; + +  if (true == twi_inRepStart) { +    // if we're in the repeated start state, then we've already sent the start, +    // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. +    // We need to remove ourselves from the repeated start state before we enable interrupts, +    // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning +    // up. Also, don't enable the START interrupt. There may be one pending from the  +    // repeated start that we sent outselves, and that would really confuse things. +    twi_inRepStart = false;			// remember, we're dealing with an ASYNC ISR +    TWDR = twi_slarw; +    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE);	// enable INTs, but not START +  } +  else +    // send start condition +    TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + +  // wait for read operation to complete +  while(TWI_MRX == twi_state){ +    continue; +  } + +  if (twi_masterBufferIndex < length) +    length = twi_masterBufferIndex; + +  // copy twi buffer to data +  for(i = 0; i < length; ++i){ +    data[i] = twi_masterBuffer[i]; +  } +	 +  return length; +} + +/*  + * Function twi_writeTo + * Desc     attempts to become twi bus master and write a + *          series of bytes to a device on the bus + * Input    address: 7bit i2c device address + *          data: pointer to byte array + *          length: number of bytes in array + *          wait: boolean indicating to wait for write or not + *          sendStop: boolean indicating whether or not to send a stop at the end + * Output   0 .. success + *          1 .. length to long for buffer + *          2 .. address send, NACK received + *          3 .. data send, NACK received + *          4 .. other twi error (lost bus arbitration, bus error, ..) + */ +uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 1; +  } + +  // wait until twi is ready, become master transmitter +  while(TWI_READY != twi_state){ +    continue; +  } +  twi_state = TWI_MTX; +  twi_sendStop = sendStop; +  // reset error state (0xFF.. no error occured) +  twi_error = 0xFF; + +  // initialize buffer iteration vars +  twi_masterBufferIndex = 0; +  twi_masterBufferLength = length; +   +  // copy data to twi buffer +  for(i = 0; i < length; ++i){ +    twi_masterBuffer[i] = data[i]; +  } +   +  // build sla+w, slave device address + w bit +  twi_slarw = TW_WRITE; +  twi_slarw |= address << 1; +   +  // if we're in a repeated start, then we've already sent the START +  // in the ISR. Don't do it again. +  // +  if (true == twi_inRepStart) { +    // if we're in the repeated start state, then we've already sent the start, +    // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. +    // We need to remove ourselves from the repeated start state before we enable interrupts, +    // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning +    // up. Also, don't enable the START interrupt. There may be one pending from the  +    // repeated start that we sent outselves, and that would really confuse things. +    twi_inRepStart = false;			// remember, we're dealing with an ASYNC ISR +    TWDR = twi_slarw;				 +    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE);	// enable INTs, but not START +  } +  else +    // send start condition +    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA);	// enable INTs + +  // wait for write operation to complete +  while(wait && (TWI_MTX == twi_state)){ +    continue; +  } +   +  if (twi_error == 0xFF) +    return 0;	// success +  else if (twi_error == TW_MT_SLA_NACK) +    return 2;	// error: address send, nack received +  else if (twi_error == TW_MT_DATA_NACK) +    return 3;	// error: data send, nack received +  else +    return 4;	// other twi error +} + +/*  + * Function twi_transmit + * Desc     fills slave tx buffer with data + *          must be called in slave tx event callback + * Input    data: pointer to byte array + *          length: number of bytes in array + * Output   1 length too long for buffer + *          2 not slave transmitter + *          0 ok + */ +uint8_t twi_transmit(const uint8_t* data, uint8_t length) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 1; +  } +   +  // ensure we are currently a slave transmitter +  if(TWI_STX != twi_state){ +    return 2; +  } +   +  // set length and copy data into tx buffer +  twi_txBufferLength = length; +  for(i = 0; i < length; ++i){ +    twi_txBuffer[i] = data[i]; +  } +   +  return 0; +} + +/*  + * Function twi_attachSlaveRxEvent + * Desc     sets function called before a slave read operation + * Input    function: callback function to use + * Output   none + */ +void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) +{ +  twi_onSlaveReceive = function; +} + +/*  + * Function twi_attachSlaveTxEvent + * Desc     sets function called before a slave write operation + * Input    function: callback function to use + * Output   none + */ +void twi_attachSlaveTxEvent( void (*function)(void) ) +{ +  twi_onSlaveTransmit = function; +} + +/*  + * Function twi_reply + * Desc     sends byte or readys receive line + * Input    ack: byte indicating to ack or to nack + * Output   none + */ +void twi_reply(uint8_t ack) +{ +  // transmit master read ready signal, with or without ack +  if(ack){ +    TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); +  }else{ +	  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); +  } +} + +/*  + * Function twi_stop + * Desc     relinquishes bus master status + * Input    none + * Output   none + */ +void twi_stop(void) +{ +  // send stop condition +  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + +  // wait for stop condition to be exectued on bus +  // TWINT is not set after a stop condition! +  while(TWCR & _BV(TWSTO)){ +    continue; +  } + +  // update twi state +  twi_state = TWI_READY; +} + +/*  + * Function twi_releaseBus + * Desc     releases bus control + * Input    none + * Output   none + */ +void twi_releaseBus(void) +{ +  // release bus +  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + +  // update twi state +  twi_state = TWI_READY; +} + +ISR(TWI_vect) +{ +  switch(TW_STATUS){ +    // All Master +    case TW_START:     // sent start condition +    case TW_REP_START: // sent repeated start condition +      // copy device address and r/w bit to output register and ack +      TWDR = twi_slarw; +      twi_reply(1); +      break; + +    // Master Transmitter +    case TW_MT_SLA_ACK:  // slave receiver acked address +    case TW_MT_DATA_ACK: // slave receiver acked data +      // if there is data to send, send it, otherwise stop  +      if(twi_masterBufferIndex < twi_masterBufferLength){ +        // copy data to output register and ack +        TWDR = twi_masterBuffer[twi_masterBufferIndex++]; +        twi_reply(1); +      }else{ +	if (twi_sendStop) +          twi_stop(); +	else { +	  twi_inRepStart = true;	// we're gonna send the START +	  // don't enable the interrupt. We'll generate the start, but we  +	  // avoid handling the interrupt until we're in the next transaction, +	  // at the point where we would normally issue the start. +	  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; +	  twi_state = TWI_READY; +	} +      } +      break; +    case TW_MT_SLA_NACK:  // address sent, nack received +      twi_error = TW_MT_SLA_NACK; +      twi_stop(); +      break; +    case TW_MT_DATA_NACK: // data sent, nack received +      twi_error = TW_MT_DATA_NACK; +      twi_stop(); +      break; +    case TW_MT_ARB_LOST: // lost bus arbitration +      twi_error = TW_MT_ARB_LOST; +      twi_releaseBus(); +      break; + +    // Master Receiver +    case TW_MR_DATA_ACK: // data received, ack sent +      // put byte into buffer +      twi_masterBuffer[twi_masterBufferIndex++] = TWDR; +    case TW_MR_SLA_ACK:  // address sent, ack received +      // ack if more bytes are expected, otherwise nack +      if(twi_masterBufferIndex < twi_masterBufferLength){ +        twi_reply(1); +      }else{ +        twi_reply(0); +      } +      break; +    case TW_MR_DATA_NACK: // data received, nack sent +      // put final byte into buffer +      twi_masterBuffer[twi_masterBufferIndex++] = TWDR; +	if (twi_sendStop) +          twi_stop(); +	else { +	  twi_inRepStart = true;	// we're gonna send the START +	  // don't enable the interrupt. We'll generate the start, but we  +	  // avoid handling the interrupt until we're in the next transaction, +	  // at the point where we would normally issue the start. +	  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; +	  twi_state = TWI_READY; +	}     +	break; +    case TW_MR_SLA_NACK: // address sent, nack received +      twi_stop(); +      break; +    // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + +    // Slave Receiver +    case TW_SR_SLA_ACK:   // addressed, returned ack +    case TW_SR_GCALL_ACK: // addressed generally, returned ack +    case TW_SR_ARB_LOST_SLA_ACK:   // lost arbitration, returned ack +    case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack +      // enter slave receiver mode +      twi_state = TWI_SRX; +      // indicate that rx buffer can be overwritten and ack +      twi_rxBufferIndex = 0; +      twi_reply(1); +      break; +    case TW_SR_DATA_ACK:       // data received, returned ack +    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack +      // if there is still room in the rx buffer +      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ +        // put byte in buffer and ack +        twi_rxBuffer[twi_rxBufferIndex++] = TWDR; +        twi_reply(1); +      }else{ +        // otherwise nack +        twi_reply(0); +      } +      break; +    case TW_SR_STOP: // stop or repeated start condition received +      // put a null char after data if there's room +      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ +        twi_rxBuffer[twi_rxBufferIndex] = '\0'; +      } +      // sends ack and stops interface for clock stretching +      twi_stop(); +      // callback to user defined callback +      twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); +      // since we submit rx buffer to "wire" library, we can reset it +      twi_rxBufferIndex = 0; +      // ack future responses and leave slave receiver state +      twi_releaseBus(); +      break; +    case TW_SR_DATA_NACK:       // data received, returned nack +    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack +      // nack back at master +      twi_reply(0); +      break; +     +    // Slave Transmitter +    case TW_ST_SLA_ACK:          // addressed, returned ack +    case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack +      // enter slave transmitter mode +      twi_state = TWI_STX; +      // ready the tx buffer index for iteration +      twi_txBufferIndex = 0; +      // set tx buffer length to be zero, to verify if user changes it +      twi_txBufferLength = 0; +      // request for txBuffer to be filled and length to be set +      // note: user must call twi_transmit(bytes, length) to do this +      twi_onSlaveTransmit(); +      // if they didn't change buffer & length, initialize it +      if(0 == twi_txBufferLength){ +        twi_txBufferLength = 1; +        twi_txBuffer[0] = 0x00; +      } +      // transmit first byte from buffer, fall +    case TW_ST_DATA_ACK: // byte sent, ack returned +      // copy data to output register +      TWDR = twi_txBuffer[twi_txBufferIndex++]; +      // if there is more to send, ack, otherwise nack +      if(twi_txBufferIndex < twi_txBufferLength){ +        twi_reply(1); +      }else{ +        twi_reply(0); +      } +      break; +    case TW_ST_DATA_NACK: // received nack, we are done  +    case TW_ST_LAST_DATA: // received ack, but we are done already! +      // ack future responses +      twi_reply(1); +      // leave slave receiver state +      twi_state = TWI_READY; +      break; + +    // All +    case TW_NO_INFO:   // no state information +      break; +    case TW_BUS_ERROR: // bus error, illegal stop/start +      twi_error = TW_BUS_ERROR; +      twi_stop(); +      break; +  } +} + diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h new file mode 100644 index 0000000..6526593 --- /dev/null +++ b/libraries/Wire/utility/twi.h @@ -0,0 +1,53 @@ +/* +  twi.h - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +#ifndef twi_h +#define twi_h + +  #include <inttypes.h> + +  //#define ATMEGA8 + +  #ifndef TWI_FREQ +  #define TWI_FREQ 100000L +  #endif + +  #ifndef TWI_BUFFER_LENGTH +  #define TWI_BUFFER_LENGTH 32 +  #endif + +  #define TWI_READY 0 +  #define TWI_MRX   1 +  #define TWI_MTX   2 +  #define TWI_SRX   3 +  #define TWI_STX   4 +   +  void twi_init(void); +  void twi_setAddress(uint8_t); +  uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); +  uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); +  uint8_t twi_transmit(const uint8_t*, uint8_t); +  void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); +  void twi_attachSlaveTxEvent( void (*)(void) ); +  void twi_reply(uint8_t); +  void twi_stop(void); +  void twi_releaseBus(void); + +#endif +  | 
