switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

16
digistump-sam/boards.txt Normal file
View File

@@ -0,0 +1,16 @@
digix.name=Digistump DigiX
digix.upload.tool=bossac
digix.upload.protocol=sam-ba
digix.upload.maximum_size=524288
digix.upload.use_1200bps_touch=true
digix.upload.wait_for_upload_port=true
digix.upload.native_usb=true
digix.build.mcu=cortex-m3
digix.build.f_cpu=84000000L
digix.build.core=digix
digix.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON
digix.build.ldscript=linker_scripts/gcc/flash.ld
digix.build.variant=digix
digix.build.variant_system_lib=libsam_sam3x8e_gcc_rel.a
digix.build.vid=0x16D0
digix.build.pid=0x078A

View File

@@ -0,0 +1,217 @@
/*
Copyright (c) 2012 Arduino. 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 Arduino_h
#define Arduino_h
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// some libraries and sketches depend on this
// AVR stuff, assuming Arduino.h or WProgram.h
// automatically includes it...
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "binary.h"
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
// Includes Atmel CMSIS
#include <chip.h>
#include "wiring_constants.h"
#define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L )
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )
void yield(void);
/* sketch */
extern void setup( void ) ;
extern void loop( void ) ;
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
//
#define digitalPinToPort(P) ( g_APinDescription[P].pPort )
#define digitalPinToBitMask(P) ( g_APinDescription[P].ulPin )
#define digitalPinToTimer(P) ( )
//#define analogInPinToBit(P) ( )
#define portOutputRegister(port) ( &(port->PIO_ODSR) )
#define portInputRegister(port) ( &(port->PIO_PDSR) )
//#define portModeRegister(P) ( )
//#define NOT_A_PIN 0 // defined in pio.h/EPioType
#define NOT_A_PORT 0
#define NOT_AN_INTERRUPT -1
typedef enum _EExt_Interrupts
{
EXTERNAL_INT_0=0,
EXTERNAL_INT_1=1,
EXTERNAL_INT_2=2,
EXTERNAL_INT_3=3,
EXTERNAL_INT_4=4,
EXTERNAL_INT_5=5,
EXTERNAL_INT_6=6,
EXTERNAL_INT_7=7,
EXTERNAL_NUM_INTERRUPTS
} EExt_Interrupts ;
typedef void (*voidFuncPtr)( void ) ;
/* Define attribute */
#if defined ( __CC_ARM ) /* Keil uVision 4 */
#define WEAK (__attribute__ ((weak)))
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define WEAK __weak
#elif defined ( __GNUC__ ) /* GCC CS */
#define WEAK __attribute__ ((weak))
#endif
/* Definitions and types for pins */
typedef enum _EAnalogChannel
{
NO_ADC=-1,
ADC0=0,
ADC1,
ADC2,
ADC3,
ADC4,
ADC5,
ADC6,
ADC7,
ADC8,
ADC9,
ADC10,
ADC11,
ADC12,
ADC13,
ADC14,
ADC15,
DA0,
DA1
} EAnalogChannel ;
#define ADC_CHANNEL_NUMBER_NONE 0xffffffff
// Definitions for PWM channels
typedef enum _EPWMChannel
{
NOT_ON_PWM=-1,
PWM_CH0=0,
PWM_CH1,
PWM_CH2,
PWM_CH3,
PWM_CH4,
PWM_CH5,
PWM_CH6,
PWM_CH7
} EPWMChannel ;
// Definitions for TC channels
typedef enum _ETCChannel
{
NOT_ON_TIMER=-1,
TC0_CHA0=0,
TC0_CHB0,
TC0_CHA1,
TC0_CHB1,
TC0_CHA2,
TC0_CHB2,
TC1_CHA3,
TC1_CHB3,
TC1_CHA4,
TC1_CHB4,
TC1_CHA5,
TC1_CHB5,
TC2_CHA6,
TC2_CHB6,
TC2_CHA7,
TC2_CHB7,
TC2_CHA8,
TC2_CHB8
} ETCChannel ;
/**
* Pin Attributes to be OR-ed
*/
#define PIN_ATTR_COMBO (1UL<<0)
#define PIN_ATTR_ANALOG (1UL<<1)
#define PIN_ATTR_DIGITAL (1UL<<2)
#define PIN_ATTR_PWM (1UL<<3)
#define PIN_ATTR_TIMER (1UL<<4)
/* Types used for the tables below */
typedef struct _PinDescription
{
Pio* pPort ;
uint32_t ulPin ;
uint32_t ulPeripheralId ;
EPioType ulPinType ;
uint32_t ulPinConfiguration ;
uint32_t ulPinAttribute ;
EAnalogChannel ulAnalogChannel ; /* Analog pin in the Arduino context (label on the board) */
EAnalogChannel ulADCChannelNumber ; /* ADC Channel number in the SAM device */
EPWMChannel ulPWMChannel ;
ETCChannel ulTCChannel ;
} PinDescription ;
/* Pins table to be instanciated into variant.cpp */
extern const PinDescription g_APinDescription[] ;
#ifdef __cplusplus
} // extern "C"
#include "WCharacter.h"
#include "WString.h"
#include "Tone.h"
#include "WMath.h"
#include "HardwareSerial.h"
#include "wiring_pulse.h"
#endif // __cplusplus
// Include board variant
#include "variant.h"
#include "wiring.h"
#include "wiring_digital.h"
#include "wiring_analog.h"
#include "wiring_shift.h"
#include "WInterrupts.h"
// USB Device
#define USB_VID 0x2341 // arduino LLC vid
#define USB_VID_DIGIX 0x16D0 // Digistump LLC vid
#define USB_PID_LEONARDO 0x0034
#define USB_PID_MICRO 0x0035
#define USB_PID_DUE 0x003E
#define USB_PID_DIGIX 0x078A
#include "USB/USBDesc.h"
#include "USB/USBCore.h"
#include "USB/USBAPI.h"
#endif // Arduino_h

View File

@@ -0,0 +1,26 @@
#ifndef client_h
#define client_h
#include "Print.h"
#include "Stream.h"
#include "IPAddress.h"
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port = 80) =0;
virtual int connect(const char *host, uint16_t port = 80) =0;
virtual size_t write(uint8_t) =0;
virtual size_t write(const uint8_t *buf, size_t size) =0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
#endif

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2011 Arduino. 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 HardwareSerial_h
#define HardwareSerial_h
#include <inttypes.h>
#include "Stream.h"
class HardwareSerial : public Stream
{
public:
void begin(unsigned long);
void end();
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
virtual size_t write(uint8_t) = 0;
using Print::write; // pull in write(str) and write(buf, size) from Print
virtual operator bool() = 0;
};
extern void serialEventRun(void) __attribute__((weak));
#endif

View File

@@ -0,0 +1,56 @@
#include <Arduino.h>
#include <IPAddress.h>
IPAddress::IPAddress()
{
memset(_address, 0, sizeof(_address));
}
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address[0] = first_octet;
_address[1] = second_octet;
_address[2] = third_octet;
_address[3] = fourth_octet;
}
IPAddress::IPAddress(uint32_t address)
{
memcpy(_address, &address, sizeof(_address));
}
IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
}
IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
return *this;
}
IPAddress& IPAddress::operator=(uint32_t address)
{
memcpy(_address, (const uint8_t *)&address, sizeof(_address));
return *this;
}
bool IPAddress::operator==(const uint8_t* addr)
{
return memcmp(addr, _address, sizeof(_address)) == 0;
}
size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for (int i =0; i < 3; i++)
{
n += p.print(_address[i], DEC);
n += p.print('.');
}
n += p.print(_address[3], DEC);
return n;
}

View File

@@ -0,0 +1,76 @@
/*
*
* MIT License:
* Copyright (c) 2011 Adrian McEwen
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* adrianm@mcqn.com 1/1/2011
*/
#ifndef IPAddress_h
#define IPAddress_h
#include <Printable.h>
// A class to make it easier to handle and pass around IP addresses
class IPAddress : public Printable {
private:
uint8_t _address[4]; // IPv4 address
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _address; };
public:
// Constructors
IPAddress();
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() { return *((uint32_t*)_address); };
bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
bool operator==(const uint8_t* addr);
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const { return _address[index]; };
uint8_t& operator[](int index) { return _address[index]; };
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);
IPAddress& operator=(uint32_t address);
virtual size_t printTo(Print& p) const;
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
};
const IPAddress INADDR_NONE(0,0,0,0);
#endif

View File

@@ -0,0 +1,261 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 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
Modified 23 November 2006 by David A. Mellis
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"
#include "Print.h"
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
n += write(*buffer++);
}
return n;
}
size_t Print::print(const __FlashStringHelper *ifsh)
{
return print(reinterpret_cast<const char *>(ifsh));
}
size_t Print::print(const String &s)
{
size_t n = 0;
for (uint16_t i = 0; i < s.length(); i++) {
n += write(s[i]);
}
return n;
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
}
}
size_t Print::print(unsigned long n, int base)
{
if (base == 0) return write(n);
else return printNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(const __FlashStringHelper *ifsh)
{
size_t n = print(ifsh);
n += println();
return n;
}
size_t Print::print(const Printable& x)
{
return x.printTo(*this);
}
size_t Print::println(void)
{
size_t n = print('\r');
n += print('\n');
return n;
}
size_t Print::println(const String &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
size_t Print::println(const Printable& x)
{
size_t n = print(x);
n += println();
return n;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base) {
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) base = 10;
do {
unsigned long m = n;
n /= base;
char c = m - base * n;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return write(str);
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0)
{
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
n += print(".");
}
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
int toPrint = int(remainder);
n += print(toPrint);
remainder -= toPrint;
}
return n;
}

View File

@@ -0,0 +1,81 @@
/*
Print.h - Base class that provides print() and println()
Copyright (c) 2008 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 Print_h
#define Print_h
#include <inttypes.h>
#include <stdio.h> // for size_t
#include "WString.h"
#include "Printable.h"
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
class Print
{
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
void setWriteError(int err = 1) { write_error = err; }
public:
Print() : write_error(0) {}
int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
virtual size_t write(const uint8_t *buffer, size_t size);
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);
};
#endif

View File

@@ -0,0 +1,40 @@
/*
Printable.h - Interface class that allows printing of complex types
Copyright (c) 2011 Adrian McEwen. 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 Printable_h
#define Printable_h
#include <stdlib.h>
class Print;
/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual size_t printTo(Print& p) const = 0;
};
#endif

View File

@@ -0,0 +1,78 @@
/*
Copyright (c) 2012 Arduino. 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
*/
#include <Arduino.h>
#include "Reset.h"
#ifdef __cplusplus
extern "C" {
#endif
__attribute__ ((long_call, section (".ramfunc")))
void banzai() {
// Disable all interrupts
__disable_irq();
// Set bootflag to run SAM-BA bootloader at restart
const int EEFC_FCMD_CGPB = 0x0C;
const int EEFC_KEY = 0x5A;
while (EFC0->EEFC_FSR & EEFC_FSR_FRDY == 0);
EFC0->EEFC_FCR =
EEFC_FCR_FCMD(EEFC_FCMD_CGPB) |
EEFC_FCR_FARG(1) |
EEFC_FCR_FKEY(EEFC_KEY);
while (EFC0->EEFC_FSR & EEFC_FSR_FRDY == 0);
// From here flash memory is no more available.
// Memory swap needs some time to stabilize
for (uint32_t i=0; i<1000000; i++)
// force compiler to not optimize this
__asm__ __volatile__("");
// BANZAIIIIIII!!!
const int RSTC_KEY = 0xA5;
RSTC->RSTC_CR =
RSTC_CR_KEY(RSTC_KEY) |
RSTC_CR_PROCRST |
RSTC_CR_PERRST;
while (true);
}
static int ticks = -1;
void initiateReset(int _ticks) {
ticks = _ticks;
}
void cancelReset() {
ticks = -1;
}
void tickReset() {
if (ticks == -1)
return;
ticks--;
if (ticks == 0)
banzai();
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2012 Arduino. 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 RESET_H
#define RESET_H
#ifdef __cplusplus
extern "C" {
#endif
void initiateReset(int ms);
void tickReset();
void cancelReset();
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "RingBuffer.h"
#include <string.h>
RingBuffer::RingBuffer( void )
{
memset( _aucBuffer, 0, SERIAL_BUFFER_SIZE ) ;
_iHead=0 ;
_iTail=0 ;
}
void RingBuffer::store_char( uint8_t c )
{
int i = (uint32_t)(_iHead + 1) % SERIAL_BUFFER_SIZE ;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if ( i != _iTail )
{
_aucBuffer[_iHead] = c ;
_iHead = i ;
}
}

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2011 Arduino. 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 _RING_BUFFER_
#define _RING_BUFFER_
#include <stdint.h>
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which head is the index of the location
// to which to write the next incoming character and tail is the index of the
// location from which to read.
#define SERIAL_BUFFER_SIZE 64
class RingBuffer
{
public:
uint8_t _aucBuffer[SERIAL_BUFFER_SIZE] ;
int _iHead ;
int _iTail ;
public:
RingBuffer( void ) ;
void store_char( uint8_t c ) ;
} ;
#endif /* _RING_BUFFER_ */

View File

@@ -0,0 +1,9 @@
#ifndef server_h
#define server_h
class Server : public Print {
public:
virtual void begin() =0;
};
#endif

View File

@@ -0,0 +1,270 @@
/*
Stream.cpp - adds parsing methods to Stream class
Copyright (c) 2008 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
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
*/
#include "Arduino.h"
#include "Stream.h"
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
// private method to read stream with timeout
int Stream::timedRead()
{
int c;
_startMillis = millis();
do {
c = read();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// private method to peek stream with timeout
int Stream::timedPeek()
{
int c;
_startMillis = millis();
do {
c = peek();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters
int Stream::peekNextDigit()
{
int c;
while (1) {
c = timedPeek();
if (c < 0) return c; // timeout
if (c == '-') return c;
if (c >= '0' && c <= '9') return c;
read(); // discard non-numeric
}
}
// Public Methods
//////////////////////////////////////////////////////////////
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
{
_timeout = timeout;
}
// find returns true if the target string is found
bool Stream::find(char *target)
{
return findUntil(target, NULL);
}
// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
}
// as find but search ends if the terminator string is found
bool Stream::findUntil(char *target, char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
// reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;
if( *target == 0)
return true; // return true if target is a null string
while( (c = timedRead()) > 0){
if(c != target[index])
index = 0; // reset index if any char does not match
if( c == target[index]){
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
if(++index >= targetLen){ // return true if all chars in the target match
return true;
}
}
if(termLen > 0 && c == terminator[termIndex]){
if(++termIndex >= termLen)
return false; // return false if terminate string found before target string
}
else
termIndex = 0;
}
return false;
}
// returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped
// function is terminated by the first character that is not a digit.
long Stream::parseInt()
{
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
}
// as above but a given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar)
{
boolean isNegative = false;
long value = 0;
int c;
c = peekNextDigit();
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if(c == skipChar)
; // ignore this charactor
else if(c == '-')
isNegative = true;
else if(c >= '0' && c <= '9') // is c a digit?
value = value * 10 + c - '0';
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || c == skipChar );
if(isNegative)
value = -value;
return value;
}
// as parseInt but returns a floating point value
float Stream::parseFloat()
{
return parseFloat(NO_SKIP_CHAR);
}
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar){
boolean isNegative = false;
boolean isFraction = false;
long value = 0;
char c;
float fraction = 1.0;
c = peekNextDigit();
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if(c == skipChar)
; // ignore
else if(c == '-')
isNegative = true;
else if (c == '.')
isFraction = true;
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
if(isFraction)
fraction *= 0.1;
}
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
if(isNegative)
value = -value;
if(isFraction)
return value * fraction;
else
return value;
}
// read characters from stream into buffer
// terminates if length characters have been read, or timeout (see setTimeout)
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
//
size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) break;
*buffer++ = (char)c;
count++;
}
return count;
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if (length < 1) return 0;
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || c == terminator) break;
*buffer++ = (char)c;
index++;
}
return index; // return number of characters, not including null terminator
}
String Stream::readString()
{
String ret;
int c = timedRead();
while (c >= 0)
{
ret += (char)c;
c = timedRead();
}
return ret;
}
String Stream::readStringUntil(char terminator)
{
String ret;
int c = timedRead();
while (c >= 0 && c != terminator)
{
ret += (char)c;
c = timedRead();
}
return ret;
}

View File

@@ -0,0 +1,96 @@
/*
Stream.h - base class for character-based streams.
Copyright (c) 2010 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
parsing functions based on TextFinder library by Michael Margolis
*/
#ifndef Stream_h
#define Stream_h
#include <inttypes.h>
#include "Print.h"
// compatability macros for testing
/*
#define getInt() parseInt()
#define getInt(skipChar) parseInt(skipchar)
#define getFloat() parseFloat()
#define getFloat(skipChar) parseFloat(skipChar)
#define getString( pre_string, post_string, buffer, length)
readBytesBetween( pre_string, terminator, buffer, length)
*/
class Stream : public Print
{
protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual void flush() = 0;
Stream() {_timeout=1000;}
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
bool find(char *target); // reads data from the stream until the target string is found
// returns true if target string is found, false if timed out (see setTimeout)
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
long parseInt(); // returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped
// integer is terminated by the first character that is not a digit.
float parseFloat(); // float version of parseInt
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
// terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
// Arduino String functions to be added here
String readString();
String readStringUntil(char terminator);
protected:
long parseInt(char skipChar); // as above but the given skipChar is ignored
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float parseFloat(char skipChar); // as above but the given skipChar is ignored
};
#endif

View File

@@ -0,0 +1,616 @@
/* Tone.cpp
A Tone Generator Library
Written by Brett Hagman
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
Version Modified By Date Comments
------- ----------- -------- --------
0001 B Hagman 09/08/02 Initial coding
0002 B Hagman 09/08/18 Multiple pins
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
0004 B Hagman 09/09/26 Fixed problems with ATmega8
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
09/11/25 Changed pin toggle method to XOR
09/11/25 Fixed timer0 from being excluded
0006 D Mellis 09/12/29 Replaced objects with functions
0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
*************************************************/
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"
#include "pins_arduino.h"
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
#define TCCR2A TCCR2
#define TCCR2B TCCR2
#define COM2A1 COM21
#define COM2A0 COM20
#define OCR2A OCR2
#define TIMSK2 TIMSK
#define OCIE2A OCIE2
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#define TIMSK1 TIMSK
#endif
// timerx_toggle_count:
// > 0 - duration specified
// = 0 - stopped
// < 0 - infinitely (until stop() method called, or new play() called)
#if !defined(__AVR_ATmega8__)
volatile long timer0_toggle_count;
volatile uint8_t *timer0_pin_port;
volatile uint8_t timer0_pin_mask;
#endif
volatile long timer1_toggle_count;
volatile uint8_t *timer1_pin_port;
volatile uint8_t timer1_pin_mask;
volatile long timer2_toggle_count;
volatile uint8_t *timer2_pin_port;
volatile uint8_t timer2_pin_mask;
#if defined(TIMSK3)
volatile long timer3_toggle_count;
volatile uint8_t *timer3_pin_port;
volatile uint8_t timer3_pin_mask;
#endif
#if defined(TIMSK4)
volatile long timer4_toggle_count;
volatile uint8_t *timer4_pin_port;
volatile uint8_t timer4_pin_mask;
#endif
#if defined(TIMSK5)
volatile long timer5_toggle_count;
volatile uint8_t *timer5_pin_port;
volatile uint8_t timer5_pin_mask;
#endif
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
#elif defined(__AVR_ATmega8__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#elif defined(__AVR_ATmega32U4__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER3
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#else
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
// Leave timer 0 to last.
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
#endif
static int8_t toneBegin(uint8_t _pin)
{
int8_t _timer = -1;
// if we're already using the pin, the timer should be configured.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
return pgm_read_byte(tone_pin_to_timer_PGM + i);
}
}
// search for an unused timer.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == 255) {
tone_pins[i] = _pin;
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
break;
}
}
if (_timer != -1)
{
// Set timer specific stuff
// All timers in CTC mode
// 8 bit timers will require changing prescalar values,
// whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
switch (_timer)
{
#if defined(TCCR0A) && defined(TCCR0B)
case 0:
// 8 bit timer
TCCR0A = 0;
TCCR0B = 0;
bitWrite(TCCR0A, WGM01, 1);
bitWrite(TCCR0B, CS00, 1);
timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer0_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
case 1:
// 16 bit timer
TCCR1A = 0;
TCCR1B = 0;
bitWrite(TCCR1B, WGM12, 1);
bitWrite(TCCR1B, CS10, 1);
timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer1_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR2A) && defined(TCCR2B)
case 2:
// 8 bit timer
TCCR2A = 0;
TCCR2B = 0;
bitWrite(TCCR2A, WGM21, 1);
bitWrite(TCCR2B, CS20, 1);
timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer2_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
case 3:
// 16 bit timer
TCCR3A = 0;
TCCR3B = 0;
bitWrite(TCCR3B, WGM32, 1);
bitWrite(TCCR3B, CS30, 1);
timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer3_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
case 4:
// 16 bit timer
TCCR4A = 0;
TCCR4B = 0;
#if defined(WGM42)
bitWrite(TCCR4B, WGM42, 1);
#elif defined(CS43)
#warning this may not be correct
// atmega32u4
bitWrite(TCCR4B, CS43, 1);
#endif
bitWrite(TCCR4B, CS40, 1);
timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer4_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
case 5:
// 16 bit timer
TCCR5A = 0;
TCCR5B = 0;
bitWrite(TCCR5B, WGM52, 1);
bitWrite(TCCR5B, CS50, 1);
timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer5_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
}
}
return _timer;
}
// frequency (in hertz) and duration (in milliseconds).
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
{
uint8_t prescalarbits = 0b001;
long toggle_count = 0;
uint32_t ocr = 0;
int8_t _timer;
_timer = toneBegin(_pin);
if (_timer >= 0)
{
// Set the pinMode as OUTPUT
pinMode(_pin, OUTPUT);
// if we are using an 8 bit timer, scan through prescalars to find the best fit
if (_timer == 0 || _timer == 2)
{
ocr = F_CPU / frequency / 2 - 1;
prescalarbits = 0b001; // ck/1: same for both timers
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 8 - 1;
prescalarbits = 0b010; // ck/8: same for both timers
if (_timer == 2 && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 32 - 1;
prescalarbits = 0b011;
}
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = _timer == 0 ? 0b011 : 0b100;
if (_timer == 2 && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 128 - 1;
prescalarbits = 0b101;
}
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 256 - 1;
prescalarbits = _timer == 0 ? 0b100 : 0b110;
if (ocr > 255)
{
// can't do any better than /1024
ocr = F_CPU / frequency / 2 / 1024 - 1;
prescalarbits = _timer == 0 ? 0b101 : 0b111;
}
}
}
}
#if defined(TCCR0B)
if (_timer == 0)
{
TCCR0B = prescalarbits;
}
else
#endif
#if defined(TCCR2B)
{
TCCR2B = prescalarbits;
}
#else
{
// dummy place holder to make the above ifdefs work
}
#endif
}
else
{
// two choices for the 16 bit timers: ck/1 or ck/64
ocr = F_CPU / frequency / 2 - 1;
prescalarbits = 0b001;
if (ocr > 0xffff)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011;
}
if (_timer == 1)
{
#if defined(TCCR1B)
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
#endif
}
#if defined(TCCR3B)
else if (_timer == 3)
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR4B)
else if (_timer == 4)
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR5B)
else if (_timer == 5)
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
#endif
}
// Calculate the toggle count
if (duration > 0)
{
toggle_count = 2 * frequency * duration / 1000;
}
else
{
toggle_count = -1;
}
// Set the OCR for the given timer,
// set the toggle count,
// then turn on the interrupts
switch (_timer)
{
#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
case 0:
OCR0A = ocr;
timer0_toggle_count = toggle_count;
bitWrite(TIMSK0, OCIE0A, 1);
break;
#endif
case 1:
#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK1, OCIE1A, 1);
#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
// this combination is for at least the ATmega32
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK, OCIE1A, 1);
#endif
break;
#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
case 2:
OCR2A = ocr;
timer2_toggle_count = toggle_count;
bitWrite(TIMSK2, OCIE2A, 1);
break;
#endif
#if defined(TIMSK3)
case 3:
OCR3A = ocr;
timer3_toggle_count = toggle_count;
bitWrite(TIMSK3, OCIE3A, 1);
break;
#endif
#if defined(TIMSK4)
case 4:
OCR4A = ocr;
timer4_toggle_count = toggle_count;
bitWrite(TIMSK4, OCIE4A, 1);
break;
#endif
#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
case 5:
OCR5A = ocr;
timer5_toggle_count = toggle_count;
bitWrite(TIMSK5, OCIE5A, 1);
break;
#endif
}
}
}
// XXX: this function only works properly for timer 2 (the only one we use
// currently). for the others, it should end the tone, but won't restore
// proper PWM functionality for the timer.
void disableTimer(uint8_t _timer)
{
switch (_timer)
{
case 0:
#if defined(TIMSK0)
TIMSK0 = 0;
#elif defined(TIMSK)
TIMSK = 0; // atmega32
#endif
break;
#if defined(TIMSK1) && defined(OCIE1A)
case 1:
bitWrite(TIMSK1, OCIE1A, 0);
break;
#endif
case 2:
#if defined(TIMSK2) && defined(OCIE2A)
bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt
#endif
#if defined(TCCR2A) && defined(WGM20)
TCCR2A = (1 << WGM20);
#endif
#if defined(TCCR2B) && defined(CS22)
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
#endif
#if defined(OCR2A)
OCR2A = 0;
#endif
break;
#if defined(TIMSK3)
case 3:
TIMSK3 = 0;
break;
#endif
#if defined(TIMSK4)
case 4:
TIMSK4 = 0;
break;
#endif
#if defined(TIMSK5)
case 5:
TIMSK5 = 0;
break;
#endif
}
}
void noTone(uint8_t _pin)
{
int8_t _timer = -1;
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
tone_pins[i] = 255;
}
}
disableTimer(_timer);
digitalWrite(_pin, 0);
}
#ifdef USE_TIMER0
ISR(TIMER0_COMPA_vect)
{
if (timer0_toggle_count != 0)
{
// toggle the pin
*timer0_pin_port ^= timer0_pin_mask;
if (timer0_toggle_count > 0)
timer0_toggle_count--;
}
else
{
disableTimer(0);
*timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER1
ISR(TIMER1_COMPA_vect)
{
if (timer1_toggle_count != 0)
{
// toggle the pin
*timer1_pin_port ^= timer1_pin_mask;
if (timer1_toggle_count > 0)
timer1_toggle_count--;
}
else
{
disableTimer(1);
*timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER2
ISR(TIMER2_COMPA_vect)
{
if (timer2_toggle_count != 0)
{
// toggle the pin
*timer2_pin_port ^= timer2_pin_mask;
if (timer2_toggle_count > 0)
timer2_toggle_count--;
}
else
{
// need to call noTone() so that the tone_pins[] entry is reset, so the
// timer gets initialized next time we call tone().
// XXX: this assumes timer 2 is always the first one used.
noTone(tone_pins[0]);
// disableTimer(2);
// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER3
ISR(TIMER3_COMPA_vect)
{
if (timer3_toggle_count != 0)
{
// toggle the pin
*timer3_pin_port ^= timer3_pin_mask;
if (timer3_toggle_count > 0)
timer3_toggle_count--;
}
else
{
disableTimer(3);
*timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER4
ISR(TIMER4_COMPA_vect)
{
if (timer4_toggle_count != 0)
{
// toggle the pin
*timer4_pin_port ^= timer4_pin_mask;
if (timer4_toggle_count > 0)
timer4_toggle_count--;
}
else
{
disableTimer(4);
*timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER5
ISR(TIMER5_COMPA_vect)
{
if (timer5_toggle_count != 0)
{
// toggle the pin
*timer5_pin_port ^= timer5_pin_mask;
if (timer5_toggle_count > 0)
timer5_toggle_count--;
}
else
{
disableTimer(5);
*timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
}
}
#endif

View File

@@ -0,0 +1,23 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_TONE_
#define _WIRING_TONE_
#endif /* _WIRING_TONE_ */

View File

@@ -0,0 +1,137 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "UARTClass.h"
// Constructors ////////////////////////////////////////////////////////////////
UARTClass::UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer )
{
_rx_buffer = pRx_buffer ;
_pUart=pUart ;
_dwIrq=dwIrq ;
_dwId=dwId ;
}
// Public Methods //////////////////////////////////////////////////////////////
void UARTClass::begin( const uint32_t dwBaudRate )
{
// Configure PMC
pmc_enable_periph_clk( _dwId ) ;
// Disable PDC channel
_pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS ;
// Reset and disable receiver and transmitter
_pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS ;
// Configure mode
_pUart->UART_MR = UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL ;
// Configure baudrate (asynchronous, no oversampling)
_pUart->UART_BRGR = (SystemCoreClock / dwBaudRate) >> 4 ;
// Configure interrupts
_pUart->UART_IDR = 0xFFFFFFFF;
_pUart->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
// Enable UART interrupt in NVIC
NVIC_EnableIRQ(_dwIrq);
// Enable receiver and transmitter
_pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ;
}
void UARTClass::end( void )
{
// clear any received data
_rx_buffer->_iHead = _rx_buffer->_iTail ;
// Disable UART interrupt in NVIC
NVIC_DisableIRQ( _dwIrq ) ;
// Wait for any outstanding data to be sent
flush();
pmc_disable_periph_clk( _dwId ) ;
}
int UARTClass::available( void )
{
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
}
int UARTClass::peek( void )
{
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
}
int UARTClass::read( void )
{
// if the head isn't ahead of the tail, we don't have any characters
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
_rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ;
return uc ;
}
void UARTClass::flush( void )
{
// Wait for transmission to complete
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
;
}
size_t UARTClass::write( const uint8_t uc_data )
{
// Check if the transmitter is ready
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
;
// Send character
_pUart->UART_THR = uc_data;
return 1;
}
void UARTClass::IrqHandler( void )
{
uint32_t status = _pUart->UART_SR;
// Did we receive data ?
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
_rx_buffer->store_char(_pUart->UART_RHR);
// Acknowledge errors
if ((status & UART_SR_OVRE) == UART_SR_OVRE ||
(status & UART_SR_FRAME) == UART_SR_FRAME)
{
// TODO: error reporting outside ISR
_pUart->UART_CR |= UART_CR_RSTSTA;
}
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2011 Arduino. 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 _UART_CLASS_
#define _UART_CLASS_
#include "HardwareSerial.h"
#include "RingBuffer.h"
// Includes Atmel CMSIS
#include <chip.h>
class UARTClass : public HardwareSerial
{
protected:
RingBuffer *_rx_buffer ;
protected:
Uart* _pUart ;
IRQn_Type _dwIrq ;
uint32_t _dwId ;
public:
UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) ;
void begin( const uint32_t dwBaudRate ) ;
void end( void ) ;
int available( void ) ;
int peek( void ) ;
int read( void ) ;
void flush( void ) ;
size_t write( const uint8_t c ) ;
void IrqHandler( void ) ;
#if defined __GNUC__ /* GCC CS3 */
using Print::write ; // pull in write(str) and write(buf, size) from Print
#elif defined __ICCARM__ /* IAR Ewarm 5.41+ */
// virtual void write( const char *str ) ;
// virtual void write( const uint8_t *buffer, size_t size ) ;
#endif
operator bool() { return true; }; // UART always active
};
#endif // _UART_CLASS_

View File

@@ -0,0 +1,183 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include <Arduino.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <wiring_digital.h>
#include <wiring_constants.h>
#include "USARTClass.h"
// Constructors ////////////////////////////////////////////////////////////////
USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer )
{
_rx_buffer = pRx_buffer ;
_pUsart=pUsart ;
_dwIrq=dwIrq ;
_dwId=dwId ;
ctsEn=false;
}
// Public Methods //////////////////////////////////////////////////////////////
void USARTClass::begin( const uint32_t dwBaudRate )
{
if(ctsEn)
{
pinMode(ctsPin, OUTPUT);
digitalWrite(ctsPin, HIGH);
cts=HIGH;
}
// Configure PMC
pmc_enable_periph_clk( _dwId ) ;
// Disable PDC channel
_pUsart->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS ;
// Reset and disable receiver and transmitter
_pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS ;
// Configure mode
_pUsart->US_MR = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK | US_MR_CHRL_8_BIT | US_MR_PAR_NO |
US_MR_NBSTOP_1_BIT | US_MR_CHMODE_NORMAL;
// Configure baudrate, asynchronous no oversampling
_pUsart->US_BRGR = (SystemCoreClock / dwBaudRate) / 16 ;
// Configure interrupts
_pUsart->US_IDR = 0xFFFFFFFF;
_pUsart->US_IER = US_IER_RXRDY | US_IER_OVRE | US_IER_FRAME;
// Enable UART interrupt in NVIC
NVIC_EnableIRQ( _dwIrq ) ;
// Enable receiver and transmitter
_pUsart->US_CR = US_CR_RXEN | US_CR_TXEN ;
if(ctsEn)
ctsCheck();
}
void USARTClass::enableCTS(boolean enabled)
{
ctsEn=enabled;
if(ctsEn)
ctsCheck();
}
void USARTClass::setCTSPin(int pin)
{
ctsPin=pin;
}
void USARTClass::end( void )
{
// clear any received data
_rx_buffer->_iHead = _rx_buffer->_iTail ;
// Disable UART interrupt in NVIC
NVIC_DisableIRQ( _dwIrq ) ;
// Wait for any outstanding data to be sent
flush();
pmc_disable_periph_clk( _dwId ) ;
}
int USARTClass::available( void )
{
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
}
int USARTClass::peek( void )
{
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
}
int USARTClass::read( void )
{
// if the head isn't ahead of the tail, we don't have any characters
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
_rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ;
if(ctsEn)
ctsCheck();
return uc ;
}
void USARTClass::flush( void )
{
// Wait for transmission to complete
while ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY)
;
}
size_t USARTClass::write( const uint8_t uc_data )
{
// Check if the transmitter is ready
while ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY)
;
// Send character
_pUsart->US_THR = uc_data ;
return 1;
}
void USARTClass::ctsCheck()
{
avail=available();
if(avail > SERIAL_BUFFER_SIZE - 8 && cts==LOW)
{
digitalWrite(ctsPin, HIGH);
cts=HIGH;
}
else if(avail < SERIAL_BUFFER_SIZE - 8 && cts==HIGH)
{
digitalWrite(ctsPin, LOW);
cts=LOW;
}
}
void USARTClass::IrqHandler( void )
{
uint32_t status = _pUsart->US_CSR;
// Did we receive data ?
if ((status & US_CSR_RXRDY) == US_CSR_RXRDY)
_rx_buffer->store_char( _pUsart->US_RHR ) ;
// Acknowledge errors
if ((status & US_CSR_OVRE) == US_CSR_OVRE ||
(status & US_CSR_FRAME) == US_CSR_FRAME)
{
// TODO: error reporting outside ISR
_pUsart->US_CR |= US_CR_RSTSTA;
}
if(ctsEn)
ctsCheck();
}

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2011 Arduino. 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 _USART_CLASS_
#define _USART_CLASS_
#include <HardwareSerial.h>
#include <RingBuffer.h>
#include <Arduino.h>
#include <wiring_digital.h>
#include <wiring_constants.h>
// Includes Atmel CMSIS
#include <chip.h>
class USARTClass : public HardwareSerial
{
protected:
RingBuffer *_rx_buffer ;
protected:
Usart* _pUsart ;
IRQn_Type _dwIrq ;
uint32_t _dwId ;
int cts;
int ctsEn;
int ctsPin;
int avail;
public:
USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) ;
void begin( const uint32_t dwBaudRate ) ;
void end( void ) ;
void enableCTS( boolean );
void setCTSPin( int ) ;
int available( void ) ;
int peek( void ) ;
int read( void ) ;
void flush( void ) ;
size_t write( const uint8_t c ) ;
void ctsCheck();
void IrqHandler( void ) ;
#if defined __GNUC__ /* GCC CS3 */
using Print::write ; // pull in write(str) and write(buf, size) from Print
#elif defined __ICCARM__ /* IAR Ewarm 5.41+ */
// virtual void write( const char *str ) ;
// virtual void write( const uint8_t *buffer, size_t size ) ;
#endif
operator bool() { return true; }; // USART always active
};
#endif // _USART_CLASS_

View File

@@ -0,0 +1,301 @@
/* Copyright (c) 2011, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#include "Arduino.h"
#include "USBAPI.h"
#include "Reset.h"
#ifdef CDC_ENABLED
#define CDC_SERIAL_BUFFER_SIZE 512
/* For information purpose only since RTS is not always handled by the terminal application */
#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready
#define CDC_LINESTATE_RTS 0x02 // Ready to Send
#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
struct ring_buffer
{
uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
volatile uint32_t head;
volatile uint32_t tail;
};
ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
typedef struct
{
uint32_t dwDTERate;
uint8_t bCharFormat;
uint8_t bParityType;
uint8_t bDataBits;
uint8_t lineState;
} LineInfo;
static volatile LineInfo _usbLineInfo = {
57600, // dWDTERate
0x00, // bCharFormat
0x00, // bParityType
0x08, // bDataBits
0x00 // lineState
};
_Pragma("pack(1)")
static const CDCDescriptor _cdcInterface =
{
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
// CDC communication interface
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10, 0x10),
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,512,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,512,0)
};
static const CDCDescriptor _cdcOtherInterface =
{
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
// CDC communication interface
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10, 0x10),
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,64,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,64,0)
};
_Pragma("pack()")
int WEAK CDC_GetInterface(uint8_t* interfaceNum)
{
interfaceNum[0] += 2; // uses 2
return USBD_SendControl(0,&_cdcInterface,sizeof(_cdcInterface));
}
int WEAK CDC_GetOtherInterface(uint8_t* interfaceNum)
{
interfaceNum[0] += 2; // uses 2
return USBD_SendControl(0,&_cdcOtherInterface,sizeof(_cdcOtherInterface));
}
bool WEAK CDC_Setup(Setup& setup)
{
uint8_t r = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
{
if (CDC_GET_LINE_CODING == r)
{
USBD_SendControl(0,(void*)&_usbLineInfo,7);
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (CDC_SET_LINE_CODING == r)
{
USBD_RecvControl((void*)&_usbLineInfo,7);
return true;
}
if (CDC_SET_CONTROL_LINE_STATE == r)
{
_usbLineInfo.lineState = setup.wValueL;
// auto-reset into the bootloader is triggered when the port, already
// open at 1200 bps, is closed.
if (1200 == _usbLineInfo.dwDTERate)
{
// We check DTR state to determine if host port is open (bit 0 of lineState).
if ((_usbLineInfo.lineState & 0x01) == 0)
initiateReset(250);
else
cancelReset();
}
return true;
}
}
return false;
}
int _serialPeek = -1;
void Serial_::begin(uint32_t baud_count)
{
}
void Serial_::begin(uint32_t baud_count, uint8_t config)
{
}
void Serial_::end(void)
{
}
void Serial_::accept(void)
{
static uint32_t guard = 0;
// synchronized access to guard
do {
if (__LDREXW(&guard) != 0) {
__CLREX();
return; // busy
}
} while (__STREXW(1, &guard) != 0); // retry until write succeed
ring_buffer *buffer = &cdc_rx_buffer;
uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
while (i != buffer->tail) {
uint32_t c;
if (!USBD_Available(CDC_RX)) {
udd_ack_fifocon(CDC_RX);
break;
}
c = USBD_Recv(CDC_RX);
// c = UDD_Recv8(CDC_RX & 0xF);
buffer->buffer[buffer->head] = c;
buffer->head = i;
i = (i + 1) % CDC_SERIAL_BUFFER_SIZE;
}
// release the guard
guard = 0;
}
int Serial_::available(void)
{
ring_buffer *buffer = &cdc_rx_buffer;
return (unsigned int)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE;
}
int Serial_::peek(void)
{
ring_buffer *buffer = &cdc_rx_buffer;
if (buffer->head == buffer->tail)
{
return -1;
}
else
{
return buffer->buffer[buffer->tail];
}
}
int Serial_::read(void)
{
ring_buffer *buffer = &cdc_rx_buffer;
// if the head isn't ahead of the tail, we don't have any characters
if (buffer->head == buffer->tail)
{
return -1;
}
else
{
unsigned char c = buffer->buffer[buffer->tail];
buffer->tail = (unsigned int)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
if (USBD_Available(CDC_RX))
accept();
return c;
}
}
void Serial_::flush(void)
{
USBD_Flush(CDC_TX);
}
size_t Serial_::write(const uint8_t *buffer, size_t size)
{
/* only try to send bytes if the high-level CDC connection itself
is open (not just the pipe) - the OS should set lineState when the port
is opened and clear lineState when the port is closed.
bytes sent before the user opens the connection or after
the connection is closed are lost - just like with a UART. */
// TODO - ZE - check behavior on different OSes and test what happens if an
// open connection isn't broken cleanly (cable is yanked out, host dies
// or locks up, or host virtual serial port hangs)
if (_usbLineInfo.lineState > 0)
{
int r = USBD_Send(CDC_TX, buffer, size);
if (r > 0)
{
return r;
} else
{
setWriteError();
return 0;
}
}
setWriteError();
return 0;
}
size_t Serial_::write(uint8_t c) {
return write(&c, 1);
}
// This operator is a convenient way for a sketch to check whether the
// port has actually been configured and opened by the host (as opposed
// to just being connected to the host). It can be used, for example, in
// setup() before printing to ensure that an application on the host is
// actually ready to receive and display the data.
// We add a short delay before returning to fix a bug observed by Federico
// where the port is configured (lineState != 0) but not quite opened.
Serial_::operator bool()
{
// this is here to avoid spurious opening after upload
if (millis() < 500)
return false;
bool result = false;
if (_usbLineInfo.lineState > 0)
{
result = true;
}
delay(10);
return result;
}
Serial_ SerialUSB;
Serial_ Serial;
#endif

View File

@@ -0,0 +1,518 @@
/* Copyright (c) 2011, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#include "Arduino.h"
#ifdef HID_ENABLED
//#define RAWHID_ENABLED
// Singletons for mouse and keyboard
Mouse_ Mouse;
Keyboard_ Keyboard;
//================================================================================
//================================================================================
// HID report descriptor
#define LSB(_x) ((_x) & 0xFF)
#define MSB(_x) ((_x) >> 8)
#define RAWHID_USAGE_PAGE 0xFFC0
#define RAWHID_USAGE 0x0C00
#define RAWHID_TX_SIZE 64
#define RAWHID_RX_SIZE 64
extern const uint8_t _hidReportDescriptor[] = {
// Mouse
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
#ifdef RAWHID_ENABLED
// RAW HID
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
0xA1, 0x01, // Collection 0x01
0x85, 0x03, // REPORT_ID (3)
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
0x95, 64, // report count TX
0x09, 0x01, // usage
0x81, 0x02, // Input (array)
0x95, 64, // report count RX
0x09, 0x02, // usage
0x91, 0x02, // Output (array)
0xC0 // end collection
#endif
};
_Pragma("pack(1)")
extern const HIDDescriptor _hidInterface =
{
D_INTERFACE(HID_INTERFACE,1,3,0,0),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
};
_Pragma("pack()")
//================================================================================
//================================================================================
// Driver
uint8_t _hid_protocol = 1;
uint8_t _hid_idle = 1;
#define WEAK __attribute__ ((weak))
int WEAK HID_GetInterface(uint8_t* interfaceNum)
{
interfaceNum[0] += 1; // uses 1
return USBD_SendControl(0,&_hidInterface,sizeof(_hidInterface));
}
int WEAK HID_GetDescriptor(int i)
{
return USBD_SendControl(0,_hidReportDescriptor,sizeof(_hidReportDescriptor));
}
void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len)
{
uint8_t p[64];
const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
p[0] = id;
for (uint32_t i=0; i<len; i++)
p[i+1] = d[i];
USBD_Send(HID_TX, p, len+1);
}
bool WEAK HID_Setup(Setup& setup)
{
uint8_t r = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
{
if (HID_GET_REPORT == r)
{
//HID_GetReport();
return true;
}
if (HID_GET_PROTOCOL == r)
{
//Send8(_hid_protocol); // TODO
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (HID_SET_PROTOCOL == r)
{
_hid_protocol = setup.wValueL;
return true;
}
if (HID_SET_IDLE == r)
{
_hid_idle = setup.wValueL;
return true;
}
}
return false;
}
//================================================================================
//================================================================================
// Mouse
Mouse_::Mouse_(void) : _buttons(0)
{
}
void Mouse_::begin(void)
{
}
void Mouse_::end(void)
{
}
void Mouse_::click(uint8_t b)
{
_buttons = b;
move(0,0,0);
_buttons = 0;
move(0,0,0);
}
void Mouse_::move(signed char x, signed char y, signed char wheel)
{
uint8_t m[4];
m[0] = _buttons;
m[1] = x;
m[2] = y;
m[3] = wheel;
HID_SendReport(1,m,4);
}
void Mouse_::buttons(uint8_t b)
{
if (b != _buttons)
{
_buttons = b;
move(0,0,0);
}
}
void Mouse_::press(uint8_t b)
{
buttons(_buttons | b);
}
void Mouse_::release(uint8_t b)
{
buttons(_buttons & ~b);
}
bool Mouse_::isPressed(uint8_t b)
{
if ((b & _buttons) > 0)
return true;
return false;
}
//================================================================================
//================================================================================
// Keyboard
Keyboard_::Keyboard_(void)
{
}
void Keyboard_::begin(void)
{
}
void Keyboard_::end(void)
{
}
void Keyboard_::sendReport(KeyReport* keys)
{
HID_SendReport(2,keys,sizeof(KeyReport));
}
#define SHIFT 0x80
extern const uint8_t _asciimap[128] =
{
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e|SHIFT, // !
0x34|SHIFT, // "
0x20|SHIFT, // #
0x21|SHIFT, // $
0x22|SHIFT, // %
0x24|SHIFT, // &
0x34, // '
0x26|SHIFT, // (
0x27|SHIFT, // )
0x25|SHIFT, // *
0x2e|SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33|SHIFT, // :
0x33, // ;
0x36|SHIFT, // <
0x2e, // =
0x37|SHIFT, // >
0x38|SHIFT, // ?
0x1f|SHIFT, // @
0x04|SHIFT, // A
0x05|SHIFT, // B
0x06|SHIFT, // C
0x07|SHIFT, // D
0x08|SHIFT, // E
0x09|SHIFT, // F
0x0a|SHIFT, // G
0x0b|SHIFT, // H
0x0c|SHIFT, // I
0x0d|SHIFT, // J
0x0e|SHIFT, // K
0x0f|SHIFT, // L
0x10|SHIFT, // M
0x11|SHIFT, // N
0x12|SHIFT, // O
0x13|SHIFT, // P
0x14|SHIFT, // Q
0x15|SHIFT, // R
0x16|SHIFT, // S
0x17|SHIFT, // T
0x18|SHIFT, // U
0x19|SHIFT, // V
0x1a|SHIFT, // W
0x1b|SHIFT, // X
0x1c|SHIFT, // Y
0x1d|SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23|SHIFT, // ^
0x2d|SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f|SHIFT, //
0x31|SHIFT, // |
0x30|SHIFT, // }
0x35|SHIFT, // ~
0 // DEL
};
uint8_t USBPutChar(uint8_t c);
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t Keyboard_::press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1<<(k-128));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i=0; i<6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t Keyboard_::release(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1<<(k-128));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i=0; i<6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void Keyboard_::releaseAll(void)
{
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t Keyboard_::write(uint8_t c)
{
uint8_t p = 0;
p = press(c); // Keydown
release(c); // Keyup
return (p); // Just return the result of press() since release() almost always returns 1
}
#endif

View File

@@ -0,0 +1,222 @@
/*
Copyright (c) 2012 Arduino. 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 __USBAPI__
#define __USBAPI__
#if defined __cplusplus
#include "RingBuffer.h"
//================================================================================
//================================================================================
// USB
class USBDevice_
{
public:
USBDevice_();
bool configured();
bool attach();
bool detach(); // Serial port goes down too...
void poll();
};
extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
// Serial over CDC (Serial1 is the physical port)
class Serial_ : public Stream
{
private:
RingBuffer *_cdc_rx_buffer;
public:
void begin(uint32_t baud_count);
void begin(uint32_t baud_count, uint8_t config);
void end(void);
virtual int available(void);
virtual void accept(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
using Print::write; // pull in write(str) from Print
operator bool();
};
extern Serial_ SerialUSB;
extern Serial_ Serial;
//================================================================================
//================================================================================
// Mouse
#define MOUSE_LEFT 1
#define MOUSE_RIGHT 2
#define MOUSE_MIDDLE 4
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
class Mouse_
{
private:
uint8_t _buttons;
void buttons(uint8_t b);
public:
Mouse_(void);
void begin(void);
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x, signed char y, signed char wheel = 0);
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default
};
extern Mouse_ Mouse;
//================================================================================
//================================================================================
// Keyboard
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
class Keyboard_ : public Print
{
private:
KeyReport _keyReport;
void sendReport(KeyReport* keys);
public:
Keyboard_(void);
void begin(void);
void end(void);
virtual size_t write(uint8_t k);
virtual size_t press(uint8_t k);
virtual size_t release(uint8_t k);
virtual void releaseAll(void);
};
extern Keyboard_ Keyboard;
//================================================================================
//================================================================================
// Low level API
typedef struct
{
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} Setup;
//================================================================================
//================================================================================
// HID 'Driver'
int HID_GetInterface(uint8_t* interfaceNum);
int HID_GetDescriptor(int i);
bool HID_Setup(Setup& setup);
void HID_SendReport(uint8_t id, const void* data, uint32_t len);
//================================================================================
//================================================================================
// MSC 'Driver'
int MSC_GetInterface(uint8_t* interfaceNum);
int MSC_GetDescriptor(int i);
bool MSC_Setup(Setup& setup);
bool MSC_Data(uint8_t rx,uint8_t tx);
//================================================================================
//================================================================================
// CSC 'Driver'
int CDC_GetInterface(uint8_t* interfaceNum);
int CDC_GetOtherInterface(uint8_t* interfaceNum);
int CDC_GetDescriptor(int i);
bool CDC_Setup(Setup& setup);
//================================================================================
//================================================================================
#define TRANSFER_RELEASE 0x40
#define TRANSFER_ZERO 0x20
void USBD_InitControl(int end);
int USBD_SendControl(uint8_t flags, const void* d, uint32_t len);
int USBD_RecvControl(void* d, uint32_t len);
int USBD_SendInterfaces(void);
bool USBD_ClassInterfaceRequest(Setup& setup);
uint32_t USBD_Available(uint32_t ep);
uint32_t USBD_SendSpace(uint32_t ep);
uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len);
uint32_t USBD_Recv(uint32_t ep, void* data, uint32_t len); // non-blocking
uint32_t USBD_Recv(uint32_t ep); // non-blocking
void USBD_Flush(uint32_t ep);
uint32_t USBD_Connected(void);
#endif
#endif

View File

@@ -0,0 +1,882 @@
// Copyright (c) 2010, Peter Barrett
/*
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#include "Arduino.h"
#include "USBAPI.h"
#include "Reset.h"
#include <stdio.h>
//#define TRACE_CORE(x) x
#define TRACE_CORE(x)
static const uint32_t EndPoints[] =
{
EP_TYPE_CONTROL,
#ifdef CDC_ENABLED
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
#endif
#ifdef HID_ENABLED
EP_TYPE_INTERRUPT_IN_HID // HID_ENDPOINT_INT
#endif
};
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
#define TX_RX_LED_PULSE_MS 100
volatile uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
volatile uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
static char isRemoteWakeUpEnabled = 0;
static char isEndpointHalt = 0;
//==================================================================
//==================================================================
extern const uint16_t STRING_LANGUAGE[];
extern const uint8_t STRING_PRODUCT[];
extern const uint8_t STRING_MANUFACTURER[];
extern const DeviceDescriptor USB_DeviceDescriptor;
extern const DeviceDescriptor USB_DeviceDescriptorA;
const uint16_t STRING_LANGUAGE[2] = {
(3<<8) | (2+2),
0x0409 // English
};
#ifndef USB_PRODUCT
// Use a hardcoded product name if none is provided
#if USB_PID == USB_PID_DUE
#define USB_PRODUCT "Arduino Due"
#elif USB_PID == USB_PID_DIGIX
#define USB_PRODUCT "Digistump DigiX"
#else
#define USB_PRODUCT "USB IO Board"
#endif
#endif
const uint8_t STRING_PRODUCT[] = USB_PRODUCT;
#define USB_MANUFACTURER "Digistump"
const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER;
#ifdef CDC_ENABLED
#define DEVICE_CLASS 0x02
#else
#define DEVICE_CLASS 0x00
#endif
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
D_DEVICE(0x00,0x00,0x00,64,USB_VID_DIGIX,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
const DeviceDescriptor USB_DeviceDescriptorA =
D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID_DIGIX,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
const DeviceDescriptor USB_DeviceQualifier =
D_QUALIFIER(0x00,0x00,0x00,64,1);
//! 7.1.20 Test Mode Support
static const unsigned char test_packet_buffer[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
};
//==================================================================
//==================================================================
volatile uint32_t _usbConfiguration = 0;
volatile uint32_t _usbInitialized = 0;
uint32_t _usbSetInterface = 0;
uint32_t _cdcComposite = 0;
//==================================================================
//==================================================================
#define USB_RECV_TIMEOUT
class LockEP
{
irqflags_t flags;
public:
LockEP(uint32_t ep) : flags(cpu_irq_save())
{
}
~LockEP()
{
cpu_irq_restore(flags);
}
};
// Number of bytes, assumes a rx endpoint
uint32_t USBD_Available(uint32_t ep)
{
LockEP lock(ep);
return UDD_FifoByteCount(ep & 0xF);
}
// Non Blocking receive
// Return number of bytes read
uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len)
{
if (!_usbConfiguration || len < 0)
return -1;
LockEP lock(ep);
uint32_t n = UDD_FifoByteCount(ep & 0xF);
len = min(n,len);
n = len;
uint8_t* dst = (uint8_t*)d;
while (n--)
*dst++ = UDD_Recv8(ep & 0xF);
if (len && !UDD_FifoByteCount(ep & 0xF)) // release empty buffer
UDD_ReleaseRX(ep & 0xF);
return len;
}
// Recv 1 byte if ready
uint32_t USBD_Recv(uint32_t ep)
{
uint8_t c;
if (USBD_Recv(ep & 0xF, &c, 1) != 1)
return -1;
else
return c;
}
// Space in send EP
//uint32_t USBD_SendSpace(uint32_t ep)
//{
//LockEP lock(ep);
//// if (!UDD_ReadWriteAllowed(ep & 0xF))
////{
////printf("pb "); // UOTGHS->UOTGHS_DEVEPTISR[%d]=0x%X\n\r", ep, UOTGHS->UOTGHS_DEVEPTISR[ep]);
////return 0;
////}
//if(ep==0) return 64 - UDD_FifoByteCount(ep & 0xF); // EP0_SIZE jcb
//else return 512 - UDD_FifoByteCount(ep & 0xF); // EPX_SIZE jcb
//}
// Blocking Send of data to an endpoint
uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len)
{
uint32_t n;
int r = len;
const uint8_t* data = (const uint8_t*)d;
if (!_usbConfiguration)
{
TRACE_CORE(printf("pb conf\n\r");)
return -1;
}
while (len)
{
if(ep==0) n = EP0_SIZE;
else n = EPX_SIZE;
if (n > len)
n = len;
len -= n;
UDD_Send(ep & 0xF, data, n);
data += n;
}
//TXLED1; // light the TX LED
//TxLEDPulse = TX_RX_LED_PULSE_MS;
return r;
}
int _cmark;
int _cend;
void USBD_InitControl(int end)
{
_cmark = 0;
_cend = end;
}
// Clipped by _cmark/_cend
int USBD_SendControl(uint8_t flags, const void* d, uint32_t len)
{
const uint8_t* data = (const uint8_t*)d;
uint32_t length = len;
uint32_t sent = 0;
uint32_t pos = 0;
TRACE_CORE(printf("=> USBD_SendControl TOTAL len=%lu\r\n", len);)
if (_cmark < _cend)
{
while (len > 0)
{
sent = UDD_Send(EP0, data + pos, len);
TRACE_CORE(printf("=> USBD_SendControl sent=%lu\r\n", sent);)
pos += sent;
len -= sent;
}
}
_cmark += length;
return length;
}
// Send a USB descriptor string. The string is stored as a
// plain ASCII string but is sent out as UTF-16 with the
// correct 2-byte prefix
static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) {
uint16_t buff[64];
int l = 1;
wLength-=2;
while (*string && wLength>0) {
buff[l++] = (uint8_t)(*string++);
wLength-=2;
}
buff[0] = (3<<8) | (l*2);
return USBD_SendControl(0, (uint8_t*)buff, l*2);
}
// Does not timeout or cross fifo boundaries
// Will only work for transfers <= 64 bytes
// TODO
int USBD_RecvControl(void* d, uint32_t len)
{
UDD_WaitOUT();
UDD_Recv(EP0, (uint8_t*)d, len);
UDD_ClearOUT();
return len;
}
// Handle CLASS_INTERFACE requests
bool USBD_ClassInterfaceRequest(Setup& setup)
{
uint8_t i = setup.wIndex;
TRACE_CORE(printf("=> USBD_ClassInterfaceRequest\r\n");)
#ifdef CDC_ENABLED
if (CDC_ACM_INTERFACE == i)
{
return CDC_Setup(setup);
}
#endif
#ifdef HID_ENABLED
if (HID_INTERFACE == i)
{
return HID_Setup(setup);
}
#endif
return false;
}
int USBD_SendInterfaces(void)
{
int total = 0;
uint8_t interfaces = 0;
#ifdef CDC_ENABLED
total = CDC_GetInterface(&interfaces);
#endif
#ifdef HID_ENABLED
total += HID_GetInterface(&interfaces);
#endif
total = total; // Get rid of compiler warning
TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);)
return interfaces;
}
int USBD_SendOtherInterfaces(void)
{
int total = 0;
uint8_t interfaces = 0;
#ifdef CDC_ENABLED
total = CDC_GetOtherInterface(&interfaces);
#endif
#ifdef HID_ENABLED
total += HID_GetInterface(&interfaces);
#endif
total = total; // Get rid of compiler warning
TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);)
return interfaces;
}
// Construct a dynamic configuration descriptor
// This really needs dynamic endpoint allocation etc
// TODO
static bool USBD_SendConfiguration(int maxlen)
{
// Count and measure interfaces
USBD_InitControl(0);
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
int interfaces = USBD_SendInterfaces();
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
_Pragma("pack(1)")
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
_Pragma("pack()")
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
// Now send them
USBD_InitControl(maxlen);
USBD_SendControl(0,&config,sizeof(ConfigDescriptor));
USBD_SendInterfaces();
return true;
}
static bool USBD_SendOtherConfiguration(int maxlen)
{
// Count and measure interfaces
USBD_InitControl(0);
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
int interfaces = USBD_SendOtherInterfaces();
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
_Pragma("pack(1)")
ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
_Pragma("pack()")
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
// Now send them
USBD_InitControl(maxlen);
USBD_SendControl(0,&config,sizeof(ConfigDescriptor));
USBD_SendOtherInterfaces();
return true;
}
static bool USBD_SendDescriptor(Setup& setup)
{
uint8_t t = setup.wValueH;
uint8_t desc_length = 0;
const uint8_t* desc_addr = 0;
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
{
TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);)
return USBD_SendConfiguration(setup.wLength);
}
USBD_InitControl(setup.wLength);
#ifdef HID_ENABLED
if (HID_REPORT_DESCRIPTOR_TYPE == t)
{
TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");)
return HID_GetDescriptor(t);
}
#endif
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
{
TRACE_CORE(puts("=> USBD_SendDescriptor : USB_DEVICE_DESCRIPTOR_TYPE\r\n");)
if (setup.wLength == 8)
{
_cdcComposite = 1;
}
desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorA : (const uint8_t*)&USB_DeviceDescriptor;
if( *desc_addr > setup.wLength ) {
desc_length = setup.wLength;
}
}
else if (USB_STRING_DESCRIPTOR_TYPE == t)
{
TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");)
if (setup.wValueL == 0) {
desc_addr = (const uint8_t*)&STRING_LANGUAGE;
}
else if (setup.wValueL == IPRODUCT) {
return USB_SendStringDescriptor(STRING_PRODUCT, setup.wLength);
}
else if (setup.wValueL == IMANUFACTURER) {
return USB_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
}
else {
return false;
}
if( *desc_addr > setup.wLength ) {
desc_length = setup.wLength;
}
}
else if (USB_DEVICE_QUALIFIER == t)
{
// Device qualifier descriptor requested
desc_addr = (const uint8_t*)&USB_DeviceQualifier;
if( *desc_addr > setup.wLength ) {
desc_length = setup.wLength;
}
}
else if (USB_OTHER_SPEED_CONFIGURATION == t)
{
// Other configuration descriptor requested
return USBD_SendOtherConfiguration(setup.wLength);
}
else
{
//printf("Device ERROR");
}
if (desc_addr == 0)
{
return false;
}
if (desc_length == 0)
{
desc_length = *desc_addr;
}
TRACE_CORE(printf("=> USBD_SendDescriptor : desc_addr=%p desc_length=%d\r\n", desc_addr, desc_length);)
USBD_SendControl(0, desc_addr, desc_length);
return true;
}
static void USB_SendZlp( void )
{
while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) )
{
if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP)
{
return;
}
}
UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC;
}
static void Test_Mode_Support( uint8_t wIndex )
{
uint8_t i;
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(2);
switch( wIndex )
{
case 4:
//Test mode Test_Packet:
//Upon command, a port must repetitively transmit the following test packet until
//the exit action is taken. This enables the testing of rise and fall times, eye
//patterns, jitter, and any other dynamic waveform specifications.
//The test packet is made up by concatenating the following strings.
//(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one
//transmitted. "S" indicates that a bit stuff occurs, which inserts an "extra" NRZI data bit.
//"* N" is used to indicate N occurrences of a string of bits or symbols.)
//A port in Test_Packet mode must send this packet repetitively. The inter-packet timing
//must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and
//no greater than 125 us.
// Send ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVDMA[0].UOTGHS_DEVDMACONTROL = 0; // raz
UOTGHS->UOTGHS_DEVDMA[1].UOTGHS_DEVDMACONTROL = 0; // raz
// Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
UOTGHS->UOTGHS_DEVEPTCFG[2] = UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE
| UOTGHS_DEVEPTCFG_EPDIR_IN
| UOTGHS_DEVEPTCFG_EPTYPE_BLK
| UOTGHS_DEVEPTCFG_EPBK_1_BANK;
// Check if the configuration is ok
UOTGHS->UOTGHS_DEVEPTCFG[2] |= UOTGHS_DEVEPTCFG_ALLOC;
while((UOTGHS->UOTGHS_DEVEPTISR[2]&UOTGHS_DEVEPTISR_CFGOK)==0) {}
UOTGHS->UOTGHS_DEVEPT |= UOTGHS_DEVEPT_EPEN2;
// Write FIFO
for( i=0; i<sizeof(test_packet_buffer); i++)
{
ptr_dest[i] = test_packet_buffer[i];;
}
// Tst PACKET
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTPCKT;
// Send packet
UOTGHS->UOTGHS_DEVEPTICR[2] = UOTGHS_DEVEPTICR_TXINIC;
UOTGHS->UOTGHS_DEVEPTIDR[2] = UOTGHS_DEVEPTIDR_FIFOCONC;
for(;;);
// break;
case 1:
//Test mode Test_J:
//Upon command, a port's transceiver must enter the high-speed J state and remain in that
//state until the exit action is taken. This enables the testing of the high output drive
//level on the D+ line.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTJ;
for(;;);
// break;
case 2:
//Test mode Test_K:
//Upon command, a port's transceiver must enter the high-speed K state and remain in
//that state until the exit action is taken. This enables the testing of the high output drive
//level on the D- line.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTK;
for(;;);
// break;
case 3:
//Test mode Test_SE0_NAK:
//Upon command, a port's transceiver must enter the high-speed receive mode
//and remain in that mode until the exit action is taken. This enables the testing
//of output impedance, low level output voltage, and loading characteristics.
//In addition, while in this mode, upstream facing ports (and only upstream facing ports)
//must respond to any IN token packet with a NAK handshake (only if the packet CRC is
//determined to be correct) within the normal allowed device response time. This enables testing of
//the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
//test for basic functional testing.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC
| UOTGHS_DEVIDR_MSOFEC
| UOTGHS_DEVIDR_SOFEC
| UOTGHS_DEVIDR_EORSTEC
| UOTGHS_DEVIDR_WAKEUPEC
| UOTGHS_DEVIDR_EORSMEC
| UOTGHS_DEVIDR_UPRSMEC
| UOTGHS_DEVIDR_PEP_0
| UOTGHS_DEVIDR_PEP_1
| UOTGHS_DEVIDR_PEP_2
| UOTGHS_DEVIDR_PEP_3
| UOTGHS_DEVIDR_PEP_4
| UOTGHS_DEVIDR_PEP_5
| UOTGHS_DEVIDR_PEP_6
| UOTGHS_DEVIDR_DMA_1
| UOTGHS_DEVIDR_DMA_2
| UOTGHS_DEVIDR_DMA_3
| UOTGHS_DEVIDR_DMA_4
| UOTGHS_DEVIDR_DMA_5
| UOTGHS_DEVIDR_DMA_6;
for(;;);
// break;
}
}
//unsigned int iii=0;
// Endpoint 0 interrupt
static void USB_ISR(void)
{
// printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb
// if( iii++ > 1500 ) while(1); // jcb
// End of bus reset
if (Is_udd_reset())
{
TRACE_CORE(printf(">>> End of Reset\r\n");)
// Reset USB address to 0
udd_configure_address(0);
udd_enable_address();
// Configure EP 0
UDD_InitEP(0, EP_TYPE_CONTROL);
udd_enable_setup_received_interrupt(0);
udd_enable_endpoint_interrupt(0);
_usbConfiguration = 0;
udd_ack_reset();
}
#ifdef CDC_ENABLED
if (Is_udd_endpoint_interrupt(CDC_RX))
{
udd_ack_out_received(CDC_RX);
// Handle received bytes
if (USBD_Available(CDC_RX))
SerialUSB.accept();
}
if (Is_udd_sof())
{
udd_ack_sof();
// USBD_Flush(CDC_TX); // jcb
}
#endif
// EP 0 Interrupt
if (Is_udd_endpoint_interrupt(0) )
{
if (!UDD_ReceivedSetupInt())
{
return;
}
Setup setup;
UDD_Recv(EP0, (uint8_t*)&setup, 8);
UDD_ClearSetupInt();
uint8_t requestType = setup.bmRequestType;
if (requestType & REQUEST_DEVICETOHOST)
{
TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");)
UDD_WaitIN();
}
else
{
TRACE_CORE(puts(">>> EP0 Int: OUT Request\r\n");)
UDD_ClearIN();
}
bool ok = true;
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
{
// Standard Requests
uint8_t r = setup.bRequest;
if (GET_STATUS == r)
{
if( setup.bmRequestType == 0 ) // device
{
// Send the device status
TRACE_CORE(puts(">>> EP0 Int: GET_STATUS\r\n");)
// Check current configuration for power mode (if device is configured)
// TODO
// Check if remote wake-up is enabled
// TODO
UDD_Send8(EP0, 0); // TODO
UDD_Send8(EP0, 0);
}
// if( setup.bmRequestType == 2 ) // Endpoint:
else
{
// Send the endpoint status
// Check if the endpoint if currently halted
if( isEndpointHalt == 1 )
UDD_Send8(EP0, 1); // TODO
else
UDD_Send8(EP0, 0); // TODO
UDD_Send8(EP0, 0);
}
}
else if (CLEAR_FEATURE == r)
{
// Check which is the selected feature
if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP
{
// Enable remote wake-up and send a ZLP
if( isRemoteWakeUpEnabled == 1 )
UDD_Send8(EP0, 1);
else
UDD_Send8(EP0, 0);
UDD_Send8(EP0, 0);
}
else // if( setup.wValueL == 0) // ENDPOINTHALT
{
isEndpointHalt = 0; // TODO
UDD_Send8(EP0, 0);
UDD_Send8(EP0, 0);
}
}
else if (SET_FEATURE == r)
{
// Check which is the selected feature
if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP
{
// Enable remote wake-up and send a ZLP
isRemoteWakeUpEnabled = 1;
UDD_Send8(EP0, 0);
}
if( setup.wValueL == 0) // ENDPOINTHALT
{
// Halt endpoint
isEndpointHalt = 1;
//USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
UDD_Send8(EP0, 0);
}
if( setup.wValueL == 2) // TEST_MODE
{
// 7.1.20 Test Mode Support, 9.4.9 SetFeature
if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) &&
((setup.wIndex & 0x000F) == 0) )
{
// the lower byte of wIndex must be zero
// the most significant byte of wIndex is used to specify the specific test mode
UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC;
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ?
Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 );
}
}
}
else if (SET_ADDRESS == r)
{
TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");)
UDD_WaitIN();
UDD_SetAddress(setup.wValueL);
}
else if (GET_DESCRIPTOR == r)
{
TRACE_CORE(puts(">>> EP0 Int: GET_DESCRIPTOR\r\n");)
ok = USBD_SendDescriptor(setup);
}
else if (SET_DESCRIPTOR == r)
{
TRACE_CORE(puts(">>> EP0 Int: SET_DESCRIPTOR\r\n");)
ok = false;
}
else if (GET_CONFIGURATION == r)
{
TRACE_CORE(puts(">>> EP0 Int: GET_CONFIGURATION\r\n");)
UDD_Send8(EP0, _usbConfiguration);
}
else if (SET_CONFIGURATION == r)
{
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
{
TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", setup.wValueL);)
UDD_InitEndpoints(EndPoints, (sizeof(EndPoints) / sizeof(EndPoints[0])));
_usbConfiguration = setup.wValueL;
#ifdef CDC_ENABLED
// Enable interrupt for CDC reception from host (OUT packet)
udd_enable_out_received_interrupt(CDC_RX);
udd_enable_endpoint_interrupt(CDC_RX);
#endif
}
else
{
TRACE_CORE(puts(">>> EP0 Int: SET_CONFIGURATION failed!\r\n");)
ok = false;
}
}
else if (GET_INTERFACE == r)
{
TRACE_CORE(puts(">>> EP0 Int: GET_INTERFACE\r\n");)
UDD_Send8(EP0, _usbSetInterface);
}
else if (SET_INTERFACE == r)
{
_usbSetInterface = setup.wValueL;
TRACE_CORE(puts(">>> EP0 Int: SET_INTERFACE\r\n");)
}
}
else
{
TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");)
UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly
USBD_InitControl(setup.wLength); // Max length of transfer
ok = USBD_ClassInterfaceRequest(setup);
}
if (ok)
{
TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");)
UDD_ClearIN();
}
else
{
TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");)
UDD_Stall();
}
}
}
void USBD_Flush(uint32_t ep)
{
if (UDD_FifoByteCount(ep))
UDD_ReleaseTX(ep);
}
// VBUS or counting frames
// Any frame counting?
uint32_t USBD_Connected(void)
{
uint8_t f = UDD_GetFrameNumber();
delay(3);
return f != UDD_GetFrameNumber();
}
//=======================================================================
//=======================================================================
USBDevice_ USBDevice;
USBDevice_::USBDevice_()
{
UDD_SetStack(&USB_ISR);
if (UDD_Init() == 0UL)
{
_usbInitialized=1UL;
}
}
bool USBDevice_::attach(void)
{
if (_usbInitialized != 0UL)
{
UDD_Attach();
_usbConfiguration = 0;
return true;
}
else
{
return false;
}
}
bool USBDevice_::detach(void)
{
if (_usbInitialized != 0UL)
{
UDD_Detach();
return true;
}
else
{
return false;
}
}
// Check for interrupts
// TODO: VBUS detection
bool USBDevice_::configured()
{
return _usbConfiguration;
}
void USBDevice_::poll()
{
}

View File

@@ -0,0 +1,311 @@
// Copyright (c) 2010, Peter Barrett
/*
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#ifndef __USBCORE_H__
#define __USBCORE_H__
// Standard requests
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
// bmRequestType
#define REQUEST_HOSTTODEVICE 0x00
#define REQUEST_DEVICETOHOST 0x80
#define REQUEST_DIRECTION 0x80
#define REQUEST_STANDARD 0x00
#define REQUEST_CLASS 0x20
#define REQUEST_VENDOR 0x40
#define REQUEST_TYPE 0x60
#define REQUEST_DEVICE 0x00
#define REQUEST_INTERFACE 0x01
#define REQUEST_ENDPOINT 0x02
#define REQUEST_OTHER 0x03
#define REQUEST_RECIPIENT 0x1F
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
// Class requests
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22
#define MSC_RESET 0xFF
#define MSC_GET_MAX_LUN 0xFE
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
// Descriptors
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGUARTION_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
#define USB_DEVICE_QUALIFIER 6
#define USB_OTHER_SPEED_CONFIGURATION 7
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
#define USB_DEVICE_CLASS_STORAGE 0x08
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
#define USB_CONFIG_POWERED_MASK 0x40
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0xC0
#define USB_CONFIG_REMOTE_WAKEUP 0x20
// bMaxPower in Configuration Descriptor
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
// bEndpointAddress in Endpoint Descriptor
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
#define MSC_SUBCLASS_SCSI 0x06
#define MSC_PROTOCOL_BULK_ONLY 0x50
#define HID_HID_DESCRIPTOR_TYPE 0x21
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
_Pragma("pack(1)")
// Device
typedef struct {
uint8_t len; // 18
uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
uint16_t usbVersion; // 0x200
uint8_t deviceClass;
uint8_t deviceSubClass;
uint8_t deviceProtocol;
uint8_t packetSize0; // Packet 0
uint16_t idVendor;
uint16_t idProduct;
uint16_t deviceVersion; // 0x100
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} DeviceDescriptor;
// Config
typedef struct {
uint8_t len; // 9
uint8_t dtype; // 2
uint16_t clen; // total length
uint8_t numInterfaces;
uint8_t config;
uint8_t iconfig;
uint8_t attributes;
uint8_t maxPower;
} ConfigDescriptor;
// String
// Interface
typedef struct
{
uint8_t len; // 9
uint8_t dtype; // 4
uint8_t number;
uint8_t alternate;
uint8_t numEndpoints;
uint8_t interfaceClass;
uint8_t interfaceSubClass;
uint8_t protocol;
uint8_t iInterface;
} InterfaceDescriptor;
// Endpoint
typedef struct
{
uint8_t len; // 7
uint8_t dtype; // 5
uint8_t addr;
uint8_t attr;
uint16_t packetSize;
uint8_t interval;
} EndpointDescriptor;
// Interface Association Descriptor
// Used to bind 2 interfaces together in CDC compostite device
typedef struct
{
uint8_t len; // 8
uint8_t dtype; // 11
uint8_t firstInterface;
uint8_t interfaceCount;
uint8_t functionClass;
uint8_t funtionSubClass;
uint8_t functionProtocol;
uint8_t iInterface;
} IADDescriptor;
// CDC CS interface descriptor
typedef struct
{
uint8_t len; // 5
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
uint8_t d1;
} CDCCSInterfaceDescriptor;
typedef struct
{
uint8_t len; // 4
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
} CDCCSInterfaceDescriptor4;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
uint8_t bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif;
CDCCSInterfaceDescriptor header;
CMFunctionalDescriptor callManagement; // Call Management
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
typedef struct
{
InterfaceDescriptor msc;
EndpointDescriptor in;
EndpointDescriptor out;
} MSCDescriptor;
typedef struct
{
uint8_t len; // 9
uint8_t dtype; // 0x21
uint8_t addr;
uint8_t versionL; // 0x101
uint8_t versionH; // 0x101
uint8_t country;
uint8_t desctype; // 0x22 report
uint8_t descLenL;
uint8_t descLenH;
} HIDDescDescriptor;
typedef struct
{
InterfaceDescriptor hid;
HIDDescDescriptor desc;
EndpointDescriptor in;
} HIDDescriptor;
_Pragma("pack()")
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_OTHERCONFIG(_totalLength,_interfaces) \
{ 9, 7, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval }
#define D_QUALIFIER(_class,_subClass,_proto,_packetSize0,_configs) \
{ 10, 6, 0x200, _class,_subClass,_proto,_packetSize0,_configs }
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
#define D_HIDREPORT(_descriptorLength) \
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
#endif

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2010, Peter Barrett
/*
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#ifndef __USBDESC_H__
#define __USBDESC_H__
#define CDC_ENABLED
#define HID_ENABLED
#ifdef CDC_ENABLED
#define CDC_INTERFACE_COUNT 2
#define CDC_ENPOINT_COUNT 3
#else
#define CDC_INTERFACE_COUNT 0
#define CDC_ENPOINT_COUNT 0
#endif
#ifdef HID_ENABLED
#define HID_INTERFACE_COUNT 1
#define HID_ENPOINT_COUNT 1
#else
#define HID_INTERFACE_COUNT 0
#define HID_ENPOINT_COUNT 0
#endif
#define CDC_ACM_INTERFACE 0 // CDC ACM
#define CDC_DATA_INTERFACE 1 // CDC Data
#define CDC_FIRST_ENDPOINT 1
#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
#ifdef CDC_ENABLED
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
#endif
#ifdef HID_ENABLED
#define HID_TX HID_ENDPOINT_INT
#endif
#define IMANUFACTURER 1
#define IPRODUCT 2
#endif /* __USBDESC_H__ */

View File

@@ -0,0 +1,88 @@
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef udp_h
#define udp_h
#include <Stream.h>
#include <IPAddress.h>
class UDP : public Stream {
public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual void stop() =0; // Finish with the UDP socket
// Sending UDP packets
// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
virtual int beginPacket(const char *host, uint16_t port) =0;
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket() =0;
// Write a single byte into the packet
virtual size_t write(uint8_t) =0;
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t *buffer, size_t size) =0;
// Start processing the next available incoming packet
// Returns the size of the packet in bytes, or 0 if no packets are available
virtual int parsePacket() =0;
// Number of bytes remaining in the current packet
virtual int available() =0;
// Read a single byte from the current packet
virtual int read() =0;
// Read up to len bytes from the current packet and place them into buffer
// Returns the number of bytes read, or 0 if none are available
virtual int read(unsigned char* buffer, size_t len) =0;
// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char* buffer, size_t len) =0;
// Return the next byte from the current packet without moving on to the next byte
virtual int peek() =0;
virtual void flush() =0; // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() =0;
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() =0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
#endif

View File

@@ -0,0 +1,180 @@
/*
WCharacter.h - Character utility functions for Wiring & Arduino
Copyright (c) 2010 Hernando Barragan. 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 Character_h
#define Character_h
#include <ctype.h>
#ifdef __cplusplus
extern "C" {
#endif
// WCharacter.h prototypes
#if defined ( __GNUC__ )
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
inline boolean isAlpha(int c) __attribute__((always_inline));
inline boolean isAscii(int c) __attribute__((always_inline));
inline boolean isWhitespace(int c) __attribute__((always_inline));
inline boolean isControl(int c) __attribute__((always_inline));
inline boolean isDigit(int c) __attribute__((always_inline));
inline boolean isGraph(int c) __attribute__((always_inline));
inline boolean isLowerCase(int c) __attribute__((always_inline));
inline boolean isPrintable(int c) __attribute__((always_inline));
inline boolean isPunct(int c) __attribute__((always_inline));
inline boolean isSpace(int c) __attribute__((always_inline));
inline boolean isUpperCase(int c) __attribute__((always_inline));
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
inline int toAscii(int c) __attribute__((always_inline));
inline int toLowerCase(int c) __attribute__((always_inline));
inline int toUpperCase(int c)__attribute__((always_inline));
#elif defined ( __ICCARM__ )
#endif
// Checks for an alphanumeric character.
// It is equivalent to (isalpha(c) || isdigit(c)).
inline boolean isAlphaNumeric(int c)
{
return ( isalnum(c) == 0 ? false : true);
}
// Checks for an alphabetic character.
// It is equivalent to (isupper(c) || islower(c)).
inline boolean isAlpha(int c)
{
return ( isalpha(c) == 0 ? false : true);
}
// Checks whether c is a 7-bit unsigned char value
// that fits into the ASCII character set.
inline boolean isAscii(int c)
{
/* return ( isascii(c) == 0 ? false : true); */
return ( (c & ~0x7f) != 0 ? false : true);
}
// Checks for a blank character, that is, a space or a tab.
inline boolean isWhitespace(int c)
{
return ( isblank (c) == 0 ? false : true);
}
// Checks for a control character.
inline boolean isControl(int c)
{
return ( iscntrl (c) == 0 ? false : true);
}
// Checks for a digit (0 through 9).
inline boolean isDigit(int c)
{
return ( isdigit (c) == 0 ? false : true);
}
// Checks for any printable character except space.
inline boolean isGraph(int c)
{
return ( isgraph (c) == 0 ? false : true);
}
// Checks for a lower-case character.
inline boolean isLowerCase(int c)
{
return (islower (c) == 0 ? false : true);
}
// Checks for any printable character including space.
inline boolean isPrintable(int c)
{
return ( isprint (c) == 0 ? false : true);
}
// Checks for any printable character which is not a space
// or an alphanumeric character.
inline boolean isPunct(int c)
{
return ( ispunct (c) == 0 ? false : true);
}
// Checks for white-space characters. For the avr-libc library,
// these are: space, formfeed ('\f'), newline ('\n'), carriage
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
inline boolean isSpace(int c)
{
return ( isspace (c) == 0 ? false : true);
}
// Checks for an uppercase letter.
inline boolean isUpperCase(int c)
{
return ( isupper (c) == 0 ? false : true);
}
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
// 8 9 a b c d e f A B C D E F.
inline boolean isHexadecimalDigit(int c)
{
return ( isxdigit (c) == 0 ? false : true);
}
// Converts c to a 7-bit unsigned char value that fits into the
// ASCII character set, by clearing the high-order bits.
inline int toAscii(int c)
{
/* return toascii (c); */
return (c & 0x7f);
}
// Warning:
// Many people will be unhappy if you use this function.
// This function will convert accented letters into random
// characters.
// Converts the letter c to lower case, if possible.
inline int toLowerCase(int c)
{
return tolower (c);
}
// Converts the letter c to upper case, if possible.
inline int toUpperCase(int c)
{
return toupper (c);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,182 @@
/*
Copyright (c) 2011-2012 Arduino. 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
*/
#include "WInterrupts.h"
typedef void (*interruptCB)(void);
static interruptCB callbacksPioA[32];
static interruptCB callbacksPioB[32];
static interruptCB callbacksPioC[32];
static interruptCB callbacksPioD[32];
/* Configure PIO interrupt sources */
static void __initialize() {
int i;
for (i=0; i<32; i++) {
callbacksPioA[i] = NULL;
callbacksPioB[i] = NULL;
callbacksPioC[i] = NULL;
callbacksPioD[i] = NULL;
}
pmc_enable_periph_clk(ID_PIOA);
NVIC_DisableIRQ(PIOA_IRQn);
NVIC_ClearPendingIRQ(PIOA_IRQn);
NVIC_SetPriority(PIOA_IRQn, 0);
NVIC_EnableIRQ(PIOA_IRQn);
pmc_enable_periph_clk(ID_PIOB);
NVIC_DisableIRQ(PIOB_IRQn);
NVIC_ClearPendingIRQ(PIOB_IRQn);
NVIC_SetPriority(PIOB_IRQn, 0);
NVIC_EnableIRQ(PIOB_IRQn);
pmc_enable_periph_clk(ID_PIOC);
NVIC_DisableIRQ(PIOC_IRQn);
NVIC_ClearPendingIRQ(PIOC_IRQn);
NVIC_SetPriority(PIOC_IRQn, 0);
NVIC_EnableIRQ(PIOC_IRQn);
pmc_enable_periph_clk(ID_PIOD);
NVIC_DisableIRQ(PIOD_IRQn);
NVIC_ClearPendingIRQ(PIOD_IRQn);
NVIC_SetPriority(PIOD_IRQn, 0);
NVIC_EnableIRQ(PIOD_IRQn);
}
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode)
{
static int enabled = 0;
if (!enabled) {
__initialize();
enabled = 1;
}
// Retrieve pin information
Pio *pio = g_APinDescription[pin].pPort;
uint32_t mask = g_APinDescription[pin].ulPin;
uint32_t pos = 0;
uint32_t t;
for (t = mask; t>1; t>>=1, pos++)
;
// Set callback function
if (pio == PIOA)
callbacksPioA[pos] = callback;
if (pio == PIOB)
callbacksPioB[pos] = callback;
if (pio == PIOC)
callbacksPioC[pos] = callback;
if (pio == PIOD)
callbacksPioD[pos] = callback;
// Configure the interrupt mode
if (mode == CHANGE) {
// Disable additional interrupt mode (detects both rising and falling edges)
pio->PIO_AIMDR = mask;
} else {
// Enable additional interrupt mode
pio->PIO_AIMER = mask;
// Select mode of operation
if (mode == LOW) {
pio->PIO_LSR = mask; // "Level" Select Register
pio->PIO_FELLSR = mask; // "Falling Edge / Low Level" Select Register
}
if (mode == HIGH) {
pio->PIO_LSR = mask; // "Level" Select Register
pio->PIO_REHLSR = mask; // "Rising Edge / High Level" Select Register
}
if (mode == FALLING) {
pio->PIO_ESR = mask; // "Edge" Select Register
pio->PIO_FELLSR = mask; // "Falling Edge / Low Level" Select Register
}
if (mode == RISING) {
pio->PIO_ESR = mask; // "Edge" Select Register
pio->PIO_REHLSR = mask; // "Rising Edge / High Level" Select Register
}
}
// Enable interrupt
pio->PIO_IER = mask;
}
void detachInterrupt(uint32_t pin)
{
// Retrieve pin information
Pio *pio = g_APinDescription[pin].pPort;
uint32_t mask = g_APinDescription[pin].ulPin;
// Disable interrupt
pio->PIO_IDR = mask;
}
#ifdef __cplusplus
extern "C" {
#endif
void PIOA_Handler(void) {
uint32_t isr = PIOA->PIO_ISR;
uint32_t i;
for (i=0; i<32; i++, isr>>=1) {
if ((isr & 0x1) == 0)
continue;
if (callbacksPioA[i])
callbacksPioA[i]();
}
}
void PIOB_Handler(void) {
uint32_t isr = PIOB->PIO_ISR;
uint32_t i;
for (i=0; i<32; i++, isr>>=1) {
if ((isr & 0x1) == 0)
continue;
if (callbacksPioB[i])
callbacksPioB[i]();
}
}
void PIOC_Handler(void) {
uint32_t isr = PIOC->PIO_ISR;
uint32_t i;
for (i=0; i<32; i++, isr>>=1) {
if ((isr & 0x1) == 0)
continue;
if (callbacksPioC[i])
callbacksPioC[i]();
}
}
void PIOD_Handler(void) {
uint32_t isr = PIOD->PIO_ISR;
uint32_t i;
for (i=0; i<32; i++, isr>>=1) {
if ((isr & 0x1) == 0)
continue;
if (callbacksPioD[i])
callbacksPioD[i]();
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,36 @@
/*
Copyright (c) 2011-2012 Arduino. 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 _WIRING_INTERRUPTS_
#define _WIRING_INTERRUPTS_
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
void detachInterrupt(uint32_t pin);
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_INTERRUPTS_ */

View File

@@ -0,0 +1,68 @@
/*
Copyright (c) 2011 Arduino. 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
*/
extern "C" {
#include "stdlib.h"
#include "stdint.h"
}
#include "WMath.h"
extern void randomSeed( uint32_t dwSeed )
{
if ( dwSeed != 0 )
{
srand( dwSeed ) ;
}
}
extern long random( long howbig )
{
if ( howbig == 0 )
{
return 0 ;
}
return rand() % howbig;
}
extern long random( long howsmall, long howbig )
{
if (howsmall >= howbig)
{
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
extern long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
extern uint16_t makeWord( uint16_t w )
{
return w ;
}
extern uint16_t makeWord( uint8_t h, uint8_t l )
{
return (h << 8) | l ;
}

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_MATH_
#define _WIRING_MATH_
extern long random( long ) ;
extern long random( long, long ) ;
extern void randomSeed( uint32_t dwSeed ) ;
extern long map( long, long, long, long, long ) ;
extern uint16_t makeWord( uint16_t w ) ;
extern uint16_t makeWord( uint8_t h, uint8_t l ) ;
#define word(...) makeWord(__VA_ARGS__)
#endif /* _WIRING_MATH_ */

View File

@@ -0,0 +1,746 @@
/*
WString.cpp - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.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
*/
#include "WString.h"
#include "itoa.h"
#include "avr/dtostrf.h"
/*********************************************/
/* Constructors */
/*********************************************/
String::String(const char *cstr)
{
init();
if (cstr) copy(cstr, strlen(cstr));
}
String::String(const String &value)
{
init();
*this = value;
}
String::String(const __FlashStringHelper *pstr)
{
init();
*this = pstr;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String::String(String &&rval)
{
init();
move(rval);
}
String::String(StringSumHelper &&rval)
{
init();
move(rval);
}
#endif
String::String(char c)
{
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
String::String(unsigned char value, unsigned char base)
{
init();
char buf[9];
utoa(value, buf, base);
*this = buf;
}
String::String(int value, unsigned char base)
{
init();
char buf[18];
itoa(value, buf, base);
*this = buf;
}
String::String(unsigned int value, unsigned char base)
{
init();
char buf[17];
utoa(value, buf, base);
*this = buf;
}
String::String(long value, unsigned char base)
{
init();
char buf[34];
ltoa(value, buf, base);
*this = buf;
}
String::String(unsigned long value, unsigned char base)
{
init();
char buf[33];
ultoa(value, buf, base);
*this = buf;
}
String::String(float value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::String(double value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::~String()
{
free(buffer);
}
/*********************************************/
/* Memory Management */
/*********************************************/
inline void String::init(void)
{
buffer = NULL;
capacity = 0;
len = 0;
}
void String::invalidate(void)
{
if (buffer) free(buffer);
buffer = NULL;
capacity = len = 0;
}
unsigned char String::reserve(unsigned int size)
{
if (buffer && capacity >= size) return 1;
if (changeBuffer(size)) {
if (len == 0) buffer[0] = 0;
return 1;
}
return 0;
}
unsigned char String::changeBuffer(unsigned int maxStrLen)
{
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
if (newbuffer) {
buffer = newbuffer;
capacity = maxStrLen;
return 1;
}
return 0;
}
/*********************************************/
/* Copy and Move */
/*********************************************/
String & String::copy(const char *cstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy(buffer, cstr);
return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy_P(buffer, (const prog_char *)pstr);
return *this;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void String::move(String &rhs)
{
if (buffer) {
if (capacity >= rhs.len) {
strcpy(buffer, rhs.buffer);
len = rhs.len;
rhs.len = 0;
return;
} else {
free(buffer);
}
}
buffer = rhs.buffer;
capacity = rhs.capacity;
len = rhs.len;
rhs.buffer = NULL;
rhs.capacity = 0;
rhs.len = 0;
}
#endif
String & String::operator = (const String &rhs)
{
if (this == &rhs) return *this;
if (rhs.buffer) copy(rhs.buffer, rhs.len);
else invalidate();
return *this;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & String::operator = (String &&rval)
{
if (this != &rval) move(rval);
return *this;
}
String & String::operator = (StringSumHelper &&rval)
{
if (this != &rval) move(rval);
return *this;
}
#endif
String & String::operator = (const char *cstr)
{
if (cstr) copy(cstr, strlen(cstr));
else invalidate();
return *this;
}
String & String::operator = (const __FlashStringHelper *pstr)
{
if (pstr) copy(pstr, strlen_P((const prog_char *)pstr));
else invalidate();
return *this;
}
/*********************************************/
/* concat */
/*********************************************/
unsigned char String::concat(const String &s)
{
return concat(s.buffer, s.len);
}
unsigned char String::concat(const char *cstr, unsigned int length)
{
unsigned int newlen = len + length;
if (!cstr) return 0;
if (length == 0) return 1;
if (!reserve(newlen)) return 0;
strcpy(buffer + len, cstr);
len = newlen;
return 1;
}
unsigned char String::concat(const char *cstr)
{
if (!cstr) return 0;
return concat(cstr, strlen(cstr));
}
unsigned char String::concat(char c)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
return concat(buf, 1);
}
unsigned char String::concat(unsigned char num)
{
char buf[4];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(int num)
{
char buf[12];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned int num)
{
char buf[11];
utoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(long num)
{
char buf[12];
ltoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned long num)
{
char buf[11];
ultoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(double num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(const __FlashStringHelper * str)
{
if (!str) return 0;
int length = strlen_P((const char *) str);
if (length == 0) return 1;
unsigned int newlen = len + length;
if (!reserve(newlen)) return 0;
strcpy_P(buffer + len, (const char *) str);
len = newlen;
return 1;
}
/*********************************************/
/* Concatenate */
/*********************************************/
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(c)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs)) a.invalidate();
return a;
}
/*********************************************/
/* Comparison */
/*********************************************/
int String::compareTo(const String &s) const
{
if (!buffer || !s.buffer) {
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
if (buffer && len > 0) return *(unsigned char *)buffer;
return 0;
}
return strcmp(buffer, s.buffer);
}
unsigned char String::equals(const String &s2) const
{
return (len == s2.len && compareTo(s2) == 0);
}
unsigned char String::equals(const char *cstr) const
{
if (len == 0) return (cstr == NULL || *cstr == 0);
if (cstr == NULL) return buffer[0] == 0;
return strcmp(buffer, cstr) == 0;
}
unsigned char String::operator<(const String &rhs) const
{
return compareTo(rhs) < 0;
}
unsigned char String::operator>(const String &rhs) const
{
return compareTo(rhs) > 0;
}
unsigned char String::operator<=(const String &rhs) const
{
return compareTo(rhs) <= 0;
}
unsigned char String::operator>=(const String &rhs) const
{
return compareTo(rhs) >= 0;
}
unsigned char String::equalsIgnoreCase( const String &s2 ) const
{
if (this == &s2) return 1;
if (len != s2.len) return 0;
if (len == 0) return 1;
const char *p1 = buffer;
const char *p2 = s2.buffer;
while (*p1) {
if (tolower(*p1++) != tolower(*p2++)) return 0;
}
return 1;
}
unsigned char String::startsWith( const String &s2 ) const
{
if (len < s2.len) return 0;
return startsWith(s2, 0);
}
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
{
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
}
unsigned char String::endsWith( const String &s2 ) const
{
if ( len < s2.len || !buffer || !s2.buffer) return 0;
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
}
/*********************************************/
/* Character Access */
/*********************************************/
char String::charAt(unsigned int loc) const
{
return operator[](loc);
}
void String::setCharAt(unsigned int loc, char c)
{
if (loc < len) buffer[loc] = c;
}
char & String::operator[](unsigned int index)
{
static char dummy_writable_char;
if (index >= len || !buffer) {
dummy_writable_char = 0;
return dummy_writable_char;
}
return buffer[index];
}
char String::operator[]( unsigned int index ) const
{
if (index >= len || !buffer) return 0;
return buffer[index];
}
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
{
if (!bufsize || !buf) return;
if (index >= len) {
buf[0] = 0;
return;
}
unsigned int n = bufsize - 1;
if (n > len - index) n = len - index;
strncpy((char *)buf, buffer + index, n);
buf[n] = 0;
}
/*********************************************/
/* Search */
/*********************************************/
int String::indexOf(char c) const
{
return indexOf(c, 0);
}
int String::indexOf( char ch, unsigned int fromIndex ) const
{
if (fromIndex >= len) return -1;
const char* temp = strchr(buffer + fromIndex, ch);
if (temp == NULL) return -1;
return temp - buffer;
}
int String::indexOf(const String &s2) const
{
return indexOf(s2, 0);
}
int String::indexOf(const String &s2, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
const char *found = strstr(buffer + fromIndex, s2.buffer);
if (found == NULL) return -1;
return found - buffer;
}
int String::lastIndexOf( char theChar ) const
{
return lastIndexOf(theChar, len - 1);
}
int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
buffer[fromIndex + 1] = tempchar;
if (temp == NULL) return -1;
return temp - buffer;
}
int String::lastIndexOf(const String &s2) const
{
return lastIndexOf(s2, len - s2.len);
}
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1;
int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) {
p = strstr(p, s2.buffer);
if (!p) break;
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
}
return found;
}
String String::substring(unsigned int left, unsigned int right) const
{
if (left > right) {
unsigned int temp = right;
right = left;
left = temp;
}
String out;
if (left > len) return out;
if (right > len) right = len;
char temp = buffer[right]; // save the replaced character
buffer[right] = '\0';
out = buffer + left; // pointer arithmetic
buffer[right] = temp; //restore character
return out;
}
/*********************************************/
/* Modification */
/*********************************************/
void String::replace(char find, char replace)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
if (*p == find) *p = replace;
}
}
void String::replace(const String& find, const String& replace)
{
if (len == 0 || find.len == 0) return;
int diff = replace.len - find.len;
char *readFrom = buffer;
char *foundAt;
if (diff == 0) {
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
memcpy(foundAt, replace.buffer, replace.len);
readFrom = foundAt + replace.len;
}
} else if (diff < 0) {
char *writeTo = buffer;
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
unsigned int n = foundAt - readFrom;
memcpy(writeTo, readFrom, n);
writeTo += n;
memcpy(writeTo, replace.buffer, replace.len);
writeTo += replace.len;
readFrom = foundAt + find.len;
len += diff;
}
strcpy(writeTo, readFrom);
} else {
unsigned int size = len; // compute size needed for result
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
readFrom = foundAt + find.len;
size += diff;
}
if (size == len) return;
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
int index = len - 1;
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = buffer + index + find.len;
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
len += diff;
buffer[len] = 0;
memcpy(buffer + index, replace.buffer, replace.len);
index--;
}
}
}
void String::remove(unsigned int index){
if (index >= len) { return; }
int count = len - index;
remove(index, count);
}
void String::remove(unsigned int index, unsigned int count){
if (index >= len) { return; }
if (count <= 0) { return; }
if (index + count > len) { count = len - index; }
char *writeTo = buffer + index;
len = len - count;
strncpy(writeTo, buffer + index + count,len - index);
buffer[len] = 0;
}
void String::toLowerCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = tolower(*p);
}
}
void String::toUpperCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = toupper(*p);
}
}
void String::trim(void)
{
if (!buffer || len == 0) return;
char *begin = buffer;
while (isspace(*begin)) begin++;
char *end = buffer + len - 1;
while (isspace(*end) && end >= begin) end--;
len = end + 1 - begin;
if (begin > buffer) memcpy(buffer, begin, len);
buffer[len] = 0;
}
/*********************************************/
/* Parsing / Conversion */
/*********************************************/
long String::toInt(void) const
{
if (buffer) return atol(buffer);
return 0;
}
float String::toFloat(void) const
{
if (buffer) return float(atof(buffer));
return 0;
}

View File

@@ -0,0 +1,224 @@
/*
WString.h - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.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
*/
#ifndef String_class_h
#define String_class_h
#ifdef __cplusplus
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <avr/pgmspace.h>
// When compiling programs with this class, the following gcc parameters
// dramatically increase performance and memory (RAM) efficiency, typically
// with little or no increase in code size.
// -felide-constructors
// -std=c++0x
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
// An inherited class for holding the result of a concatenation. These
// result objects are assumed to be writable by subsequent concatenations.
class StringSumHelper;
// The string class
class String
{
// use a function pointer to allow for "if (s)" without the
// complications of an operator bool(). for more information, see:
// http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
public:
// constructors
// creates a copy of the initial value.
// if the initial value is null or invalid, or if memory allocation
// fails, the string will be marked as invalid (i.e. "if (s)" will
// be false).
String(const char *cstr = "");
String(const String &str);
String(const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String(String &&rval);
String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base=10);
explicit String(int, unsigned char base=10);
explicit String(unsigned int, unsigned char base=10);
explicit String(long, unsigned char base=10);
explicit String(unsigned long, unsigned char base=10);
explicit String(float, unsigned char decimalPlaces=2);
explicit String(double, unsigned char decimalPlaces=2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const {return len;}
// creates a copy of the assigned value. if the value is null or
// invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator = (const String &rhs);
String & operator = (const char *cstr);
String & operator = (const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & operator = (String &&rval);
String & operator = (StringSumHelper &&rval);
#endif
// concatenate (works w/ built-in types)
// returns true on success, false on failure (in which case, the string
// is left unchanged). if the argument is null or invalid, the
// concatenation is considered unsucessful.
unsigned char concat(const String &str);
unsigned char concat(const char *cstr);
unsigned char concat(char c);
unsigned char concat(unsigned char c);
unsigned char concat(int num);
unsigned char concat(unsigned int num);
unsigned char concat(long num);
unsigned char concat(unsigned long num);
unsigned char concat(float num);
unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str);
// if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way)
String & operator += (const String &rhs) {concat(rhs); return (*this);}
String & operator += (const char *cstr) {concat(cstr); return (*this);}
String & operator += (char c) {concat(c); return (*this);}
String & operator += (unsigned char num) {concat(num); return (*this);}
String & operator += (int num) {concat(num); return (*this);}
String & operator += (unsigned int num) {concat(num); return (*this);}
String & operator += (long num) {concat(num); return (*this);}
String & operator += (unsigned long num) {concat(num); return (*this);}
String & operator += (float num) {concat(num); return (*this);}
String & operator += (double num) {concat(num); return (*this);}
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
// comparison (only works w/ Strings and "strings")
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
int compareTo(const String &s) const;
unsigned char equals(const String &s) const;
unsigned char equals(const char *cstr) const;
unsigned char operator == (const String &rhs) const {return equals(rhs);}
unsigned char operator == (const char *cstr) const {return equals(cstr);}
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
unsigned char operator < (const String &rhs) const;
unsigned char operator > (const String &rhs) const;
unsigned char operator <= (const String &rhs) const;
unsigned char operator >= (const String &rhs) const;
unsigned char equalsIgnoreCase(const String &s) const;
unsigned char startsWith( const String &prefix) const;
unsigned char startsWith(const String &prefix, unsigned int offset) const;
unsigned char endsWith(const String &suffix) const;
// character acccess
char charAt(unsigned int index) const;
void setCharAt(unsigned int index, char c);
char operator [] (unsigned int index) const;
char& operator [] (unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
{getBytes((unsigned char *)buf, bufsize, index);}
const char * c_str() const { return buffer; }
// search
int indexOf( char ch ) const;
int indexOf( char ch, unsigned int fromIndex ) const;
int indexOf( const String &str ) const;
int indexOf( const String &str, unsigned int fromIndex ) const;
int lastIndexOf( char ch ) const;
int lastIndexOf( char ch, unsigned int fromIndex ) const;
int lastIndexOf( const String &str ) const;
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
// modification
void replace(char find, char replace);
void replace(const String& find, const String& replace);
void remove(unsigned int index);
void remove(unsigned int index, unsigned int count);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
// parsing/conversion
long toInt(void) const;
float toFloat(void) const;
protected:
char *buffer; // the actual char array
unsigned int capacity; // the array length minus one (for the '\0')
unsigned int len; // the String length (not counting the '\0')
protected:
void init(void);
void invalidate(void);
unsigned char changeBuffer(unsigned int maxStrLen);
unsigned char concat(const char *cstr, unsigned int length);
// copy and move
String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void move(String &rhs);
#endif
};
class StringSumHelper : public String
{
public:
StringSumHelper(const String &s) : String(s) {}
StringSumHelper(const char *p) : String(p) {}
StringSumHelper(char c) : String(c) {}
StringSumHelper(unsigned char num) : String(num) {}
StringSumHelper(int num) : String(num) {}
StringSumHelper(unsigned int num) : String(num) {}
StringSumHelper(long num) : String(num) {}
StringSumHelper(unsigned long num) : String(num) {}
StringSumHelper(float num) : String(num) {}
StringSumHelper(double num) : String(num) {}
};
#endif // __cplusplus
#endif // String_class_h

View File

@@ -0,0 +1,27 @@
/*
dtostrf - Emulation for dtostrf function from avr-libc
Copyright (c) 2013 Arduino. All rights reserved.
Written by Cristian Maglie <c.maglie@bug.st>
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
*/
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
char fmt[20];
sprintf(fmt, "%%%d.%df", width, prec);
sprintf(sout, fmt, val);
return sout;
}

View File

@@ -0,0 +1,29 @@
/*
dtostrf - Emulation for dtostrf function from avr-libc
Copyright (c) 2013 Arduino. All rights reserved.
Written by Cristian Maglie <c.maglie@bug.st>
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
*/
#ifdef __cplusplus
extern "C" {
#endif
char *dtostrf (double val, signed char width, unsigned char prec, char *sout);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,44 @@
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
#define _SFR_BYTE(n) (n)
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcat_P(dest, src) strcat((dest), (src))
#define strcmp_P(a, b) strcmp((a), (b))
#define strstr_P(a, b) strstr((a), (b))
#define strlen_P(a) strlen((a))
#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#endif

View File

@@ -0,0 +1,515 @@
#ifndef Binary_h
#define Binary_h
#define B0 0
#define B00 0
#define B000 0
#define B0000 0
#define B00000 0
#define B000000 0
#define B0000000 0
#define B00000000 0
#define B1 1
#define B01 1
#define B001 1
#define B0001 1
#define B00001 1
#define B000001 1
#define B0000001 1
#define B00000001 1
#define B10 2
#define B010 2
#define B0010 2
#define B00010 2
#define B000010 2
#define B0000010 2
#define B00000010 2
#define B11 3
#define B011 3
#define B0011 3
#define B00011 3
#define B000011 3
#define B0000011 3
#define B00000011 3
#define B100 4
#define B0100 4
#define B00100 4
#define B000100 4
#define B0000100 4
#define B00000100 4
#define B101 5
#define B0101 5
#define B00101 5
#define B000101 5
#define B0000101 5
#define B00000101 5
#define B110 6
#define B0110 6
#define B00110 6
#define B000110 6
#define B0000110 6
#define B00000110 6
#define B111 7
#define B0111 7
#define B00111 7
#define B000111 7
#define B0000111 7
#define B00000111 7
#define B1000 8
#define B01000 8
#define B001000 8
#define B0001000 8
#define B00001000 8
#define B1001 9
#define B01001 9
#define B001001 9
#define B0001001 9
#define B00001001 9
#define B1010 10
#define B01010 10
#define B001010 10
#define B0001010 10
#define B00001010 10
#define B1011 11
#define B01011 11
#define B001011 11
#define B0001011 11
#define B00001011 11
#define B1100 12
#define B01100 12
#define B001100 12
#define B0001100 12
#define B00001100 12
#define B1101 13
#define B01101 13
#define B001101 13
#define B0001101 13
#define B00001101 13
#define B1110 14
#define B01110 14
#define B001110 14
#define B0001110 14
#define B00001110 14
#define B1111 15
#define B01111 15
#define B001111 15
#define B0001111 15
#define B00001111 15
#define B10000 16
#define B010000 16
#define B0010000 16
#define B00010000 16
#define B10001 17
#define B010001 17
#define B0010001 17
#define B00010001 17
#define B10010 18
#define B010010 18
#define B0010010 18
#define B00010010 18
#define B10011 19
#define B010011 19
#define B0010011 19
#define B00010011 19
#define B10100 20
#define B010100 20
#define B0010100 20
#define B00010100 20
#define B10101 21
#define B010101 21
#define B0010101 21
#define B00010101 21
#define B10110 22
#define B010110 22
#define B0010110 22
#define B00010110 22
#define B10111 23
#define B010111 23
#define B0010111 23
#define B00010111 23
#define B11000 24
#define B011000 24
#define B0011000 24
#define B00011000 24
#define B11001 25
#define B011001 25
#define B0011001 25
#define B00011001 25
#define B11010 26
#define B011010 26
#define B0011010 26
#define B00011010 26
#define B11011 27
#define B011011 27
#define B0011011 27
#define B00011011 27
#define B11100 28
#define B011100 28
#define B0011100 28
#define B00011100 28
#define B11101 29
#define B011101 29
#define B0011101 29
#define B00011101 29
#define B11110 30
#define B011110 30
#define B0011110 30
#define B00011110 30
#define B11111 31
#define B011111 31
#define B0011111 31
#define B00011111 31
#define B100000 32
#define B0100000 32
#define B00100000 32
#define B100001 33
#define B0100001 33
#define B00100001 33
#define B100010 34
#define B0100010 34
#define B00100010 34
#define B100011 35
#define B0100011 35
#define B00100011 35
#define B100100 36
#define B0100100 36
#define B00100100 36
#define B100101 37
#define B0100101 37
#define B00100101 37
#define B100110 38
#define B0100110 38
#define B00100110 38
#define B100111 39
#define B0100111 39
#define B00100111 39
#define B101000 40
#define B0101000 40
#define B00101000 40
#define B101001 41
#define B0101001 41
#define B00101001 41
#define B101010 42
#define B0101010 42
#define B00101010 42
#define B101011 43
#define B0101011 43
#define B00101011 43
#define B101100 44
#define B0101100 44
#define B00101100 44
#define B101101 45
#define B0101101 45
#define B00101101 45
#define B101110 46
#define B0101110 46
#define B00101110 46
#define B101111 47
#define B0101111 47
#define B00101111 47
#define B110000 48
#define B0110000 48
#define B00110000 48
#define B110001 49
#define B0110001 49
#define B00110001 49
#define B110010 50
#define B0110010 50
#define B00110010 50
#define B110011 51
#define B0110011 51
#define B00110011 51
#define B110100 52
#define B0110100 52
#define B00110100 52
#define B110101 53
#define B0110101 53
#define B00110101 53
#define B110110 54
#define B0110110 54
#define B00110110 54
#define B110111 55
#define B0110111 55
#define B00110111 55
#define B111000 56
#define B0111000 56
#define B00111000 56
#define B111001 57
#define B0111001 57
#define B00111001 57
#define B111010 58
#define B0111010 58
#define B00111010 58
#define B111011 59
#define B0111011 59
#define B00111011 59
#define B111100 60
#define B0111100 60
#define B00111100 60
#define B111101 61
#define B0111101 61
#define B00111101 61
#define B111110 62
#define B0111110 62
#define B00111110 62
#define B111111 63
#define B0111111 63
#define B00111111 63
#define B1000000 64
#define B01000000 64
#define B1000001 65
#define B01000001 65
#define B1000010 66
#define B01000010 66
#define B1000011 67
#define B01000011 67
#define B1000100 68
#define B01000100 68
#define B1000101 69
#define B01000101 69
#define B1000110 70
#define B01000110 70
#define B1000111 71
#define B01000111 71
#define B1001000 72
#define B01001000 72
#define B1001001 73
#define B01001001 73
#define B1001010 74
#define B01001010 74
#define B1001011 75
#define B01001011 75
#define B1001100 76
#define B01001100 76
#define B1001101 77
#define B01001101 77
#define B1001110 78
#define B01001110 78
#define B1001111 79
#define B01001111 79
#define B1010000 80
#define B01010000 80
#define B1010001 81
#define B01010001 81
#define B1010010 82
#define B01010010 82
#define B1010011 83
#define B01010011 83
#define B1010100 84
#define B01010100 84
#define B1010101 85
#define B01010101 85
#define B1010110 86
#define B01010110 86
#define B1010111 87
#define B01010111 87
#define B1011000 88
#define B01011000 88
#define B1011001 89
#define B01011001 89
#define B1011010 90
#define B01011010 90
#define B1011011 91
#define B01011011 91
#define B1011100 92
#define B01011100 92
#define B1011101 93
#define B01011101 93
#define B1011110 94
#define B01011110 94
#define B1011111 95
#define B01011111 95
#define B1100000 96
#define B01100000 96
#define B1100001 97
#define B01100001 97
#define B1100010 98
#define B01100010 98
#define B1100011 99
#define B01100011 99
#define B1100100 100
#define B01100100 100
#define B1100101 101
#define B01100101 101
#define B1100110 102
#define B01100110 102
#define B1100111 103
#define B01100111 103
#define B1101000 104
#define B01101000 104
#define B1101001 105
#define B01101001 105
#define B1101010 106
#define B01101010 106
#define B1101011 107
#define B01101011 107
#define B1101100 108
#define B01101100 108
#define B1101101 109
#define B01101101 109
#define B1101110 110
#define B01101110 110
#define B1101111 111
#define B01101111 111
#define B1110000 112
#define B01110000 112
#define B1110001 113
#define B01110001 113
#define B1110010 114
#define B01110010 114
#define B1110011 115
#define B01110011 115
#define B1110100 116
#define B01110100 116
#define B1110101 117
#define B01110101 117
#define B1110110 118
#define B01110110 118
#define B1110111 119
#define B01110111 119
#define B1111000 120
#define B01111000 120
#define B1111001 121
#define B01111001 121
#define B1111010 122
#define B01111010 122
#define B1111011 123
#define B01111011 123
#define B1111100 124
#define B01111100 124
#define B1111101 125
#define B01111101 125
#define B1111110 126
#define B01111110 126
#define B1111111 127
#define B01111111 127
#define B10000000 128
#define B10000001 129
#define B10000010 130
#define B10000011 131
#define B10000100 132
#define B10000101 133
#define B10000110 134
#define B10000111 135
#define B10001000 136
#define B10001001 137
#define B10001010 138
#define B10001011 139
#define B10001100 140
#define B10001101 141
#define B10001110 142
#define B10001111 143
#define B10010000 144
#define B10010001 145
#define B10010010 146
#define B10010011 147
#define B10010100 148
#define B10010101 149
#define B10010110 150
#define B10010111 151
#define B10011000 152
#define B10011001 153
#define B10011010 154
#define B10011011 155
#define B10011100 156
#define B10011101 157
#define B10011110 158
#define B10011111 159
#define B10100000 160
#define B10100001 161
#define B10100010 162
#define B10100011 163
#define B10100100 164
#define B10100101 165
#define B10100110 166
#define B10100111 167
#define B10101000 168
#define B10101001 169
#define B10101010 170
#define B10101011 171
#define B10101100 172
#define B10101101 173
#define B10101110 174
#define B10101111 175
#define B10110000 176
#define B10110001 177
#define B10110010 178
#define B10110011 179
#define B10110100 180
#define B10110101 181
#define B10110110 182
#define B10110111 183
#define B10111000 184
#define B10111001 185
#define B10111010 186
#define B10111011 187
#define B10111100 188
#define B10111101 189
#define B10111110 190
#define B10111111 191
#define B11000000 192
#define B11000001 193
#define B11000010 194
#define B11000011 195
#define B11000100 196
#define B11000101 197
#define B11000110 198
#define B11000111 199
#define B11001000 200
#define B11001001 201
#define B11001010 202
#define B11001011 203
#define B11001100 204
#define B11001101 205
#define B11001110 206
#define B11001111 207
#define B11010000 208
#define B11010001 209
#define B11010010 210
#define B11010011 211
#define B11010100 212
#define B11010101 213
#define B11010110 214
#define B11010111 215
#define B11011000 216
#define B11011001 217
#define B11011010 218
#define B11011011 219
#define B11011100 220
#define B11011101 221
#define B11011110 222
#define B11011111 223
#define B11100000 224
#define B11100001 225
#define B11100010 226
#define B11100011 227
#define B11100100 228
#define B11100101 229
#define B11100110 230
#define B11100111 231
#define B11101000 232
#define B11101001 233
#define B11101010 234
#define B11101011 235
#define B11101100 236
#define B11101101 237
#define B11101110 238
#define B11101111 239
#define B11110000 240
#define B11110001 241
#define B11110010 242
#define B11110011 243
#define B11110100 244
#define B11110101 245
#define B11110110 246
#define B11110111 247
#define B11111000 248
#define B11111001 249
#define B11111010 250
#define B11111011 251
#define B11111100 252
#define B11111101 253
#define B11111110 254
#define B11111111 255
#endif

View File

@@ -0,0 +1,127 @@
/*
Copyright (c) 2012 Arduino. 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
*/
#include "Arduino.h"
#include "Reset.h"
#ifdef __cplusplus
extern "C" {
#endif
static void __halt() {
// Halts
while (1)
;
}
extern void svcHook(void);
extern void pendSVHook(void);
extern int sysTickHook(void);
/* Cortex-M3 core handlers */
void NMI_Handler (void) __attribute__ ((weak, alias("__halt")));
void HardFault_Handler (void) __attribute__ ((weak, alias("__halt")));
void MemManage_Handler (void) __attribute__ ((weak, alias("__halt")));
void BusFault_Handler (void) __attribute__ ((weak, alias("__halt")));
void UsageFault_Handler(void) __attribute__ ((weak, alias("__halt")));
void DebugMon_Handler (void) __attribute__ ((weak, alias("__halt")));
void SVC_Handler (void) { svcHook(); }
void PendSV_Handler (void) { pendSVHook(); }
void SysTick_Handler(void)
{
if (sysTickHook())
return;
tickReset();
// Increment tick count each ms
TimeTick_Increment();
}
/* Peripherals handlers */
void SUPC_Handler (void) __attribute__ ((weak, alias("__halt")));
void RSTC_Handler (void) __attribute__ ((weak, alias("__halt")));
void RTC_Handler (void) __attribute__ ((weak, alias("__halt")));
void RTT_Handler (void) __attribute__ ((weak, alias("__halt")));
void WDT_Handler (void) __attribute__ ((weak, alias("__halt")));
void PMC_Handler (void) __attribute__ ((weak, alias("__halt")));
void EFC0_Handler (void) __attribute__ ((weak, alias("__halt")));
void EFC1_Handler (void) __attribute__ ((weak, alias("__halt")));
void UART_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_SMC_INSTANCE_
void SMC_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
#ifdef _SAM3XA_SDRAMC_INSTANCE_
void SDRAMC_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void PIOA_Handler (void) __attribute__ ((weak, alias("__halt")));
void PIOB_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_PIOC_INSTANCE_
void PIOC_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
#ifdef _SAM3XA_PIOD_INSTANCE_
void PIOD_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
#ifdef _SAM3XA_PIOE_INSTANCE_
void PIOE_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
#ifdef _SAM3XA_PIOF_INSTANCE_
void PIOF_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void USART0_Handler (void) __attribute__ ((weak, alias("__halt")));
void USART1_Handler (void) __attribute__ ((weak, alias("__halt")));
void USART2_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_USART3_INSTANCE_
void USART3_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void HSMCI_Handler (void) __attribute__ ((weak, alias("__halt")));
void TWI0_Handler (void) __attribute__ ((weak, alias("__halt")));
void TWI1_Handler (void) __attribute__ ((weak, alias("__halt")));
void SPI0_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_SPI1_INSTANCE_
void SPI1_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void SSC_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC0_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC1_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC2_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC3_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC4_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC5_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_TC2_INSTANCE_
void TC6_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC7_Handler (void) __attribute__ ((weak, alias("__halt")));
void TC8_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void PWM_Handler (void) __attribute__ ((weak, alias("__halt")));
void ADC_Handler (void) __attribute__ ((weak, alias("__halt")));
void DACC_Handler (void) __attribute__ ((weak, alias("__halt")));
void DMAC_Handler (void) __attribute__ ((weak, alias("__halt")));
void UOTGHS_Handler (void) __attribute__ ((weak, alias("__halt")));
void TRNG_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef _SAM3XA_EMAC_INSTANCE_
void EMAC_Handler (void) __attribute__ ((weak, alias("__halt")));
#endif
void CAN0_Handler (void) __attribute__ ((weak, alias("__halt")));
void CAN1_Handler (void) __attribute__ ((weak, alias("__halt")));
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,26 @@
/*
Copyright (c) 2011 Arduino. 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
*/
extern "C" void __cxa_pure_virtual(void) ;
/* We compile with nodefaultlibs, so we need to provide an error
* handler for an empty pure virtual function */
extern "C" void __cxa_pure_virtual(void) {
while(1)
;
}

View File

@@ -0,0 +1,58 @@
/*
Copyright (c) 2012 Arduino. 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
*/
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));
/**
* SysTick hook
*
* This function is called from SysTick handler, before the default
* handler provided by Arduino.
*/
static int __false() {
// Return false
return 0;
}
int sysTickHook(void) __attribute__ ((weak, alias("__false")));
/**
* SVC hook
* PendSV hook
*
* These functions are called from SVC handler, and PensSV handler.
* Default action is halting.
*/
static void __halt() {
// Halts
while (1)
;
}
void svcHook(void) __attribute__ ((weak, alias("__halt")));
void pendSVHook(void) __attribute__ ((weak, alias("__halt")));

View File

@@ -0,0 +1,109 @@
/*
Copyright (c) 2011 Arduino. 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
*/
/**
* \file
*
* Implementation of low level library.
*
*/
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */
#include "board.h"
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <yfuns.h>
#include <uart.h>
extern __weak size_t __write( int handle, const unsigned char *buf, size_t bufSize )
{
size_t nChars = 0 ;
/* Check for the command to flush all handles */
if ( handle == -1 )
{
return 0 ;
}
/* Check for stdout and stderr (only necessary if FILE descriptors are enabled.) */
if ( handle != 1 && handle != 2 )
{
/* remove warnings */
return 0xfffffff ;
}
for ( /* Empty */ ; bufSize > 0 ; --bufSize )
{
while ( !uart_is_tx_ready(CONSOLE_UART) )
;
uart_write( CONSOLE_UART, *buf ) ;
++buf ;
++nChars ;
}
return nChars ;
}
extern __weak size_t __read( int handle, unsigned char *buf, size_t bufSize )
{
size_t nChars = 0 ;
/* Check for stdin (only necessary if FILE descriptors are enabled) */
if ( handle != 0 )
{
/* remove warnings */
return 0xfffffff ;
}
for ( /*Empty*/; bufSize > 0 ; --bufSize )
{
uint8_t c;
while (uart_read( CONSOLE_UART, &c ))
;
if ( c == 0 )
{
break ;
}
*buf++ = c ;
++nChars ;
}
return nChars ;
}
/**
* \brief Outputs a character on the UART.
*
* \param c Character to output.
*
* \return The character that was output.
*/
extern __weak signed int putchar( signed int c )
{
while ( !uart_is_tx_ready(CONSOLE_UART) )
;
uart_write( CONSOLE_UART, c ) ;
return c ;
}
#endif // defined __ICCARM__

View File

@@ -0,0 +1,170 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "itoa.h"
#include <string.h>
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
#if 0
/* reverse: reverse string s in place */
static void reverse( char s[] )
{
int i, j ;
char c ;
for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- )
{
c = s[i] ;
s[i] = s[j] ;
s[j] = c ;
}
}
/* itoa: convert n to characters in s */
extern void itoa( int n, char s[] )
{
int i, sign ;
if ( (sign = n) < 0 ) /* record sign */
{
n = -n; /* make n positive */
}
i = 0;
do
{ /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0) ; /* delete it */
if (sign < 0 )
{
s[i++] = '-';
}
s[i] = '\0';
reverse( s ) ;
}
#else
extern char* itoa( int value, char *string, int radix )
{
return ltoa( value, string, radix ) ;
}
extern char* ltoa( long value, char *string, int radix )
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v;
int sign;
char *sp;
if ( string == NULL )
{
return 0 ;
}
if (radix > 36 || radix <= 1)
{
return 0 ;
}
sign = (radix == 10 && value < 0);
if (sign)
{
v = -value;
}
else
{
v = (unsigned long)value;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+'0';
else
*tp++ = i + 'a' - 10;
}
sp = string;
if (sign)
*sp++ = '-';
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
extern char* utoa( unsigned long value, char *string, int radix )
{
return ultoa( value, string, radix ) ;
}
extern char* ultoa( unsigned long value, char *string, int radix )
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v = value;
char *sp;
if ( string == NULL )
{
return 0;
}
if (radix > 36 || radix <= 1)
{
return 0;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+'0';
else
*tp++ = i + 'a' - 10;
}
sp = string;
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
#endif /* 0 */
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2011 Arduino. 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 _ITOA_
#define _ITOA_
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
#if 0
extern void itoa( int n, char s[] ) ;
#else
extern char* itoa( int value, char *string, int radix ) ;
extern char* ltoa( long value, char *string, int radix ) ;
extern char* utoa( unsigned long value, char *string, int radix ) ;
extern char* ultoa( unsigned long value, char *string, int radix ) ;
#endif /* 0 */
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // _ITOA_

View File

@@ -0,0 +1,55 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#define ARDUINO_MAIN
#include "Arduino.h"
/*
* Cortex-M3 Systick IT handler
*/
/*
extern void SysTick_Handler( void )
{
// Increment tick count each ms
TimeTick_Increment() ;
}
*/
/*
* \brief Main entry point of Arduino application
*/
int main( void )
{
init();
delay(1);
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;)
{
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}

View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2011 Arduino. 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
*/
/**
* \file syscalls.h
*
* Implementation of newlib syscall.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
extern caddr_t _sbrk( int incr ) ;
extern int link( char *cOld, char *cNew ) ;
extern int _close( int file ) ;
extern int _fstat( int file, struct stat *st ) ;
extern int _isatty( int file ) ;
extern int _lseek( int file, int ptr, int dir ) ;
extern int _read(int file, char *ptr, int len) ;
extern int _write( int file, char *ptr, int len ) ;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,140 @@
/*
Copyright (c) 2011 Arduino. 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
*/
/**
* \file syscalls_sam3.c
*
* Implementation of newlib syscall.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "syscalls.h"
#include <stdio.h>
#include <stdarg.h>
#include "sam.h"
#if defined ( __GNUC__ ) /* GCC CS3 */
#include <sys/types.h>
#include <sys/stat.h>
#endif
/*----------------------------------------------------------------------------
* Exported variables
*----------------------------------------------------------------------------*/
#undef errno
extern int errno ;
extern int _end ;
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void _exit( int status ) ;
extern void _kill( int pid, int sig ) ;
extern int _getpid ( void ) ;
extern caddr_t _sbrk ( int incr )
{
static unsigned char *heap = NULL ;
unsigned char *prev_heap ;
if ( heap == NULL )
{
heap = (unsigned char *)&_end ;
}
prev_heap = heap;
heap += incr ;
return (caddr_t) prev_heap ;
}
extern int link( char *cOld, char *cNew )
{
return -1 ;
}
extern int _close( int file )
{
return -1 ;
}
extern int _fstat( int file, struct stat *st )
{
st->st_mode = S_IFCHR ;
return 0 ;
}
extern int _isatty( int file )
{
return 1 ;
}
extern int _lseek( int file, int ptr, int dir )
{
return 0 ;
}
extern int _read(int file, char *ptr, int len)
{
return 0 ;
}
extern int _write( int file, char *ptr, int len )
{
int iIndex ;
// for ( ; *ptr != 0 ; ptr++ )
for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ )
{
// UART_PutChar( *ptr ) ;
// Check if the transmitter is ready
while ((UART->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
;
// Send character
UART->UART_THR = *ptr;
}
return iIndex ;
}
extern void _exit( int status )
{
printf( "Exiting with status %d.\n", status ) ;
for ( ; ; ) ;
}
extern void _kill( int pid, int sig )
{
return ;
}
extern int _getpid ( void )
{
return -1 ;
}

View File

@@ -0,0 +1,99 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32_t millis( void )
{
// todo: ensure no interrupts
return GetTickCount() ;
}
// Interrupt-compatible version of micros
// Theory: repeatedly take readings of SysTick counter, millis counter and SysTick interrupt pending flag.
// When it appears that millis counter and pending is stable and SysTick hasn't rolled over, use these
// values to calculate micros. If there is a pending SysTick, add one to the millis counter in the calculation.
uint32_t micros( void )
{
uint32_t ticks, ticks2;
uint32_t pend, pend2;
uint32_t count, count2;
ticks2 = SysTick->VAL;
pend2 = !!((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk)||((SCB->SHCSR & SCB_SHCSR_SYSTICKACT_Msk))) ;
count2 = GetTickCount();
do {
ticks=ticks2;
pend=pend2;
count=count2;
ticks2 = SysTick->VAL;
pend2 = !!((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk)||((SCB->SHCSR & SCB_SHCSR_SYSTICKACT_Msk))) ;
count2 = GetTickCount();
} while ((pend != pend2) || (count != count2) || (ticks < ticks2));
return ((count+pend) * 1000) + (((SysTick->LOAD - ticks)*(1048576/(F_CPU/1000000)))>>20) ;
// this is an optimization to turn a runtime division into two compile-time divisions and
// a runtime multiplication and shift, saving a few cycles
}
// original function:
// uint32_t micros( void )
// {
// uint32_t ticks ;
// uint32_t count ;
//
// SysTick->CTRL;
// do {
// ticks = SysTick->VAL;
// count = GetTickCount();
// } while (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk);
//
// return count * 1000 + (SysTick->LOAD + 1 - ticks) / (SystemCoreClock/1000000) ;
// }
void delay( uint32_t ms )
{
uint32_t end = GetTickCount() + ms;
while (GetTickCount() < end)
yield();
}
#if defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
extern signed int putchar( signed int c ) ;
/**
* \brief
*
* \param c Character to output.
*
* \return The character that was output.
*/
extern WEAK signed int putchar( signed int c )
{
return c ;
}
#endif /* __ICCARM__ */
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,80 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_
#define _WIRING_
#ifdef __cplusplus
extern "C" {
#endif
/**
*
*/
extern void init( void ) ;
/**
* \brief Returns the number of milliseconds since the Arduino board began running the current program.
*
* This number will overflow (go back to zero), after approximately 50 days.
*
* \return Number of milliseconds since the program started (uint32_t)
*/
extern uint32_t millis( void ) ;
/**
* \brief Returns the number of microseconds since the Arduino board began running the current program.
*
* This number will overflow (go back to zero), after approximately 70 minutes. On 16 MHz Arduino boards
* (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is
* always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution
* of eight microseconds.
*
* \note There are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second.
*/
extern uint32_t micros( void ) ;
/**
* \brief Pauses the program for the amount of time (in miliseconds) specified as parameter.
* (There are 1000 milliseconds in a second.)
*
* \param dwMs the number of milliseconds to pause (uint32_t)
*/
extern void delay( uint32_t dwMs ) ;
/**
* \brief Pauses the program for the amount of time (in microseconds) specified as parameter.
*
* \param dwUs the number of microseconds to pause (uint32_t)
*/
static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused));
static inline void delayMicroseconds(uint32_t usec){
uint32_t n = usec * (VARIANT_MCK / 3000000);
asm volatile(
"L_%=_delayMicroseconds:" "\n\t"
"subs %0, #1" "\n\t"
"bge L_%=_delayMicroseconds" "\n"
: "+r" (n) :
);
}
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_ */

View File

@@ -0,0 +1,353 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
static int _readResolution = 10;
static int _writeResolution = 8;
void analogReadResolution(int res) {
_readResolution = res;
}
void analogWriteResolution(int res) {
_writeResolution = res;
}
static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to) {
if (from == to)
return value;
if (from > to)
return value >> (from-to);
else
return value << (to-from);
}
eAnalogReference analog_reference = AR_DEFAULT;
void analogReference(eAnalogReference ulMode)
{
analog_reference = ulMode;
}
uint32_t analogRead(uint32_t ulPin)
{
uint32_t ulValue = 0;
uint32_t ulChannel;
if (ulPin < A0)
ulPin += A0;
ulChannel = g_APinDescription[ulPin].ulADCChannelNumber ;
#if defined __SAM3U4E__
switch ( g_APinDescription[ulPin].ulAnalogChannel )
{
// Handling ADC 10 bits channels
case ADC0 :
case ADC1 :
case ADC2 :
case ADC3 :
case ADC4 :
case ADC5 :
case ADC6 :
case ADC7 :
// Enable the corresponding channel
adc_enable_channel( ADC, ulChannel );
// Start the ADC
adc_start( ADC );
// Wait for end of conversion
while ((adc_get_status(ADC) & ADC_SR_DRDY) != ADC_SR_DRDY)
;
// Read the value
ulValue = adc_get_latest_value(ADC);
ulValue = mapResolution(ulValue, 10, _readResolution);
// Disable the corresponding channel
adc_disable_channel( ADC, ulChannel );
// Stop the ADC
// adc_stop( ADC ) ; // never do adc_stop() else we have to reconfigure the ADC each time
break;
// Handling ADC 12 bits channels
case ADC8 :
case ADC9 :
case ADC10 :
case ADC11 :
case ADC12 :
case ADC13 :
case ADC14 :
case ADC15 :
// Enable the corresponding channel
adc12b_enable_channel( ADC12B, ulChannel );
// Start the ADC12B
adc12b_start( ADC12B );
// Wait for end of conversion
while ((adc12b_get_status(ADC12B) & ADC12B_SR_DRDY) != ADC12B_SR_DRDY)
;
// Read the value
ulValue = adc12b_get_latest_value(ADC12B) >> 2;
ulValue = mapResolution(ulValue, 12, _readResolution);
// Stop the ADC12B
// adc12_stop( ADC12B ) ; // never do adc12_stop() else we have to reconfigure the ADC12B each time
// Disable the corresponding channel
adc12b_disable_channel( ADC12B, ulChannel );
break;
// Compiler could yell because we don't handle DAC pins
default :
ulValue=0;
break;
}
#endif
#if defined __SAM3X8E__ || defined __SAM3X8H__
switch ( g_APinDescription[ulPin].ulAnalogChannel )
{
// Handling ADC 12 bits channels
case ADC0 :
case ADC1 :
case ADC2 :
case ADC3 :
case ADC4 :
case ADC5 :
case ADC6 :
case ADC7 :
case ADC8 :
case ADC9 :
case ADC10 :
case ADC11 :
// Enable the corresponding channel
adc_enable_channel( ADC, ulChannel );
// Start the ADC
adc_start( ADC );
// Wait for end of conversion
while ((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY)
;
// Read the value
ulValue = adc_get_latest_value(ADC);
ulValue = mapResolution(ulValue, ADC_RESOLUTION, _readResolution);
// Disable the corresponding channel
adc_disable_channel(ADC, ulChannel);
break;
// Compiler could yell because we don't handle DAC pins
default :
ulValue=0;
break;
}
#endif
return ulValue;
}
static void TC_SetCMR_ChannelA(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xFFF0FFFF) | v;
}
static void TC_SetCMR_ChannelB(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xF0FFFFFF) | v;
}
static uint8_t PWMEnabled = 0;
static uint8_t pinEnabled[PINS_COUNT];
static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
void analogOutputInit(void) {
uint8_t i;
for (i=0; i<PINS_COUNT; i++)
pinEnabled[i] = 0;
}
// Right now, PWM output only works on the pins with
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(uint32_t ulPin, uint32_t ulValue) {
uint32_t attr = g_APinDescription[ulPin].ulPinAttribute;
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG) {
EAnalogChannel channel = g_APinDescription[ulPin].ulADCChannelNumber;
if (channel == DA0 || channel == DA1) {
uint32_t chDACC = ((channel == DA0) ? 0 : 1);
if (dacc_get_channel_status(DACC_INTERFACE) == 0) {
/* Enable clock for DACC_INTERFACE */
pmc_enable_periph_clk(DACC_INTERFACE_ID);
/* Reset DACC registers */
dacc_reset(DACC_INTERFACE);
/* Half word transfer mode */
dacc_set_transfer_mode(DACC_INTERFACE, 0);
/* Power save:
* sleep mode - 0 (disabled)
* fast wakeup - 0 (disabled)
*/
dacc_set_power_save(DACC_INTERFACE, 0, 0);
/* Timing:
* refresh - 0x08 (1024*8 dacc clocks)
* max speed mode - 0 (disabled)
* startup time - 0x10 (1024 dacc clocks)
*/
dacc_set_timing(DACC_INTERFACE, 0x08, 0, 0x10);
/* Set up analog current */
dacc_set_analog_control(DACC_INTERFACE, DACC_ACR_IBCTLCH0(0x02) |
DACC_ACR_IBCTLCH1(0x02) |
DACC_ACR_IBCTLDACCORE(0x01));
}
/* Disable TAG and select output channel chDACC */
dacc_set_channel_selection(DACC_INTERFACE, chDACC);
if ((dacc_get_channel_status(DACC_INTERFACE) & (1 << chDACC)) == 0) {
dacc_enable_channel(DACC_INTERFACE, chDACC);
}
// Write user value
ulValue = mapResolution(ulValue, _writeResolution, DACC_RESOLUTION);
dacc_write_conversion_data(DACC_INTERFACE, ulValue);
while ((dacc_get_interrupt_status(DACC_INTERFACE) & DACC_ISR_EOC) == 0);
return;
}
}
if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) {
ulValue = mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
if (!PWMEnabled) {
// PWM Startup code
pmc_enable_periph_clk(PWM_INTERFACE_ID);
PWMC_ConfigureClocks(PWM_FREQUENCY * PWM_MAX_DUTY_CYCLE, 0, VARIANT_MCK);
PWMEnabled = 1;
}
uint32_t chan = g_APinDescription[ulPin].ulPWMChannel;
if (!pinEnabled[ulPin]) {
// Setup PWM for this pin
PIO_Configure(g_APinDescription[ulPin].pPort,
g_APinDescription[ulPin].ulPinType,
g_APinDescription[ulPin].ulPin,
g_APinDescription[ulPin].ulPinConfiguration);
PWMC_ConfigureChannel(PWM_INTERFACE, chan, PWM_CMR_CPRE_CLKA, 0, 0);
PWMC_SetPeriod(PWM_INTERFACE, chan, PWM_MAX_DUTY_CYCLE);
PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
PWMC_EnableChannel(PWM_INTERFACE, chan);
pinEnabled[ulPin] = 1;
}
PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
return;
}
if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
// We use MCLK/2 as clock.
const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;
// Map value to Timer ranges 0..255 => 0..TC
ulValue = mapResolution(ulValue, _writeResolution, TC_RESOLUTION);
ulValue = ulValue * TC;
ulValue = ulValue / TC_MAX_DUTY_CYCLE;
// Setup Timer for this pin
ETCChannel channel = g_APinDescription[ulPin].ulTCChannel;
static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2 };
static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
static const Tc *channelToTC[] = {
TC0, TC0, TC0, TC0, TC0, TC0,
TC1, TC1, TC1, TC1, TC1, TC1,
TC2, TC2, TC2, TC2, TC2, TC2 };
static const uint32_t channelToId[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 };
uint32_t chNo = channelToChNo[channel];
uint32_t chA = channelToAB[channel];
Tc *chTC = channelToTC[channel];
uint32_t interfaceID = channelToId[channel];
if (!TCChanEnabled[interfaceID]) {
pmc_enable_periph_clk(TC_INTERFACE_ID + interfaceID);
TC_Configure(chTC, chNo,
TC_CMR_TCCLKS_TIMER_CLOCK1 |
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
TC_SetRC(chTC, chNo, TC);
}
if (ulValue == 0) {
if (chA)
TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR);
else
TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
} else {
if (chA) {
TC_SetRA(chTC, chNo, ulValue);
TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
} else {
TC_SetRB(chTC, chNo, ulValue);
TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_SET);
}
}
if (!pinEnabled[ulPin]) {
PIO_Configure(g_APinDescription[ulPin].pPort,
g_APinDescription[ulPin].ulPinType,
g_APinDescription[ulPin].ulPin,
g_APinDescription[ulPin].ulPinConfiguration);
pinEnabled[ulPin] = 1;
}
if (!TCChanEnabled[interfaceID]) {
TC_Start(chTC, chNo);
TCChanEnabled[interfaceID] = 1;
}
return;
}
// Defaults to digital write
pinMode(ulPin, OUTPUT);
ulValue = mapResolution(ulValue, _writeResolution, 8);
if (ulValue < 128)
digitalWrite(ulPin, LOW);
else
digitalWrite(ulPin, HIGH);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,79 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_ANALOG_
#define _WIRING_ANALOG_
#ifdef __cplusplus
extern "C" {
#endif
/*
* \brief SAM3 products have only one reference for ADC
*/
typedef enum _eAnalogReference
{
AR_DEFAULT,
} eAnalogReference ;
/*
* \brief Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
* This function is kept only for compatibility with existing AVR based API.
*
* \param ulMmode Should be set to AR_DEFAULT.
*/
extern void analogReference( eAnalogReference ulMode ) ;
/*
* \brief Writes an analog value (PWM wave) to a pin.
*
* \param ulPin
* \param ulValue
*/
extern void analogWrite( uint32_t ulPin, uint32_t ulValue ) ;
/*
* \brief Reads the value from the specified analog pin.
*
* \param ulPin
*
* \return Read value from selected pin, if no error.
*/
extern uint32_t analogRead( uint32_t ulPin ) ;
/*
* \brief Set the resolution of analogRead return values. Default is 10 bits (range from 0 to 1023).
*
* \param res
*/
extern void analogReadResolution(int res);
/*
* \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 0 to 255).
*
* \param res
*/
extern void analogWriteResolution(int res);
extern void analogOutputInit( void ) ;
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_ANALOG_ */

View File

@@ -0,0 +1,103 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_CONSTANTS_
#define _WIRING_CONSTANTS_
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define true 0x1
#define false 0x0
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define SERIAL 0x0
#define DISPLAY 0x1
enum BitOrder {
LSBFIRST = 0,
MSBFIRST = 1
};
// LOW 0
// HIGH 1
#define CHANGE 2
#define FALLING 3
#define RISING 4
#define DEFAULT 1
#define EXTERNAL 0
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif // abs
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif // min
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif // max
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
#define interrupts() __enable_irq()
#define noInterrupts() __disable_irq()
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
typedef unsigned int word;
#define bit(b) (1UL << (b))
// TODO: to be checked
typedef uint8_t boolean ;
typedef uint8_t byte ;
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* _WIRING_CONSTANTS_ */

View File

@@ -0,0 +1,109 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void pinMode( uint32_t ulPin, uint32_t ulMode )
{
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
{
return ;
}
switch ( ulMode )
{
case INPUT:
/* Enable peripheral for clocking input */
pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
PIO_Configure(
g_APinDescription[ulPin].pPort,
PIO_INPUT,
g_APinDescription[ulPin].ulPin,
0 ) ;
break ;
case INPUT_PULLUP:
/* Enable peripheral for clocking input */
pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
PIO_Configure(
g_APinDescription[ulPin].pPort,
PIO_INPUT,
g_APinDescription[ulPin].ulPin,
PIO_PULLUP ) ;
break ;
case OUTPUT:
PIO_Configure(
g_APinDescription[ulPin].pPort,
PIO_OUTPUT_1,
g_APinDescription[ulPin].ulPin,
g_APinDescription[ulPin].ulPinConfiguration ) ;
/* if all pins are output, disable PIO Controller clocking, reduce power consumption */
if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff )
{
pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
}
break ;
default:
break ;
}
}
extern void digitalWrite( uint32_t ulPin, uint32_t ulVal )
{
/* Handle */
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
{
return ;
}
if ( PIO_GetOutputDataStatus( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin ) == 0 )
{
PIO_PullUp( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin, ulVal ) ;
}
else
{
PIO_SetOutput( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin, ulVal, 0, PIO_PULLUP ) ;
}
}
extern int digitalRead( uint32_t ulPin )
{
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
{
return LOW ;
}
if ( PIO_Get( g_APinDescription[ulPin].pPort, PIO_INPUT, g_APinDescription[ulPin].ulPin ) == 1 )
{
return HIGH ;
}
return LOW ;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_DIGITAL_
#define _WIRING_DIGITAL_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Configures the specified pin to behave either as an input or an output. See the description of digital pins for details.
*
* \param ulPin The number of the pin whose mode you wish to set
* \param ulMode Either INPUT or OUTPUT
*/
extern void pinMode( uint32_t dwPin, uint32_t dwMode ) ;
/**
* \brief Write a HIGH or a LOW value to a digital pin.
*
* If the pin has been configured as an OUTPUT with pinMode(), its voltage will be set to the
* corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH, 0V (ground) for LOW.
*
* If the pin is configured as an INPUT, writing a HIGH value with digitalWrite() will enable an internal
* 20K pullup resistor (see the tutorial on digital pins). Writing LOW will disable the pullup. The pullup
* resistor is enough to light an LED dimly, so if LEDs appear to work, but very dimly, this is a likely
* cause. The remedy is to set the pin to an output with the pinMode() function.
*
* \note Digital pin PIN_LED is harder to use as a digital input than the other digital pins because it has an LED
* and resistor attached to it that's soldered to the board on most boards. If you enable its internal 20k pull-up
* resistor, it will hang at around 1.7 V instead of the expected 5V because the onboard LED and series resistor
* pull the voltage level down, meaning it always returns LOW. If you must use pin PIN_LED as a digital input, use an
* external pull down resistor.
*
* \param dwPin the pin number
* \param dwVal HIGH or LOW
*/
extern void digitalWrite( uint32_t dwPin, uint32_t dwVal ) ;
/**
* \brief Reads the value from a specified digital pin, either HIGH or LOW.
*
* \param ulPin The number of the digital pin you want to read (int)
*
* \return HIGH or LOW
*/
extern int digitalRead( uint32_t ulPin ) ;
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_DIGITAL_ */

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2011 Arduino. 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 WiringPrivate_h
#define WiringPrivate_h
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C"{
#endif
// Includes Atmel CMSIS
#include <chip.h>
#include "wiring_constants.h"
#ifdef __cplusplus
} // extern "C"
#include "HardwareSerial.h"
#endif
#endif

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "Arduino.h"
#include "wiring_private.h"
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
extern uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout )
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
PinDescription p = g_APinDescription[pin];
uint32_t width = 0; // keep initialization out of time critical area
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 22 clock cycles per iteration.
uint32_t numloops = 0;
uint32_t maxloops = microsecondsToClockCycles(timeout) / 22;
// wait for any previous pulse to end
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) == state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) != state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) == state) {
if (numloops++ == maxloops)
return 0;
width++;
}
// convert the reading to microseconds. The loop has been determined
// to be 52 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
return clockCyclesToMicroseconds(width * 52 + 16);
}

View File

@@ -0,0 +1,39 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_PULSE_
#define _WIRING_PULSE_
#ifdef __cplusplus
extern "C" {
#endif
/*
* \brief Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*/
extern uint32_t pulseIn( uint32_t ulPin, uint32_t ulState, uint32_t ulTimeout = 1000000L ) ;
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_PULSE_ */

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2011 Arduino. 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
*/
#include "Arduino.h"
#ifdef __cplusplus
extern "C"{
#endif
uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
{
uint8_t value = 0 ;
uint8_t i ;
for ( i=0 ; i < 8 ; ++i )
{
digitalWrite( ulClockPin, HIGH ) ;
if ( ulBitOrder == LSBFIRST )
{
value |= digitalRead( ulDataPin ) << i ;
}
else
{
value |= digitalRead( ulDataPin ) << (7 - i) ;
}
digitalWrite( ulClockPin, LOW ) ;
}
return value ;
}
void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
{
uint8_t i ;
for ( i=0 ; i < 8 ; i++ )
{
if ( ulBitOrder == LSBFIRST )
{
digitalWrite( ulDataPin, !!(ulVal & (1 << i)) ) ;
}
else
{
digitalWrite( ulDataPin, !!(ulVal & (1 << (7 - i))) ) ;
}
digitalWrite( ulClockPin, HIGH ) ;
digitalWrite( ulClockPin, LOW ) ;
}
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2011 Arduino. 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 _WIRING_SHIFT_
#define _WIRING_SHIFT_
#ifdef __cplusplus
extern "C" {
#endif
/*
* \brief
*/
extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder ) ;
/*
* \brief
*/
extern void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal ) ;
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_SHIFT_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
// DigiX WiFi module example - released by Digistump LLC/Erik Kettenburg under CC-BY-SA 3.0
#ifndef DigiFi_h
#define DigiFi_h
#include "Arduino.h"
#include "Print.h"
#include <string.h>
#include "Client.h"
#include "IPAddress.h"
#define DIGIFI_RTS 105
#define DIGIFI_CTS 104
#define TCP 1
#define UDP 0
class DigiFi : public Client
{
public:
static const int requestTimeout = 15;
String serverRequestPathString;
DigiFi();
void begin(int aBaud = 9600, bool en = false);
bool ready();
void setDebug(bool debugStateVar);
void setTCPTimeout(uint16_t timeout);
bool serverRequest();
void serverResponse(String response, int code = 200);
String server(uint16_t port);
String serverRequestPath();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual int disconnect();
int get(char *aHost, char *aPath);
int post(char *aHost, char *aPath, String postData);
void startATMode();
void endATMode();
void close();
void closeChunk();
void printChunk(const char *str);
void printChunk(int str);
void printChunk(long str);
void printChunk(String str);
void setMode(uint8_t protocol = TCP);
String header();
String body();
int lastError();
void debug(String output);
void debugWrite(char output);
String URLEncode(String smsg);
void setFlowControl(boolean);
//Ethernet implimentation
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsServerIP();
uint8_t maintain();
/* Client Implementation */
virtual uint8_t connected();
//uint8_t status();
virtual operator bool();
virtual int available( void ) ;
virtual int peek( void ) ;
virtual int read( void ) ;
virtual int read(uint8_t *buf, size_t size);
virtual void flush( void ) ;
virtual void stop( void ) ;
virtual size_t write( const uint8_t c ) ;
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write ; // pull in write(str) and write(buf, size) from Print
/* AT Wrappers */
String AT(char *cmd, char *params);
void toggleEcho(); //E
String getWifiMode(); //WMODE AP STA APSTA
void setWifiMode(char *mode);
void setTransparent(); //ENTM
String getTMode(); //TMODE throughput cmd
void setTMode(char *mode);
String getModId(); //MID
String version(); //VER
void factoryRestore(); //RELD rebooting...
void reset(); //Z (No return)
String help();//H
int readConfig(byte* buffer);//CFGRD
void writeConfig(byte* config, int len);//CFGWR
int readFactoryDef(byte* buffer);//CFGFR
void makeFactory(); //CFGTF
String getUart();//UART baudrate,data_bits,stop_bit,parity
void setUart(int baudrate,int data_bits,int stop_bit,char *parity);
/* These are commented out as I'm unsure how they should be named
String getAutoFrame(); //UARTF
void setAutoFrame(char *para);
int getAutoFrmTrigTime(); //UARTFT
void setAutoFrmTrigTime(int ms);
int getAutoFrmTrigLength(); //UARTFL
void setAutoFrmTrigLength(int v);
*/
void sendData(int len, char *data);//SEND
String recvData(int len);//RECV len,data (+ok=0 if timeout (3sec))
String ping(char *ip);//PING Success Timeout Unknown host
String getNetParams();//NETP (TCP|UDP),(SERVER|CLIENT),port,IP
void setNetParams(char *proto, char *cs, int port, const char *ip);
String getTCPLnk();//TCPLK on|off
String getTCPTimeout();//TCPTO 0 <= int <= 600 (Def 300)
String getTCPConn();//TCPDIS On|off
void setTCPConn(char *sta);
String getWSSSID();//WSSSID
void setWSSSID(char *ssid);
String getSTAKey();//WSKEY (OPEN|SHARED|WPAPSK|WPA2PSK),(NONE|WEP|TKIP|AES),key
void setSTAKey(char* auth,char *encry,char *key);
String getSTANetwork();//WANN (static|DHCP),ip,subnet,gateway
void setSTANetwork(char *mode, char *ip, char *subnet, char *gateway);
String getSTAMac();//WSMAC returns MAC
void setSTAMac(int code, char *mac);//Code default is 8888, no idea what its for
String STALinkStatus();//WSLK (Disconnected|AP SSID (AP MAC)|RF Off)
String STASignalStrength();//WSLQ (Disconnected|Value)
String scan();//WSCAN returns list
String getSTADNS();//WSDNS address
void setSTADNS(char *dns);
String getAPNetwork();//LANN ip,subnet
void setAPNetwork(char *ip, char *subnet);
String getAPParams();//WAP (11B|11BG|11BGN),SSID,(AUTO|C1...C11)
void setAPParams(char *mode, char *ssid, char *channel);
String getAPKey();//WAKEY (OPEN|WPA2PSK),(NONE|AES),key
void setAPKey(char* auth,char *encry,char *key);
String getAPMac();//WAMAC returns MAC
String getAPDHCP();//WADHCP (on|off)
void setAPDHCP(char *status);
String getAPPageDomain();//WADMN domain
void setAPPageDomain(char *domain);
void setPageDisplayMode(char *mode);//WEBSWITCH (iw|ew)
void setPageLanguage(char *lang);//PLANG CN|EN
String getUpgradeUrl();//UPURL url !!!DANGEROUS!!!
void setUpgradeUrl(char *url);//url,filename (filename is optional, if provided upgrade is auto started)
String getUpgradeFile();//UPFILE filename !!!DANGEROUS!!!
void setUpgradeFile(char *filename);
String startUpgrade();//UPST !!!DANGEROUS!!!
String getWebAuth();//WEBU user,pass
void setWebAuth(char *user, char *pass);
String getSleepMode();//MSLP normal|standby
void setSleepMode(char *mode);
void setModId(char *modid);//WRMID
String getWifiCfgPassword();//ASWD aswd
void setWifiCfgPassword(char *aswd);
private:
String readResponse(int contentLength);
bool startATSequence();
String aHeader;
String aBody;
//String lastHost;
int lastErr;
bool debugState;
};
#endif

View File

@@ -0,0 +1,4 @@
DigiFi
======
DigiX WiFi Library for the WIFI232-G Module

View File

@@ -0,0 +1,61 @@
// DigiX WiFi module example - released by Digistump LLC/Erik Kettenburg under CC-BY-SA 3.0
// Inspired by HttpClient library by MCQN Ltd.
#include <DigiFi.h>
DigiFi wifi;
void setup()
{
// initialize serial communications at 9600 bps:
Serial.begin(9600);
wifi.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
Serial.println("Starting");
while (wifi.ready() != 1)
{
Serial.println("Error connecting to network");
delay(15000);
}
Serial.println("Connected to wifi!");
//GET request example
if(wifi.get("digistump.com","/test.txt")){
String body = wifi.body();
Serial.println(body);
}
else{
Serial.println("error");
}
//POST request example
Serial.println("Sending tweet!");
//To use thingspeak for sending tweets see: http://community.thingspeak.com/documentation/apps/thingtweet/
if(wifi.post("api.thingspeak.com","/apps/thingtweet/1/statuses/update","api_key=[YOURTHINGTWEETAPIKEY]&status="+wifi.URLEncode("Tweet from my new DigiX! #digix #digistump http://digistump.com"))){
String body = wifi.body();
Serial.println(body);
}
else{
Serial.println("error");
}
wifi.close();
}
void loop()
{
}

View File

@@ -0,0 +1,77 @@
/*
Chat Server
A simple server that distributes any incoming messages to all
connected clients. To use telnet to your device's IP address and type.
You can see the client's input in the serial monitor as well.
Using a DigiX.
Circuit:
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified Dec 22, 2013 for use with DigiX by Erik Kettenburg
*/
#include <DigiFi.h>
DigiFi server;
boolean alreadyConnected = false; // whether or not the client was connected previously
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// start listening for clients
server.begin();
server.server(8080); //connect to it on port 8080
while (server.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
Serial.print("Chat server address:");
Serial.println(server.localIP());
}
void loop() {
// wait for a new client:
// when the client sends the first byte, say hello:
if (server.available() > 0) {
if (!alreadyConnected) {
// clead out the input buffer:
server.flush();
Serial.println("We have a new client");
server.println("Hello, client!");
alreadyConnected = true;
}
// read the bytes incoming from the client:
char thisChar = server.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.write(thisChar);
}
}

View File

@@ -0,0 +1,89 @@
/*
Telnet client
This sketch connects to a a telnet server (http://www.google.com)
using a DigiX. You'll need a telnet server
to test this with.
Processing's ChatServer example (part of the network library) works well,
running on port 10002. It can be found as part of the examples
in the Processing application, available at
http://processing.org/
created 14 Sep 2010
modified 9 Apr 2012
by Tom Igoe
modified Dec 22, 2013 for use with DigiX by Erik Kettenburg
*/
#include <DigiFi.h>
// Enter the IP address of the server you're connecting to:
IPAddress server(1, 1, 1, 1);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 23 is default for telnet;
// if you're using Processing's ChatServer, use port 10002):
DigiFi client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
Serial.println("Connecting...");
// start the connection:
client.begin(9600);
client.connect(server,23);
Serial.println("Connected.");
//client.setDebug(true);
//wait for module to be ready
while (client.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// as long as there are bytes in the serial queue,
// read them and send them out the socket if it's open:
while (Serial.available() > 0) {
char inChar = Serial.read();
if (client.connected()) {
client.print(inChar);
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing:
while (true);
}
}

View File

@@ -0,0 +1,127 @@
/*
Udp NTP Client
Get the time from a Network Time Protocol (NTP) time server
Demonstrates use of UDP sendPacket and ReceivePacket
For more on NTP time servers and the messages needed to communicate with them,
see http://en.wikipedia.org/wiki/Network_Time_Protocol
created 4 Sep 2010
by Michael Margolis
modified 9 Apr 2012
by Tom Igoe
modified Dec 22, 2013 for use with DigiX by Erik Kettenburg
This code is in the public domain.
*/
#include <DigiFi.h>
char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
uint8_t packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
DigiFi client;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// start the connection:
client.begin(9600);
//client.setDebug(true);
//wait for module to be ready
while (client.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
client.setMode(UDP); //must come before connect
Serial.println("Setting up UDP connection");
client.connect(timeServer,123);
}
void loop()
{
sendNTPpacket(); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);
if ( client.available() ) {
// We've received a packet, read the data from it
client.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = " );
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);
// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if ( ((epoch % 3600) / 60) < 10 ) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ( (epoch % 60) < 10 ) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch % 60); // print the second
}
// wait ten seconds before asking for the time again
delay(10000);
}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket()
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
client.write(packetBuffer, NTP_PACKET_SIZE);
}

View File

@@ -0,0 +1,86 @@
/*
Web client
This sketch connects to a website (http://www.google.com)
using an DigiX.
Based on example by David A. Mellis, Tom Igoe, and Adrian McEwen
*/
#include <DigiFi.h>
// if you don't want to use DNS - though it is handeled by the WiFI module
//so there is no size penalty for using it -
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "digistump.com"; // name address for Google (using DNS)
// Initialize the Wifi library (client/server/and main all in one)
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
DigiFi client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// start the connection:
client.begin(9600);
//client.setDebug(true);
//wait for module to be ready
while (client.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /test.txt HTTP/1.1");
client.println("Host: www.digistump.com");
client.println("Connection: close");
client.println();
}
else {
// kf you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
//while(!Serial1.available()){}
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
while(true);
}
}

View File

@@ -0,0 +1,100 @@
/*
Web Server
A simple web server that shows the value of the analog input pins.
Using a DigiX.
Circuit:
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified Dec 22, 2013 for use with DigiX by Erik Kettenburg
*/
#include <DigiFi.h>
// Initialize the DigiFi library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
DigiFi server;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// start the server:
server.begin();
server.server(8080); //start server on port 8080
server.setTCPTimeout(1); //force wifi to close connection after idle for 1 second
//fix for not being able to close client connections
//see WebServerChunked for a better approach
while (server.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
Serial.print("server is at ");
Serial.println(server.localIP());
}
boolean currentLineIsBlank = false;
void loop() {
// listen for incoming
// an http request ends with a blank line
if (server.available()) {
char c = server.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
server.println("HTTP/1.1 200 OK");
server.println("Content-Type: text/html");
server.println("Connection: close"); // the connection will be closed after completion of the response
server.println("Refresh: 5"); // refresh the page automatically every 5 sec
server.println();
server.println("<!DOCTYPE HTML>");
server.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
server.print("analog input ");
server.print(analogChannel);
server.print(" is ");
server.print(sensorReading);
server.println("<br />");
}
server.println("</html>");
server.println("");
server.println("");
currentLineIsBlank = false;
}
else if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
// give the web browser time to receive the data
delay(1);
}

View File

@@ -0,0 +1,98 @@
/*
Web Server
A simple web server that shows the value of the analog input pins.
Using a DigiX.
Circuit:
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified Dec 22, 2013 for use with DigiX by Erik Kettenburg
*/
#include <DigiFi.h>
// Initialize the DigiFi library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
DigiFi server;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// start the server:
server.begin();
server.server(8080); //start server on port 8080
while (server.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
Serial.print("server is at ");
Serial.println(server.localIP());
}
boolean currentLineIsBlank = false;
void loop() {
// listen for incoming
// an http request ends with a blank line
if (server.available()) {
char c = server.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
server.println("HTTP/1.1 200 OK");
server.println("Content-Type: text/html");
server.println("Connection: close"); // the connection will be closed after completion of the response
//server.println("Refresh: 5"); // refresh the page automatically every 5 sec
server.println("Transfer-Encoding: chunked");
server.println();
server.printChunk("<!DOCTYPE HTML>");
server.printChunk("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
server.printChunk("analog input ");
server.printChunk(analogChannel);
server.printChunk(" is ");
server.printChunk(sensorReading);
server.printChunk("<br />");
}
server.printChunk("</html>");
server.closeChunk();
currentLineIsBlank = false;
}
else if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
// give the web browser time to receive the data
delay(1);
}

View File

@@ -0,0 +1,118 @@
bool start = true;
String message = "";
#include <DigiFi.h>
DigiFi wifi;
//#define DEBUG
#include <Wire.h> // I2C Master lib for ATTinys which use USI - comment this out to use with standard arduinos
#include <LiquidCrystal_I2C.h> // for LCD w/ GPIO MODIFIED for the ATtiny85
#define GPIO_ADDR 0x27 // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A - 0x27 is the address of the Digispark LCD modules.
LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines
// Require keyboard control library
#include <KeyboardController.h>
// Initialize USB Controller
USBHost usb;
// Attach keyboard controller to USB
KeyboardController keyboard(usb);
// This function intercepts key press
void keyPressed() {
}
// This function intercepts key release
void keyReleased() {
printKey();
}
void printKey() {
if(start){
lcd.clear();
lcd.home();
start = false;
}
if(keyboard.getOemKey()==40){//enter pressed
lcd.noAutoscroll();
lcd.clear();
lcd.home();
lcd.print("Sending tweet...");
if(wifi.post("api.thingspeak.com","/apps/thingtweet/1/statuses/update","api_key=[YOURTHINGTWEETAPIKEY]&status="+wifi.URLEncode(message))){
lcd.clear();
lcd.home();
lcd.print("Tweet sent!");
}
else{
lcd.clear();
lcd.home();
lcd.print("Error sending!");
}
delay(3000);
lcd.clear();
lcd.home();
lcd.print("DigiX - Ready!");
message ="";
start=true;
lcd.noAutoscroll();
}
else{
// getKey() returns the ASCII translation of OEM key
// combined with modifiers.
char nextChar = keyboard.getKey();
lcd.print(nextChar);
message += nextChar;
if(message.length()==16)
lcd.autoscroll();
}
}
void setup()
{
Wire1.begin(); // initialize I2C lib - comment this out to use with standard arduinos
lcd.init(); // initialize the lcd
lcd.backlight(); // Print a message to the LCD.
lcd.print("Starting....");
delay(5000); //give wifi some time to warm up
lcd.clear();
lcd.print("WiFi Starting...");
wifi.begin(9600);
delay(200);
while (wifi.ready() != 1)
{
lcd.home();
lcd.print("WiFi not ready");
delay(15000);
}
lcd.clear();
lcd.home();
lcd.print("DigiX - Ready!");
}
void loop()
{
// Process USB tasks
usb.Task();
}

View File

@@ -0,0 +1,44 @@
#include <DigiFi.h>
DigiFi wifi;
void setup()
{
Serial.begin(9600);
wifi.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
Serial.println("Starting");
while (wifi.ready() != 1)
{
Serial.println("Error connecting to network");
delay(15000);
}
Serial.println("Connected to wifi!");
Serial.print("Server running at: ");
String address = wifi.server(8080);//sets up server and returns IP
Serial.println(address);
// wifi.close();
}
void loop()
{
if ( wifi.serverRequest()){
Serial.print("Request for: ");
Serial.println(wifi.serverRequestPath());
if(wifi.serverRequestPath()!="/")
wifi.serverResponse("404 Not Found",404);
else
wifi.serverResponse("<html><body><h1>This is a test</h1></body></html>"); //defaults to 200
}
delay(10);
}

View File

@@ -0,0 +1,155 @@
/*
Udp NTP Client
Uses both Due_RTC library and DigiFi to connect to NTP server
get current time and set RTC to that time.
This code is in the public domain.
*/
#include <rtc_clock.h>
#include <DigiFi.h>
RTC_clock rtc_clock(XTAL);
char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int hh,mm,ss,dow,dd,mon,yyyy;
char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
uint8_t packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
DigiFi client;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
rtc_clock.init();
// start the connection:
client.begin(9600);
//client.setDebug(true);
//wait for module to be ready
while (client.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
client.setMode(UDP); //must come before connect
rtc_clock.set_time(__TIME__);
Serial.println("Setting up UDP connection");
client.connect(timeServer,123);
unsigned long ntpUnixTime = 0;
while(ntpUnixTime == 0){
sendNTPpacket(); // send an NTP packet to a time server
delay(1000);
ntpUnixTime = getNTPpacket();
}
Serial.print("Got NTP Timestamp: ");
Serial.println(ntpUnixTime);
Serial.println("Setting RTC Clock");
rtc_clock.set_timestamp(ntpUnixTime);
}
void loop()
{
Serial.print("Time: ");
rtc_clock.get_time(&hh,&mm,&ss);
rtc_clock.get_date(&dow,&dd,&mon,&yyyy);
digitprint(hh, 2);
Serial.print(":");
digitprint(mm, 2);
Serial.print(":");
digitprint(ss, 2);
Serial.println("");
Serial.print("Date: ");
Serial.print(daynames[dow-1]);
Serial.print(" ");
digitprint(dd, 2);
Serial.print(".");
digitprint(mon, 2);
Serial.print(".");
Serial.println(yyyy);
Serial.println("");
delay(1000);
}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket()
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
client.write(packetBuffer, NTP_PACKET_SIZE);
}
unsigned long getNTPpacket(){
if ( client.available() ) {
// We've received a packet, read the data from it
client.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
//Serial.print("Seconds since Jan 1 1900 = " );
//Serial.println(secsSince1900);
// now convert NTP time into everyday time:
//Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
return epoch;
}
else{
return 0;
}
}
void digitprint(int value, int lenght){
for (int i = 0; i < (lenght - numdigits(value)); i++){
Serial.print("0");
}
Serial.print(value);
}
int numdigits(int i){
int digits;
if (i < 10)
digits = 1;
else
digits = (int)(log10((double)i)) + 1;
return digits;
}

View File

@@ -0,0 +1,99 @@
#include <DigiFi.h>
// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
String writeAPIKey = "XXXMX2WYYR0EV68M";
const int updateThingSpeakInterval = 16 * 1000; // Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval)
// Variable Setup
long lastConnectionTime = 0;
int failedCounter = 0;
// Initialize DigiFi
DigiFi client;
void setup()
{
// Start Serial for debugging on the Serial Monitor
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
// Start DigiFi
startDigiFi();
}
void loop()
{
// Read value from Analog Input Pin 0
String analogPin0 = String(analogRead(A0), DEC);
// Update ThingSpeak
if(millis() - lastConnectionTime > updateThingSpeakInterval)
{
updateThingSpeak("field1="+analogPin0);
}
// Check if Arduino Ethernet needs to be restarted
if (failedCounter > 3 ) {startDigiFi();}
}
void updateThingSpeak(String tsData)
{
if (client.connect(thingSpeakAddress, 80))
{
lastConnectionTime = millis();
if(wifi.post("api.thingspeak.com","/update","api_key="++writeAPIKey++"&status="+wifi.URLEncode(tsData)))
{
Serial.println("Sent to ThingSpeak");
Serial.println();
failedCounter = 0;
Serial.println(wifi.body());
}
else
{
failedCounter++;
Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
Serial.println();
}
}
else
{
failedCounter++;
Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
Serial.println();
lastConnectionTime = millis();
}
}
void startDigiFi()
{
Serial.println("Connecting Arduino to network...");
Serial.println();
delay(1000);
// Connect to network amd obtain an IP address using DHCP
client.begin();
client.setDebug(true);
while (client.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
delay(1000);
}

View File

@@ -0,0 +1,61 @@
// DigiX WiFi module example - released by Digistump LLC/Erik Kettenburg under CC-BY-SA 3.0
// Inspired by HttpClient library by MCQN Ltd.
#include <DigiFi.h>
DigiFi wifi;
void setup()
{
// initialize serial communications at 9600 bps:
Serial.begin(9600);
wifi.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
Serial.println("Starting");
while (wifi.ready() != 1)
{
Serial.println("Error connecting to network");
delay(15000);
}
Serial.println("Connected to wifi!");
//GET request example
if(wifi.get("digistump.com","/test.txt")){
String body = wifi.body();
Serial.println(body);
}
else{
Serial.println("error");
}
//POST request example
Serial.println("Sending tweet!");
//To use thingspeak for sending tweets see: http://community.thingspeak.com/documentation/apps/thingtweet/
if(wifi.post("api.thingspeak.com","/apps/thingtweet/1/statuses/update","api_key=[YOURTHINGTWEETAPIKEY]&status="+wifi.URLEncode("Tweet from my new DigiX! #digix #digistump http://digistump.com"))){
String body = wifi.body();
Serial.println(body);
}
else{
Serial.println("error");
}
wifi.close();
}
void loop()
{
}

View File

@@ -0,0 +1,33 @@
#include <DigiFi.h>
DigiFi wifi;
void setup()
{
Serial.begin(9600);
wifi.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
while(!Serial.available()){
Serial.println("Enter any key to begin");
delay(1000);
}
Serial.println("Starting");
while (wifi.ready() != 1)
{
Serial.println("Error connecting to network");
delay(15000);
}
Serial.println("Connected to wifi!");
wifi.startATMode();
Serial.println(wifi.ping("192.168.2.1"));
wifi.endATMode();
wifi.close();
}
void loop()
{
}

View File

@@ -0,0 +1,70 @@
/* Software Debouncing - Mechanical Rotary Encoder */
#define encoder0PinA 9
#define encoder0PinB 10
const int buttonPin = 12;
volatile unsigned int encoder0Pos = 0;
static boolean rotating=false;
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);
pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH);
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH);
attachInterrupt(encoder0PinA, rotEncoder, CHANGE);
SerialUSB.begin (9600);
}
void rotEncoder(){
rotating=true;
// If a signal change (noise or otherwise) is detected
// in the rotary encoder, the flag is set to true
}
void loop() {
while(rotating) {
delay(2);
// When signal changes we wait 2 milliseconds for it to
// stabilise before reading (increase this value if there
// still bounce issues)
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos++;
}
else {
encoder0Pos--;
}
rotating=false; // Reset the flag back to false
SerialUSB.println(encoder0Pos);
}
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
SerialUSB.print("Button: ");
SerialUSB.println(reading);
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonState = reading;
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonState = reading;
}

View File

@@ -0,0 +1,27 @@
int irPin=11;
void setup()
{
pinMode(irPin,INPUT);
pinMode(13,OUTPUT);
Serial.begin(9600);
digitalWrite(13,HIGH);
Serial.println("You pressed a button");
delay(1000);
digitalWrite(13,LOW);
}
void loop()
{
if(pulseIn(irPin,LOW))
{
//button pressed
delay(100);
digitalWrite(13,HIGH);
Serial.println("You pressed a button");
delay(1000);
digitalWrite(13,LOW);
}
}

View File

@@ -0,0 +1,20 @@
int RedPin = 5;
int GreenPin = 6;
int BluePin = 7;
void setup() {
// put your setup code here, to run once:
pinMode(RedPin, OUTPUT);
pinMode(GreenPin, OUTPUT);
pinMode(BluePin, OUTPUT);
}
void loop() {
randomSeed(analogRead(0));
// put your main code here, to run repeatedly:
analogWrite(RedPin,random(255));
analogWrite(GreenPin,random(255));
analogWrite(BluePin,random(255));
delay(500);
}

View File

@@ -0,0 +1,112 @@
#include <OneWire.h>
//DigiX Bonus Shield Temp example - modfied by Erik Kettenburg, Digistump LLC from:
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library
OneWire ds(8); // on pin 10 (a 4.7K resistor is necessary)
void setup(void) {
SerialUSB.begin(9600);
}
void loop(void) {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
SerialUSB.println("No more addresses.");
SerialUSB.println();
ds.reset_search();
delay(250);
return;
}
SerialUSB.print("ROM =");
for( i = 0; i < 8; i++) {
SerialUSB.write(' ');
SerialUSB.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
SerialUSB.println("CRC is not valid!");
return;
}
SerialUSB.println();
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
SerialUSB.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
SerialUSB.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
SerialUSB.println(" Chip = DS1822");
type_s = 0;
break;
default:
SerialUSB.println("Device is not a DS18x20 family device.");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
SerialUSB.print(" Data = ");
SerialUSB.print(present, HEX);
SerialUSB.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
SerialUSB.print(data[i], HEX);
SerialUSB.print(" ");
}
SerialUSB.print(" CRC=");
SerialUSB.print(OneWire::crc8(data, 8), HEX);
SerialUSB.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
SerialUSB.print(" Temperature = ");
SerialUSB.print(celsius);
SerialUSB.print(" Celsius, ");
SerialUSB.print(fahrenheit);
SerialUSB.println(" Fahrenheit");
}

View File

@@ -0,0 +1,179 @@
/*
Extensive TWI/I2C EEPROM Library - for 24LCxxx devices
version: 0.4.1
target device: Microchip 24LC256 or similar
compatibility: designed with Arduino Due
-> Ver. 0.4.1: Successfully tested with Arduino Uno R3 and Arduino Micro!
author: Dennis Schweer (Inglorious Engineer)
license: CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/deed.en)
Overview:
-bytewise reading/writing
void extEEPROMwrite(int chip_address, int address, byte value);
byte extEEPROMread(int chip_address, int address);
-pagewise reading/writing
void extEEPROMwritePage(int chip_address, int startaddress, byte* data_origin_array, int amount_of_transfered_bytes)
(!!!ATTENTION!!!: Limited to 30 Bytes only!)
void extEEPROMreadPage(int chip_address, int startaddress, byte* data_target_array, int amount_of_transfered_bytes)
(!!!ATTENTION!!!: Limited to 32 Bytes only)
Do not care about their size, just save them!
-read/write complete 32bit integers [Requires four bytes of your EEPROM.]
void extEEPROMwriteInt(int chip_address, int address, int data_to_be_stored)
int extEEPROMreadInt(int chip_address, int address)
-read/write your 10/12 bit sensor values (e.g., ADC values) [Requires two bytes of your EEPROM.]
void extEEPROMwriteSensor(int chip_address, int addresse, int data_to_be_stored)
int extEEPROMreadSensor(int chip_address, int addresse)
NEW IN VERSION 0.4:
Now all functions include a device address parameter, allowing you to use two
or more external EEPROM chips simultaneously on a single bus. Just choose the
right device addresses and feet them into the library functions!
NEW IN VERSION 0.4.1:
My library is designed with an Arduino Due, but now everything is successfully
tested to work on Arduino Uno R3 and Arduino Micro as well! Since all current
Arduinos are based on either ATmega328 (e.g., Uno), ATmega32U4 (e.g., Micro/
Leonardo/Esplora) or ATSAM3X8E (Due), my library should work with ALL official
or 1:1-compatible boards.
!!! Unfortunately, Arduino Due appears to be the only device with the ability
to handle 32 bit integers. Hence none of my "writeInt" / "readInt" functions
run on 8-bit Arduinos !!!
Planned for future releases:
-erase byte
-erase page
-erase complete EEPROM
-read/write with autocorrection of "startaddress"-value
*/
#include "Arduino.h"
//========FUNCTIONS=========================
///////////////// WRITE /////////////////////
void extEEPROMwrite(int EEPROM_addr, int addr, byte data)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.write((byte) data); // send data
Wire.endTransmission(true); // stop transmitting
delay(6); // wait for a successful write
}
void extEEPROMwritePage(int EEPROM_addr, int addr, byte* data_origin, int amount)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
for(int i = 0; i<amount; i++) //write array into EEPROM
{
Wire.write((byte) data_origin[i]);
}
Wire.endTransmission(true); // stop transmitting
delay(6); // wait for a successful write
}
void extEEPROMwriteInt(int EEPROM_addr, int addr, int data)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.write(lowByte(data)); // send lowest byte of 32 bit integer
data = data >> 8;
Wire.write(lowByte(data)); // send 2nd lowest byte of 32 bit integer
data = data >> 8;
Wire.write(lowByte(data)); // send 2nd highest byte of 32 bit integer
data = data >> 8;
Wire.write(lowByte(data)); // send highest byte of 32 bit integer
Wire.endTransmission(true); // stop transmitting
delay(6); // wait for a successful write
}
void extEEPROMwriteSensor(int EEPROM_addr, int addr, int data)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.write(lowByte(data)); // send low byte of 12 bit integer
data = data >> 8;
Wire.write(lowByte(data)); // send high byte of 12 bit integer
Wire.endTransmission(true); // stop transmitting
delay(6); // wait for a successful write
}
///////////////// READ /////////////////////
byte extEEPROMread(int EEPROM_addr, int addr)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.endTransmission(true); // stop transmitting
Wire.requestFrom(EEPROM_addr, 0x01, true); // request 1 byte form the device attached to EEPROM_addr
byte data_out = 64;
// read that byte
while(Wire.available() == 0) {} // wait for data
data_out = Wire.read(); //read single byte
return data_out;
}
void extEEPROMreadPage(int EEPROM_addr, int addr, byte* data_target, int amount)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.endTransmission(true); // stop transmitting
Wire.requestFrom(EEPROM_addr, amount, true); // request 1 byte form the device attached to EEPROM_addr
// read that byte
while(Wire.available() == 0) {} // wait for data
for(int i = 0; i<amount; i++) //write data into array
{
data_target[i] = Wire.read();
}
}
int extEEPROMreadInt(int EEPROM_addr, int addr)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.endTransmission(true); // stop transmitting
Wire.requestFrom(EEPROM_addr, 0x04, true); // request 1 byte form the device attached to EEPROM_addr
int data_out = 0xDEADBEEF;
int temp = 0xDEADBEEF;
// read that byte
while(Wire.available() == 0) {} // wait for data
data_out = Wire.read(); //read single byte
//reconstruct value
temp = Wire.read();
temp = temp << 8;
data_out = data_out | temp;
temp = Wire.read();
temp = temp << 16;
data_out = data_out | temp;
temp = Wire.read();
temp = temp << 24;
data_out = data_out | temp;
return data_out;
}
int extEEPROMreadSensor(int EEPROM_addr, int addr)
{
Wire.beginTransmission(EEPROM_addr); //Start transmission to EEPROM
Wire.write(highByte(addr)); // send high byte of address
Wire.write(lowByte(addr)); // send low byte of address
Wire.endTransmission(true); // stop transmitting
Wire.requestFrom(EEPROM_addr, 0x04, true); // request 1 byte form the device attached to EEPROM_addr
int data_out = 0xDEAD;
int temp = 0xBEEF;
// read that byte
while(Wire.available() == 0) {} // wait for data
data_out = Wire.read(); //read single byte
//reconstruct value
temp = Wire.read();
temp = temp << 8;
data_out = data_out | temp;
return data_out;
}

View File

@@ -0,0 +1,130 @@
/*
Extensive TWI/I2C EEPROM Library - for 24LCxxx devices
version: 0.4.1
target device: Microchip 24LC256 or similar
compatibility: designed with Arduino Due
-> Ver. 0.4.1: Successfully tested with Arduino Uno R3 and Arduino Micro!
author: Dennis Schweer (Inglorious Engineer)
license: CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/deed.en)
Overview:
-bytewise reading/writing
void extEEPROMwrite(int chip_address, int address, byte value);
byte extEEPROMread(int chip_address, int address);
-pagewise reading/writing
void extEEPROMwritePage(int chip_address, int startaddress, byte* data_origin_array, int amount_of_transfered_bytes)
(!!!ATTENTION!!!: Limited to 30 Bytes only!)
void extEEPROMreadPage(int chip_address, int startaddress, byte* data_target_array, int amount_of_transfered_bytes)
(!!!ATTENTION!!!: Limited to 32 Bytes only)
Do not care about their size, just save them!
-read/write complete 32bit integers [Requires four bytes of your EEPROM.]
void extEEPROMwriteInt(int chip_address, int address, int data_to_be_stored)
int extEEPROMreadInt(int chip_address, int address)
-read/write your 10/12 bit sensor values (e.g., ADC values) [Requires two bytes of your EEPROM.]
void extEEPROMwriteSensor(int chip_address, int addresse, int data_to_be_stored)
int extEEPROMreadSensor(int chip_address, int addresse)
NEW IN VERSION 0.4:
Now all functions include a device address parameter, allowing you to use two
or more external EEPROM chips simultaneously on a single bus. Just choose the
right device addresses and feet them into the library functions!
NEW IN VERSION 0.4.1:
My library is designed with an Arduino Due, but now everything is successfully
tested to work on Arduino Uno R3 and Arduino Micro as well! Since all current
Arduinos are based on either ATmega328 (e.g., Uno), ATmega32U4 (e.g., Micro/
Leonardo/Esplora) or ATSAM3X8E (Due), my library should work with ALL official
or 1:1-compatible boards.
!!! Unfortunately, Arduino Due appears to be the only device with the ability
to handle 32 bit integers. Hence none of my "writeInt" / "readInt" functions
run on 8-bit Arduinos !!!
Planned for future releases:
-erase byte
-erase page
-erase complete EEPROM
-read/write with autocorrection of "startaddress"-value
*/
#include <Wire.h>
#include <Extensive_EEPROM.h>
const int EEPROM_addr = 0x50;
// Testbed variables
int test = 1;
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600);
test = 1;
}
void loop()
{
//Testbed
if(test == 1) //only run it once
{
//byte-wise writing/reading
Serial.println("//byte-wise writing/reading");
for(int i = 0; i < 32; i++)
{
extEEPROMwrite(EEPROM_addr, i, i); //void extEEPROMwrite(int chip_address, int address, byte value);
}
int data_back;
for(int i = 0; i < 32; i++)
{
data_back = extEEPROMread(EEPROM_addr, i); //byte extEEPROMread(int chip_address, int address);
Serial.print("original data= ");
Serial.print(i);
Serial.print(" read_back= ");
Serial.println(data_back);
}
//page-wise writing/reading
Serial.println("//page-wise writing/reading");
byte data_to_be_written[30];
for(int i=0; i<30; i++)
{
data_to_be_written[i] = (29-i); //writes the numbers 29 downto 0 into cells 0-29
Serial.print("Original Data = ");
Serial.println((29-i));
}
//store array in EEPROM (max. 30 Bytes)
extEEPROMwritePage(EEPROM_addr, 32, data_to_be_written, 30); //void extEEPROMwritePage(int chip_address, int startaddress, byte* data_origin_array, int amount_of_transfered_bytes)
//read page into an array (max. 32 Bytes)
byte data_output[30];
extEEPROMreadPage(EEPROM_addr, 32, data_output, 30); // void extEEPROMreadPage(int chip_address, int startaddress, byte* data_target_array, int amountof_transfered_bytes)
for(int j=0; j<30; j++)
{
Serial.print("Read Page= ");
Serial.println(data_output[j]); // Print array
}
//write/read 32 bit integer
Serial.println("//write/read 32 bit integer");
int original_int = 0x7FFFFFFF;
extEEPROMwriteInt(EEPROM_addr, 70, original_int);
int original_int_output;
original_int_output = extEEPROMreadInt(EEPROM_addr, 70);
Serial.print("Integer: in = ");
Serial.print(original_int);
Serial.print(" / out = ");
Serial.println(original_int_output);
//write/read 10/12 bit sensor data
Serial.println("//write/read 10/12 bit sensor data");
int original_sensor = 0x7FFF;
extEEPROMwriteInt(EEPROM_addr, 75, original_sensor);
int original_sensor_output;
original_sensor_output = extEEPROMreadInt(EEPROM_addr, 75);
Serial.print("Sensordata: in = ");
Serial.print(original_sensor);
Serial.print(" / out = ");
Serial.println(original_sensor_output);
}
test = 2; // only perform this procedure once
}

View File

@@ -0,0 +1,321 @@
// LiquidCrystal_I2C V2.0
#include "LiquidCrystal_I2C.h"
#include <inttypes.h>
#if defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
#include "TinyWireM.h" // include this if ATtiny85 or ATtiny2313
#else
#include <Wire.h> // original lib include
#endif
#include "Arduino.h"
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
{
_Addr = lcd_Addr;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
}
void LiquidCrystal_I2C::init(){
init_priv();
}
void LiquidCrystal_I2C::init_priv()
{
#if defined (__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
TinyWireM.begin(); // initialize I2C lib
#else // original call
Wire1.begin();
#endif
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
}
void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
delay(50);
// Now we pull both RS and R/W low to begin commands
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
delay(1000);
//put the LCD into 4 bit mode
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// second try
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// third go!
write4bits(0x03 << 4);
delayMicroseconds(150);
// finally, set to 4-bit interface
write4bits(0x02 << 4);
// set # lines, font size, etc.
command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for roman languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);
home();
}
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear(){
command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::home(){
command(LCD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if ( row > _numlines ) {
row = _numlines-1; // we count rows starting w/0
}
command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
_displaycontrol |= LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
_displaycontrol |= LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
_displaycontrol |= LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval=LCD_NOBACKLIGHT;
expanderWrite(0);
}
void LiquidCrystal_I2C::backlight(void) {
_backlightval=LCD_BACKLIGHT;
expanderWrite(0);
}
/*********** mid level commands, for sending data/cmds */
inline void LiquidCrystal_I2C::command(uint8_t value) {
send(value, 0);
}
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 0;
}
/************ low level data pushing commands **********/
// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
uint8_t highnib=value&0xf0;
uint8_t lownib=(value<<4)&0xf0;
write4bits((highnib)|mode);
write4bits((lownib)|mode);
}
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
#if defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__) // Replaced Wire calls with ATtiny TWI calls
TinyWireM.beginTransmission(_Addr);
TinyWireM.send(((int)(_data) | _backlightval));
TinyWireM.endTransmission();
#else // original lib function
Wire1.beginTransmission(_Addr);
Wire1.write((int)(_data) | _backlightval);
Wire1.endTransmission();
#endif
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
}
// Alias functions
void LiquidCrystal_I2C::cursor_on(){
cursor();
}
void LiquidCrystal_I2C::cursor_off(){
noCursor();
}
void LiquidCrystal_I2C::blink_on(){
blink();
}
void LiquidCrystal_I2C::blink_off(){
noBlink();
}
void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){
createChar(char_num, rows);
}
void LiquidCrystal_I2C::setBacklight(uint8_t new_val){
if(new_val){
backlight(); // turn backlight on
}else{
noBacklight(); // turn backlight off
}
}
void LiquidCrystal_I2C::printstr(const char c[]){
//This function is not identical to the function used for "real" I2C displays
//it's here so the user sketch doesn't have to be changed
print(c);
}
// unsupported API functions
void LiquidCrystal_I2C::off(){}
void LiquidCrystal_I2C::on(){}
void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {}
uint8_t LiquidCrystal_I2C::status(){return 0;}
uint8_t LiquidCrystal_I2C::keypad (){return 0;}
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end){}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end){}
void LiquidCrystal_I2C::setContrast(uint8_t new_val){}

View File

@@ -0,0 +1,135 @@
// LiquidCrystal_I2C V2.0
// Note: The original libe file has beem modified to support the ATtiny85 1/20/11 by "BroHogan"
// All changes can be located by searching for "__AVR_ATtiny85__".
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
#include <inttypes.h>
#include "Print.h"
#if defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
#include "TinyWireM.h" // include this if ATtiny85 or ATtiny2313
#else
#include <Wire.h> // original lib include
#endif
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En B00000100 // Enable bit
#define Rw B00000010 // Read/Write bit
#define Rs B00000001 // Register select bit
class LiquidCrystal_I2C : public Print {
public:
LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void printLeft();
void printRight();
void leftToRight();
void rightToLeft();
void shiftIncrement();
void shiftDecrement();
void noBacklight();
void backlight();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
void command(uint8_t);
void init();
////compatibility API function aliases
void blink_on(); // alias for blink()
void blink_off(); // alias for noBlink()
void cursor_on(); // alias for cursor()
void cursor_off(); // alias for noCursor()
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar()
void printstr(const char[]);
////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
private:
void init_priv();
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void expanderWrite(uint8_t);
void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
};
#endif

View File

@@ -0,0 +1,26 @@
/* ATtiny85 as an I2C Master Ex2 BroHogan 1/21/11
* Modified for Digistump/DigiX - Digispark LCD Shield by Erik Kettenburg 11/2012
*/
//#define DEBUG
#include <Wire.h> // I2C Master lib for ATTinys which use USI - comment this out to use with standard arduinos
#include <LiquidCrystal_I2C.h> // for LCD w/ GPIO MODIFIED for the ATtiny85
#define GPIO_ADDR 0x27 // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A - 0x27 is the address of the Digispark LCD modules.
LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines
void setup(){
Wire1.begin(); // initialize I2C lib - comment this out to use with standard arduinos
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.print("DigiX!"); // Print a message to the LCD.
}
void loop(){
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

@@ -0,0 +1,55 @@
Notes for users with a Pollin.de interface board
http://www.pollin.de/shop/dt/NDU4OTgxOTk-/Bausaetze_Module/Bausaetze/LCD_I2C_Modul.html
The pollin interface board will not work with de default library.
To get it working two control lines to the LCD need to be changed.
Open file "LiquidCrystal_I2C.h" with a text editor like Notepad (not WordPad !)
In that file look for:
#define En B00010000 // Enable bit
#define Rw B00100000 // Read/Write bit
#define Rs B01000000 // Register select bit
Replace these lines by:
#define En B01000000 // Enable bit
#define Rw B00100000 // Read/Write bit
#define Rs B00010000 // Register select bit
People at Pollin also have misunderstood the PCF8574 Datasheet and list the wrong addresses on their PCB
For PCF8574A the addressing is:
Jp3 Jp2 Jp1
A2 A1 A0 Dec Hex
L L L 56 0x38
L L H 57 0x39
L H L 64 0x40
L H H 74 0x4A
H L L 75 0x4B
H L H 76 0x4C
H H L 77 0x4D
H H H 78 0x4E
They also seem to ship boards with a PCF8574
For PCF8574 the addressing is:
Jp3 Jp2 Jp1
A2 A1 A0 Dec Hex
L L L 32 0x20
L L H 33 0x21
L H L 34 0x22
L H H 35 0x23
H L L 36 0x24
H L H 37 0x25
H H L 38 0x26
H H H 39 0x27
They have also chosen two rather high pull-up resistors (10K) for the I2C lines. Usually two 4K7 resistors should do the job.
Please note that on a I2C bus only one device should have the pull-up resistors installed!
I hope this helps in getting your LCD working.
Mario

View File

@@ -0,0 +1,36 @@
LiquidCrystal_I2C V2.0
The LiquidCrystal_I2C library is a modified version of the standard LiquidCrystal library as found on
the Arduino website.
This library is intended to be used when a parallel HD44780 compatible LCD is controlled over I2C using
a PCF8574 extender (see datasheet for details).
4 of the 8 outputs are used for LDC data lines 4 to 7.
3 outputs are used for the Enable, register-select and Read/Write lines.
The one output left can be used to control the backlight of the LCD (if available).
For backlight control some extra resistors and a pnp-type transistor are required (for details see
schematic diagram).
The PCF8574 extender is available in two versions, the PCF8574 and the PCF8574A.
The only difference between the two is the I2C base address.
The base address for the PCF8574 is 0x20 and the base address for the PCF8574A is 0x38.
The examples included in this zip file assume the use of an PCF8574 set for address 0x20
(A0, A1 and A3 grounded).
For compatibility reasons this library contains some aliases for functions that are known under different
names in other libraries. This should make it fairly easy to implement the library in existing sketches
without changing to much code.
Functions not supported by this library will return nothing at all and in case a return value is expected
the function will return 0.
Update 8-12-2011:
Due to the relaese of Arduino IDE 1.0 some changes were made to the library to get it working under the new IDE.
Because of these changes this version of the LiquidCrystal_I2C library can not be used for older IDE versions.
The old version of the LiquidCrystal_I2Clibrary can be downloaded form http://www.xs4all.nl/~hmario/arduino/LiquidCrystal_I2C/V1.0/LiquidCrystal_I2C_V1.0.zip
Download the latest version from:
http://www.xs4all.nl/~hmario/arduino/LiquidCrystal_I2C/LiquidCrystal_I2C.zip
(Thanks to Ailton F. for beta testing.)
Mario H.
atmega@xs4all.nl

View File

@@ -0,0 +1,47 @@
###########################################
# Syntax Coloring Map For LiquidCrystal_I2C
# Version 2.0
###########################################
###########################################
# Datatypes (KEYWORD1)
###########################################
LiquidCrystal_I2C KEYWORD1
###########################################
# Methods and Functions (KEYWORD2)
###########################################
init KEYWORD2
begin KEYWORD2
clear KEYWORD2
home KEYWORD2
noDisplay KEYWORD2
display KEYWORD2
noBlink KEYWORD2
blink KEYWORD2
noCursor KEYWORD2
cursor KEYWORD2
scrollDisplayLeft KEYWORD2
scrollDisplayRight KEYWORD2
leftToRight KEYWORD2
rightToLeft KEYWORD2
shiftIncrement KEYWORD2
shiftDecrement KEYWORD2
noBacklight KEYWORD2
backlight KEYWORD2
autoscroll KEYWORD2
noAutoscroll KEYWORD2
createChar KEYWORD2
setCursor KEYWORD2
print KEYWORD2
blink_on KEYWORD2
blink_off KEYWORD2
cursor_on KEYWORD2
cursor_off KEYWORD2
setBacklight KEYWORD2
load_custom_character KEYWORD2
printstr KEYWORD2
###########################################
# Constants (LITERAL1)
###########################################

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,268 @@
// I2Cdev library collection - Main I2C device class header file
// Abstracts bit and byte I2C R/W functions into a convenient class
// 6/9/2012 by Jeff Rowberg <jeff@rowberg.net>
//
// Changelog:
// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan)
// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire
// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation
// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums)
// 2011-10-03 - added automatic Arduino version detection for ease of use
// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications
// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x)
// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default
// 2011-08-02 - added support for 16-bit registers
// - fixed incorrect Doxygen comments on some methods
// - added timeout value for read operations (thanks mem @ Arduino forums)
// 2011-07-30 - changed read/write function structures to return success or byte counts
// - made all methods static for multi-device memory savings
// 2011-07-28 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#ifndef _I2CDEV_H_
#define _I2CDEV_H_
// comment this out if you are using a non-optimal IDE/implementation setting
// but want the compiler to shut up about it
#define I2CDEV_IMPLEMENTATION_WARNINGS
// -----------------------------------------------------------------------------
// I2C interface implementation options
// -----------------------------------------------------------------------------
#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino
#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project
// ^^^ NBWire implementation is still buggy w/some interrupts!
#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project
// ^^^ FastWire implementation in I2Cdev is INCOMPLETE!
#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at
// https://github.com/DSSCircuits/I2C-Master-Library
// -----------------------------------------------------------------------------
// I2C interface implementation setting
// -----------------------------------------------------------------------------
#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE
// -----------------------------------------------------------------------------
// Arduino-style "Serial.print" debug constant (uncomment to enable)
// -----------------------------------------------------------------------------
//#define I2CDEV_SERIAL_DEBUG
#ifdef ARDUINO
#if ARDUINO < 100
#include "WProgram.h"
#else
#include "Arduino.h"
#endif
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include <Wire.h>
#else
#if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY
#include <I2C.h>
#endif
#endif
#else
#include "ArduinoWrapper.h"
#endif
// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];")
#define I2CDEV_DEFAULT_READ_TIMEOUT 1000
class I2Cdev {
public:
I2Cdev();
static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
static uint16_t readTimeout;
};
#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
//////////////////////
// FastWire 0.2
// This is a library to help faster programs to read I2C devices.
// Copyright(C) 2011
// Francesco Ferrara
//////////////////////
/* Master */
#define TW_START 0x08
#define TW_REP_START 0x10
/* Master Transmitter */
#define TW_MT_SLA_ACK 0x18
#define TW_MT_SLA_NACK 0x20
#define TW_MT_DATA_ACK 0x28
#define TW_MT_DATA_NACK 0x30
#define TW_MT_ARB_LOST 0x38
/* Master Receiver */
#define TW_MR_ARB_LOST 0x38
#define TW_MR_SLA_ACK 0x40
#define TW_MR_SLA_NACK 0x48
#define TW_MR_DATA_ACK 0x50
#define TW_MR_DATA_NACK 0x58
#define TW_OK 0
#define TW_ERROR 1
class Fastwire {
private:
static boolean waitInt();
public:
static void setup(int khz, boolean pullup);
static byte write(byte device, byte address, byte value);
static byte readBuf(byte device, byte address, byte *data, byte num);
};
#endif
#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
// NBWire implementation based heavily on code by Gene Knight <Gene@Telobot.com>
// Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html
// Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html
#define NBWIRE_BUFFER_LENGTH 32
class TwoWire {
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 beginTransmission(uint8_t);
//void beginTransmission(int);
uint8_t endTransmission(uint16_t timeout=0);
void nbendTransmission(void (*function)(int)) ;
uint8_t requestFrom(uint8_t, int, uint16_t timeout=0);
//uint8_t requestFrom(int, int);
void nbrequestFrom(uint8_t, int, void (*function)(int));
void send(uint8_t);
void send(uint8_t*, uint8_t);
//void send(int);
void send(char*);
uint8_t available(void);
uint8_t receive(void);
void onReceive(void (*)(int));
void onRequest(void (*)(void));
};
#define TWI_READY 0
#define TWI_MRX 1
#define TWI_MTX 2
#define TWI_SRX 3
#define TWI_STX 4
#define TW_WRITE 0
#define TW_READ 1
#define TW_MT_SLA_NACK 0x20
#define TW_MT_DATA_NACK 0x30
#define CPU_FREQ 16000000L
#define TWI_FREQ 100000L
#define TWI_BUFFER_LENGTH 32
/* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
#define TW_STATUS (TWSR & TW_STATUS_MASK)
#define TW_START 0x08
#define TW_REP_START 0x10
#define TW_MT_SLA_ACK 0x18
#define TW_MT_SLA_NACK 0x20
#define TW_MT_DATA_ACK 0x28
#define TW_MT_DATA_NACK 0x30
#define TW_MT_ARB_LOST 0x38
#define TW_MR_ARB_LOST 0x38
#define TW_MR_SLA_ACK 0x40
#define TW_MR_SLA_NACK 0x48
#define TW_MR_DATA_ACK 0x50
#define TW_MR_DATA_NACK 0x58
#define TW_ST_SLA_ACK 0xA8
#define TW_ST_ARB_LOST_SLA_ACK 0xB0
#define TW_ST_DATA_ACK 0xB8
#define TW_ST_DATA_NACK 0xC0
#define TW_ST_LAST_DATA 0xC8
#define TW_SR_SLA_ACK 0x60
#define TW_SR_ARB_LOST_SLA_ACK 0x68
#define TW_SR_GCALL_ACK 0x70
#define TW_SR_ARB_LOST_GCALL_ACK 0x78
#define TW_SR_DATA_ACK 0x80
#define TW_SR_DATA_NACK 0x88
#define TW_SR_GCALL_DATA_ACK 0x90
#define TW_SR_GCALL_DATA_NACK 0x98
#define TW_SR_STOP 0xA0
#define TW_NO_INFO 0xF8
#define TW_BUS_ERROR 0x00
//#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
//#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
#ifndef sbi // set bit
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif // sbi
#ifndef cbi // clear bit
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif // cbi
extern TwoWire Wire;
#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
#endif /* _I2CDEV_H_ */

View File

@@ -0,0 +1,38 @@
#######################################
# Syntax Coloring Map For I2Cdev
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
I2Cdev KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
readBit KEYWORD2
readBitW KEYWORD2
readBits KEYWORD2
readBitsW KEYWORD2
readByte KEYWORD2
readBytes KEYWORD2
readWord KEYWORD2
readWords KEYWORD2
writeBit KEYWORD2
writeBitW KEYWORD2
writeBits KEYWORD2
writeBitsW KEYWORD2
writeByte KEYWORD2
writeBytes KEYWORD2
writeWord KEYWORD2
writeWords KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,356 @@
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error
// 2012-06-20 - improved FIFO overflow handling and simplified read process
// 2012-06-19 - completely rearranged DMP initialization code and simplification
// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly
// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING
// 2012-06-05 - add gravity-compensated initial reference frame acceleration output
// - add 3D math helper file to DMP6 example sketch
// - add Euler output and Yaw/Pitch/Roll output formats
// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)
// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250
// 2012-05-30 - basic DMP initialization working
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
/* =========================================================================
NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
depends on the MPU-6050's INT pin being connected to the Arduino's
external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
digital I/O pin 2.
* ========================================================================= */
/* =========================================================================
NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
when using Serial.write(buf, len). The Teapot output uses this method.
The solution requires a modification to the Arduino USBAPI.h file, which
is fortunately simple, but annoying. This will be fixed in the next IDE
release. For more info, see these links:
http://arduino.cc/forum/index.php/topic,109987.0.html
http://code.google.com/p/arduino/issues/detail?id=958
* ========================================================================= */
// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION
// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER
// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
// pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL
// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL
// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
//#define OUTPUT_READABLE_WORLDACCEL
// uncomment "OUTPUT_TEAPOT" if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
// ================================================================
// === INTERRUPT DETECTION ROUTINE ===
// ================================================================
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
// ================================================================
// === INITIAL SETUP ===
// ================================================================
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire1.begin();
// initialize serial communication
// (115200 chosen because it is required for Teapot Demo output, but it's
// really up to you depending on your project)
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
// Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
// the baud timing being too misaligned with processor ticks. You must use
// 38400 or slower in these cases, or use some kind of external separate
// crystal solution for the UART timer.
// initialize device
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// wait for ready
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()); // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 2)..."));
attachInterrupt(2, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop() {
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// other program behavior stuff here
// .
// .
// .
// if you are really paranoid you can frequently test in between other
// stuff to see if mpuInterrupt is true, and if so, "break;" from the
// while() loop to immediately process the MPU data
// .
// .
// .
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_QUATERNION
// display quaternion values in easy matrix form: w x y z
mpu.dmpGetQuaternion(&q, fifoBuffer);
Serial.print("quat\t");
Serial.print(q.w);
Serial.print("\t");
Serial.print(q.x);
Serial.print("\t");
Serial.print(q.y);
Serial.print("\t");
Serial.println(q.z);
#endif
#ifdef OUTPUT_READABLE_EULER
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_REALACCEL
// display real acceleration, adjusted to remove gravity
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
Serial.print("areal\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\t");
Serial.println(aaReal.z);
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
// display initial world-frame acceleration, adjusted to remove gravity
// and rotated based on known orientation from quaternion
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
Serial.print("aworld\t");
Serial.print(aaWorld.x);
Serial.print("\t");
Serial.print(aaWorld.y);
Serial.print("\t");
Serial.println(aaWorld.z);
#endif
#ifdef OUTPUT_TEAPOT
// display quaternion values in InvenSense Teapot demo format:
teapotPacket[2] = fifoBuffer[0];
teapotPacket[3] = fifoBuffer[1];
teapotPacket[4] = fifoBuffer[4];
teapotPacket[5] = fifoBuffer[5];
teapotPacket[6] = fifoBuffer[8];
teapotPacket[7] = fifoBuffer[9];
teapotPacket[8] = fifoBuffer[12];
teapotPacket[9] = fifoBuffer[13];
Serial.write(teapotPacket, 14);
teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
#endif
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}

View File

@@ -0,0 +1,246 @@
// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output
// 6/20/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2012-06-20 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
import processing.serial.*;
import processing.opengl.*;
import toxi.geom.*;
import toxi.processing.*;
// NOTE: requires ToxicLibs to be installed in order to run properly.
// 1. Download from http://toxiclibs.org/downloads
// 2. Extract into [userdir]/Processing/libraries
// (location may be different on Mac/Linux)
// 3. Run and bask in awesomeness
ToxiclibsSupport gfx;
Serial port; // The serial port
char[] teapotPacket = new char[14]; // InvenSense Teapot packet
int serialCount = 0; // current packet byte position
int aligned = 0;
int interval = 0;
float[] q = new float[4];
Quaternion quat = new Quaternion(1, 0, 0, 0);
float[] gravity = new float[3];
float[] euler = new float[3];
float[] ypr = new float[3];
void setup() {
// 300px square viewport using OpenGL rendering
size(300, 300, OPENGL);
gfx = new ToxiclibsSupport(this);
// setup lights and antialiasing
lights();
smooth();
// display serial port list for debugging/clarity
println(Serial.list());
// get the first available port (use EITHER this OR the specific port code below)
String portName = Serial.list()[0];
// get a specific serial port (use EITHER this OR the first-available code above)
//String portName = "COM4";
// open the serial port
port = new Serial(this, portName, 115200);
// send single character to trigger DMP init/start
// (expected by MPU6050_DMP6 example Arduino sketch)
port.write('r');
}
void draw() {
if (millis() - interval > 1000) {
// resend single character to trigger DMP init/start
// in case the MPU is halted/reset while applet is running
port.write('r');
interval = millis();
}
// black background
background(0);
// translate everything to the middle of the viewport
pushMatrix();
translate(width / 2, height / 2);
// 3-step rotation from yaw/pitch/roll angles (gimbal lock!)
// ...and other weirdness I haven't figured out yet
//rotateY(-ypr[0]);
//rotateZ(-ypr[1]);
//rotateX(-ypr[2]);
// toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!)
// (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of
// different coordinate system orientation assumptions between Processing
// and InvenSense DMP)
float[] axis = quat.toAxisAngle();
rotate(axis[0], -axis[1], axis[3], axis[2]);
// draw main body in red
fill(255, 0, 0, 200);
box(10, 10, 200);
// draw front-facing tip in blue
fill(0, 0, 255, 200);
pushMatrix();
translate(0, 0, -120);
rotateX(PI/2);
drawCylinder(0, 20, 20, 8);
popMatrix();
// draw wings and tail fin in green
fill(0, 255, 0, 200);
beginShape(TRIANGLES);
vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer
vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer
vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer
vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer
endShape();
beginShape(QUADS);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
endShape();
popMatrix();
}
void serialEvent(Serial port) {
interval = millis();
while (port.available() > 0) {
int ch = port.read();
print((char)ch);
if (aligned < 4) {
// make sure we are properly aligned on a 14-byte packet
if (serialCount == 0) {
if (ch == '$') aligned++; else aligned = 0;
} else if (serialCount == 1) {
if (ch == 2) aligned++; else aligned = 0;
} else if (serialCount == 12) {
if (ch == '\r') aligned++; else aligned = 0;
} else if (serialCount == 13) {
if (ch == '\n') aligned++; else aligned = 0;
}
//println(ch + " " + aligned + " " + serialCount);
serialCount++;
if (serialCount == 14) serialCount = 0;
} else {
if (serialCount > 0 || ch == '$') {
teapotPacket[serialCount++] = (char)ch;
if (serialCount == 14) {
serialCount = 0; // restart packet byte position
// get quaternion from data packet
q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f;
q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f;
q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f;
q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f;
for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i];
// set our toxilibs quaternion to new data
quat.set(q[0], q[1], q[2], q[3]);
/*
// below calculations unnecessary for orientation only using toxilibs
// calculate gravity vector
gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]);
gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]);
gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
// calculate Euler angles
euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]);
euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1);
// calculate yaw/pitch/roll angles
ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2]));
ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2]));
// output various components for debugging
//println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f);
//println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI);
//println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI);
*/
}
}
}
}
}
void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {
float angle = 0;
float angleIncrement = TWO_PI / sides;
beginShape(QUAD_STRIP);
for (int i = 0; i < sides + 1; ++i) {
vertex(topRadius*cos(angle), 0, topRadius*sin(angle));
vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle));
angle += angleIncrement;
}
endShape();
// If it is not a cone, draw the circular top cap
if (topRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, 0, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(topRadius * cos(angle), 0, topRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
// If it is not a cone, draw the circular bottom cap
if (bottomRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, tall, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
}

View File

@@ -0,0 +1,95 @@
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2011-10-07 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
int16_t ax, ay, az;
int16_t gx, gy, gz;
#define LED_PIN 13
bool blinkState = false;
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire1.begin();
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
SerialUSB.begin(9600);
// initialize device
SerialUSB.println("Initializing I2C devices...");
accelgyro.initialize();
// verify connection
SerialUSB.println("Testing device connections...");
SerialUSB.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// these methods (and a few others) are also available
//accelgyro.getAcceleration(&ax, &ay, &az);
//accelgyro.getRotation(&gx, &gy, &gz);
// display tab-separated accel/gyro x/y/z values
SerialUSB.print("a/g:\t");
SerialUSB.print(ax); SerialUSB.print("\t");
SerialUSB.print(ay); SerialUSB.print("\t");
SerialUSB.print(az); SerialUSB.print("\t");
SerialUSB.print(gx); SerialUSB.print("\t");
SerialUSB.print(gy); SerialUSB.print("\t");
SerialUSB.println(gz);
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
delay(500);
}

Some files were not shown because too many files have changed in this diff Show More