aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Maglie <c.maglie@bug.st>2012-06-27 13:51:16 +0200
committerCristian Maglie <c.maglie@bug.st>2012-06-27 13:51:16 +0200
commita5564b6525c37cb295d05d88963d1ea3c63dd63c (patch)
tree613aa68f2c79923d313c6ea4a6cd1fdd9b5c7481
parent4596b23bb844d2bae2a698607073f8f0911cf4ab (diff)
parent8ad1900facadb793a33a0fd04d884d8cdf3947d6 (diff)
Merged master
-rw-r--r--avr/boards.txt20
-rwxr-xr-xavr/cores/arduino/Arduino.h1
-rw-r--r--avr/cores/arduino/CDC.cpp106
-rw-r--r--avr/cores/arduino/HID.cpp144
-rw-r--r--avr/cores/arduino/HardwareSerial.cpp8
-rw-r--r--avr/cores/arduino/HardwareSerial.h1
-rwxr-xr-xavr/cores/arduino/Print.cpp5
-rwxr-xr-xavr/cores/arduino/Print.h5
-rw-r--r--avr/cores/arduino/Stream.cpp44
-rw-r--r--avr/cores/arduino/Stream.h2
-rw-r--r--avr/cores/arduino/USBAPI.h82
-rw-r--r--avr/cores/arduino/USBCore.cpp34
-rw-r--r--avr/cores/arduino/USBDesc.h4
-rw-r--r--[-rwxr-xr-x]avr/cores/arduino/WInterrupts.c66
-rw-r--r--avr/cores/arduino/WString.cpp4
-rw-r--r--[-rwxr-xr-x]avr/cores/arduino/main.cpp2
-rw-r--r--[-rwxr-xr-x]avr/cores/arduino/wiring.c11
-rw-r--r--avr/cores/arduino/wiring_analog.c26
-rw-r--r--[-rwxr-xr-x]avr/cores/arduino/wiring_digital.c18
-rwxr-xr-xavr/cores/arduino/wiring_private.h2
-rw-r--r--avr/platform.txt38
-rw-r--r--sam/cores/arduino/Client.h26
-rw-r--r--sam/cores/arduino/IPAddress.cpp56
-rw-r--r--sam/cores/arduino/IPAddress.h76
-rw-r--r--sam/cores/arduino/Print.cpp3
-rw-r--r--sam/cores/arduino/Print.h5
-rw-r--r--sam/cores/arduino/Server.h9
-rw-r--r--sam/cores/arduino/Stream.cpp270
-rw-r--r--sam/cores/arduino/Stream.h63
-rw-r--r--sam/cores/arduino/USB/USBAPI.h7
-rw-r--r--sam/cores/arduino/USB/USBCore.cpp12
-rw-r--r--sam/cores/arduino/Udp.h88
-rw-r--r--sam/cores/arduino/main.cpp5
-rw-r--r--sam/cores/arduino/wiring_analog.c90
-rw-r--r--sam/cores/arduino/wiring_constants.h1
-rw-r--r--sam/cores/arduino/wiring_digital.c25
-rw-r--r--sam/cores/arduino/wiring_shift.c4
-rw-r--r--sam/platform.txt23
38 files changed, 1171 insertions, 215 deletions
diff --git a/avr/boards.txt b/avr/boards.txt
index af2ad8e..85a9bf3 100644
--- a/avr/boards.txt
+++ b/avr/boards.txt
@@ -7,10 +7,15 @@ uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.speed=115200
+
uno.bootloader.tool=avrdude
-uno.bootloader.erase.params=-e -Ulock:w:0x3F:m -Uefuse:w:0x05:m -Uhfuse:w:0xde:m -Ulfuse:w:0xff:m
-uno.bootloader.write.params=-Uflash:w:{bootloader.file}:i -Ulock:w:0x0F:m
-uno.bootloader.file={runtime.ide.path}/hardware/arduino/avr/optiboot/optiboot_atmega328.hex
+uno.bootloader.low_fuses=0xFF
+uno.bootloader.high_fuses=0xDE
+uno.bootloader.extended_fuses=0x05
+uno.bootloader.unlock_bits=0x3F
+uno.bootloader.lock_bits=0x0F
+uno.bootloader.file=optiboot/optiboot_atmega328.hex
+
uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.core=arduino
@@ -145,23 +150,28 @@ mega.build.variant=mega
##############################################################
leonardo.name=Arduino Leonardo
+leonardo.upload.tool=avrdude
leonardo.upload.protocol=avr109
leonardo.upload.maximum_size=28672
leonardo.upload.speed=57600
leonardo.upload.disable_flushing=true
+leonardo.upload.use_1200bps_touch=true
+
+leonardo.bootloader.tool=avrdude
leonardo.bootloader.low_fuses=0xff
leonardo.bootloader.high_fuses=0xd8
leonardo.bootloader.extended_fuses=0xcb
-leonardo.bootloader.path=caterina
-leonardo.bootloader.file=Caterina-Leonardo.hex
+leonardo.bootloader.file=caterina/Caterina-Leonardo.hex
leonardo.bootloader.unlock_bits=0x3F
leonardo.bootloader.lock_bits=0x2F
+
leonardo.build.mcu=atmega32u4
leonardo.build.f_cpu=16000000L
leonardo.build.vid=0x2341
leonardo.build.pid=0x8036
leonardo.build.core=arduino
leonardo.build.variant=leonardo
+leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid}
##############################################################
diff --git a/avr/cores/arduino/Arduino.h b/avr/cores/arduino/Arduino.h
index bfec943..830c995 100755
--- a/avr/cores/arduino/Arduino.h
+++ b/avr/cores/arduino/Arduino.h
@@ -20,6 +20,7 @@ extern "C"{
#define INPUT 0x0
#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
#define true 0x1
#define false 0x0
diff --git a/avr/cores/arduino/CDC.cpp b/avr/cores/arduino/CDC.cpp
index 14a0eae..1ee3a48 100644
--- a/avr/cores/arduino/CDC.cpp
+++ b/avr/cores/arduino/CDC.cpp
@@ -23,12 +23,20 @@
#if defined(USBCON)
#ifdef CDC_ENABLED
-void Reboot()
+#if (RAMEND < 1000)
+#define SERIAL_BUFFER_SIZE 16
+#else
+#define SERIAL_BUFFER_SIZE 64
+#endif
+
+struct ring_buffer
{
- USB.detach();
- cli();
- asm volatile("jmp 0x7800"); // jump to bootloader - DiskLoader takes up last 2 kB
-}
+ unsigned char buffer[SERIAL_BUFFER_SIZE];
+ volatile int head;
+ volatile int tail;
+};
+
+ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
typedef struct
{
@@ -92,9 +100,28 @@ bool WEAK CDC_Setup(Setup& setup)
if (CDC_SET_CONTROL_LINE_STATE == r)
{
- if (0 != _usbLineInfo.lineState && 1200 == _usbLineInfo.dwDTERate) // auto-reset is triggered when the port, already open at 1200 bps, is closed
- Reboot();
_usbLineInfo.lineState = setup.wValueL;
+
+ // auto-reset into the bootloader is triggered when the port, already
+ // open at 1200 bps, is closed. this is the signal to start the watchdog
+ // with a relatively long period so it can finish housekeeping tasks
+ // like servicing endpoints before the sketch ends
+ if (1200 == _usbLineInfo.dwDTERate) {
+ // We check DTR state to determine if host port is open (bit 0 of lineState).
+ if ((_usbLineInfo.lineState & 0x01) == 0) {
+ *(uint16_t *)0x0800 = 0x7777;
+ wdt_enable(WDTO_120MS);
+ } else {
+ // Most OSs do some intermediate steps when configuring ports and DTR can
+ // twiggle more than once before stabilizing.
+ // To avoid spurious resets we set the watchdog to 250ms and eventually
+ // cancel if DTR goes back high.
+
+ wdt_disable();
+ wdt_reset();
+ *(uint16_t *)0x0800 = 0x0;
+ }
+ }
return true;
}
}
@@ -111,33 +138,49 @@ void Serial_::end(void)
{
}
+void Serial_::accept(void)
+{
+ ring_buffer *buffer = &cdc_rx_buffer;
+ int c = USB_Recv(CDC_RX);
+ int i = (unsigned int)(buffer->head+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 != buffer->tail) {
+ buffer->buffer[buffer->head] = c;
+ buffer->head = i;
+ }
+}
+
int Serial_::available(void)
{
- u8 avail = USB_Available(CDC_RX);
- if (_serialPeek != -1)
- avail++;
- return avail;
+ ring_buffer *buffer = &cdc_rx_buffer;
+ return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;
}
-// peek is nasty
int Serial_::peek(void)
{
- if (_serialPeek == -1)
- _serialPeek = read();
- return _serialPeek;
+ ring_buffer *buffer = &cdc_rx_buffer;
+ if (buffer->head == buffer->tail) {
+ return -1;
+ } else {
+ return buffer->buffer[buffer->tail];
+ }
}
int Serial_::read(void)
{
- int c;
- if (_serialPeek != -1)
- {
- c = _serialPeek;
- _serialPeek = -1;
+ 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 {
- c = USB_Recv(CDC_RX);
- }
- return c;
+ unsigned char c = buffer->buffer[buffer->tail];
+ buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE;
+ return c;
+ }
}
void Serial_::flush(void)
@@ -169,7 +212,22 @@ size_t Serial_::write(uint8_t c)
return 0;
}
+// 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() {
+ bool result = false;
+ if (_usbLineInfo.lineState > 0)
+ result = true;
+ delay(10);
+ return result;
+}
+
Serial_ Serial;
#endif
-#endif /* if defined(USBCON) */ \ No newline at end of file
+#endif /* if defined(USBCON) */
diff --git a/avr/cores/arduino/HID.cpp b/avr/cores/arduino/HID.cpp
index 8ed1566..ac63608 100644
--- a/avr/cores/arduino/HID.cpp
+++ b/avr/cores/arduino/HID.cpp
@@ -144,7 +144,6 @@ u8 _hid_protocol = 1;
u8 _hid_idle = 1;
#define WEAK __attribute__ ((weak))
-#define WEAK
int WEAK HID_GetInterface(u8* interfaceNum)
{
@@ -202,7 +201,15 @@ bool WEAK HID_Setup(Setup& setup)
//================================================================================
// Mouse
-Mouse_::Mouse_() : _buttons(0)
+Mouse_::Mouse_(void) : _buttons(0)
+{
+}
+
+void Mouse_::begin(void)
+{
+}
+
+void Mouse_::end(void)
{
}
@@ -245,7 +252,7 @@ void Mouse_::release(uint8_t b)
bool Mouse_::isPressed(uint8_t b)
{
- if (b & _buttons > 0)
+ if ((b & _buttons) > 0)
return true;
return false;
}
@@ -254,18 +261,21 @@ bool Mouse_::isPressed(uint8_t b)
//================================================================================
// Keyboard
-Keyboard_::Keyboard_() : _keyMap(0)
+Keyboard_::Keyboard_(void)
{
}
-void Keyboard_::sendReport(KeyReport* keys)
+void Keyboard_::begin(void)
+{
+}
+
+void Keyboard_::end(void)
{
- HID_SendReport(2,keys,sizeof(KeyReport));
}
-void Keyboard_::setKeyMap(KeyMap* keyMap)
+void Keyboard_::sendReport(KeyReport* keys)
{
- _keyMap = keyMap;
+ HID_SendReport(2,keys,sizeof(KeyReport));
}
extern
@@ -406,41 +416,105 @@ const uint8_t _asciimap[128] =
};
uint8_t USBPutChar(uint8_t c);
-size_t Keyboard_::write(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)
{
- // Keydown
- {
- KeyReport keys = {0};
- if (_keyMap)
- _keyMap->charToKey(c,&keys);
- else
- {
- if (c >= 128) {
- setWriteError();
- return 0;
- }
- c = pgm_read_byte(_asciimap + c);
- if (!c) {
- setWriteError();
- return 0;
- }
- if (c & 0x80)
- {
- keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT;
- c &= 0x7F;
+ 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 = pgm_read_byte(_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;
}
- keys.keys[0] = c;
}
- sendReport(&keys);
+ if (i == 6) {
+ setWriteError();
+ return 0;
+ }
}
- // Keyup
- {
- KeyReport keys = {0};
- sendReport(&keys);
+ 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 = pgm_read_byte(_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 = press(c); // Keydown
+ uint8_t r = release(c); // Keyup
+ return (p); // just return the result of press() since release() almost always returns 1
+}
+
#endif
#endif /* if defined(USBCON) */ \ No newline at end of file
diff --git a/avr/cores/arduino/HardwareSerial.cpp b/avr/cores/arduino/HardwareSerial.cpp
index 1b1fa71..f40ddee 100644
--- a/avr/cores/arduino/HardwareSerial.cpp
+++ b/avr/cores/arduino/HardwareSerial.cpp
@@ -46,8 +46,8 @@
struct ring_buffer
{
unsigned char buffer[SERIAL_BUFFER_SIZE];
- volatile int head;
- volatile int tail;
+ volatile unsigned int head;
+ volatile unsigned int tail;
};
#if defined(USBCON)
@@ -398,6 +398,10 @@ size_t HardwareSerial::write(uint8_t c)
return 1;
}
+HardwareSerial::operator bool() {
+ return true;
+}
+
// Preinstantiate Objects //////////////////////////////////////////////////////
#if defined(UBRRH) && defined(UBRRL)
diff --git a/avr/cores/arduino/HardwareSerial.h b/avr/cores/arduino/HardwareSerial.h
index 176abe1..bf4924c 100644
--- a/avr/cores/arduino/HardwareSerial.h
+++ b/avr/cores/arduino/HardwareSerial.h
@@ -57,6 +57,7 @@ class HardwareSerial : public Stream
virtual void flush(void);
virtual size_t write(uint8_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
+ operator bool();
};
#if defined(UBRRH) || defined(UBRR0H)
diff --git a/avr/cores/arduino/Print.cpp b/avr/cores/arduino/Print.cpp
index ff9b154..711251c 100755
--- a/avr/cores/arduino/Print.cpp
+++ b/avr/cores/arduino/Print.cpp
@@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)
size_t Print::print(const __FlashStringHelper *ifsh)
{
- const prog_char *p = (const prog_char *)ifsh;
+ const char PROGMEM *p = (const char PROGMEM *)ifsh;
size_t n = 0;
while (1) {
unsigned char c = pgm_read_byte(p++);
@@ -226,6 +226,9 @@ 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");
+
// Handle negative numbers
if (number < 0.0)
{
diff --git a/avr/cores/arduino/Print.h b/avr/cores/arduino/Print.h
index 1af6b72..dc76150 100755
--- a/avr/cores/arduino/Print.h
+++ b/avr/cores/arduino/Print.h
@@ -46,7 +46,10 @@ class Print
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
- size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
+ 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 *);
diff --git a/avr/cores/arduino/Stream.cpp b/avr/cores/arduino/Stream.cpp
index 5fad8dd..aafb7fc 100644
--- a/avr/cores/arduino/Stream.cpp
+++ b/avr/cores/arduino/Stream.cpp
@@ -99,25 +99,27 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
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
+ 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);
+ //////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;
}
}
- else{
- index = 0; // reset index if any char does not match
- }
+
if(termLen > 0 && c == terminator[termIndex]){
- if(++termIndex >= termLen)
- return false; // return false if terminate string found before target string
+ if(++termIndex >= termLen)
+ return false; // return false if terminate string found before target string
}
else
- termIndex = 0;
+ termIndex = 0;
}
return false;
}
@@ -242,3 +244,27 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
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;
+}
+
diff --git a/avr/cores/arduino/Stream.h b/avr/cores/arduino/Stream.h
index 13f11be..58bbf75 100644
--- a/avr/cores/arduino/Stream.h
+++ b/avr/cores/arduino/Stream.h
@@ -82,6 +82,8 @@ class Stream : public Print
// 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
diff --git a/avr/cores/arduino/USBAPI.h b/avr/cores/arduino/USBAPI.h
index 26a2032..eb2e593 100644
--- a/avr/cores/arduino/USBAPI.h
+++ b/avr/cores/arduino/USBAPI.h
@@ -9,17 +9,17 @@
//================================================================================
// USB
-class USB_
+class USBDevice_
{
public:
- USB_();
+ USBDevice_();
bool configured();
void attach();
void detach(); // Serial port goes down too...
void poll();
};
-extern USB_ USB;
+extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
@@ -27,15 +27,20 @@ extern USB_ USB;
class Serial_ : public Stream
{
+private:
+ ring_buffer *_cdc_rx_buffer;
public:
void begin(uint16_t baud_count);
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);
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+ operator bool();
};
extern Serial_ Serial;
@@ -54,12 +59,14 @@ private:
uint8_t _buttons;
void buttons(uint8_t b);
public:
- Mouse_();
+ 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
+ bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
};
extern Mouse_ Mouse;
@@ -67,14 +74,42 @@ extern Mouse_ Mouse;
//================================================================================
// Keyboard
-#define KEY_MODIFIER_LEFT_CTRL 0x01
-#define KEY_MODIFIER_LEFT_SHIFT 0x02
-#define KEY_MODIFIER_LEFT_ALT 0x04
-#define KEY_MODIFIER_LEFT_GUI 0x08
-#define KEY_MODIFIER_RIGHT_CTRL 0x010
-#define KEY_MODIFIER_RIGHT_SHIFT 0x020
-#define KEY_MODIFIER_RIGHT_ALT 0x040
-#define KEY_MODIFIER_RIGHT_GUI 0x080
+#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
@@ -84,24 +119,19 @@ typedef struct
uint8_t keys[6];
} KeyReport;
-// Map a character into a key report
-// Called from Print to map text to keycodes
-class KeyMap
-{
-public:
- virtual void charToKey(int c, KeyReport* keyReport) = 0;
-};
-
-//
class Keyboard_ : public Print
{
private:
- KeyMap* _keyMap;
+ KeyReport _keyReport;
void sendReport(KeyReport* keys);
- void setKeyMap(KeyMap* keyMap);
public:
- Keyboard_();
- virtual size_t write(uint8_t);
+ 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;
diff --git a/avr/cores/arduino/USBCore.cpp b/avr/cores/arduino/USBCore.cpp
index 4c71b34..6766be6 100644
--- a/avr/cores/arduino/USBCore.cpp
+++ b/avr/cores/arduino/USBCore.cpp
@@ -51,16 +51,20 @@ const u16 STRING_LANGUAGE[2] = {
const u16 STRING_IPRODUCT[17] = {
(3<<8) | (2+2*16),
-#if USB_PID == USB_PID_LEONARDO
+#if USB_PID == 0x8036
'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o'
-#elif USB_PID == USB_PID_MICRO
- 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' '
+#else
+ 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' '
#endif
};
const u16 STRING_IMANUFACTURER[12] = {
(3<<8) | (2+2*11),
+#if USB_VID == 0x2341
'A','r','d','u','i','n','o',' ','L','L','C'
+#else
+ 'U','n','k','n','o','w','n',' ',' ',' ',' '
+#endif
};
#ifdef CDC_ENABLED
@@ -230,7 +234,7 @@ int USB_Recv(u8 ep, void* d, int len)
n = len;
u8* dst = (u8*)d;
while (n--)
- *dst++ = USBD_Recv8();
+ *dst++ = Recv8();
if (len && !FifoByteCount()) // release empty buffer
ReleaseRX();
@@ -599,6 +603,8 @@ ISR(USB_GEN_vect)
{
#ifdef CDC_ENABLED
USB_Flush(CDC_TX); // Send a tx frame if found
+ while (USB_Available(CDC_RX)) // Handle received bytes (if any)
+ Serial.accept();
#endif
// check whether the one-shot period has elapsed. if so, turn off the LED
@@ -621,13 +627,13 @@ u8 USBConnected()
//=======================================================================
//=======================================================================
-USB_ USB;
+USBDevice_ USBDevice;
-USB_::USB_()
+USBDevice_::USBDevice_()
{
}
-void USB_::attach()
+void USBDevice_::attach()
{
_usbConfiguration = 0;
UHWCON = 0x01; // power internal reg
@@ -635,6 +641,12 @@ void USB_::attach()
PLLCSR = 0x12; // Need 16 MHz xtal
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
;
+
+ // Some tests on specific versions of macosx (10.7.3), reported some
+ // strange behaviuors when the board is reset using the serial
+ // port touch at 1200 bps. This delay fixes this behaviour.
+ delay(1);
+
USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
UDCON = 0; // enable attach resistor
@@ -642,19 +654,19 @@ void USB_::attach()
TX_RX_LED_INIT;
}
-void USB_::detach()
+void USBDevice_::detach()
{
}
// Check for interrupts
// TODO: VBUS detection
-bool USB_::configured()
+bool USBDevice_::configured()
{
return _usbConfiguration;
}
-void USB_::poll()
+void USBDevice_::poll()
{
}
-#endif /* if defined(USBCON) */ \ No newline at end of file
+#endif /* if defined(USBCON) */
diff --git a/avr/cores/arduino/USBDesc.h b/avr/cores/arduino/USBDesc.h
index 549ed9e..900713e 100644
--- a/avr/cores/arduino/USBDesc.h
+++ b/avr/cores/arduino/USBDesc.h
@@ -60,8 +60,4 @@
#define IMANUFACTURER 1
#define IPRODUCT 2
-#define USB_PID_LEONARDO 0x0034
-#define USB_PID_MICRO 0x0035
-#define USB_VID 0x2341 // arduino LLC vid
-#define USB_PID ARDUINO_MODEL_USB_PID
diff --git a/avr/cores/arduino/WInterrupts.c b/avr/cores/arduino/WInterrupts.c
index 1449cfb..62efc9c 100755..100644
--- a/avr/cores/arduino/WInterrupts.c
+++ b/avr/cores/arduino/WInterrupts.c
@@ -32,7 +32,7 @@
#include "wiring_private.h"
-volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
+static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
// volatile static voidFuncPtr twiIntFunc;
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
@@ -47,7 +47,27 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
// Enable the interrupt.
switch (interruptNum) {
-#if defined(EICRA) && defined(EICRB) && defined(EIMSK)
+#if defined(__AVR_ATmega32U4__)
+ // I hate doing this, but the register assignment differs between the 1280/2560
+ // and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
+ // even present on the 32U4 this is the only way to distinguish between them.
+ case 0:
+ EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
+ EIMSK |= (1<<INT0);
+ break;
+ case 1:
+ EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
+ EIMSK |= (1<<INT1);
+ break;
+ case 2:
+ EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
+ EIMSK |= (1<<INT2);
+ break;
+ case 3:
+ EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
+ EIMSK |= (1<<INT3);
+ break;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
@@ -80,7 +100,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
-#else
+#else
case 0:
#if defined(EICRA) && defined(ISC00) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
@@ -121,8 +141,6 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
#elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GIMSK |= (1 << INT2);
- #else
- #warning attachInterrupt may need some more work for this cpu (case 1)
#endif
break;
#endif
@@ -136,7 +154,20 @@ void detachInterrupt(uint8_t interruptNum) {
// to the number of the EIMSK bit to clear, as this isn't true on the
// ATmega8. There, INT0 is 6 and INT1 is 7.)
switch (interruptNum) {
-#if defined(EICRA) && defined(EICRB) && defined(EIMSK)
+#if defined(__AVR_ATmega32U4__)
+ case 0:
+ EIMSK &= ~(1<<INT0);
+ break;
+ case 1:
+ EIMSK &= ~(1<<INT1);
+ break;
+ case 2:
+ EIMSK &= ~(1<<INT2);
+ break;
+ case 3:
+ EIMSK &= ~(1<<INT3);
+ break;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK &= ~(1 << INT0);
break;
@@ -198,7 +229,28 @@ void attachInterruptTwi(void (*userFunc)(void) ) {
}
*/
-#if defined(EICRA) && defined(EICRB)
+#if defined(__AVR_ATmega32U4__)
+SIGNAL(INT0_vect) {
+ if(intFunc[EXTERNAL_INT_0])
+ intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT1_vect) {
+ if(intFunc[EXTERNAL_INT_1])
+ intFunc[EXTERNAL_INT_1]();
+}
+
+SIGNAL(INT2_vect) {
+ if(intFunc[EXTERNAL_INT_2])
+ intFunc[EXTERNAL_INT_2]();
+}
+
+SIGNAL(INT3_vect) {
+ if(intFunc[EXTERNAL_INT_3])
+ intFunc[EXTERNAL_INT_3]();
+}
+
+#elif defined(EICRA) && defined(EICRB)
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_2])
diff --git a/avr/cores/arduino/WString.cpp b/avr/cores/arduino/WString.cpp
index 3e81331..c6839fc 100644
--- a/avr/cores/arduino/WString.cpp
+++ b/avr/cores/arduino/WString.cpp
@@ -500,7 +500,7 @@ int String::lastIndexOf( char theChar ) const
int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
- if (fromIndex >= len || fromIndex < 0) return -1;
+ if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
@@ -516,7 +516,7 @@ int String::lastIndexOf(const String &s2) const
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
- if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1;
+ 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++) {
diff --git a/avr/cores/arduino/main.cpp b/avr/cores/arduino/main.cpp
index 34450f4..3d4e079 100755..100644
--- a/avr/cores/arduino/main.cpp
+++ b/avr/cores/arduino/main.cpp
@@ -5,7 +5,7 @@ int main(void)
init();
#if defined(USBCON)
- USB.attach();
+ USBDevice.attach();
#endif
setup();
diff --git a/avr/cores/arduino/wiring.c b/avr/cores/arduino/wiring.c
index e7f7cde..ac8bb6f 100755..100644
--- a/avr/cores/arduino/wiring.c
+++ b/avr/cores/arduino/wiring.c
@@ -278,12 +278,21 @@ void init()
sbi(TCCR3B, CS30);
sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
#endif
-
+
+#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
+ sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
+ sbi(TCCR4B, CS41);
+ sbi(TCCR4B, CS40);
+ sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
+ sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
+ sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
+#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
sbi(TCCR4B, CS40);
sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
#endif
+#endif /* end timer4 block for ATMEGA1280/2560 and similar */
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
diff --git a/avr/cores/arduino/wiring_analog.c b/avr/cores/arduino/wiring_analog.c
index 902b153..0e9881f 100644
--- a/avr/cores/arduino/wiring_analog.c
+++ b/avr/cores/arduino/wiring_analog.c
@@ -45,6 +45,8 @@ int analogRead(uint8_t pin)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
+#elif defined(__AVR_ATmega1284__)
+ if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
@@ -204,14 +206,17 @@ void analogWrite(uint8_t pin, int val)
break;
#endif
- #if defined(TCCR4A) && defined(COM4A1)
+ #if defined(TCCR4A)
case TIMER4A:
- // connect pwm to pin on timer 4, channel A
+ //connect pwm to pin on timer 4, channel A
sbi(TCCR4A, COM4A1);
- OCR4A = val; // set pwm duty
+ #if defined(COM4A0) // only used on 32U4
+ cbi(TCCR4A, COM4A0);
+ #endif
+ OCR4A = val; // set pwm duty
break;
#endif
-
+
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B:
// connect pwm to pin on timer 4, channel B
@@ -228,14 +233,18 @@ void analogWrite(uint8_t pin, int val)
break;
#endif
- #if defined(TCCR4A) && defined(COM4D1)
- case TIMER4D:
+ #if defined(TCCR4C) && defined(COM4D1)
+ case TIMER4D:
// connect pwm to pin on timer 4, channel D
- sbi(TCCR4A, COM4D1);
- OCR4D = val; // set pwm duty
+ sbi(TCCR4C, COM4D1);
+ #if defined(COM4D0) // only used on 32U4
+ cbi(TCCR4C, COM4D0);
+ #endif
+ OCR4D = val; // set pwm duty
break;
#endif
+
#if defined(TCCR5A) && defined(COM5A1)
case TIMER5A:
// connect pwm to pin on timer 5, channel A
@@ -270,3 +279,4 @@ void analogWrite(uint8_t pin, int val)
}
}
}
+
diff --git a/avr/cores/arduino/wiring_digital.c b/avr/cores/arduino/wiring_digital.c
index 97ef134..be323b1 100755..100644
--- a/avr/cores/arduino/wiring_digital.c
+++ b/avr/cores/arduino/wiring_digital.c
@@ -32,17 +32,25 @@ void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
- volatile uint8_t *reg;
+ volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
+ out = portOutputRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
+ *out &= ~bit;
+ SREG = oldSREG;
+ } else if (mode == INPUT_PULLUP) {
+ uint8_t oldSREG = SREG;
+ cli();
+ *reg &= ~bit;
+ *out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
@@ -107,13 +115,17 @@ static void turnOffPWM(uint8_t timer)
#if defined(TCCR4A) && defined(COM4A1)
case TIMER4A: cbi(TCCR4A, COM4A1); break;
- #endif
+ #endif
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B: cbi(TCCR4A, COM4B1); break;
#endif
#if defined(TCCR4A) && defined(COM4C1)
case TIMER4C: cbi(TCCR4A, COM4C1); break;
- #endif
+ #endif
+ #if defined(TCCR4C) && defined(COM4D1)
+ case TIMER4D: cbi(TCCR4C, COM4D1); break;
+ #endif
+
#if defined(TCCR5A)
case TIMER5A: cbi(TCCR5A, COM5A1); break;
case TIMER5B: cbi(TCCR5A, COM5B1); break;
diff --git a/avr/cores/arduino/wiring_private.h b/avr/cores/arduino/wiring_private.h
index f0ceb0c..026ce1a 100755
--- a/avr/cores/arduino/wiring_private.h
+++ b/avr/cores/arduino/wiring_private.h
@@ -56,6 +56,8 @@ extern "C"{
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284P__)
#define EXTERNAL_NUM_INTERRUPTS 3
+#elif defined(__AVR_ATmega32U4__)
+#define EXTERNAL_NUM_INTERRUPTS 4
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif
diff --git a/avr/platform.txt b/avr/platform.txt
index c47cd8b..557b2d3 100644
--- a/avr/platform.txt
+++ b/avr/platform.txt
@@ -6,12 +6,12 @@ name=Arduino
# Default "compiler.path" is correct, change only if you want to overidde the initial value
#compiler.path={ide.path}/tools/avr/bin/..
compiler.c.cmd=avr-gcc
-compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections
+compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD
compiler.c.elf.flags=-Os -Wl,--gc-sections
compiler.c.elf.cmd=avr-gcc
compiler.S.flags=-c -g -assembler-with-cpp
compiler.cpp.cmd=avr-g++
-compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections
+compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD
compiler.ar.cmd=avr-ar
compiler.ar.flags=rcs
compiler.objcopy.cmd=avr-objcopy
@@ -20,48 +20,56 @@ compiler.elf2hex.flags=-O ihex -R .eeprom
compiler.elf2hex.cmd=avr-objcopy
compiler.ldflags=
compiler.size.cmd=avr-size
+# this can be overriden in boards.txt
+build.extra_flags=
# AVR compile patterns
# --------------------
## Compile c files
-recipe.c.o.pattern={compiler.path}{compiler.c.cmd} {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {includes} {source_file} -o {object_file}
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
-recipe.cpp.o.pattern={compiler.path}{compiler.cpp.cmd} {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {includes} {source_file} -o {object_file}
+recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
-recipe.ar.pattern={compiler.path}{compiler.ar.cmd} {compiler.ar.flags} {build.path}/{archive_file} {object_file}
+recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{build.path}/{archive_file}" "{object_file}"
## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern={compiler.path}{compiler.c.elf.cmd} {compiler.c.elf.flags} -mmcu={build.mcu} -o {build.path}/{build.project_name}.elf {object_files} {build.path}/{archive_file} -L{build.path} -lm
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
## Create eeprom
-recipe.objcopy.eep.pattern={compiler.path}{compiler.objcopy.cmd} {compiler.objcopy.eep.flags} {build.path}/{build.project_name}.elf {build.path}/{build.project_name}.eep
+recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep"
## Create hex
-recipe.objcopy.hex.pattern={compiler.path}{compiler.elf2hex.cmd} {compiler.elf2hex.flags} {build.path}/{build.project_name}.elf {build.path}/{build.project_name}.hex
+recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
## Compute size
-recipe.size.pattern={compiler.path}{compiler.size.cmd} -A {build.path}/{build.project_name}.hex
+recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.hex"
recipe.size.regex=Total\s+([0-9]+).*
# AVR Uploader/Programmers tools
# -------------------
-tools.avrdude.cmd=avrdude
-tools.avrdude.path={runtime.ide.path}/hardware/tools
-tools.avrdude.config.path={path}/avrdude.conf
+tools.avrdude.cmd.path={runtime.ide.path}/hardware/tools/avr/bin/avrdude
+tools.avrdude.config.path={runtime.ide.path}/hardware/tools/avr/etc/avrdude.conf
+tools.avrdude.cmd.path.linux={runtime.ide.path}/hardware/tools/avrdude
+tools.avrdude.config.path.linux={runtime.ide.path}/hardware/tools/avrdude.conf
tools.avrdude.upload.params.verbose=-v -v -v -v
tools.avrdude.upload.params.quiet=-q -q
-tools.avrdude.upload.pattern={path}/{cmd} -C{config.path} {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D -Uflash:w:{build.path}/{build.project_name}.hex:i
+tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i"
tools.avrdude.program.params.verbose=-v -v -v -v
tools.avrdude.program.params.quiet=-q -q
-tools.avrdude.program.pattern={path}/{cmd} -C{config.path} {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -Uflash:w:{build.path}/{build.project_name}.hex:i
+tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
+
+tools.avrdude.erase.params.verbose=-v -v -v -v
+tools.avrdude.erase.params.quiet=-q -q
+tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m
tools.avrdude.bootloader.params.verbose=-v -v -v -v
tools.avrdude.bootloader.params.quiet=-q -q
-tools.avrdude.bootloader.pattern={path}/{cmd} -C{config.path} {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} {bootloader.params}
+tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.ide.path}/hardware/arduino/avr/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m
+
diff --git a/sam/cores/arduino/Client.h b/sam/cores/arduino/Client.h
new file mode 100644
index 0000000..ea13483
--- /dev/null
+++ b/sam/cores/arduino/Client.h
@@ -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) =0;
+ virtual int connect(const char *host, uint16_t port) =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
diff --git a/sam/cores/arduino/IPAddress.cpp b/sam/cores/arduino/IPAddress.cpp
new file mode 100644
index 0000000..fe3deb7
--- /dev/null
+++ b/sam/cores/arduino/IPAddress.cpp
@@ -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;
+}
+
diff --git a/sam/cores/arduino/IPAddress.h b/sam/cores/arduino/IPAddress.h
new file mode 100644
index 0000000..2585aec
--- /dev/null
+++ b/sam/cores/arduino/IPAddress.h
@@ -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
diff --git a/sam/cores/arduino/Print.cpp b/sam/cores/arduino/Print.cpp
index 123370f..4a21176 100644
--- a/sam/cores/arduino/Print.cpp
+++ b/sam/cores/arduino/Print.cpp
@@ -219,6 +219,9 @@ 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");
+
// Handle negative numbers
if (number < 0.0)
{
diff --git a/sam/cores/arduino/Print.h b/sam/cores/arduino/Print.h
index 1af6b72..dc76150 100644
--- a/sam/cores/arduino/Print.h
+++ b/sam/cores/arduino/Print.h
@@ -46,7 +46,10 @@ class Print
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
- size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
+ 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 *);
diff --git a/sam/cores/arduino/Server.h b/sam/cores/arduino/Server.h
new file mode 100644
index 0000000..9674c76
--- /dev/null
+++ b/sam/cores/arduino/Server.h
@@ -0,0 +1,9 @@
+#ifndef server_h
+#define server_h
+
+class Server : public Print {
+public:
+ virtual void begin() =0;
+};
+
+#endif
diff --git a/sam/cores/arduino/Stream.cpp b/sam/cores/arduino/Stream.cpp
new file mode 100644
index 0000000..aafb7fc
--- /dev/null
+++ b/sam/cores/arduino/Stream.cpp
@@ -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;
+}
+
diff --git a/sam/cores/arduino/Stream.h b/sam/cores/arduino/Stream.h
index aaa189f..58bbf75 100644
--- a/sam/cores/arduino/Stream.h
+++ b/sam/cores/arduino/Stream.h
@@ -15,21 +15,82 @@
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 <stdint.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
{
+ private:
+ 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
diff --git a/sam/cores/arduino/USB/USBAPI.h b/sam/cores/arduino/USB/USBAPI.h
index 592d3a0..de98895 100644
--- a/sam/cores/arduino/USB/USBAPI.h
+++ b/sam/cores/arduino/USB/USBAPI.h
@@ -27,17 +27,17 @@
//================================================================================
// USB
-class USB_
+class USBDevice_
{
public:
- USB_();
+ USBDevice_();
bool configured();
bool attach();
bool detach(); // Serial port goes down too...
void poll();
};
-extern USB_ USB;
+extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
@@ -57,6 +57,7 @@ public:
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
+ using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
};
extern Serial_ Serial;
diff --git a/sam/cores/arduino/USB/USBCore.cpp b/sam/cores/arduino/USB/USBCore.cpp
index 77eaee1..3b4a2ce 100644
--- a/sam/cores/arduino/USB/USBCore.cpp
+++ b/sam/cores/arduino/USB/USBCore.cpp
@@ -536,9 +536,9 @@ uint32_t USBD_Connected(void)
//=======================================================================
//=======================================================================
-USB_ USB;
+USBDevice_ USBDevice;
-USB_::USB_()
+USBDevice_::USBDevice_()
{
UDD_SetStack(&USB_ISR);
@@ -548,7 +548,7 @@ USB_::USB_()
}
}
-bool USB_::attach(void)
+bool USBDevice_::attach(void)
{
if (_usbInitialized != 0UL)
{
@@ -562,7 +562,7 @@ bool USB_::attach(void)
}
}
-bool USB_::detach(void)
+bool USBDevice_::detach(void)
{
if (_usbInitialized != 0UL)
{
@@ -577,11 +577,11 @@ bool USB_::detach(void)
// Check for interrupts
// TODO: VBUS detection
-bool USB_::configured()
+bool USBDevice_::configured()
{
return _usbConfiguration;
}
-void USB_::poll()
+void USBDevice_::poll()
{
}
diff --git a/sam/cores/arduino/Udp.h b/sam/cores/arduino/Udp.h
new file mode 100644
index 0000000..dc5644b
--- /dev/null
+++ b/sam/cores/arduino/Udp.h
@@ -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
diff --git a/sam/cores/arduino/main.cpp b/sam/cores/arduino/main.cpp
index 69f25f2..f28b6fd 100644
--- a/sam/cores/arduino/main.cpp
+++ b/sam/cores/arduino/main.cpp
@@ -39,13 +39,16 @@ int main( void )
delay(1);
- USB.attach();
+#if defined(USBCON)
+ USBDevice.attach();
+#endif
setup();
for (;;)
{
loop();
+ if (serialEventRun) serialEventRun();
}
return 0;
diff --git a/sam/cores/arduino/wiring_analog.c b/sam/cores/arduino/wiring_analog.c
index 0cdc789..d5bf6dd 100644
--- a/sam/cores/arduino/wiring_analog.c
+++ b/sam/cores/arduino/wiring_analog.c
@@ -91,7 +91,7 @@ uint32_t analogRead(uint32_t ulPin)
;
// Read the value
- ulValue = adc12b_get_latest_value(ADC12B);
+ ulValue = adc12b_get_latest_value(ADC12B) >> 2;
// Stop the ADC12B
// adc12_stop( ADC12B ) ; // never do adc12_stop() else we have to reconfigure the ADC12B each time
@@ -135,7 +135,7 @@ uint32_t analogRead(uint32_t ulPin)
;
// Read the value
- ulValue = adc_get_latest_value(ADC);
+ ulValue = adc_get_latest_value(ADC) >> 2;
// Disable the corresponding channel
adc_disable_channel(ADC, ulChannel);
@@ -151,24 +151,34 @@ uint32_t analogRead(uint32_t ulPin)
return ulValue;
}
-static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RA = v;
}
-static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RB = v;
}
-static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RC = v;
}
+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};
+static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
void analogOutputInit(void) {
uint8_t i;
@@ -254,38 +264,52 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
}
if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
- // We use MCLK/2 => 96Mhz/2 => 48Mhz as clock.
- // To get 1KHz we should use 48000 as TC
- // 48Mhz/48000 = 1KHz
+ // We use MCLK/2 as clock.
const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;
- // Map value to Timer ranges 0..255=>0..48000
+ // Map value to Timer ranges 0..255 => 0..TC
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 };
- static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0 };
+ 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];
-
- if (!TCChanEnabled[chNo]) {
- pmc_enable_periph_clk(TC_INTERFACE_ID + chNo);
- TC_Configure(TC_INTERFACE, chNo,
- TC_CMR_TCCLKS_TIMER_CLOCK1 |
- TC_CMR_WAVE |
- TC_CMR_WAVSEL_UP_RC |
- TC_CMR_ACPA_CLEAR | // RA Compare Effect on OA: clear
- TC_CMR_ACPC_SET | // RC Compare Effect on OA: set
- TC_CMR_BCPB_CLEAR | // RB Compare Effect on OB: clear
- TC_CMR_BCPC_SET); // RC Compare Effect on OB: set
- TC_SetRC(TC_INTERFACE, chNo, TC);
+ 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 (chA)
- TC_SetRA(TC_INTERFACE, chNo, ulValue);
- else
- TC_SetRB(TC_INTERFACE, chNo, ulValue);
if (!pinEnabled[ulPin]) {
PIO_Configure(g_APinDescription[ulPin].pPort,
g_APinDescription[ulPin].ulPinType,
@@ -293,14 +317,14 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
g_APinDescription[ulPin].ulPinConfiguration);
pinEnabled[ulPin] = 1;
}
- if (!TCChanEnabled[chNo]) {
- TC_Start(TC_INTERFACE, chNo);
- TCChanEnabled[chNo] = 1;
+ if (!TCChanEnabled[interfaceID]) {
+ TC_Start(chTC, chNo);
+ TCChanEnabled[interfaceID] = 1;
}
return;
}
- // Default to digital write
+ // Defaults to digital write
pinMode(ulPin, OUTPUT);
if (ulValue < 128)
digitalWrite(ulPin, LOW);
diff --git a/sam/cores/arduino/wiring_constants.h b/sam/cores/arduino/wiring_constants.h
index 0555d71..868d46d 100644
--- a/sam/cores/arduino/wiring_constants.h
+++ b/sam/cores/arduino/wiring_constants.h
@@ -28,6 +28,7 @@ extern "C"{
#define INPUT 0x0
#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
#define true 0x1
#define false 0x0
diff --git a/sam/cores/arduino/wiring_digital.c b/sam/cores/arduino/wiring_digital.c
index bbd940d..ac6eb18 100644
--- a/sam/cores/arduino/wiring_digital.c
+++ b/sam/cores/arduino/wiring_digital.c
@@ -34,16 +34,35 @@ extern void pinMode( uint32_t ulPin, uint32_t 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 ) ;
+ 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:
- /* if all pins are output, disable PIO Controller clocking, reduce power consomption */
+ 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 ) ;
}
- PIO_Configure( g_APinDescription[ulPin].pPort, PIO_OUTPUT_1, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ;
break ;
default:
diff --git a/sam/cores/arduino/wiring_shift.c b/sam/cores/arduino/wiring_shift.c
index 30d3f43..302f0b5 100644
--- a/sam/cores/arduino/wiring_shift.c
+++ b/sam/cores/arduino/wiring_shift.c
@@ -22,7 +22,7 @@
extern "C"{
#endif
-extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
+uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
{
uint8_t value = 0 ;
uint8_t i ;
@@ -46,7 +46,7 @@ extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBit
return value ;
}
-extern void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
+void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
{
uint8_t i ;
diff --git a/sam/platform.txt b/sam/platform.txt
index e928040..17c4344 100644
--- a/sam/platform.txt
+++ b/sam/platform.txt
@@ -6,12 +6,12 @@ name=Atmel SAM3
compiler.path={runtime.ide.path}/hardware/tools/g++_arm_none_eabi/bin/
#compiler.path=C:/arm-none-eabi-gcc-4_6/bin/
compiler.c.cmd=arm-none-eabi-gcc
-compiler.c.flags=-c -g -Os -w -mlong-calls -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf
+compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf
compiler.c.elf.cmd=arm-none-eabi-gcc
compiler.c.elf.flags=-Os -Wl,--gc-sections
compiler.S.flags=-c -g -assembler-with-cpp
compiler.cpp.cmd=arm-none-eabi-g++
-compiler.cpp.flags=-c -g -Os -w -mlong-calls -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf
+compiler.cpp.flags=-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf
compiler.ar.cmd=arm-none-eabi-ar
compiler.ar.flags=rcs
compiler.objcopy.cmd=arm-none-eabi-objcopy
@@ -21,32 +21,35 @@ compiler.elf2hex.cmd=arm-none-eabi-objcopy
compiler.ldflags=
compiler.size.cmd=arm-none-eabi-size
compiler.define=-DARDUINO=
+# this can be overriden in boards.txt
+build.extra_flags=
-compiler.libsam.c.flags=-I{build.system.path}/libsam -I{build.system.path}/CMSIS/CMSIS/Include/ -I{build.system.path}/CMSIS/Device/ATMEL/
+
+compiler.libsam.c.flags="-I{build.system.path}/libsam" "-I{build.system.path}/CMSIS/CMSIS/Include/" "-I{build.system.path}/CMSIS/Device/ATMEL/"
# SAM3 compile patterns
# ---------------------
## Compile c files
-recipe.c.o.pattern={compiler.path}{compiler.c.cmd} {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} {source_file} -o {object_file}
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
-recipe.cpp.o.pattern={compiler.path}{compiler.cpp.cmd} {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} {source_file} -o {object_file}
+recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
-recipe.ar.pattern={compiler.path}{compiler.ar.cmd} {compiler.ar.flags} {build.path}/{archive_file} {object_file}
+recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{build.path}/{archive_file}" "{object_file}"
## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern={compiler.path}{compiler.c.elf.cmd} {compiler.c.elf.flags} -mcpu={build.mcu} -T{build.variant.path}/{build.ldscript} -Wl,-Map,{build.path}/{build.project_name}.map -o {build.path}/{build.project_name}.elf -L{build.path} -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} {build.variant.path}/{build.variant_system_lib} {build.path}/{archive_file} -Wl,--end-group
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group
## Create eeprom
recipe.objcopy.eep.pattern=
## Create hex
-recipe.objcopy.hex.pattern={compiler.path}{compiler.elf2hex.cmd} {compiler.elf2hex.flags} {build.path}/{build.project_name}.elf {build.path}/{build.project_name}.bin
+recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"
## Compute size
-recipe.size.pattern={compiler.path}{compiler.size.cmd} -A {build.path}/{build.project_name}.elf
+recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=\.text\s+([0-9]+).*
@@ -59,7 +62,7 @@ tools.bossac.path={runtime.ide.path}/hardware/tools
tools.bossac.upload.params.verbose=-i -d
tools.bossac.upload.params.quiet=
-tools.bossac.upload.pattern={path}/{cmd} {upload.verbose} --port={serial.port.file} -e -w -v -b {build.path}/{build.project_name}.bin
+tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -e -w -v -b "{build.path}/{build.project_name}.bin"
# specialized tool for adk2 to twiddle the erase line before running bossac
tools.adk2install.cmd=adk2install