diff options
Diffstat (limited to 'cores')
-rwxr-xr-x | cores/arduino/Arduino.h | 205 | ||||
-rw-r--r-- | cores/arduino/HardwareSerial.cpp | 255 | ||||
-rw-r--r-- | cores/arduino/HardwareSerial.h | 11 | ||||
-rw-r--r-- | cores/arduino/IPAddress.cpp | 14 | ||||
-rw-r--r-- | cores/arduino/IPAddress.h | 6 | ||||
-rwxr-xr-x | cores/arduino/Print.cpp | 213 | ||||
-rwxr-xr-x | cores/arduino/Print.h | 62 | ||||
-rw-r--r-- | cores/arduino/Printable.h | 40 | ||||
-rw-r--r-- | cores/arduino/Stream.cpp | 233 | ||||
-rw-r--r-- | cores/arduino/Stream.h | 58 | ||||
-rwxr-xr-x | cores/arduino/Tone.cpp | 2 | ||||
-rw-r--r-- | cores/arduino/WConstants.h | 1 | ||||
-rwxr-xr-x | cores/arduino/WInterrupts.c | 1 | ||||
-rwxr-xr-x | cores/arduino/WProgram.h | 63 | ||||
-rw-r--r-- | cores/arduino/WString.cpp | 736 | ||||
-rw-r--r-- | cores/arduino/WString.h | 255 | ||||
-rwxr-xr-x | cores/arduino/main.cpp | 3 | ||||
-rw-r--r-- | cores/arduino/new.cpp | 18 | ||||
-rw-r--r-- | cores/arduino/new.h | 22 | ||||
-rwxr-xr-x | cores/arduino/pins_arduino.c | 465 | ||||
-rw-r--r-- | cores/arduino/pins_arduino.h | 88 | ||||
-rwxr-xr-x | cores/arduino/wiring.c | 2 | ||||
-rwxr-xr-x | cores/arduino/wiring.h | 135 | ||||
-rwxr-xr-x | cores/arduino/wiring_digital.c | 11 | ||||
-rwxr-xr-x | cores/arduino/wiring_private.h | 2 |
25 files changed, 1597 insertions, 1304 deletions
diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h new file mode 100755 index 0000000..ebdbe9a --- /dev/null +++ b/cores/arduino/Arduino.h @@ -0,0 +1,205 @@ +#ifndef Arduino_h +#define Arduino_h + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <avr/pgmspace.h> +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#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 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#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() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) + +#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)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +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 analogInPinToBit(P) (P) + +// On the ATmega1280, the addresses of some of the port registers are +// greater than 255, so we can't store them in uint8_t's. +extern const uint16_t PROGMEM port_to_mode_PGM[]; +extern const uint16_t PROGMEM port_to_input_PGM[]; +extern const uint16_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; + +// 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. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 +#define PE 5 +#define PF 6 +#define PG 7 +#define PH 8 +#define PJ 10 +#define PK 11 +#define PL 12 + +#define NOT_ON_TIMER 0 +#define TIMER0A 1 +#define TIMER0B 2 +#define TIMER1A 3 +#define TIMER1B 4 +#define TIMER2 5 +#define TIMER2A 6 +#define TIMER2B 7 + +#define TIMER3A 8 +#define TIMER3B 9 +#define TIMER3C 10 +#define TIMER4A 11 +#define TIMER4B 12 +#define TIMER4C 13 +#define TIMER5A 14 +#define TIMER5B 15 +#define TIMER5C 16 + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#endif + +#include "pins_arduino.h" + +#endif
\ No newline at end of file diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 4397efb..d6be218 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -24,7 +24,7 @@ #include <stdio.h> #include <string.h> #include <inttypes.h> -#include "wiring.h" +#include "Arduino.h" #include "wiring_private.h" // this next line disables the entire HardwareSerial.cpp, @@ -34,149 +34,223 @@ #include "HardwareSerial.h" // Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. +// 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. #if (RAMEND < 1000) - #define RX_BUFFER_SIZE 32 + #define SERIAL_BUFFER_SIZE 16 #else - #define RX_BUFFER_SIZE 128 + #define SERIAL_BUFFER_SIZE 64 #endif struct ring_buffer { - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; + unsigned char buffer[SERIAL_BUFFER_SIZE]; + volatile int head; + volatile int tail; }; #if defined(UBRRH) || defined(UBRR0H) ring_buffer rx_buffer = { { 0 }, 0, 0 }; + ring_buffer tx_buffer = { { 0 }, 0, 0 }; #endif #if defined(UBRR1H) ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; #endif #if defined(UBRR2H) ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; #endif #if defined(UBRR3H) ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; #endif -inline void store_char(unsigned char c, ring_buffer *rx_buffer) +inline void store_char(unsigned char c, ring_buffer *buffer) { - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + 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 != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; + if (i != buffer->tail) { + buffer->buffer[buffer->head] = c; + buffer->head = i; } } +#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \ + !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \ + !defined(SIG_UART_RECV) + #error Don't know what the Data Received vector is called for the first UART +#else + void serialEvent() __attribute__((weak)); + void serialEvent() {} #if defined(USART_RX_vect) SIGNAL(USART_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8535 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_USART0_RECV) && defined(UDR0) +#elif defined(SIG_USART0_RECV) SIGNAL(SIG_USART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART0_RECV) && defined(UDR0) +#elif defined(SIG_UART0_RECV) SIGNAL(SIG_UART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -//#elif defined(SIG_USART_RECV) #elif defined(USART0_RX_vect) - // fixed by Mark Sproul this is on the 644/644p - //SIGNAL(SIG_USART_RECV) SIGNAL(USART0_RX_vect) +#elif defined(SIG_UART_RECV) + SIGNAL(SIG_UART_RECV) +#endif { #if defined(UDR0) unsigned char c = UDR0; #elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 + unsigned char c = UDR; #else #error UDR not defined #endif store_char(c, &rx_buffer); + serialEvent(); } -#elif defined(SIG_UART_RECV) - // this is for atmega8 - SIGNAL(SIG_UART_RECV) - { - #if defined(UDR0) - unsigned char c = UDR0; // atmega645 - #elif defined(UDR) - unsigned char c = UDR; // atmega8 - #endif - store_char(c, &rx_buffer); - } -#elif defined(USBCON) - #warning No interrupt handler for usart 0 - #warning Serial(0) is on USB interface -#else - #error No interrupt handler for usart 0 #endif -//#if defined(SIG_USART1_RECV) #if defined(USART1_RX_vect) - //SIGNAL(SIG_USART1_RECV) + void serialEvent1() __attribute__((weak)); + void serialEvent1() {} SIGNAL(USART1_RX_vect) { unsigned char c = UDR1; store_char(c, &rx_buffer1); + serialEvent1(); } #elif defined(SIG_USART1_RECV) #error SIG_USART1_RECV #endif #if defined(USART2_RX_vect) && defined(UDR2) + void serialEvent2() __attribute__((weak)); + void serialEvent2() {} SIGNAL(USART2_RX_vect) { unsigned char c = UDR2; store_char(c, &rx_buffer2); + serialEvent2(); } #elif defined(SIG_USART2_RECV) #error SIG_USART2_RECV #endif #if defined(USART3_RX_vect) && defined(UDR3) + void serialEvent3() __attribute__((weak)); + void serialEvent3() {} SIGNAL(USART3_RX_vect) { unsigned char c = UDR3; store_char(c, &rx_buffer3); + serialEvent3(); } #elif defined(SIG_USART3_RECV) #error SIG_USART3_RECV #endif +#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) + #error Don't know what the Data Register Empty vector is called for the first UART +#else +#if defined(UART0_UDRE_vect) +ISR(UART0_UDRE_vect) +#elif defined(UART_UDRE_vect) +ISR(UART_UDRE_vect) +#elif defined(USART0_UDRE_vect) +ISR(USART0_UDRE_vect) +#elif defined(USART_UDRE_vect) +ISR(USART_UDRE_vect) +#endif +{ + if (tx_buffer.head == tx_buffer.tail) { + // Buffer empty, so disable interrupts +#if defined(UCSR0B) + cbi(UCSR0B, UDRIE0); +#else + cbi(UCSRB, UDRIE); +#endif + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer.buffer[tx_buffer.tail]; + tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + + #if defined(UDR0) + UDR0 = c; + #elif defined(UDR) + UDR = c; + #else + #error UDR not defined + #endif + } +} +#endif + +#ifdef USART1_UDRE_vect +ISR(USART1_UDRE_vect) +{ + if (tx_buffer1.head == tx_buffer1.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR1B, UDRIE1); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; + tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR1 = c; + } +} +#endif + +#ifdef USART2_UDRE_vect +ISR(USART2_UDRE_vect) +{ + if (tx_buffer2.head == tx_buffer2.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR2B, UDRIE2); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; + tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR2 = c; + } +} +#endif + +#ifdef USART3_UDRE_vect +ISR(USART3_UDRE_vect) +{ + if (tx_buffer3.head == tx_buffer3.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR3B, UDRIE3); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; + tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR3 = c; + } +} +#endif + // Constructors //////////////////////////////////////////////////////////////// -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) { _rx_buffer = rx_buffer; + _tx_buffer = tx_buffer; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -185,13 +259,13 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, _rxen = rxen; _txen = txen; _rxcie = rxcie; - _udre = udre; + _udrie = udrie; _u2x = u2x; } // Public Methods ////////////////////////////////////////////////////////////// -void HardwareSerial::begin(long baud) +void HardwareSerial::begin(unsigned long baud) { uint16_t baud_setting; bool use_u2x = true; @@ -204,6 +278,8 @@ void HardwareSerial::begin(long baud) use_u2x = false; } #endif + +try_again: if (use_u2x) { *_ucsra = 1 << _u2x; @@ -212,6 +288,12 @@ void HardwareSerial::begin(long baud) *_ucsra = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; } + + if ((baud_setting > 4095) && use_u2x) + { + use_u2x = false; + goto try_again; + } // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) *_ubrrh = baud_setting >> 8; @@ -220,18 +302,27 @@ void HardwareSerial::begin(long baud) sbi(*_ucsrb, _rxen); sbi(*_ucsrb, _txen); sbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); } void HardwareSerial::end() { + // wait for transmission of outgoing data + while (_tx_buffer->head != _tx_buffer->tail) + ; + cbi(*_ucsrb, _rxen); cbi(*_ucsrb, _txen); cbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); + + // clear any received data + _rx_buffer->head = _rx_buffer->tail; } int HardwareSerial::available(void) { - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; } int HardwareSerial::peek(void) @@ -250,39 +341,41 @@ int HardwareSerial::read(void) return -1; } else { unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; return c; } } void HardwareSerial::flush() { - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; + while (_tx_buffer->head != _tx_buffer->tail) + ; } -void HardwareSerial::write(uint8_t c) +size_t HardwareSerial::write(uint8_t c) { - while (!((*_ucsra) & (1 << _udre))) + int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; + + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit + // ???: return 0 here instead? + while (i == _tx_buffer->tail) ; - - *_udr = c; + + _tx_buffer->buffer[_tx_buffer->head] = c; + _tx_buffer->head = i; + + sbi(*_ucsrb, _udrie); + + return 1; } // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); #elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); #elif defined(USBCON) #warning no serial port defined (port 0) #else @@ -290,13 +383,13 @@ void HardwareSerial::write(uint8_t c) #endif #if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); + HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); #endif #if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); + HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); #endif #if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); + HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); #endif #endif // whole file diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 3efa775..1895f08 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -32,6 +32,7 @@ class HardwareSerial : public Stream { private: ring_buffer *_rx_buffer; + ring_buffer *_tx_buffer; volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; @@ -40,21 +41,21 @@ class HardwareSerial : public Stream uint8_t _rxen; uint8_t _txen; uint8_t _rxcie; - uint8_t _udre; + uint8_t _udrie; uint8_t _u2x; public: - HardwareSerial(ring_buffer *rx_buffer, + HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); - void begin(long); + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x); + void begin(unsigned long); void end(); virtual int available(void); virtual int peek(void); virtual int read(void); virtual void flush(void); - virtual void write(uint8_t); + virtual size_t write(uint8_t); using Print::write; // pull in write(str) and write(buf, size) from Print }; diff --git a/cores/arduino/IPAddress.cpp b/cores/arduino/IPAddress.cpp index 408d518..fe3deb7 100644 --- a/cores/arduino/IPAddress.cpp +++ b/cores/arduino/IPAddress.cpp @@ -1,5 +1,5 @@ -#include <WProgram.h> +#include <Arduino.h> #include <IPAddress.h> IPAddress::IPAddress() @@ -42,3 +42,15 @@ 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/cores/arduino/IPAddress.h b/cores/arduino/IPAddress.h index 487e420..2585aec 100644 --- a/cores/arduino/IPAddress.h +++ b/cores/arduino/IPAddress.h @@ -26,9 +26,11 @@ #ifndef IPAddress_h #define IPAddress_h +#include <Printable.h> + // A class to make it easier to handle and pass around IP addresses -class IPAddress { +class IPAddress : public Printable { private: uint8_t _address[4]; // IPv4 address // Access the raw byte array containing the address. Because this returns a pointer @@ -58,6 +60,8 @@ public: 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; diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index 4ee556d..8190d4f 100755 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -23,173 +23,223 @@ #include <stdio.h> #include <string.h> #include <math.h> -#include "wiring.h" +#include "Arduino.h" #include "Print.h" // Public Methods ////////////////////////////////////////////////////////////// /* default implementation: may be overridden */ -void Print::write(const char *str) +size_t Print::write(const char *str) { - while (*str) - write(*str++); + size_t n = 0; + while (*str) { + n += write(*str++); + } + return n; } /* default implementation: may be overridden */ -void Print::write(const uint8_t *buffer, size_t size) +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) { - while (size--) - write(*buffer++); + const prog_char *p = (const prog_char *)ifsh; + size_t n = 0; + while (1) { + unsigned char c = pgm_read_byte(p++); + if (c == 0) break; + n += write(c); + } + return n; } -void Print::print(const String &s) +size_t Print::print(const String &s) { + size_t n = 0; for (int i = 0; i < s.length(); i++) { - write(s[i]); + n += write(s[i]); } + return n; } -void Print::print(const char str[]) +size_t Print::print(const char str[]) { - write(str); + return write(str); } -void Print::print(char c, int base) +size_t Print::print(char c) { - print((long) c, base); + return write(c); } -void Print::print(unsigned char b, int base) +size_t Print::print(unsigned char b, int base) { - print((unsigned long) b, base); + return print((unsigned long) b, base); } -void Print::print(int n, int base) +size_t Print::print(int n, int base) { - print((long) n, base); + return print((long) n, base); } -void Print::print(unsigned int n, int base) +size_t Print::print(unsigned int n, int base) { - print((unsigned long) n, base); + return print((unsigned long) n, base); } -void Print::print(long n, int base) +size_t Print::print(long n, int base) { if (base == 0) { - write(n); + return write(n); } else if (base == 10) { if (n < 0) { - print('-'); + int t = print('-'); n = -n; + return printNumber(n, 10) + t; } - printNumber(n, 10); + return printNumber(n, 10); } else { - printNumber(n, base); + return printNumber(n, base); } } -void Print::print(unsigned long n, int base) +size_t Print::print(unsigned long n, int base) { - if (base == 0) write(n); - else printNumber(n, base); + if (base == 0) return write(n); + else return printNumber(n, base); } -void Print::print(double n, int digits) +size_t Print::print(double n, int digits) { - printFloat(n, digits); + return printFloat(n, digits); } -void Print::println(void) +size_t Print::println(const __FlashStringHelper *ifsh) { - print('\r'); - print('\n'); + size_t n = print(ifsh); + n += println(); + return n; } -void Print::println(const String &s) +size_t Print::print(const Printable& x) { - print(s); - println(); + return x.printTo(*this); } -void Print::println(const char c[]) +size_t Print::println(void) { - print(c); - println(); + size_t n = print('\r'); + n += print('\n'); + return n; } -void Print::println(char c, int base) +size_t Print::println(const String &s) { - print(c, base); - println(); + size_t n = print(s); + n += println(); + return n; } -void Print::println(unsigned char b, int base) +size_t Print::println(const char c[]) { - print(b, base); - println(); + size_t n = print(c); + n += println(); + return n; } -void Print::println(int n, int base) +size_t Print::println(char c) { - print(n, base); - println(); + size_t n = print(c); + n += println(); + return n; } -void Print::println(unsigned int n, int base) +size_t Print::println(unsigned char b, int base) { - print(n, base); - println(); + size_t n = print(b, base); + n += println(); + return n; } -void Print::println(long n, int base) +size_t Print::println(int num, int base) { - print(n, base); - println(); + size_t n = print(num, base); + n += println(); + return n; } -void Print::println(unsigned long n, int base) +size_t Print::println(unsigned int num, int base) { - print(n, base); - println(); + size_t n = print(num, base); + n += println(); + return n; } -void Print::println(double n, int digits) +size_t Print::println(long num, int base) { - print(n, digits); - println(); + size_t n = print(num, base); + n += println(); + return n; } -// Private Methods ///////////////////////////////////////////////////////////// +size_t Print::println(unsigned long num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} -void Print::printNumber(unsigned long n, uint8_t base) +size_t Print::println(double num, int digits) { - unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. - unsigned long i = 0; + size_t n = print(num, digits); + n += println(); + return n; +} - if (n == 0) { - print('0'); - return; - } +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'; - while (n > 0) { - buf[i++] = n % base; + // 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); - for (; i > 0; i--) - print((char) (buf[i - 1] < 10 ? - '0' + buf[i - 1] : - 'A' + buf[i - 1] - 10)); + return write(str); } -void Print::printFloat(double number, uint8_t digits) +size_t Print::printFloat(double number, uint8_t digits) { + size_t n = 0; + // Handle negative numbers if (number < 0.0) { - print('-'); + n += print('-'); number = -number; } @@ -203,18 +253,21 @@ void Print::printFloat(double number, uint8_t digits) // Extract the integer part of the number and print it unsigned long int_part = (unsigned long)number; double remainder = number - (double)int_part; - print(int_part); + n += print(int_part); // Print the decimal point, but only if there are digits beyond - if (digits > 0) - print("."); + if (digits > 0) { + n += print("."); + } // Extract digits from the remainder one at a time while (digits-- > 0) { remainder *= 10.0; int toPrint = int(remainder); - print(toPrint); + n += print(toPrint); remainder -= toPrint; } + + return n; } diff --git a/cores/arduino/Print.h b/cores/arduino/Print.h index b092ae5..fce302e 100755 --- a/cores/arduino/Print.h +++ b/cores/arduino/Print.h @@ -24,43 +24,55 @@ #include <stdio.h> // for size_t #include "WString.h" +#include "Printable.h" #define DEC 10 #define HEX 16 #define OCT 8 #define BIN 2 -#define BYTE 0 class Print { private: - void printNumber(unsigned long, uint8_t); - void printFloat(double, uint8_t); + 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: - virtual void write(uint8_t) = 0; - virtual void write(const char *str); - virtual void write(const uint8_t *buffer, size_t size); + Print() : write_error(0) {} + + int writeError() { return write_error; } + void clearWriteError() { setWriteError(0); } + + virtual size_t write(uint8_t) = 0; + virtual size_t write(const char *str); + virtual size_t write(const uint8_t *buffer, size_t size); - void print(const String &); - void print(const char[]); - void print(char, int = BYTE); - void print(unsigned char, int = BYTE); - void print(int, int = DEC); - void print(unsigned int, int = DEC); - void print(long, int = DEC); - void print(unsigned long, int = DEC); - void print(double, int = 2); + 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&); - void println(const String &s); - void println(const char[]); - void println(char, int = BYTE); - void println(unsigned char, int = BYTE); - void println(int, int = DEC); - void println(unsigned int, int = DEC); - void println(long, int = DEC); - void println(unsigned long, int = DEC); - void println(double, int = 2); - void println(void); + 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 diff --git a/cores/arduino/Printable.h b/cores/arduino/Printable.h new file mode 100644 index 0000000..d03c9af --- /dev/null +++ b/cores/arduino/Printable.h @@ -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 <new.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 + diff --git a/cores/arduino/Stream.cpp b/cores/arduino/Stream.cpp new file mode 100644 index 0000000..d267bf0 --- /dev/null +++ b/cores/arduino/Stream.cpp @@ -0,0 +1,233 @@ +/* + 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() +{ + //Serial.println(_timeout); + this->_startMillis = millis(); + while(millis() - this->_startMillis < this->_timeout) + { + if (this->available() > 0) { + return this->read(); + } + } + return -1; // -1 indicates timeout +} + +// returns the next digit in the stream or -1 if timeout +// discards non-numeric characters +int Stream::getNextDigit() +{ + int c; + do{ + c = timedRead(); + if( c < 0) + return c; // timeout + } + while( c != '-' && (c < '0' || c > '9') ) ; + +return c; +} + +// Public Methods +////////////////////////////////////////////////////////////// + +void Stream::setTimeout( long timeout) // sets the maximum number of milliseconds to wait +{ + this->_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]){ + //////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 + } + 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 = getNextDigit(); + // 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'; + c = timedRead(); + } + while( (c >= '0' && c <= '9') || c == skipChar ); + + if(isNegative) + value = -value; + return value; +} + + +// as parseInt but returns a floating point value +float Stream::parseFloat() +{ + 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; + float fValue; + char c; + float fraction = 1.0; + + c = getNextDigit(); + // 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; + } + c = timedRead(); + } + 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, null is detected or timeout (see setTimeout) +// returns the number of characters placed in the buffer (0 means no valid data found) +int Stream::readBytes( char *buffer, size_t length) +{ + return readBytesUntil( 0, buffer, 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) + +int Stream::readBytesUntil( char terminator, char *buffer, size_t length) +{ + int index = 0; + *buffer = 0; + while(index < length-1 ){ + int c = timedRead(); + if( c <= 0 ){ + return 0; // timeout returns 0 ! + } + else if( c == terminator){ + buffer[index] = 0; // terminate the string + return index; // data got successfully + } + else{ + buffer[index++] = (char)c; + } + } + buffer[index] = 0; + return index; // here if buffer is full before detecting the terminator +} + diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h index 93d8275..1633f15 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -15,6 +15,8 @@ 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 @@ -23,13 +25,69 @@ #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: + long _timeout; // number of milliseconds to wait for the next char before aborting timed read + long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int getNextDigit(); // 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(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. + + 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(); // float version of parseInt + + float parseFloat(char skipChar); // as above but the given skipChar is ignored + + int 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) + + int 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 + }; #endif diff --git a/cores/arduino/Tone.cpp b/cores/arduino/Tone.cpp index c3910e7..20eed3f 100755 --- a/cores/arduino/Tone.cpp +++ b/cores/arduino/Tone.cpp @@ -33,7 +33,7 @@ Version Modified By Date Comments #include <avr/interrupt.h> #include <avr/pgmspace.h> -#include "wiring.h" +#include "Arduino.h" #include "pins_arduino.h" #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) diff --git a/cores/arduino/WConstants.h b/cores/arduino/WConstants.h deleted file mode 100644 index 3e19ac4..0000000 --- a/cores/arduino/WConstants.h +++ /dev/null @@ -1 +0,0 @@ -#include "wiring.h" diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 3b3e0c9..75c713b 100755 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -30,7 +30,6 @@ #include <avr/pgmspace.h> #include <stdio.h> -#include "WConstants.h" #include "wiring_private.h" volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; diff --git a/cores/arduino/WProgram.h b/cores/arduino/WProgram.h deleted file mode 100755 index f73e760..0000000 --- a/cores/arduino/WProgram.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef WProgram_h -#define WProgram_h - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include <avr/interrupt.h> - -#include "wiring.h" - -#ifdef __cplusplus -#include "WCharacter.h" -#include "WString.h" -#include "HardwareSerial.h" - -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned int); -long map(long, long, long, long, long); - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -const static uint8_t A0 = 54; -const static uint8_t A1 = 55; -const static uint8_t A2 = 56; -const static uint8_t A3 = 57; -const static uint8_t A4 = 58; -const static uint8_t A5 = 59; -const static uint8_t A6 = 60; -const static uint8_t A7 = 61; -const static uint8_t A8 = 62; -const static uint8_t A9 = 63; -const static uint8_t A10 = 64; -const static uint8_t A11 = 65; -const static uint8_t A12 = 66; -const static uint8_t A13 = 67; -const static uint8_t A14 = 68; -const static uint8_t A15 = 69; -#else -const static uint8_t A0 = 14; -const static uint8_t A1 = 15; -const static uint8_t A2 = 16; -const static uint8_t A3 = 17; -const static uint8_t A4 = 18; -const static uint8_t A5 = 19; -const static uint8_t A6 = 20; -const static uint8_t A7 = 21; -#endif - -#endif - -#endif
\ No newline at end of file diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index db5a441..f90cef0 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -1,6 +1,8 @@ /* 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 @@ -17,427 +19,627 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <stdlib.h> -#include "WProgram.h" #include "WString.h" -String::String( const char *value ) +/*********************************************/ +/* Constructors */ +/*********************************************/ + +String::String(const char *cstr) { - if ( value == NULL ) - value = ""; - getBuffer( _length = strlen( value ) ); - if ( _buffer != NULL ) - strcpy( _buffer, value ); + init(); + if (cstr) copy(cstr, strlen(cstr)); } -String::String( const String &value ) +String::String(const String &value) { - getBuffer( _length = value._length ); - if ( _buffer != NULL ) - strcpy( _buffer, value._buffer ); + init(); + *this = value; } -String::String( const char value ) +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String::String(String &&rval) { - _length = 1; - getBuffer(1); - if ( _buffer != NULL ) { - _buffer[0] = value; - _buffer[1] = 0; - } + init(); + move(rval); } - -String::String( const unsigned char value ) +String::String(StringSumHelper &&rval) { - _length = 1; - getBuffer(1); - if ( _buffer != NULL) { - _buffer[0] = value; - _buffer[1] = 0; - } + init(); + move(rval); } +#endif -String::String( const int value, const int base ) +String::String(char c) { - char buf[33]; - itoa((signed long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this = buf; } -String::String( const unsigned int value, const int base ) +String::String(unsigned char value, unsigned char base) { - char buf[33]; - ultoa((unsigned long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + char buf[9]; + utoa(value, buf, base); + *this = buf; } -String::String( const long value, const int base ) +String::String(int value, unsigned char base) { - char buf[33]; - ltoa(value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + char buf[18]; + itoa(value, buf, base); + *this = buf; } -String::String( const unsigned long value, const int base ) +String::String(unsigned int value, unsigned char base) { - char buf[33]; - ultoa(value, buf, 10); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + char buf[17]; + utoa(value, buf, base); + *this = buf; } -char String::charAt( unsigned int loc ) const +String::String(long value, unsigned char base) { - return operator[]( loc ); + init(); + char buf[34]; + ltoa(value, buf, base); + *this = buf; } -void String::setCharAt( unsigned int loc, const char aChar ) +String::String(unsigned long value, unsigned char base) { - if(_buffer == NULL) return; - if(_length > loc) { - _buffer[loc] = aChar; - } + init(); + char buf[33]; + ultoa(value, buf, base); + *this = buf; } -int String::compareTo( const String &s2 ) const +String::~String() { - return strcmp( _buffer, s2._buffer ); + free(buffer); } -const String & String::concat( const String &s2 ) +/*********************************************/ +/* Memory Management */ +/*********************************************/ + +inline void String::init(void) { - return (*this) += s2; + buffer = NULL; + capacity = 0; + len = 0; + flags = 0; } -const String & String::operator=( const String &rhs ) +void String::invalidate(void) { - if ( this == &rhs ) - return *this; - - if ( rhs._length > _length ) - { - free(_buffer); - getBuffer( rhs._length ); - } - - if ( _buffer != NULL ) { - _length = rhs._length; - strcpy( _buffer, rhs._buffer ); - } - return *this; + if (buffer) free(buffer); + buffer = NULL; + capacity = len = 0; } -//const String & String::operator+=( const char aChar ) -//{ -// if ( _length == _capacity ) -// doubleBuffer(); -// -// _buffer[ _length++ ] = aChar; -// _buffer[ _length ] = '\0'; -// return *this; -//} +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; +} -const String & String::operator+=( const String &other ) +unsigned char String::changeBuffer(unsigned int maxStrLen) { - _length += other._length; - if ( _length > _capacity ) - { - char *temp = (char *)realloc(_buffer, _length + 1); - if ( temp != NULL ) { - _buffer = temp; - _capacity = _length; - } else { - _length -= other._length; - return *this; - } - } - strcat( _buffer, other._buffer ); - return *this; + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; } +/*********************************************/ +/* Copy and Move */ +/*********************************************/ -int String::operator==( const String &rhs ) const +String & String::copy(const char *cstr, unsigned int length) { - return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; } -int String::operator!=( const String &rhs ) const +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +void String::move(String &rhs) { - return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); + 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 -int String::operator<( const String &rhs ) const +String & String::operator = (const String &rhs) { - return strcmp( _buffer, rhs._buffer ) < 0; + if (this == &rhs) return *this; + + if (rhs.buffer) copy(rhs.buffer, rhs.len); + else invalidate(); + + return *this; } -int String::operator>( const String &rhs ) const +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String & String::operator = (String &&rval) { - return strcmp( _buffer, rhs._buffer ) > 0; + if (this != &rval) move(rval); + return *this; } -int String::operator<=( const String &rhs ) const +String & String::operator = (StringSumHelper &&rval) { - return strcmp( _buffer, rhs._buffer ) <= 0; + if (this != &rval) move(rval); + return *this; } +#endif -int String::operator>=( const String & rhs ) const +String & String::operator = (const char *cstr) { - return strcmp( _buffer, rhs._buffer ) >= 0; + if (cstr) copy(cstr, strlen(cstr)); + else invalidate(); + + return *this; } -char & String::operator[]( unsigned int index ) +/*********************************************/ +/* concat */ +/*********************************************/ + +unsigned char String::concat(const String &s) { - static char dummy_writable_char; - if (index >= _length || !_buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return _buffer[ index ]; + return concat(s.buffer, s.len); } -char String::operator[]( unsigned int index ) const +unsigned char String::concat(const char *cstr, unsigned int length) { - // need to check for valid index, to do later - return _buffer[ index ]; + 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; } -boolean String::endsWith( const String &s2 ) const +unsigned char String::concat(const char *cstr) { - if ( _length < s2._length ) - return 0; - - return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); } -boolean String::equals( const String &s2 ) const +unsigned char String::concat(char c) { - return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); } -boolean String::equalsIgnoreCase( const String &s2 ) const +unsigned char String::concat(unsigned char num) { - if ( this == &s2 ) - return true; //1; - else if ( _length != s2._length ) - return false; //0; + char buf[4]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} - return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; +unsigned char String::concat(int num) +{ + char buf[7]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); } -String String::replace( char findChar, char replaceChar ) +unsigned char String::concat(unsigned int num) { - if ( _buffer == NULL ) return *this; - String theReturn = _buffer; - char* temp = theReturn._buffer; - while( (temp = strchr( temp, findChar )) != 0 ) - *temp = replaceChar; + char buf[6]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); +} - return theReturn; +unsigned char String::concat(long num) +{ + char buf[12]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); } -String String::replace( const String& match, const String& replace ) +unsigned char String::concat(unsigned long num) { - if ( _buffer == NULL ) return *this; - String temp = _buffer, newString; + char buf[11]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +/*********************************************/ +/* Concatenate */ +/*********************************************/ - int loc; - while ( (loc = temp.indexOf( match )) != -1 ) - { - newString += temp.substring( 0, loc ); - newString += replace; - temp = temp.substring( loc + match._length ); - } - newString += temp; - return newString; +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; } -int String::indexOf( char temp ) const +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) { - return indexOf( temp, 0 ); + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; } -int String::indexOf( char ch, unsigned int fromIndex ) const +StringSumHelper & operator + (const StringSumHelper &lhs, char c) { - if ( fromIndex >= _length ) - return -1; + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(c)) a.invalidate(); + return a; +} - const char* temp = strchr( &_buffer[fromIndex], ch ); - if ( temp == NULL ) - return -1; +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} - return temp - _buffer; +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -int String::indexOf( const String &s2 ) const +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) { - return indexOf( s2, 0 ); + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -int String::indexOf( const String &s2, unsigned int fromIndex ) const +StringSumHelper & operator + (const StringSumHelper &lhs, long num) { - if ( fromIndex >= _length ) - return -1; + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} - const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} - if ( theFind == NULL ) - return -1; +/*********************************************/ +/* Comparison */ +/*********************************************/ - return theFind - _buffer; // pointer subtraction +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); } -int String::lastIndexOf( char theChar ) const +unsigned char String::equals(const String &s2) const { - return lastIndexOf( theChar, _length - 1 ); + return (len == s2.len && compareTo(s2) == 0); } -int String::lastIndexOf( char ch, unsigned int fromIndex ) const +unsigned char String::equals(const char *cstr) const { - if ( fromIndex >= _length ) - return -1; + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; +} - char tempchar = _buffer[fromIndex + 1]; - _buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( _buffer, ch ); - _buffer[fromIndex + 1] = tempchar; +unsigned char String::operator<(const String &rhs) const +{ + return compareTo(rhs) < 0; +} - if ( temp == NULL ) - return -1; +unsigned char String::operator>(const String &rhs) const +{ + return compareTo(rhs) > 0; +} - return temp - _buffer; +unsigned char String::operator<=(const String &rhs) const +{ + return compareTo(rhs) <= 0; } -int String::lastIndexOf( const String &s2 ) const +unsigned char String::operator>=(const String &rhs) const { - return lastIndexOf( s2, _length - s2._length ); + return compareTo(rhs) >= 0; } -int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const +unsigned char String::equalsIgnoreCase( const String &s2 ) const { - // check for empty strings - if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) - return -1; + 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; +} - // matching first character - char temp = s2[ 0 ]; +unsigned char String::startsWith( const String &s2 ) const +{ + if (len < s2.len) return 0; + return startsWith(s2, 0); +} - for ( int i = fromIndex; i >= 0; i-- ) - { - if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) - return i; - } - return -1; +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; } -boolean String::startsWith( const String &s2 ) const +unsigned char String::endsWith( const String &s2 ) const { - if ( _length < s2._length ) - return 0; + if ( len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +} + +/*********************************************/ +/* Character Access */ +/*********************************************/ - return startsWith( s2, 0 ); +char String::charAt(unsigned int loc) const +{ + return operator[](loc); } -boolean String::startsWith( const String &s2, unsigned int offset ) const +void String::setCharAt(unsigned int loc, char c) { - if ( offset > _length - s2._length ) - return 0; + if (loc < len) buffer[loc] = c; +} - return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; +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]; } -String String::substring( unsigned int left ) const +char String::operator[]( unsigned int index ) const { - return substring( left, _length ); + if (index >= len || !buffer) return 0; + return buffer[index]; } -String String::substring( unsigned int left, unsigned int right ) const +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { - if ( left > right ) - { - int temp = right; - right = left; - left = temp; - } + 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; +} - if ( right > _length ) - { - right = _length; - } +/*********************************************/ +/* Search */ +/*********************************************/ - char temp = _buffer[ right ]; // save the replaced character - _buffer[ right ] = '\0'; - String outPut = ( _buffer + left ); // pointer arithmetic - _buffer[ right ] = temp; //restore character - return outPut; +int String::indexOf(char c) const +{ + return indexOf(c, 0); } -String String::toLowerCase() const +int String::indexOf( char ch, unsigned int fromIndex ) const { - String temp = _buffer; - - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); - return temp; + if (fromIndex >= len) return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; } -String String::toUpperCase() const +int String::indexOf(const String &s2) const { - String temp = _buffer; - - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); - return temp; + return indexOf(s2, 0); } -String String::trim() const +int String::indexOf(const String &s2, unsigned int fromIndex) const { - if ( _buffer == NULL ) return *this; - String temp = _buffer; - unsigned int i,j; + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; +} - for ( i = 0; i < _length; i++ ) - { - if ( !isspace(_buffer[i]) ) - break; - } +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf(theChar, len - 1); +} - for ( j = temp._length - 1; j > i; j-- ) - { - if ( !isspace(_buffer[j]) ) - break; - } +int String::lastIndexOf(char ch, int fromIndex) const +{ + if (fromIndex >= len || fromIndex < 0) 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; +} - return temp.substring( i, j + 1); +int String::lastIndexOf(const String &s2) const +{ + return lastIndexOf(s2, len - s2.len); } -void String::getBytes(unsigned char *buf, unsigned int bufsize) +int String::lastIndexOf(const String &s2, int fromIndex) const { - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy((char *)buf, _buffer, len); - buf[len] = 0; + if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) 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 (p - buffer <= fromIndex) found = p - buffer; + } + return found; } -void String::toCharArray(char *buf, unsigned int bufsize) +String String::substring( unsigned int left ) const { - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy(buf, _buffer, len); - buf[len] = 0; + return substring(left, len); +} + +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 = 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::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; } -long String::toInt() { - return atol(_buffer); -} diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h index cadddb9..a601aca 100644 --- a/cores/arduino/WString.h +++ b/cores/arduino/WString.h @@ -1,6 +1,8 @@ /* 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 @@ -17,96 +19,187 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef String_h -#define String_h +#ifndef String_class_h +#define String_class_h +#ifdef __cplusplus -//#include "WProgram.h" #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<__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 { - public: - // constructors - String( const char *value = "" ); - String( const String &value ); - String( const char ); - String( const unsigned char ); - String( const int, const int base=10); - String( const unsigned int, const int base=10 ); - String( const long, const int base=10 ); - String( const unsigned long, const int base=10 ); - ~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0; - - // operators - const String & operator = ( const String &rhs ); - const String & operator +=( const String &rhs ); - //const String & operator +=( const char ); - int operator ==( const String &rhs ) const; - int operator !=( const String &rhs ) const; - int operator < ( const String &rhs ) const; - int operator > ( const String &rhs ) const; - int operator <=( const String &rhs ) const; - int operator >=( const String &rhs ) const; - char operator []( unsigned int index ) const; - char& operator []( unsigned int index ); - //operator const char *() const { return _buffer; } - - // general methods - char charAt( unsigned int index ) const; - int compareTo( const String &anotherString ) const; - unsigned char endsWith( const String &suffix ) const; - unsigned char equals( const String &anObject ) const; - unsigned char equalsIgnoreCase( const String &anotherString ) const; - 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; - const unsigned int length( ) const { return _length; } - void setCharAt(unsigned int index, const char ch); - unsigned char startsWith( const String &prefix ) const; - unsigned char startsWith( const String &prefix, unsigned int toffset ) const; - String substring( unsigned int beginIndex ) const; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - String toLowerCase( ) const; - String toUpperCase( ) const; - String trim( ) const; - void getBytes(unsigned char *buf, unsigned int bufsize); - void toCharArray(char *buf, unsigned int bufsize); - long toInt( ); - const String& concat( const String &str ); - String replace( char oldChar, char newChar ); - String replace( const String& match, const String& replace ); - friend String operator + ( String lhs, const String &rhs ); - - protected: - char *_buffer; // the actual char array - unsigned int _capacity; // the array length minus one (for the '\0') - unsigned int _length; // the String length (not counting the '\0') - - void getBuffer(unsigned int maxStrLen); - - private: + // 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); + #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); + ~String(void); -// allocate buffer space -inline void String::getBuffer(unsigned int maxStrLen) -{ - _capacity = maxStrLen; - _buffer = (char *) malloc(_capacity + 1); - if (_buffer == NULL) _length = _capacity = 0; -} + // 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;} -inline String operator+( String lhs, const String &rhs ) -{ - return lhs += rhs; -} + // 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); + #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); + + // 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);} + + 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); + + // 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);} + + // 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, int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, int fromIndex ) const; + String substring( unsigned int beginIndex ) const; + 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 toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(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') + unsigned char flags; // unused, for future features +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); + #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) {} +}; -#endif +#endif // __cplusplus +#endif // String_class_h diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index cc6e81d..3c46f1e 100755 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -1,4 +1,5 @@ -#include <WProgram.h> +#define ARDUINO_MAIN +#include <Arduino.h> int main(void) { diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp new file mode 100644 index 0000000..0f6d422 --- /dev/null +++ b/cores/arduino/new.cpp @@ -0,0 +1,18 @@ +#include <new.h> + +void * operator new(size_t size) +{ + return malloc(size); +} + +void operator delete(void * ptr) +{ + free(ptr); +} + +int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; +void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; +void __cxa_guard_abort (__guard *) {}; + +void __cxa_pure_virtual(void) {}; + diff --git a/cores/arduino/new.h b/cores/arduino/new.h new file mode 100644 index 0000000..cd940ce --- /dev/null +++ b/cores/arduino/new.h @@ -0,0 +1,22 @@ +/* Header to define new/delete operators as they aren't provided by avr-gcc by default + Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453 + */ + +#ifndef NEW_H +#define NEW_H + +#include <stdlib.h> + +void * operator new(size_t size); +void operator delete(void * ptr); + +__extension__ typedef int __guard __attribute__((mode (__DI__))); + +extern "C" int __cxa_guard_acquire(__guard *); +extern "C" void __cxa_guard_release (__guard *); +extern "C" void __cxa_guard_abort (__guard *); + +extern "C" void __cxa_pure_virtual(void); + +#endif + diff --git a/cores/arduino/pins_arduino.c b/cores/arduino/pins_arduino.c deleted file mode 100755 index 0c816e9..0000000 --- a/cores/arduino/pins_arduino.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - pins_arduino.c - pin definitions for the Arduino board - Part of Arduino / Wiring Lite - - Copyright (c) 2005 David A. Mellis - - 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., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -#include <avr/io.h> -#include "wiring_private.h" -#include "pins_arduino.h" - -// On the Arduino board, digital pins are also used -// for the analog output (software PWM). Analog input -// pins are a separate set. - -// ATMEL ATMEGA8 & 168 / ARDUINO -// -// +-\/-+ -// PC6 1| |28 PC5 (AI 5) -// (D 0) PD0 2| |27 PC4 (AI 4) -// (D 1) PD1 3| |26 PC3 (AI 3) -// (D 2) PD2 4| |25 PC2 (AI 2) -// PWM+ (D 3) PD3 5| |24 PC1 (AI 1) -// (D 4) PD4 6| |23 PC0 (AI 0) -// VCC 7| |22 GND -// GND 8| |21 AREF -// PB6 9| |20 AVCC -// PB7 10| |19 PB5 (D 13) -// PWM+ (D 5) PD5 11| |18 PB4 (D 12) -// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -// (D 7) PD7 13| |16 PB2 (D 10) PWM -// (D 8) PB0 14| |15 PB1 (D 9) PWM -// +----+ -// -// (PWM+ indicates the additional PWM pins on the ATmega168.) - -// ATMEL ATMEGA1280 / ARDUINO -// -// 0-7 PE0-PE7 works -// 8-13 PB0-PB5 works -// 14-21 PA0-PA7 works -// 22-29 PH0-PH7 works -// 30-35 PG5-PG0 works -// 36-43 PC7-PC0 works -// 44-51 PJ7-PJ0 works -// 52-59 PL7-PL0 works -// 60-67 PD7-PD0 works -// A0-A7 PF0-PF7 -// A8-A15 PK0-PK7 - -#define PA 1 -#define PB 2 -#define PC 3 -#define PD 4 -#define PE 5 -#define PF 6 -#define PG 7 -#define PH 8 -#define PJ 10 -#define PK 11 -#define PL 12 - - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, - &DDRA, - &DDRB, - &DDRC, - &DDRD, - &DDRE, - &DDRF, - &DDRG, - &DDRH, - NOT_A_PORT, - &DDRJ, - &DDRK, - &DDRL, -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, - &PORTA, - &PORTB, - &PORTC, - &PORTD, - &PORTE, - &PORTF, - &PORTG, - &PORTH, - NOT_A_PORT, - &PORTJ, - &PORTK, - &PORTL, -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PIN, - &PINA, - &PINB, - &PINC, - &PIND, - &PINE, - &PINF, - &PING, - &PINH, - NOT_A_PIN, - &PINJ, - &PINK, - &PINL, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { - // PORTLIST - // ------------------------------------------- - PE , // PE 0 ** 0 ** USART0_RX - PE , // PE 1 ** 1 ** USART0_TX - PE , // PE 4 ** 2 ** PWM2 - PE , // PE 5 ** 3 ** PWM3 - PG , // PG 5 ** 4 ** PWM4 - PE , // PE 3 ** 5 ** PWM5 - PH , // PH 3 ** 6 ** PWM6 - PH , // PH 4 ** 7 ** PWM7 - PH , // PH 5 ** 8 ** PWM8 - PH , // PH 6 ** 9 ** PWM9 - PB , // PB 4 ** 10 ** PWM10 - PB , // PB 5 ** 11 ** PWM11 - PB , // PB 6 ** 12 ** PWM12 - PB , // PB 7 ** 13 ** PWM13 - PJ , // PJ 1 ** 14 ** USART3_TX - PJ , // PJ 0 ** 15 ** USART3_RX - PH , // PH 1 ** 16 ** USART2_TX - PH , // PH 0 ** 17 ** USART2_RX - PD , // PD 3 ** 18 ** USART1_TX - PD , // PD 2 ** 19 ** USART1_RX - PD , // PD 1 ** 20 ** I2C_SDA - PD , // PD 0 ** 21 ** I2C_SCL - PA , // PA 0 ** 22 ** D22 - PA , // PA 1 ** 23 ** D23 - PA , // PA 2 ** 24 ** D24 - PA , // PA 3 ** 25 ** D25 - PA , // PA 4 ** 26 ** D26 - PA , // PA 5 ** 27 ** D27 - PA , // PA 6 ** 28 ** D28 - PA , // PA 7 ** 29 ** D29 - PC , // PC 7 ** 30 ** D30 - PC , // PC 6 ** 31 ** D31 - PC , // PC 5 ** 32 ** D32 - PC , // PC 4 ** 33 ** D33 - PC , // PC 3 ** 34 ** D34 - PC , // PC 2 ** 35 ** D35 - PC , // PC 1 ** 36 ** D36 - PC , // PC 0 ** 37 ** D37 - PD , // PD 7 ** 38 ** D38 - PG , // PG 2 ** 39 ** D39 - PG , // PG 1 ** 40 ** D40 - PG , // PG 0 ** 41 ** D41 - PL , // PL 7 ** 42 ** D42 - PL , // PL 6 ** 43 ** D43 - PL , // PL 5 ** 44 ** D44 - PL , // PL 4 ** 45 ** D45 - PL , // PL 3 ** 46 ** D46 - PL , // PL 2 ** 47 ** D47 - PL , // PL 1 ** 48 ** D48 - PL , // PL 0 ** 49 ** D49 - PB , // PB 3 ** 50 ** SPI_MISO - PB , // PB 2 ** 51 ** SPI_MOSI - PB , // PB 1 ** 52 ** SPI_SCK - PB , // PB 0 ** 53 ** SPI_SS - PF , // PF 0 ** 54 ** A0 - PF , // PF 1 ** 55 ** A1 - PF , // PF 2 ** 56 ** A2 - PF , // PF 3 ** 57 ** A3 - PF , // PF 4 ** 58 ** A4 - PF , // PF 5 ** 59 ** A5 - PF , // PF 6 ** 60 ** A6 - PF , // PF 7 ** 61 ** A7 - PK , // PK 0 ** 62 ** A8 - PK , // PK 1 ** 63 ** A9 - PK , // PK 2 ** 64 ** A10 - PK , // PK 3 ** 65 ** A11 - PK , // PK 4 ** 66 ** A12 - PK , // PK 5 ** 67 ** A13 - PK , // PK 6 ** 68 ** A14 - PK , // PK 7 ** 69 ** A15 -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { - // PIN IN PORT - // ------------------------------------------- - _BV( 0 ) , // PE 0 ** 0 ** USART0_RX - _BV( 1 ) , // PE 1 ** 1 ** USART0_TX - _BV( 4 ) , // PE 4 ** 2 ** PWM2 - _BV( 5 ) , // PE 5 ** 3 ** PWM3 - _BV( 5 ) , // PG 5 ** 4 ** PWM4 - _BV( 3 ) , // PE 3 ** 5 ** PWM5 - _BV( 3 ) , // PH 3 ** 6 ** PWM6 - _BV( 4 ) , // PH 4 ** 7 ** PWM7 - _BV( 5 ) , // PH 5 ** 8 ** PWM8 - _BV( 6 ) , // PH 6 ** 9 ** PWM9 - _BV( 4 ) , // PB 4 ** 10 ** PWM10 - _BV( 5 ) , // PB 5 ** 11 ** PWM11 - _BV( 6 ) , // PB 6 ** 12 ** PWM12 - _BV( 7 ) , // PB 7 ** 13 ** PWM13 - _BV( 1 ) , // PJ 1 ** 14 ** USART3_TX - _BV( 0 ) , // PJ 0 ** 15 ** USART3_RX - _BV( 1 ) , // PH 1 ** 16 ** USART2_TX - _BV( 0 ) , // PH 0 ** 17 ** USART2_RX - _BV( 3 ) , // PD 3 ** 18 ** USART1_TX - _BV( 2 ) , // PD 2 ** 19 ** USART1_RX - _BV( 1 ) , // PD 1 ** 20 ** I2C_SDA - _BV( 0 ) , // PD 0 ** 21 ** I2C_SCL - _BV( 0 ) , // PA 0 ** 22 ** D22 - _BV( 1 ) , // PA 1 ** 23 ** D23 - _BV( 2 ) , // PA 2 ** 24 ** D24 - _BV( 3 ) , // PA 3 ** 25 ** D25 - _BV( 4 ) , // PA 4 ** 26 ** D26 - _BV( 5 ) , // PA 5 ** 27 ** D27 - _BV( 6 ) , // PA 6 ** 28 ** D28 - _BV( 7 ) , // PA 7 ** 29 ** D29 - _BV( 7 ) , // PC 7 ** 30 ** D30 - _BV( 6 ) , // PC 6 ** 31 ** D31 - _BV( 5 ) , // PC 5 ** 32 ** D32 - _BV( 4 ) , // PC 4 ** 33 ** D33 - _BV( 3 ) , // PC 3 ** 34 ** D34 - _BV( 2 ) , // PC 2 ** 35 ** D35 - _BV( 1 ) , // PC 1 ** 36 ** D36 - _BV( 0 ) , // PC 0 ** 37 ** D37 - _BV( 7 ) , // PD 7 ** 38 ** D38 - _BV( 2 ) , // PG 2 ** 39 ** D39 - _BV( 1 ) , // PG 1 ** 40 ** D40 - _BV( 0 ) , // PG 0 ** 41 ** D41 - _BV( 7 ) , // PL 7 ** 42 ** D42 - _BV( 6 ) , // PL 6 ** 43 ** D43 - _BV( 5 ) , // PL 5 ** 44 ** D44 - _BV( 4 ) , // PL 4 ** 45 ** D45 - _BV( 3 ) , // PL 3 ** 46 ** D46 - _BV( 2 ) , // PL 2 ** 47 ** D47 - _BV( 1 ) , // PL 1 ** 48 ** D48 - _BV( 0 ) , // PL 0 ** 49 ** D49 - _BV( 3 ) , // PB 3 ** 50 ** SPI_MISO - _BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI - _BV( 1 ) , // PB 1 ** 52 ** SPI_SCK - _BV( 0 ) , // PB 0 ** 53 ** SPI_SS - _BV( 0 ) , // PF 0 ** 54 ** A0 - _BV( 1 ) , // PF 1 ** 55 ** A1 - _BV( 2 ) , // PF 2 ** 56 ** A2 - _BV( 3 ) , // PF 3 ** 57 ** A3 - _BV( 4 ) , // PF 4 ** 58 ** A4 - _BV( 5 ) , // PF 5 ** 59 ** A5 - _BV( 6 ) , // PF 6 ** 60 ** A6 - _BV( 7 ) , // PF 7 ** 61 ** A7 - _BV( 0 ) , // PK 0 ** 62 ** A8 - _BV( 1 ) , // PK 1 ** 63 ** A9 - _BV( 2 ) , // PK 2 ** 64 ** A10 - _BV( 3 ) , // PK 3 ** 65 ** A11 - _BV( 4 ) , // PK 4 ** 66 ** A12 - _BV( 5 ) , // PK 5 ** 67 ** A13 - _BV( 6 ) , // PK 6 ** 68 ** A14 - _BV( 7 ) , // PK 7 ** 69 ** A15 -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { - // TIMERS - // ------------------------------------------- - NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX - NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX - TIMER3B , // PE 4 ** 2 ** PWM2 - TIMER3C , // PE 5 ** 3 ** PWM3 - TIMER0B , // PG 5 ** 4 ** PWM4 - TIMER3A , // PE 3 ** 5 ** PWM5 - TIMER4A , // PH 3 ** 6 ** PWM6 - TIMER4B , // PH 4 ** 7 ** PWM7 - TIMER4C , // PH 5 ** 8 ** PWM8 - TIMER2B , // PH 6 ** 9 ** PWM9 - TIMER2A , // PB 4 ** 10 ** PWM10 - TIMER1A , // PB 5 ** 11 ** PWM11 - TIMER1B , // PB 6 ** 12 ** PWM12 - TIMER0A , // PB 7 ** 13 ** PWM13 - NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX - NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX - NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX - NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX - NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX - NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX - NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA - NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL - NOT_ON_TIMER , // PA 0 ** 22 ** D22 - NOT_ON_TIMER , // PA 1 ** 23 ** D23 - NOT_ON_TIMER , // PA 2 ** 24 ** D24 - NOT_ON_TIMER , // PA 3 ** 25 ** D25 - NOT_ON_TIMER , // PA 4 ** 26 ** D26 - NOT_ON_TIMER , // PA 5 ** 27 ** D27 - NOT_ON_TIMER , // PA 6 ** 28 ** D28 - NOT_ON_TIMER , // PA 7 ** 29 ** D29 - NOT_ON_TIMER , // PC 7 ** 30 ** D30 - NOT_ON_TIMER , // PC 6 ** 31 ** D31 - NOT_ON_TIMER , // PC 5 ** 32 ** D32 - NOT_ON_TIMER , // PC 4 ** 33 ** D33 - NOT_ON_TIMER , // PC 3 ** 34 ** D34 - NOT_ON_TIMER , // PC 2 ** 35 ** D35 - NOT_ON_TIMER , // PC 1 ** 36 ** D36 - NOT_ON_TIMER , // PC 0 ** 37 ** D37 - NOT_ON_TIMER , // PD 7 ** 38 ** D38 - NOT_ON_TIMER , // PG 2 ** 39 ** D39 - NOT_ON_TIMER , // PG 1 ** 40 ** D40 - NOT_ON_TIMER , // PG 0 ** 41 ** D41 - NOT_ON_TIMER , // PL 7 ** 42 ** D42 - NOT_ON_TIMER , // PL 6 ** 43 ** D43 - TIMER5C , // PL 5 ** 44 ** D44 - TIMER5B , // PL 4 ** 45 ** D45 - TIMER5A , // PL 3 ** 46 ** D46 - NOT_ON_TIMER , // PL 2 ** 47 ** D47 - NOT_ON_TIMER , // PL 1 ** 48 ** D48 - NOT_ON_TIMER , // PL 0 ** 49 ** D49 - NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO - NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI - NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK - NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS - NOT_ON_TIMER , // PF 0 ** 54 ** A0 - NOT_ON_TIMER , // PF 1 ** 55 ** A1 - NOT_ON_TIMER , // PF 2 ** 56 ** A2 - NOT_ON_TIMER , // PF 3 ** 57 ** A3 - NOT_ON_TIMER , // PF 4 ** 58 ** A4 - NOT_ON_TIMER , // PF 5 ** 59 ** A5 - NOT_ON_TIMER , // PF 6 ** 60 ** A6 - NOT_ON_TIMER , // PF 7 ** 61 ** A7 - NOT_ON_TIMER , // PK 0 ** 62 ** A8 - NOT_ON_TIMER , // PK 1 ** 63 ** A9 - NOT_ON_TIMER , // PK 2 ** 64 ** A10 - NOT_ON_TIMER , // PK 3 ** 65 ** A11 - NOT_ON_TIMER , // PK 4 ** 66 ** A12 - NOT_ON_TIMER , // PK 5 ** 67 ** A13 - NOT_ON_TIMER , // PK 6 ** 68 ** A14 - NOT_ON_TIMER , // PK 7 ** 69 ** A15 -}; -#else -// these arrays map port names (e.g. port B) to the -// appropriate addresses for various functions (e.g. reading -// and writing) -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - &DDRB, - &DDRC, - &DDRD, -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - &PORTB, - &PORTC, - &PORTD, -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - &PINB, - &PINC, - &PIND, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { - PD, /* 0 */ - PD, - PD, - PD, - PD, - PD, - PD, - PD, - PB, /* 8 */ - PB, - PB, - PB, - PB, - PB, - PC, /* 14 */ - PC, - PC, - PC, - PC, - PC, -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { - _BV(0), /* 0, port D */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(6), - _BV(7), - _BV(0), /* 8, port B */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(0), /* 14, port C */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { - NOT_ON_TIMER, /* 0 - port D */ - NOT_ON_TIMER, - NOT_ON_TIMER, - // on the ATmega168, digital pin 3 has hardware pwm -#if defined(__AVR_ATmega8__) - NOT_ON_TIMER, -#else - TIMER2B, -#endif - NOT_ON_TIMER, - // on the ATmega168, digital pins 5 and 6 have hardware pwm -#if defined(__AVR_ATmega8__) - NOT_ON_TIMER, - NOT_ON_TIMER, -#else - TIMER0B, - TIMER0A, -#endif - NOT_ON_TIMER, - NOT_ON_TIMER, /* 8 - port B */ - TIMER1A, - TIMER1B, -#if defined(__AVR_ATmega8__) - TIMER2, -#else - TIMER2A, -#endif - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, /* 14 - port C */ - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, -}; -#endif diff --git a/cores/arduino/pins_arduino.h b/cores/arduino/pins_arduino.h deleted file mode 100644 index bc931c5..0000000 --- a/cores/arduino/pins_arduino.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - 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., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include <avr/pgmspace.h> - -#define NOT_A_PIN 0 -#define NOT_A_PORT 0 - -#define NOT_ON_TIMER 0 -#define TIMER0A 1 -#define TIMER0B 2 -#define TIMER1A 3 -#define TIMER1B 4 -#define TIMER2 5 -#define TIMER2A 6 -#define TIMER2B 7 - -#define TIMER3A 8 -#define TIMER3B 9 -#define TIMER3C 10 -#define TIMER4A 11 -#define TIMER4B 12 -#define TIMER4C 13 -#define TIMER5A 14 -#define TIMER5B 15 -#define TIMER5C 16 - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -const static uint8_t SS = 53; -const static uint8_t MOSI = 51; -const static uint8_t MISO = 50; -const static uint8_t SCK = 52; -#else -const static uint8_t SS = 10; -const static uint8_t MOSI = 11; -const static uint8_t MISO = 12; -const static uint8_t SCK = 13; -#endif - -// On the ATmega1280, the addresses of some of the port registers are -// greater than 255, so we can't store them in uint8_t's. -extern const uint16_t PROGMEM port_to_mode_PGM[]; -extern const uint16_t PROGMEM port_to_input_PGM[]; -extern const uint16_t PROGMEM port_to_output_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; - -// 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. -// -// These perform slightly better as macros compared to inline functions -// -#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) -#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) -#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) -#define analogInPinToBit(P) (P) -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) - -#endif diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index b90d07e..ce4cad6 100755 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -212,10 +212,10 @@ void init() // note, however, that fast pwm mode can achieve a frequency of up // 8 MHz (with a 16 MHz clock) at 50% duty cycle +#if defined(TCCR1B) && defined(CS11) && defined(CS10) TCCR1B = 0; // set timer 1 prescale factor to 64 -#if defined(TCCR1B) && defined(CS11) && defined(CS10) sbi(TCCR1B, CS11); sbi(TCCR1B, CS10); #elif defined(TCCR1) && defined(CS11) && defined(CS10) diff --git a/cores/arduino/wiring.h b/cores/arduino/wiring.h deleted file mode 100755 index e29959b..0000000 --- a/cores/arduino/wiring.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - wiring.h - Partial implementation of the Wiring API for the ATmega8. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - 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., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -#ifndef Wiring_h -#define Wiring_h - -#include <avr/io.h> -#include <stdlib.h> -#include "binary.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define HIGH 0x1 -#define LOW 0x0 - -#define INPUT 0x0 -#define OUTPUT 0x1 - -#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 - -#define LSBFIRST 0 -#define MSBFIRST 1 - -#define CHANGE 1 -#define FALLING 2 -#define RISING 3 - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define INTERNAL1V1 2 -#define INTERNAL2V56 3 -#else -#define INTERNAL 3 -#endif -#define DEFAULT 1 -#define EXTERNAL 0 - -// undefine stdlib's abs if encountered -#ifdef abs -#undef abs -#endif - -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#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() sei() -#define noInterrupts() cli() - -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) -#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) - -#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)) - -typedef uint8_t boolean; -typedef uint8_t byte; - -void init(void); - -void pinMode(uint8_t, uint8_t); -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); -void analogReference(uint8_t mode); -void analogWrite(uint8_t, int); - -unsigned long millis(void); -unsigned long micros(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int us); -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); - -void attachInterrupt(uint8_t, void (*)(void), int mode); -void detachInterrupt(uint8_t); - -void setup(void); -void loop(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 0949da4..dd1b949 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -136,17 +136,16 @@ void digitalWrite(uint8_t pin, uint8_t val) out = portOutputRegister(port); + uint8_t oldSREG = SREG; + cli(); + if (val == LOW) { - uint8_t oldSREG = SREG; - cli(); *out &= ~bit; - SREG = oldSREG; } else { - uint8_t oldSREG = SREG; - cli(); *out |= bit; - SREG = oldSREG; } + + SREG = oldSREG; } int digitalRead(uint8_t pin) diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index 11f6f00..74c0d06 100755 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -31,7 +31,7 @@ #include <stdio.h> #include <stdarg.h> -#include "wiring.h" +#include "Arduino.h" #ifdef __cplusplus extern "C"{ |