| @@ -0,0 +1,9 @@ | |||
| Teensy 2.0 and 3.0 core libraries for Arduino. | |||
| The latest stable version of Teensy's core library is always available in the Teensyduino installer, at this page: | |||
| http://www.pjrc.com/teensy/td_download.html | |||
| This github repository contains work-in-progress code, which may not be stable. It is not recommended for use in actual projects. | |||
| @@ -0,0 +1,2 @@ | |||
| #include "WProgram.h" | |||
| #include "pins_arduino.h" | |||
| @@ -0,0 +1,29 @@ | |||
| #if ARDUINO >= 100 | |||
| #ifndef client_h | |||
| #define client_h | |||
| #include "Print.h" | |||
| #include "Stream.h" | |||
| #include "IPAddress.h" | |||
| class Client : public Stream { | |||
| public: | |||
| virtual int connect(IPAddress ip, uint16_t port) =0; | |||
| virtual int connect(const char *host, uint16_t port) =0; | |||
| virtual size_t write(uint8_t) =0; | |||
| virtual size_t write(const uint8_t *buf, size_t size) =0; | |||
| virtual int available() = 0; | |||
| virtual int read() = 0; | |||
| virtual int read(uint8_t *buf, size_t size) = 0; | |||
| virtual int peek() = 0; | |||
| virtual void flush() = 0; | |||
| virtual void stop() = 0; | |||
| virtual uint8_t connected() = 0; | |||
| virtual operator bool() = 0; | |||
| protected: | |||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,195 @@ | |||
| /* UART (hardware serial) for Teensy & Teensy++ | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2008 PJRC.COM, LLC | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| #include <avr/io.h> | |||
| #include <avr/interrupt.h> | |||
| #include "core_pins.h" | |||
| #include "HardwareSerial.h" | |||
| #define RX_BUFFER_SIZE 64 | |||
| static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; | |||
| static volatile uint8_t rx_buffer_head = 0; | |||
| static volatile uint8_t rx_buffer_tail = 0; | |||
| #define TX_BUFFER_SIZE 40 | |||
| static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; | |||
| static volatile uint8_t tx_buffer_head = 0; | |||
| static volatile uint8_t tx_buffer_tail = 0; | |||
| static volatile uint8_t transmitting = 0; | |||
| static volatile uint8_t tx_enable_pin = 255; | |||
| // Public Methods ////////////////////////////////////////////////////////////// | |||
| void HardwareSerial::_begin(uint16_t baud_count, uint8_t txen_pin) | |||
| { | |||
| tx_enable_pin = txen_pin; | |||
| if (txen_pin < 255) { | |||
| pinMode(txen_pin, OUTPUT); | |||
| digitalWrite(txen_pin, LOW); | |||
| } | |||
| if ((baud_count & 1) && baud_count <= 4096) { | |||
| UCSR1A = (1<<U2X1); | |||
| UBRR1 = baud_count - 1; | |||
| } else { | |||
| UCSR1A = 0; | |||
| UBRR1 = (baud_count >> 1) - 1; | |||
| } | |||
| if (!(UCSR1B & (1<<TXEN1))) { | |||
| rx_buffer_head = 0; | |||
| rx_buffer_tail = 0; | |||
| tx_buffer_head = 0; | |||
| tx_buffer_tail = 0; | |||
| transmitting = 0; | |||
| UCSR1C = (1<<UCSZ11) | (1<<UCSZ10); | |||
| UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1); | |||
| } | |||
| } | |||
| void HardwareSerial::end(void) | |||
| { | |||
| while (transmitting) ; // wait for buffered data to send | |||
| UCSR1B = 0; | |||
| rx_buffer_head = 0; | |||
| rx_buffer_tail = 0; | |||
| } | |||
| int HardwareSerial::available(void) | |||
| { | |||
| uint8_t head, tail; | |||
| head = rx_buffer_head; | |||
| tail = rx_buffer_tail; | |||
| if (head >= tail) return head - tail; | |||
| return RX_BUFFER_SIZE + head - tail; | |||
| } | |||
| int HardwareSerial::peek(void) | |||
| { | |||
| uint8_t head, tail; | |||
| head = rx_buffer_head; | |||
| tail = rx_buffer_tail; | |||
| if (head == tail) return -1; | |||
| if (++tail >= RX_BUFFER_SIZE) tail = 0; | |||
| return rx_buffer[tail]; | |||
| } | |||
| int HardwareSerial::read(void) | |||
| { | |||
| uint8_t c, i; | |||
| if (rx_buffer_head == rx_buffer_tail) return -1; | |||
| i = rx_buffer_tail + 1; | |||
| if (i >= RX_BUFFER_SIZE) i = 0; | |||
| c = rx_buffer[i]; | |||
| rx_buffer_tail = i; | |||
| return c; | |||
| } | |||
| void HardwareSerial::flush() | |||
| { | |||
| #if ARDUINO >= 100 | |||
| while (transmitting) ; // wait for buffered data to send | |||
| #else | |||
| rx_buffer_head = rx_buffer_tail; | |||
| #endif | |||
| } | |||
| void HardwareSerial::clear() | |||
| { | |||
| rx_buffer_head = rx_buffer_tail; | |||
| } | |||
| #if ARDUINO >= 100 | |||
| size_t HardwareSerial::write(uint8_t c) | |||
| #else | |||
| void HardwareSerial::write(uint8_t c) | |||
| #endif | |||
| { | |||
| uint8_t i; | |||
| if (!(UCSR1B & (1<<TXEN1))) { | |||
| #if ARDUINO >= 100 | |||
| setWriteError(); | |||
| return 0; | |||
| #else | |||
| return; | |||
| #endif | |||
| } | |||
| if (tx_enable_pin < 255 && !transmitting) { | |||
| digitalWrite(tx_enable_pin, HIGH); | |||
| } | |||
| i = tx_buffer_head + 1; | |||
| if (i >= TX_BUFFER_SIZE) i = 0; | |||
| while (tx_buffer_tail == i) ; // wait until space in buffer | |||
| tx_buffer[i] = c; | |||
| transmitting = 1; | |||
| tx_buffer_head = i; | |||
| UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1) | (1<<UDRIE1); | |||
| #if ARDUINO >= 100 | |||
| return 1; | |||
| #endif | |||
| } | |||
| ISR(USART1_RX_vect) | |||
| { | |||
| uint8_t c, i; | |||
| c = UDR1; | |||
| i = rx_buffer_head + 1; | |||
| if (i >= RX_BUFFER_SIZE) i = 0; | |||
| if (i != rx_buffer_tail) { | |||
| rx_buffer[i] = c; | |||
| rx_buffer_head = i; | |||
| } | |||
| } | |||
| ISR(USART1_UDRE_vect) | |||
| { | |||
| uint8_t i; | |||
| if (tx_buffer_head == tx_buffer_tail) { | |||
| // buffer is empty, disable transmit interrupt | |||
| UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1); | |||
| } else { | |||
| i = tx_buffer_tail + 1; | |||
| if (i >= TX_BUFFER_SIZE) i = 0; | |||
| UDR1 = tx_buffer[i]; | |||
| tx_buffer_tail = i; | |||
| } | |||
| } | |||
| ISR(USART1_TX_vect) | |||
| { | |||
| transmitting = 0; | |||
| if (tx_enable_pin < 255) { | |||
| digitalWrite(tx_enable_pin, LOW); | |||
| } | |||
| } | |||
| // Preinstantiate Objects ////////////////////////////////////////////////////// | |||
| HardwareSerial Serial1; | |||
| @@ -0,0 +1,30 @@ | |||
| #ifndef HardwareSerial_h | |||
| #define HardwareSerial_h | |||
| #include <inttypes.h> | |||
| #include "Stream.h" | |||
| class HardwareSerial : public Stream | |||
| { | |||
| public: | |||
| inline void begin(uint32_t baud, uint8_t txen_pin=255) { | |||
| _begin(((F_CPU / 8) + (baud / 2)) / baud, txen_pin); | |||
| } | |||
| void _begin(uint16_t baud_count, uint8_t pin); | |||
| void end(void); | |||
| virtual int available(void); | |||
| virtual int peek(void); | |||
| virtual int read(void); | |||
| virtual void flush(void); | |||
| void clear(void); | |||
| #if ARDUINO >= 100 | |||
| virtual size_t write(uint8_t); | |||
| #else | |||
| virtual void write(uint8_t); | |||
| #endif | |||
| using Print::write; | |||
| }; | |||
| extern HardwareSerial Serial1; | |||
| #endif | |||
| @@ -0,0 +1,57 @@ | |||
| #if ARDUINO >= 100 | |||
| #include "Arduino.h" | |||
| #include "IPAddress.h" | |||
| IPAddress::IPAddress() | |||
| { | |||
| memset(_address, 0, sizeof(_address)); | |||
| } | |||
| IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) | |||
| { | |||
| _address[0] = first_octet; | |||
| _address[1] = second_octet; | |||
| _address[2] = third_octet; | |||
| _address[3] = fourth_octet; | |||
| } | |||
| IPAddress::IPAddress(uint32_t address) | |||
| { | |||
| memcpy(_address, &address, sizeof(_address)); | |||
| } | |||
| IPAddress::IPAddress(const uint8_t *address) | |||
| { | |||
| memcpy(_address, address, sizeof(_address)); | |||
| } | |||
| IPAddress& IPAddress::operator=(const uint8_t *address) | |||
| { | |||
| memcpy(_address, address, sizeof(_address)); | |||
| return *this; | |||
| } | |||
| IPAddress& IPAddress::operator=(uint32_t address) | |||
| { | |||
| memcpy(_address, (const uint8_t *)&address, sizeof(_address)); | |||
| return *this; | |||
| } | |||
| bool IPAddress::operator==(const uint8_t* addr) | |||
| { | |||
| return memcmp(addr, _address, sizeof(_address)) == 0; | |||
| } | |||
| size_t IPAddress::printTo(Print& p) const | |||
| { | |||
| size_t n = 0; | |||
| for (int i =0; i < 3; i++) | |||
| { | |||
| n += p.print(_address[i], DEC); | |||
| n += p.print('.'); | |||
| } | |||
| n += p.print(_address[3], DEC); | |||
| return n; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,78 @@ | |||
| /* | |||
| * | |||
| * MIT License: | |||
| * Copyright (c) 2011 Adrian McEwen | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| * | |||
| * adrianm@mcqn.com 1/1/2011 | |||
| */ | |||
| #if ARDUINO >= 100 | |||
| #ifndef IPAddress_h | |||
| #define IPAddress_h | |||
| #include <Printable.h> | |||
| // A class to make it easier to handle and pass around IP addresses | |||
| class IPAddress : public Printable { | |||
| private: | |||
| uint8_t _address[4]; // IPv4 address | |||
| // Access the raw byte array containing the address. Because this returns a pointer | |||
| // to the internal structure rather than a copy of the address this function should only | |||
| // be used when you know that the usage of the returned uint8_t* will be transient and not | |||
| // stored. | |||
| uint8_t* raw_address() { return _address; }; | |||
| public: | |||
| // Constructors | |||
| IPAddress(); | |||
| IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); | |||
| IPAddress(uint32_t address); | |||
| IPAddress(const uint8_t *address); | |||
| // Overloaded cast operator to allow IPAddress objects to be used where a pointer | |||
| // to a four-byte uint8_t array is expected | |||
| operator uint32_t() { return *((uint32_t*)_address); }; | |||
| bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; | |||
| bool operator==(const uint8_t* addr); | |||
| // Overloaded index operator to allow getting and setting individual octets of the address | |||
| uint8_t operator[](int index) const { return _address[index]; }; | |||
| uint8_t& operator[](int index) { return _address[index]; }; | |||
| // Overloaded copy operators to allow initialisation of IPAddress objects from other types | |||
| IPAddress& operator=(const uint8_t *address); | |||
| IPAddress& operator=(uint32_t address); | |||
| virtual size_t printTo(Print& p) const; | |||
| friend class EthernetClass; | |||
| friend class UDP; | |||
| friend class Client; | |||
| friend class Server; | |||
| friend class DhcpClass; | |||
| friend class DNSClient; | |||
| }; | |||
| const IPAddress INADDR_NONE(0,0,0,0); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,484 @@ | |||
| /* | |||
| Print.cpp - Base class that provides print() and println() | |||
| Copyright (c) 2008 David A. Mellis. All right reserved. | |||
| many modifications, by Paul Stoffregen <paul@pjrc.com> | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| Modified 23 November 2006 by David A. Mellis | |||
| */ | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <inttypes.h> | |||
| #include <math.h> | |||
| #include <avr/pgmspace.h> | |||
| #include "wiring.h" | |||
| #include "Print.h" | |||
| #if ARDUINO >= 100 | |||
| #else | |||
| void Print::write(const char *str) | |||
| { | |||
| write((const uint8_t *)str, strlen(str)); | |||
| } | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::write(const uint8_t *buffer, size_t size) | |||
| { | |||
| size_t count = 0; | |||
| while (size--) count += write(*buffer++); | |||
| return count; | |||
| } | |||
| #else | |||
| void Print::write(const uint8_t *buffer, size_t size) | |||
| { | |||
| while (size--) write(*buffer++); | |||
| } | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::print(const String &s) | |||
| { | |||
| uint8_t buffer[33]; | |||
| size_t count = 0; | |||
| unsigned int index = 0; | |||
| unsigned int len = s.length(); | |||
| while (len > 0) { | |||
| s.getBytes(buffer, sizeof(buffer), index); | |||
| unsigned int nbytes = len; | |||
| if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1; | |||
| index += nbytes; | |||
| len -= nbytes; | |||
| count += write(buffer, nbytes); | |||
| } | |||
| return count; | |||
| } | |||
| #else | |||
| void Print::print(const String &s) | |||
| { | |||
| unsigned int len = s.length(); | |||
| for (unsigned int i=0; i < len; i++) { | |||
| write(s[i]); | |||
| } | |||
| } | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::print(const __FlashStringHelper *ifsh) | |||
| { | |||
| uint8_t buffer[32]; | |||
| size_t count = 0; | |||
| const char PROGMEM *p = (const char PROGMEM *)ifsh; | |||
| unsigned int len = strlen_P(p); | |||
| while (len > 0) { | |||
| unsigned int nbytes = len; | |||
| if (nbytes > sizeof(buffer)) nbytes = sizeof(buffer); | |||
| memcpy_P(buffer, p, nbytes); | |||
| p += nbytes; | |||
| len -= nbytes; | |||
| count += write(buffer, nbytes); | |||
| } | |||
| return count; | |||
| } | |||
| #else | |||
| void Print::print(const __FlashStringHelper *ifsh) | |||
| { | |||
| const char PROGMEM *p = (const char PROGMEM *)ifsh; | |||
| while (1) { | |||
| unsigned char c = pgm_read_byte(p++); | |||
| if (c == 0) return; | |||
| write(c); | |||
| } | |||
| } | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::print(long n) | |||
| { | |||
| uint8_t sign=0; | |||
| if (n < 0) { | |||
| sign = 1; | |||
| n = -n; | |||
| } | |||
| return printNumber(n, sign, 10); | |||
| } | |||
| #else | |||
| void Print::print(long n) | |||
| { | |||
| uint8_t sign=0; | |||
| if (n < 0) { | |||
| sign = 1; | |||
| n = -n; | |||
| } | |||
| printNumber(n, sign, 10); | |||
| } | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::println(void) | |||
| { | |||
| uint8_t buf[2]={'\r', '\n'}; | |||
| return write(buf, 2); | |||
| } | |||
| #else | |||
| void Print::println(void) | |||
| { | |||
| uint8_t buf[2]={'\r', '\n'}; | |||
| write(buf, 2); | |||
| } | |||
| #endif | |||
| //#define USE_HACKER_DELIGHT_OPTIMIZATION | |||
| #define USE_STIMMER_OPTIMIZATION | |||
| //#define USE_BENCHMARK_CODE | |||
| #ifdef USE_HACKER_DELIGHT_OPTIMIZATION | |||
| // Adapted from Hacker's Delight (Henry Warren, ISBN 0321842685) www.hackersdelight.org | |||
| // by Rob Tillaart, Tom Carpenter, "genom2" with input from others... | |||
| // http://forum.arduino.cc/index.php?topic=167414.0 | |||
| // | |||
| #define divmod10_asm(in32, tmp32, mod8) \ | |||
| asm volatile ( \ | |||
| "mov %2, %A0 \n\t" /* mod = in */ \ | |||
| "ori %A0, 1 \n\t" /* q = in | 1 */ \ | |||
| "movw %A1, %A0 \n\t" /* x = q */ \ | |||
| "movw %C1, %C0 \n\t" \ | |||
| "lsr %D1 \n\t" /* x = x >> 2 */ \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "lsr %D1 \n\t" \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "sub %A0, %A1 \n\t" /* q = q - x */ \ | |||
| "sbc %B0, %B1 \n\t" \ | |||
| "sbc %C0, %C1 \n\t" \ | |||
| "sbc %D0, %D1 \n\t" \ | |||
| "movw %A1, %A0 \n\t" /* x = q */ \ | |||
| "movw %C1, %C0 \n\t" \ | |||
| "lsr %D1 \n\t" /* x = x >> 4 */ \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "lsr %D1 \n\t" \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "lsr %D1 \n\t" \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "lsr %D1 \n\t" \ | |||
| "ror %C1 \n\t" \ | |||
| "ror %B1 \n\t" \ | |||
| "ror %A1 \n\t" \ | |||
| "add %A1, %A0 \n\t" /* x = x + q */ \ | |||
| "adc %B1, %B0 \n\t" \ | |||
| "adc %C1, %C0 \n\t" \ | |||
| "adc %D1, %D0 \n\t" \ | |||
| "movw %A0, %A1 \n\t" /* q = x */ \ | |||
| "movw %C0, %C1 \n\t" \ | |||
| "add %A0, %B1 \n\t" /* q = q + (x >> 8) */ \ | |||
| "adc %B0, %C1 \n\t" \ | |||
| "adc %C0, %D1 \n\t" \ | |||
| "adc %D0, r1 \n\t" \ | |||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||
| "mov %B0, %C0 \n\t" \ | |||
| "mov %C0, %D0 \n\t" \ | |||
| "eor %D0, %D0 \n\t" \ | |||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||
| "adc %B0, %B1 \n\t" \ | |||
| "adc %C0, %C1 \n\t" \ | |||
| "adc %D0, %D1 \n\t" \ | |||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||
| "mov %B0, %C0 \n\t" \ | |||
| "mov %C0, %D0 \n\t" \ | |||
| "eor %D0, %D0 \n\t" \ | |||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||
| "adc %B0, %B1 \n\t" \ | |||
| "adc %C0, %C1 \n\t" \ | |||
| "adc %D0, %D1 \n\t" \ | |||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||
| "mov %B0, %C0 \n\t" \ | |||
| "mov %C0, %D0 \n\t" \ | |||
| "eor %D0, %D0 \n\t" \ | |||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||
| "adc %B0, %B1 \n\t" \ | |||
| "adc %C0, %C1 \n\t" \ | |||
| "adc %D0, %D1 \n\t" \ | |||
| "andi %A0, 0xF8 \n\t" /* q = q & ~0x7 */ \ | |||
| "sub %2, %A0 \n\t" /* mod = mod - q */ \ | |||
| "lsr %D0 \n\t" /* q = q >> 2 */ \ | |||
| "ror %C0 \n\t" \ | |||
| "ror %B0 \n\t" \ | |||
| "ror %A0 \n\t" \ | |||
| "lsr %D0 \n\t" \ | |||
| "ror %C0 \n\t" \ | |||
| "ror %B0 \n\t" \ | |||
| "ror %A0 \n\t" \ | |||
| "sub %2, %A0 \n\t" /* mod = mod - q */ \ | |||
| "lsr %D0 \n\t" /* q = q >> 1 */ \ | |||
| "ror %C0 \n\t" \ | |||
| "ror %B0 \n\t" \ | |||
| "ror %A0 \n\t" \ | |||
| : "+d" (in32), "=r" (tmp32), "=r" (mod8) : : "r0" \ | |||
| ) | |||
| #endif // USE_HACKER_DELIGHT_OPTIMIZATION | |||
| #ifdef USE_STIMMER_OPTIMIZATION | |||
| // http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679 | |||
| // http://forum.arduino.cc/index.php?topic=167414.msg1309482#msg1309482 | |||
| // equivelant code: | |||
| // mod8 = in32 % 10; | |||
| // in32 = in32 / 10; | |||
| // tmp8 = 10; | |||
| #define divmod10_asm(in32, mod8, tmp8) \ | |||
| asm volatile ( \ | |||
| " ldi %2,51 \n\t" \ | |||
| " mul %A0,%2 \n\t" \ | |||
| " clr %A0 \n\t" \ | |||
| " add r0,%2 \n\t" \ | |||
| " adc %A0,r1 \n\t" \ | |||
| " mov %1,r0 \n\t" \ | |||
| " mul %B0,%2 \n\t" \ | |||
| " clr %B0 \n\t" \ | |||
| " add %A0,r0 \n\t" \ | |||
| " adc %B0,r1 \n\t" \ | |||
| " mul %C0,%2 \n\t" \ | |||
| " clr %C0 \n\t" \ | |||
| " add %B0,r0 \n\t" \ | |||
| " adc %C0,r1 \n\t" \ | |||
| " mul %D0,%2 \n\t" \ | |||
| " clr %D0 \n\t" \ | |||
| " add %C0,r0 \n\t" \ | |||
| " adc %D0,r1 \n\t" \ | |||
| " clr r1 \n\t" \ | |||
| " add %1,%A0 \n\t" \ | |||
| " adc %A0,%B0 \n\t" \ | |||
| " adc %B0,%C0 \n\t" \ | |||
| " adc %C0,%D0 \n\t" \ | |||
| " adc %D0,r1 \n\t" \ | |||
| " add %1,%B0 \n\t" \ | |||
| " adc %A0,%C0 \n\t" \ | |||
| " adc %B0,%D0 \n\t" \ | |||
| " adc %C0,r1 \n\t" \ | |||
| " adc %D0,r1 \n\t" \ | |||
| " add %1,%D0 \n\t" \ | |||
| " adc %A0,r1 \n\t" \ | |||
| " adc %B0,r1 \n\t" \ | |||
| " adc %C0,r1 \n\t" \ | |||
| " adc %D0,r1 \n\t" \ | |||
| " lsr %D0 \n\t" \ | |||
| " ror %C0 \n\t" \ | |||
| " ror %B0 \n\t" \ | |||
| " ror %A0 \n\t" \ | |||
| " ror %1 \n\t" \ | |||
| " ldi %2,10 \n\t" \ | |||
| " mul %1,%2 \n\t" \ | |||
| " mov %1,r1 \n\t" \ | |||
| " clr r1 \n\t" \ | |||
| :"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0") | |||
| #endif // USE_STIMMER_OPTIMIZATION | |||
| #ifdef USE_BENCHMARK_CODE | |||
| uint32_t usec_print = 0; | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| size_t Print::printNumberDec(unsigned long n, uint8_t sign) | |||
| #else | |||
| void Print::printNumberDec(unsigned long n, uint8_t sign) | |||
| #endif | |||
| { | |||
| uint8_t digit, buf[11], *p; | |||
| #if defined(USE_HACKER_DELIGHT_OPTIMIZATION) | |||
| uint32_t tmp32; | |||
| #elif defined(USE_STIMMER_OPTIMIZATION) | |||
| uint8_t tmp8; | |||
| #endif | |||
| #ifdef USE_BENCHMARK_CODE | |||
| uint32_t usec = micros(); | |||
| #endif | |||
| p = buf + (sizeof(buf)-1); | |||
| do { | |||
| #if defined(USE_HACKER_DELIGHT_OPTIMIZATION) | |||
| divmod10_asm(n, tmp32, digit); | |||
| #elif defined(USE_STIMMER_OPTIMIZATION) | |||
| divmod10_asm(n, digit, tmp8); | |||
| #else | |||
| tmp32 = n; | |||
| n = n / 10; | |||
| digit = tmp32 - n * 10; | |||
| #endif | |||
| *--p = digit + '0'; | |||
| } while (n); | |||
| if (sign) *--p = '-'; | |||
| #ifdef USE_BENCHMARK_CODE | |||
| usec_print += micros() - usec; | |||
| #endif | |||
| #if ARDUINO >= 100 | |||
| return write(p, sizeof(buf)-1 - (p - buf)); | |||
| #else | |||
| write(p, sizeof(buf)-1 - (p - buf)); | |||
| #endif | |||
| } | |||
| #if ARDUINO >= 100 | |||
| size_t Print::printNumberHex(unsigned long n) | |||
| #else | |||
| void Print::printNumberHex(unsigned long n) | |||
| #endif | |||
| { | |||
| uint8_t digit, buf[8], *p; | |||
| p = buf + (sizeof(buf)-1); | |||
| do { | |||
| digit = n & 15; | |||
| *--p = (digit < 10) ? '0' + digit : 'A' + digit - 10; | |||
| n >>= 4; | |||
| } while (n); | |||
| #if ARDUINO >= 100 | |||
| return write(p, sizeof(buf)-1 - (p - buf)); | |||
| #else | |||
| write(p, sizeof(buf)-1 - (p - buf)); | |||
| #endif | |||
| } | |||
| #if ARDUINO >= 100 | |||
| size_t Print::printNumberBin(unsigned long n) | |||
| #else | |||
| void Print::printNumberBin(unsigned long n) | |||
| #endif | |||
| { | |||
| uint8_t buf[32], *p; | |||
| p = buf + (sizeof(buf)-1); | |||
| do { | |||
| *--p = '0' + ((uint8_t)n & 1); | |||
| n >>= 1; | |||
| } while (n); | |||
| #if ARDUINO >= 100 | |||
| return write(p, sizeof(buf)-1 - (p - buf)); | |||
| #else | |||
| write(p, sizeof(buf)-1 - (p - buf)); | |||
| #endif | |||
| } | |||
| #if ARDUINO >= 100 | |||
| size_t Print::printNumberAny(unsigned long n, uint8_t base) | |||
| #else | |||
| void Print::printNumberAny(unsigned long n, uint8_t base) | |||
| #endif | |||
| { | |||
| uint8_t digit, buf[21], *p; | |||
| uint32_t tmp; | |||
| //uint32_t usec; | |||
| //usec = micros(); | |||
| p = buf + (sizeof(buf)-1); | |||
| do { | |||
| tmp = n; | |||
| n = n / base; | |||
| digit = tmp - n * base; | |||
| *--p = (digit < 10) ? '0' + digit : 'A' + digit - 10; | |||
| } while (n); | |||
| //usec_print += micros() - usec; | |||
| #if ARDUINO >= 100 | |||
| return write(p, sizeof(buf)-1 - (p - buf)); | |||
| #else | |||
| write(p, sizeof(buf)-1 - (p - buf)); | |||
| #endif | |||
| } | |||
| #if ARDUINO >= 100 | |||
| size_t Print::printFloat(double number, uint8_t digits) | |||
| #else | |||
| void Print::printFloat(double number, uint8_t digits) | |||
| #endif | |||
| { | |||
| uint8_t sign=0; | |||
| #if ARDUINO >= 100 | |||
| size_t count=0; | |||
| #endif | |||
| // Handle negative numbers | |||
| if (number < 0.0) { | |||
| sign = 1; | |||
| number = -number; | |||
| } | |||
| // Round correctly so that print(1.999, 2) prints as "2.00" | |||
| double rounding = 0.5; | |||
| for (uint8_t i=0; i<digits; ++i) { | |||
| rounding *= 0.1; | |||
| } | |||
| number += rounding; | |||
| // Extract the integer part of the number and print it | |||
| unsigned long int_part = (unsigned long)number; | |||
| double remainder = number - (double)int_part; | |||
| #if ARDUINO >= 100 | |||
| count += printNumber(int_part, sign, 10); | |||
| #else | |||
| printNumber(int_part, sign, 10); | |||
| #endif | |||
| // Print the decimal point, but only if there are digits beyond | |||
| if (digits > 0) { | |||
| uint8_t n, buf[8], count=1; | |||
| buf[0] = '.'; | |||
| // Extract digits from the remainder one at a time | |||
| if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1; | |||
| while (digits-- > 0) { | |||
| remainder *= 10.0; | |||
| n = (uint8_t)(remainder); | |||
| buf[count++] = '0' + n; | |||
| remainder -= n; | |||
| } | |||
| #if ARDUINO >= 100 | |||
| count += write(buf, count); | |||
| #else | |||
| write(buf, count); | |||
| #endif | |||
| } | |||
| #if ARDUINO >= 100 | |||
| return count; | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,167 @@ | |||
| /* | |||
| Print.h - Base class that provides print() and println() | |||
| Copyright (c) 2008 David A. Mellis. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef Print_h | |||
| #define Print_h | |||
| #include <inttypes.h> | |||
| #include <stdio.h> // for size_t | |||
| #include "core_id.h" | |||
| #include "WString.h" | |||
| #include "Printable.h" | |||
| #define DEC 10 | |||
| #define HEX 16 | |||
| #define OCT 8 | |||
| #define BIN 2 | |||
| #define BYTE 0 | |||
| class __FlashStringHelper; | |||
| #if ARDUINO >= 100 | |||
| class Print | |||
| { | |||
| public: | |||
| Print() : write_error(0) {} | |||
| virtual size_t write(uint8_t b); | |||
| size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } | |||
| virtual size_t write(const uint8_t *buffer, size_t size); | |||
| size_t print(const String &s); | |||
| size_t print(char c) { return write((uint8_t)c); } | |||
| size_t print(const char s[]) { return write(s); } | |||
| size_t print(const __FlashStringHelper *f); | |||
| size_t print(uint8_t b) { return printNumber(b, 0, 10); } | |||
| size_t print(int n) { return print((long)n); } | |||
| size_t print(unsigned int n) { return printNumber(n, 0, 10); } | |||
| size_t print(long n); | |||
| size_t print(unsigned long n) { return printNumber(n, 0, 10); } | |||
| size_t print(unsigned char n, int base) { return printNumber(n, 0, base); } | |||
| size_t print(int n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); } | |||
| size_t print(unsigned int n, int base) { return printNumber(n, 0, base); } | |||
| size_t print(long n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); } | |||
| size_t print(unsigned long n, int base) { return printNumber(n, 0, base); } | |||
| size_t print(double n, int digits = 2) { return printFloat(n, digits); } | |||
| size_t print(const Printable &obj) { return obj.printTo(*this); } | |||
| size_t println(void); | |||
| size_t println(const String &s) { return print(s) + println(); } | |||
| size_t println(char c) { return print(c) + println(); } | |||
| size_t println(const char s[]) { return print(s) + println(); } | |||
| size_t println(const __FlashStringHelper *f) { return print(f) + println(); } | |||
| size_t println(uint8_t b) { return print(b) + println(); } | |||
| size_t println(int n) { return print(n) + println(); } | |||
| size_t println(unsigned int n) { return print(n) + println(); } | |||
| size_t println(long n) { return print(n) + println(); } | |||
| size_t println(unsigned long n) { return print(n) + println(); } | |||
| size_t println(unsigned char n, int base) { return print(n, base) + println(); } | |||
| size_t println(int n, int base) { return print(n, base) + println(); } | |||
| size_t println(unsigned int n, int base) { return print(n, base) + println(); } | |||
| size_t println(long n, int base) { return print(n, base) + println(); } | |||
| size_t println(unsigned long n, int base) { return print(n, base) + println(); } | |||
| size_t println(double n, int digits = 2) { return print(n, digits) + println(); } | |||
| size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } | |||
| int getWriteError() { return write_error; } | |||
| void clearWriteError() { setWriteError(0); } | |||
| protected: | |||
| void setWriteError(int err = 1) { write_error = err; } | |||
| private: | |||
| char write_error; | |||
| size_t printNumberDec(unsigned long n, uint8_t sign); | |||
| size_t printNumberHex(unsigned long n); | |||
| size_t printNumberBin(unsigned long n); | |||
| size_t printNumberAny(unsigned long n, uint8_t base); | |||
| inline size_t printNumber(unsigned long n, uint8_t sign, uint8_t base) __attribute__((always_inline)) { | |||
| // when "base" is a constant (pretty much always), the | |||
| // compiler optimizes this to a single function call. | |||
| if (base == 0) return write((uint8_t)n); | |||
| if (base == 10 || base < 2) return printNumberDec(n, sign); | |||
| //if (base == 10 || base < 2) return printNumberAny(n, 10); // testing only | |||
| if (base == 16) return printNumberHex(n); | |||
| if (base == 2) return printNumberBin(n); | |||
| return printNumberAny(n, base); | |||
| } | |||
| size_t printFloat(double n, uint8_t digits); | |||
| }; | |||
| #else | |||
| class Print | |||
| { | |||
| public: | |||
| virtual void write(uint8_t); | |||
| virtual void write(const char *str); | |||
| virtual void write(const uint8_t *buffer, size_t size); | |||
| void print(const String &s); | |||
| void print(char c) { write((uint8_t)c); } | |||
| void print(const char s[]) { write(s); } | |||
| void print(const __FlashStringHelper *f); | |||
| void print(uint8_t b) { write(b); } | |||
| void print(int n) { print((long)n); } | |||
| void print(unsigned int n) { printNumber(n, 0, 10); } | |||
| void print(long n); | |||
| void print(unsigned long n) { printNumber(n, 0, 10); } | |||
| void print(unsigned char n, int base) { printNumber(n, 0, base); } | |||
| void print(int n, int base) { (base == 10) ? print(n) : printNumber(n, 0, base); } | |||
| void print(unsigned int n, int base) { printNumber(n, 0, base); } | |||
| void print(long n, int base) { (base == 10) ? print(n) : printNumber(n, 0, base); } | |||
| void print(unsigned long n, int base) { printNumber(n, 0, base); } | |||
| void print(double n, int digits = 2) { printFloat(n, digits); } | |||
| void println(void); | |||
| void println(const String &s) { print(s); println(); } | |||
| void println(char c) { print(c); println(); } | |||
| void println(const char s[]) { print(s); println(); } | |||
| void println(const __FlashStringHelper *f) { print(f); println(); } | |||
| void println(uint8_t b) { print(b); println(); } | |||
| void println(int n) { print(n); println(); } | |||
| void println(unsigned int n) { print(n); println(); } | |||
| void println(long n) { print(n); println(); } | |||
| void println(unsigned long n) { print(n); println(); } | |||
| void println(unsigned char n, int base) { print(n, base); println(); } | |||
| void println(int n, int base) { print(n, base); println(); } | |||
| void println(unsigned int n, int base) { print(n, base); println(); } | |||
| void println(long n, int base) { print(n, base); println(); } | |||
| void println(unsigned long n, int base) { print(n, base); println(); } | |||
| void println(double n, int digits = 2) { print(n, digits); println(); } | |||
| private: | |||
| void printNumberDec(unsigned long n, uint8_t sign); | |||
| void printNumberHex(unsigned long n); | |||
| void printNumberBin(unsigned long n); | |||
| void printNumberAny(unsigned long n, uint8_t base); | |||
| inline size_t printNumber(unsigned long n, uint8_t sign, uint8_t base) __attribute__((always_inline)) { | |||
| if (base == 0) { write((uint8_t)n); return; } | |||
| if (base == 10 || base < 2) { printNumberDec(n, sign); return; } | |||
| if (base == 16) { printNumberHex(n); return; } | |||
| if (base == 2) { printNumberBin(n); return; } | |||
| printNumberAny(n, base); | |||
| } | |||
| void printFloat(double n, uint8_t digits); | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -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 | |||
| */ | |||
| #if ARDUINO >= 100 | |||
| #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 | |||
| #endif | |||
| @@ -0,0 +1,12 @@ | |||
| #if ARDUINO >= 100 | |||
| #ifndef server_h | |||
| #define server_h | |||
| class Server : public Print { | |||
| public: | |||
| virtual void begin() =0; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,310 @@ | |||
| /* | |||
| Stream.cpp - adds parsing methods to Stream class | |||
| Copyright (c) 2008 David A. Mellis. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| Created July 2011 | |||
| parsing functions based on TextFinder library by Michael Margolis | |||
| */ | |||
| #include "Arduino.h" | |||
| #include "Stream.h" | |||
| #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait | |||
| #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field | |||
| // private method to read stream with timeout | |||
| int Stream::timedRead() | |||
| { | |||
| int c; | |||
| unsigned long startMillis = millis(); | |||
| do { | |||
| c = read(); | |||
| if (c >= 0) return c; | |||
| } while(millis() - startMillis < _timeout); | |||
| return -1; // -1 indicates timeout | |||
| } | |||
| // private method to peek stream with timeout | |||
| int Stream::timedPeek() | |||
| { | |||
| int c; | |||
| unsigned long startMillis = millis(); | |||
| do { | |||
| c = peek(); | |||
| if (c >= 0) return c; | |||
| } while(millis() - startMillis < _timeout); | |||
| return -1; // -1 indicates timeout | |||
| } | |||
| // returns peek of the next digit in the stream or -1 if timeout | |||
| // discards non-numeric characters | |||
| int Stream::peekNextDigit() | |||
| { | |||
| int c; | |||
| while (1) { | |||
| c = timedPeek(); | |||
| if (c < 0) return c; // timeout | |||
| if (c == '-') return c; | |||
| if (c >= '0' && c <= '9') return c; | |||
| read(); // discard non-numeric | |||
| } | |||
| } | |||
| // Public Methods | |||
| ////////////////////////////////////////////////////////////// | |||
| void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait | |||
| { | |||
| _timeout = timeout; | |||
| } | |||
| // find returns true if the target string is found | |||
| bool Stream::find(char *target) | |||
| { | |||
| return findUntil(target, NULL); | |||
| } | |||
| // reads data from the stream until the target string of given length is found | |||
| // returns true if target string is found, false if timed out | |||
| bool Stream::find(char *target, size_t length) | |||
| { | |||
| return findUntil(target, length, NULL, 0); | |||
| } | |||
| // as find but search ends if the terminator string is found | |||
| bool Stream::findUntil(char *target, char *terminator) | |||
| { | |||
| return findUntil(target, strlen(target), terminator, strlen(terminator)); | |||
| } | |||
| // reads data from the stream until the target string of the given length is found | |||
| // search terminated if the terminator string is found | |||
| // returns true if target string is found, false if terminated or timed out | |||
| bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) | |||
| { | |||
| size_t index = 0; // maximum target string length is 64k bytes! | |||
| size_t termIndex = 0; | |||
| int c; | |||
| if( *target == 0) | |||
| return true; // return true if target is a null string | |||
| while( (c = timedRead()) > 0){ | |||
| if( c == target[index]){ | |||
| //////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 = peekNextDigit(); | |||
| // ignore non numeric leading characters | |||
| if(c < 0) | |||
| return 0; // zero returned if timeout | |||
| do{ | |||
| if(c == skipChar) | |||
| ; // ignore this charactor | |||
| else if(c == '-') | |||
| isNegative = true; | |||
| else if(c >= '0' && c <= '9') // is c a digit? | |||
| value = value * 10 + c - '0'; | |||
| read(); // consume the character we got with peek | |||
| c = timedPeek(); | |||
| } | |||
| while( (c >= '0' && c <= '9') || c == skipChar ); | |||
| if(isNegative) | |||
| value = -value; | |||
| return value; | |||
| } | |||
| // as parseInt but returns a floating point value | |||
| float Stream::parseFloat() | |||
| { | |||
| return parseFloat(NO_SKIP_CHAR); | |||
| } | |||
| // as above but the given skipChar is ignored | |||
| // this allows format characters (typically commas) in values to be ignored | |||
| float Stream::parseFloat(char skipChar){ | |||
| boolean isNegative = false; | |||
| boolean isFraction = false; | |||
| long value = 0; | |||
| char c; | |||
| float fraction = 1.0; | |||
| c = peekNextDigit(); | |||
| // ignore non numeric leading characters | |||
| if(c < 0) | |||
| return 0; // zero returned if timeout | |||
| do{ | |||
| if(c == skipChar) | |||
| ; // ignore | |||
| else if(c == '-') | |||
| isNegative = true; | |||
| else if (c == '.') | |||
| isFraction = true; | |||
| else if(c >= '0' && c <= '9') { // is c a digit? | |||
| value = value * 10 + c - '0'; | |||
| if(isFraction) | |||
| fraction *= 0.1; | |||
| } | |||
| read(); // consume the character we got with peek | |||
| c = timedPeek(); | |||
| } | |||
| while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); | |||
| if(isNegative) | |||
| value = -value; | |||
| if(isFraction) | |||
| return value * fraction; | |||
| else | |||
| return value; | |||
| } | |||
| // read characters from stream into buffer | |||
| // terminates if length characters have been read, or timeout (see setTimeout) | |||
| // returns the number of characters placed in the buffer | |||
| // the buffer is NOT null terminated. | |||
| // | |||
| size_t Stream::readBytes(char *buffer, size_t length) | |||
| { | |||
| size_t count = 0; | |||
| while (count < length) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; | |||
| } | |||
| *buffer++ = (char)c; | |||
| count++; | |||
| } | |||
| return count; | |||
| } | |||
| // as readBytes with terminator character | |||
| // terminates if length characters have been read, timeout, or if the terminator character detected | |||
| // returns the number of characters placed in the buffer (0 means no valid data found) | |||
| size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) | |||
| { | |||
| if (length < 1) return 0; | |||
| length--; | |||
| size_t index = 0; | |||
| while (index < length) { | |||
| int c = timedRead(); | |||
| if (c == terminator) break; | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; | |||
| } | |||
| *buffer++ = (char)c; | |||
| index++; | |||
| } | |||
| *buffer = 0; | |||
| return index; // return number of characters, not including null terminator | |||
| } | |||
| String Stream::readString(size_t max) | |||
| { | |||
| String str; | |||
| size_t length = str.length(); | |||
| while (length < max) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; // timeout | |||
| } | |||
| if (c == 0) break; | |||
| str += (char)c; | |||
| } | |||
| return str; | |||
| } | |||
| String Stream::readStringUntil(char terminator, size_t max) | |||
| { | |||
| String str; | |||
| size_t length = str.length(); | |||
| while (length < max) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; // timeout | |||
| } | |||
| if (c == 0 || c == terminator) break; | |||
| str += (char)c; | |||
| } | |||
| return str; | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| Stream.h - base class for character-based streams. | |||
| Copyright (c) 2010 David A. Mellis. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef Stream_h | |||
| #define Stream_h | |||
| #include <inttypes.h> | |||
| #include "Print.h" | |||
| class Stream : public Print | |||
| { | |||
| public: | |||
| Stream() : _timeout(1000), read_error(0) {} | |||
| virtual int available() = 0; | |||
| virtual int read() = 0; | |||
| virtual int peek() = 0; | |||
| virtual void flush() = 0; | |||
| void setTimeout(unsigned long timeout); | |||
| bool find(char *target); | |||
| bool find(char *target, size_t length); | |||
| bool findUntil(char *target, char *terminator); | |||
| bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); | |||
| long parseInt(); | |||
| long parseInt(char skipChar); | |||
| float parseFloat(); | |||
| float parseFloat(char skipChar); | |||
| size_t readBytes(char *buffer, size_t length); | |||
| size_t readBytesUntil(char terminator, char *buffer, size_t length); | |||
| String readString(size_t max = 120); | |||
| String readStringUntil(char terminator, size_t max = 120); | |||
| int getReadError() { return read_error; } | |||
| void clearReadError() { setReadError(0); } | |||
| protected: | |||
| void setReadError(int err = 1) { read_error = err; } | |||
| unsigned long _timeout; | |||
| private: | |||
| char read_error; | |||
| int timedRead(); | |||
| int timedPeek(); | |||
| int peekNextDigit(); | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,269 @@ | |||
| /* Tone generation for the Teensy and Teensy++ | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2010 PJRC.COM, LLC | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| #include <avr/interrupt.h> | |||
| #include "wiring.h" | |||
| #include "core_pins.h" | |||
| #include "pins_arduino.h" | |||
| static uint8_t timer_acquired = 0; | |||
| static uint8_t *tone1_reg = (uint8_t *)0; | |||
| static uint8_t tone1_mask = 0; | |||
| static uint16_t tone1_inc = 0; | |||
| static uint32_t tone1_count = 0; | |||
| static uint8_t *tone2_reg = (uint8_t *)0; | |||
| static uint8_t tone2_mask = 0; | |||
| static uint16_t tone2_inc = 0; | |||
| static uint32_t tone2_count = 0; | |||
| static uint8_t *tone3_reg = (uint8_t *)0; | |||
| static uint8_t tone3_mask = 0; | |||
| static uint16_t tone3_inc = 0; | |||
| static uint32_t tone3_count = 0; | |||
| #define MAX_FREQ (F_CPU / 16 / 25) | |||
| #define MIN_FREQ (F_CPU / 16 / 65535 + 1) | |||
| #define PIN_REG_AND_MASK_LOOKUP(pin, reg, mask) \ | |||
| asm volatile( \ | |||
| "lsl %2" "\n\t" \ | |||
| "add %A3, %2" "\n\t" \ | |||
| "adc %B3, __zero_reg__" "\n\n" \ | |||
| "lpm %1, Z+" "\n\t" \ | |||
| "lpm %A0, Z" "\n\t" \ | |||
| "ldi %B0, 0" "\n" \ | |||
| : "=z" (reg), "=r" (mask), "+r" (pin) \ | |||
| : "z" (digital_pin_table_PGM), "2" (pin)) | |||
| #if defined(__AVR_ATmega32U4__) | |||
| //#define TONE_USE_TIMER1 | |||
| #define TONE_USE_TIMER3 | |||
| #elif defined(__AVR_AT90USB1286__) | |||
| //#define TONE_USE_TIMER1 | |||
| #define TONE_USE_TIMER3 | |||
| #elif defined(__AVR_AT90USB162__) | |||
| #define TONE_USE_TIMER1 | |||
| #elif defined(__AVR_AT90USB646__) | |||
| //#define TONE_USE_TIMER1 | |||
| #define TONE_USE_TIMER3 | |||
| #endif | |||
| #ifdef TONE_USE_TIMER3 | |||
| #define TIMSKx TIMSK3 | |||
| #define OCIExA OCIE3A | |||
| #define OCIExB OCIE3B | |||
| #define OCIExC OCIE3C | |||
| #define TCCRxA TCCR3A | |||
| #define WGMx0 WGM30 | |||
| #define TCCRxB TCCR3B | |||
| #define CSx1 CS31 | |||
| #define TCNTx TCNT3 | |||
| #define OCRxA OCR3A | |||
| #define OCRxB OCR3B | |||
| #define OCRxC OCR3C | |||
| #define TIFRx TIFR3 | |||
| #define OCFxA OCF3A | |||
| #define OCFxB OCF3B | |||
| #define OCFxC OCF3C | |||
| #define VECTxA TIMER3_COMPA_vect | |||
| #define VECTxB TIMER3_COMPB_vect | |||
| #define VECTxC TIMER3_COMPC_vect | |||
| #endif | |||
| #ifdef TONE_USE_TIMER1 | |||
| #define TIMSKx TIMSK1 | |||
| #define OCIExA OCIE1A | |||
| #define OCIExB OCIE1B | |||
| #define OCIExC OCIE1C | |||
| #define TCCRxA TCCR1A | |||
| #define WGMx0 WGM10 | |||
| #define TCCRxB TCCR1B | |||
| #define CSx1 CS11 | |||
| #define TCNTx TCNT1 | |||
| #define OCRxA OCR1A | |||
| #define OCRxB OCR1B | |||
| #define OCRxC OCR1C | |||
| #define TIFRx TIFR1 | |||
| #define OCFxA OCF1A | |||
| #define OCFxB OCF1B | |||
| #define OCFxC OCF1C | |||
| #define VECTxA TIMER1_COMPA_vect | |||
| #define VECTxB TIMER1_COMPB_vect | |||
| #define VECTxC TIMER1_COMPC_vect | |||
| #endif | |||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration) | |||
| { | |||
| uint8_t *reg; | |||
| uint8_t mask; | |||
| uint16_t inc; | |||
| uint32_t count; | |||
| if (pin >= CORE_NUM_TOTAL_PINS) return; | |||
| if (frequency < MIN_FREQ) { | |||
| frequency = MIN_FREQ; | |||
| } else if (frequency > MAX_FREQ) { | |||
| frequency = MAX_FREQ; | |||
| } | |||
| inc = (F_CPU / 16 + frequency / 2) / frequency; | |||
| if (duration) { | |||
| count = duration * frequency / 500; | |||
| } else { | |||
| count = 0; | |||
| } | |||
| if (!timer_acquired) { | |||
| TIMSKx = 0; // disable all interrupts | |||
| TCCRxA = 0; | |||
| TCCRxB = (1<<CSx1); // normal mode, div8 prescale | |||
| timer_acquired = 1; | |||
| } | |||
| PIN_REG_AND_MASK_LOOKUP(pin, reg, mask); | |||
| if (!tone1_mask || (tone1_mask == mask && tone1_reg == reg)) { | |||
| TIMSKx &= ~(1<<OCIExA); // disable compare interrupt | |||
| tone1_reg = reg; | |||
| tone1_mask = mask; | |||
| tone1_count = count; | |||
| tone1_inc = inc; | |||
| cli(); | |||
| *(reg + 2) &= ~mask; // clear pin | |||
| *(reg + 1) |= mask; // output mode | |||
| OCRxA = TCNTx + inc; | |||
| TIFRx |= (1<<OCFxA); // clear any pending compare match | |||
| sei(); | |||
| TIMSKx |= (1<<OCIExA); // enable compare interrupt | |||
| return; | |||
| } | |||
| if (!tone2_mask || (tone2_mask == mask && tone2_reg == reg)) { | |||
| TIMSKx &= ~(1<<OCIExB); // disable compare interrupt | |||
| tone2_reg = reg; | |||
| tone2_mask = mask; | |||
| tone2_count = count; | |||
| tone2_inc = inc; | |||
| cli(); | |||
| *(reg + 2) &= ~mask; // clear pin | |||
| *(reg + 1) |= mask; // output mode | |||
| OCRxB = TCNTx + inc; | |||
| TIFRx |= (1<<OCFxB); // clear any pending compare match | |||
| sei(); | |||
| TIMSKx |= (1<<OCIExB); // enable compare interrupt | |||
| return; | |||
| } | |||
| if (!tone3_mask || (tone3_mask == mask && tone3_reg == reg)) { | |||
| TIMSKx &= ~(1<<OCIExC); // disable compare interrupt | |||
| tone3_reg = reg; | |||
| tone3_mask = mask; | |||
| tone3_count = count; | |||
| tone3_inc = inc; | |||
| cli(); | |||
| *(reg + 2) &= ~mask; // clear pin | |||
| *(reg + 1) |= mask; // output mode | |||
| OCRxC = TCNTx + inc; | |||
| TIFRx |= (1<<OCFxC); // clear any pending compare match | |||
| sei(); | |||
| TIMSKx |= (1<<OCIExC); // enable compare interrupt | |||
| return; | |||
| } | |||
| } | |||
| void noTone(uint8_t pin) | |||
| { | |||
| uint8_t *reg; | |||
| uint8_t mask; | |||
| if (pin >= CORE_NUM_TOTAL_PINS) return; | |||
| PIN_REG_AND_MASK_LOOKUP(pin, reg, mask); | |||
| if (tone1_mask == mask && tone1_reg == reg) { | |||
| TIMSKx &= ~(1<<OCIExA); | |||
| tone1_mask = 0; | |||
| } else if (tone2_mask == mask && tone2_reg == reg) { | |||
| TIMSKx &= ~(1<<OCIExB); | |||
| tone2_mask = 0; | |||
| } else if (tone3_mask == mask && tone3_reg == reg) { | |||
| TIMSKx &= ~(1<<OCIExC); | |||
| tone3_mask = 0; | |||
| } | |||
| if (!tone1_mask && !tone2_mask && !tone3_mask) { | |||
| TCCRxA = (1<<WGMx0); // restore timer | |||
| timer_acquired = 0; | |||
| } | |||
| } | |||
| ISR(VECTxA) | |||
| { | |||
| OCRxA += tone1_inc; | |||
| *(tone1_reg) = tone1_mask; | |||
| if (tone1_count > 0) { | |||
| if ((--tone1_count) == 0) { | |||
| *(tone1_reg + 2) &= ~tone1_mask; | |||
| TIMSKx &= ~(1<<OCIExA); | |||
| tone1_mask = 0; | |||
| if (!tone2_mask && !tone3_mask) { | |||
| TCCRxA = (1<<WGMx0); | |||
| timer_acquired = 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| ISR(VECTxB) | |||
| { | |||
| OCRxB += tone2_inc; | |||
| *(tone2_reg) = tone2_mask; | |||
| if (tone2_count > 0) { | |||
| if ((--tone2_count) == 0) { | |||
| *(tone2_reg + 2) &= ~tone2_mask; | |||
| TIMSKx &= ~(1<<OCIExB); | |||
| tone2_mask = 0; | |||
| if (!tone1_mask && !tone3_mask) { | |||
| TCCRxA = (1<<WGMx0); | |||
| timer_acquired = 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| ISR(VECTxC) | |||
| { | |||
| OCRxC += tone3_inc; | |||
| *(tone3_reg) = tone3_mask; | |||
| if (tone3_count > 0) { | |||
| if ((--tone3_count) == 0) { | |||
| *(tone3_reg + 2) &= ~tone3_mask; | |||
| TIMSKx &= ~(1<<OCIExC); | |||
| tone3_mask = 0; | |||
| if (!tone1_mask && !tone2_mask) { | |||
| TCCRxA = (1<<WGMx0); | |||
| timer_acquired = 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,91 @@ | |||
| /* | |||
| * Udp.cpp: Library to send/receive UDP packets. | |||
| * | |||
| * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) | |||
| * 1) UDP does not guarantee the order in which assembled UDP packets are received. This | |||
| * might not happen often in practice, but in larger network topologies, a UDP | |||
| * packet can be received out of sequence. | |||
| * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being | |||
| * aware of it. Again, this may not be a concern in practice on small local networks. | |||
| * For more information, see http://www.cafeaulait.org/course/week12/35.html | |||
| * | |||
| * MIT License: | |||
| * Copyright (c) 2008 Bjoern Hartmann | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| * | |||
| * bjoern@cs.stanford.edu 12/30/2008 | |||
| */ | |||
| #if ARDUINO >= 100 | |||
| #ifndef udp_h | |||
| #define udp_h | |||
| #include <Stream.h> | |||
| #include <IPAddress.h> | |||
| class UDP : public Stream { | |||
| public: | |||
| virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use | |||
| virtual void stop() =0; // Finish with the UDP socket | |||
| // Sending UDP packets | |||
| // Start building up a packet to send to the remote host specific in ip and port | |||
| // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port | |||
| virtual int beginPacket(IPAddress ip, uint16_t port) =0; | |||
| // Start building up a packet to send to the remote host specific in host and port | |||
| // Returns 1 if successful, 0 if there was a problem resolving the hostname or port | |||
| virtual int beginPacket(const char *host, uint16_t port) =0; | |||
| // Finish off this packet and send it | |||
| // Returns 1 if the packet was sent successfully, 0 if there was an error | |||
| virtual int endPacket() =0; | |||
| // Write a single byte into the packet | |||
| virtual size_t write(uint8_t) =0; | |||
| // Write size bytes from buffer into the packet | |||
| virtual size_t write(const uint8_t *buffer, size_t size) =0; | |||
| // Start processing the next available incoming packet | |||
| // Returns the size of the packet in bytes, or 0 if no packets are available | |||
| virtual int parsePacket() =0; | |||
| // Number of bytes remaining in the current packet | |||
| virtual int available() =0; | |||
| // Read a single byte from the current packet | |||
| virtual int read() =0; | |||
| // Read up to len bytes from the current packet and place them into buffer | |||
| // Returns the number of bytes read, or 0 if none are available | |||
| virtual int read(unsigned char* buffer, size_t len) =0; | |||
| // Read up to len characters from the current packet and place them into buffer | |||
| // Returns the number of characters read, or 0 if none are available | |||
| virtual int read(char* buffer, size_t len) =0; | |||
| // Return the next byte from the current packet without moving on to the next byte | |||
| virtual int peek() =0; | |||
| virtual void flush() =0; // Finish reading the current packet | |||
| // Return the IP address of the host who sent the current incoming packet | |||
| virtual IPAddress remoteIP() =0; | |||
| // Return the port of the host who sent the current incoming packet | |||
| virtual uint16_t remotePort() =0; | |||
| protected: | |||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,168 @@ | |||
| /* | |||
| WCharacter.h - Character utility functions for Wiring & Arduino | |||
| Copyright (c) 2010 Hernando Barragan. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef Character_h | |||
| #define Character_h | |||
| #include <ctype.h> | |||
| // WCharacter.h prototypes | |||
| inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); | |||
| inline boolean isAlpha(int c) __attribute__((always_inline)); | |||
| inline boolean isAscii(int c) __attribute__((always_inline)); | |||
| inline boolean isWhitespace(int c) __attribute__((always_inline)); | |||
| inline boolean isControl(int c) __attribute__((always_inline)); | |||
| inline boolean isDigit(int c) __attribute__((always_inline)); | |||
| inline boolean isGraph(int c) __attribute__((always_inline)); | |||
| inline boolean isLowerCase(int c) __attribute__((always_inline)); | |||
| inline boolean isPrintable(int c) __attribute__((always_inline)); | |||
| inline boolean isPunct(int c) __attribute__((always_inline)); | |||
| inline boolean isSpace(int c) __attribute__((always_inline)); | |||
| inline boolean isUpperCase(int c) __attribute__((always_inline)); | |||
| inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); | |||
| inline int toAscii(int c) __attribute__((always_inline)); | |||
| inline int toLowerCase(int c) __attribute__((always_inline)); | |||
| inline int toUpperCase(int c)__attribute__((always_inline)); | |||
| // Checks for an alphanumeric character. | |||
| // It is equivalent to (isalpha(c) || isdigit(c)). | |||
| inline boolean isAlphaNumeric(int c) | |||
| { | |||
| return ( isalnum(c) == 0 ? false : true); | |||
| } | |||
| // Checks for an alphabetic character. | |||
| // It is equivalent to (isupper(c) || islower(c)). | |||
| inline boolean isAlpha(int c) | |||
| { | |||
| return ( isalpha(c) == 0 ? false : true); | |||
| } | |||
| // Checks whether c is a 7-bit unsigned char value | |||
| // that fits into the ASCII character set. | |||
| inline boolean isAscii(int c) | |||
| { | |||
| return ( isascii (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a blank character, that is, a space or a tab. | |||
| inline boolean isWhitespace(int c) | |||
| { | |||
| return ( isblank (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a control character. | |||
| inline boolean isControl(int c) | |||
| { | |||
| return ( iscntrl (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a digit (0 through 9). | |||
| inline boolean isDigit(int c) | |||
| { | |||
| return ( isdigit (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character except space. | |||
| inline boolean isGraph(int c) | |||
| { | |||
| return ( isgraph (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a lower-case character. | |||
| inline boolean isLowerCase(int c) | |||
| { | |||
| return (islower (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character including space. | |||
| inline boolean isPrintable(int c) | |||
| { | |||
| return ( isprint (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character which is not a space | |||
| // or an alphanumeric character. | |||
| inline boolean isPunct(int c) | |||
| { | |||
| return ( ispunct (c) == 0 ? false : true); | |||
| } | |||
| // Checks for white-space characters. For the avr-libc library, | |||
| // these are: space, formfeed ('\f'), newline ('\n'), carriage | |||
| // return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). | |||
| inline boolean isSpace(int c) | |||
| { | |||
| return ( isspace (c) == 0 ? false : true); | |||
| } | |||
| // Checks for an uppercase letter. | |||
| inline boolean isUpperCase(int c) | |||
| { | |||
| return ( isupper (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 | |||
| // 8 9 a b c d e f A B C D E F. | |||
| inline boolean isHexadecimalDigit(int c) | |||
| { | |||
| return ( isxdigit (c) == 0 ? false : true); | |||
| } | |||
| // Converts c to a 7-bit unsigned char value that fits into the | |||
| // ASCII character set, by clearing the high-order bits. | |||
| inline int toAscii(int c) | |||
| { | |||
| return toascii (c); | |||
| } | |||
| // Warning: | |||
| // Many people will be unhappy if you use this function. | |||
| // This function will convert accented letters into random | |||
| // characters. | |||
| // Converts the letter c to lower case, if possible. | |||
| inline int toLowerCase(int c) | |||
| { | |||
| return tolower (c); | |||
| } | |||
| // Converts the letter c to upper case, if possible. | |||
| inline int toUpperCase(int c) | |||
| { | |||
| return toupper (c); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1 @@ | |||
| #include "wiring.h" | |||
| @@ -0,0 +1,132 @@ | |||
| /* Interrupt functions for the Teensy and Teensy++ | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2008-2010 PJRC.COM, LLC | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| #include <avr/io.h> | |||
| #include <avr/interrupt.h> | |||
| #include <avr/pgmspace.h> | |||
| #include <stdint.h> | |||
| #include "wiring.h" | |||
| #include "wiring_private.h" | |||
| #if defined(__AVR_ATmega32U4__) | |||
| #define NUM_INTERRUPT 4 | |||
| #else | |||
| #define NUM_INTERRUPT 8 | |||
| #endif | |||
| volatile static voidFuncPtr intFunc[NUM_INTERRUPT]; | |||
| static const uint8_t PROGMEM interrupt_mode_mask[] = {0xFC, 0xF3, 0xCF, 0x3F}; | |||
| static uint8_t pin2int(uint8_t pin) | |||
| { | |||
| switch (pin) { | |||
| case CORE_INT0_PIN: return 0; | |||
| case CORE_INT1_PIN: return 1; | |||
| case CORE_INT2_PIN: return 2; | |||
| case CORE_INT3_PIN: return 3; | |||
| #if !defined(__AVR_ATmega32U4__) | |||
| case CORE_INT4_PIN: return 4; | |||
| case CORE_INT5_PIN: return 5; | |||
| case CORE_INT6_PIN: return 6; | |||
| case CORE_INT7_PIN: return 7; | |||
| #endif | |||
| default: return 255; | |||
| } | |||
| } | |||
| #if defined(__AVR_ATmega32U4__) | |||
| void attachInterrupt(uint8_t inum, void (*userFunc)(void), uint8_t mode) | |||
| { | |||
| uint8_t mask; | |||
| if (inum >= NUM_INTERRUPT) { | |||
| inum = pin2int(inum); | |||
| if (inum >= NUM_INTERRUPT) return; | |||
| } | |||
| intFunc[inum] = userFunc; | |||
| mask = pgm_read_byte(interrupt_mode_mask + inum); | |||
| mode &= 0x03; | |||
| EICRA = (EICRA & mask) | (mode << (inum * 2)); | |||
| EIMSK |= (1 << inum); | |||
| } | |||
| #else | |||
| void attachInterrupt(uint8_t inum, void (*userFunc)(void), uint8_t mode) | |||
| { | |||
| uint8_t mask, index; | |||
| if (inum >= NUM_INTERRUPT) { | |||
| inum = pin2int(inum); | |||
| if (inum >= NUM_INTERRUPT) return; | |||
| } | |||
| intFunc[inum] = userFunc; | |||
| index = inum & 3; | |||
| mask = pgm_read_byte(interrupt_mode_mask + index); | |||
| mode &= 0x03; | |||
| if (inum & 4) { | |||
| EICRB = (EICRB & mask) | (mode << (index * 2)); | |||
| } else { | |||
| EICRA = (EICRA & mask) | (mode << (index * 2)); | |||
| } | |||
| EIMSK |= (1 << inum); | |||
| } | |||
| #endif | |||
| void detachInterrupt(uint8_t inum) | |||
| { | |||
| if (inum >= NUM_INTERRUPT) { | |||
| inum = pin2int(inum); | |||
| if (inum >= NUM_INTERRUPT) return; | |||
| } | |||
| EIMSK &= ~(1 << inum); | |||
| intFunc[inum] = 0; | |||
| } | |||
| SIGNAL(INT0_vect) { | |||
| if (intFunc[0]) intFunc[0](); // INT0 is pin 0 (PD0) | |||
| } | |||
| SIGNAL(INT1_vect) { | |||
| if (intFunc[1]) intFunc[1](); // INT1 is pin 1 (PD1) | |||
| } | |||
| SIGNAL(INT2_vect) { | |||
| if (intFunc[2]) intFunc[2](); // INT2 is pin 2 (PD2) (also Serial RX) | |||
| } | |||
| SIGNAL(INT3_vect) { | |||
| if (intFunc[3]) intFunc[3](); // INT3 is pin 3 (PD3) (also Serial TX) | |||
| } | |||
| #if !defined(__AVR_ATmega32U4__) | |||
| SIGNAL(INT4_vect) { | |||
| if (intFunc[4]) intFunc[4](); // INT4 is pin 20 (PC7) | |||
| } | |||
| SIGNAL(INT5_vect) { | |||
| if (intFunc[5]) intFunc[5](); // INT5 is pin 4 (PD4) | |||
| } | |||
| SIGNAL(INT6_vect) { | |||
| if (intFunc[6]) intFunc[6](); // INT6 is pin 6 (PD6) | |||
| } | |||
| SIGNAL(INT7_vect) { | |||
| if (intFunc[7]) intFunc[7](); // INT7 is pin 7 (PD7) | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,60 @@ | |||
| /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ | |||
| /* | |||
| Part of the Wiring project - http://wiring.org.co | |||
| Copyright (c) 2004-06 Hernando Barragan | |||
| Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ | |||
| 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$ | |||
| */ | |||
| extern "C" { | |||
| #include "stdlib.h" | |||
| } | |||
| void randomSeed(unsigned int seed) | |||
| { | |||
| if (seed != 0) { | |||
| srandom(seed); | |||
| } | |||
| } | |||
| long random(long howbig) | |||
| { | |||
| if (howbig == 0) { | |||
| return 0; | |||
| } | |||
| return random() % howbig; | |||
| } | |||
| long random(long howsmall, long howbig) | |||
| { | |||
| if (howsmall >= howbig) { | |||
| return howsmall; | |||
| } | |||
| long diff = howbig - howsmall; | |||
| return random(diff) + howsmall; | |||
| } | |||
| long map(long x, long in_min, long in_max, long out_min, long out_max) | |||
| { | |||
| return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | |||
| } | |||
| unsigned int makeWord(unsigned int w) { return w; } | |||
| unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } | |||
| @@ -0,0 +1,48 @@ | |||
| #ifndef WProgram_h | |||
| #define WProgram_h | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| #ifdef GCC_VERSION | |||
| #if (GCC_VERSION < 40300) | |||
| #warning "Your avr-gcc and avr-libc are too old, please upgrade" | |||
| #endif | |||
| #if (GCC_VERSION >= 40300) && (GCC_VERSION < 40302) | |||
| // gcc 4.3.0 fails to save context for some interrupt routines - very ugly | |||
| #warning "Buggy GCC 4.3.0 compiler, please upgrade!" | |||
| #endif | |||
| #endif | |||
| #include <avr/interrupt.h> | |||
| #include "wiring.h" | |||
| #ifdef __cplusplus | |||
| #include "usb_api.h" | |||
| #include "WCharacter.h" | |||
| #include "WString.h" | |||
| #include "HardwareSerial.h" | |||
| #include "elapsedMillis.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, uint16_t frequency, uint32_t 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); | |||
| #include "pins_arduino.h" | |||
| #endif // __cplusplus | |||
| #endif // WProgram_h | |||
| @@ -0,0 +1,759 @@ | |||
| /* | |||
| WString.cpp - String library for Wiring & Arduino | |||
| ...mostly rewritten by Paul Stoffregen... | |||
| Copyright (c) 2009-10 Hernando Barragan. All rights reserved. | |||
| Copyright 2011, Paul Stoffregen, paul@pjrc.com | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "WString.h" | |||
| /*********************************************/ | |||
| /* Constructors */ | |||
| /*********************************************/ | |||
| String::String(const char *cstr) | |||
| { | |||
| init(); | |||
| if (cstr) copy(cstr, strlen(cstr)); | |||
| } | |||
| String::String(const __FlashStringHelper *pgmstr) | |||
| { | |||
| init(); | |||
| *this = pgmstr; | |||
| } | |||
| String::String(const String &value) | |||
| { | |||
| init(); | |||
| *this = value; | |||
| } | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String::String(String &&rval) | |||
| { | |||
| init(); | |||
| move(rval); | |||
| } | |||
| String::String(StringSumHelper &&rval) | |||
| { | |||
| init(); | |||
| move(rval); | |||
| } | |||
| #endif | |||
| String::String(char c) | |||
| { | |||
| init(); | |||
| *this = c; | |||
| } | |||
| String::String(unsigned char c) | |||
| { | |||
| init(); | |||
| *this = (char)c; | |||
| } | |||
| String::String(const int value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[18]; | |||
| itoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(unsigned int value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[17]; | |||
| utoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(long value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[34]; | |||
| ltoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(unsigned long value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[33]; | |||
| ultoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(float num, unsigned char digits) | |||
| { | |||
| init(); | |||
| char buf[40]; | |||
| *this = dtostrf(num, digits + 2, digits, buf); | |||
| } | |||
| String::String(double num, unsigned char digits) | |||
| { | |||
| init(); | |||
| char buf[40]; | |||
| *this = dtostrf(num, digits + 2, digits, buf); | |||
| } | |||
| String::~String() | |||
| { | |||
| free(buffer); | |||
| } | |||
| /*********************************************/ | |||
| /* Memory Management */ | |||
| /*********************************************/ | |||
| inline void String::init(void) | |||
| { | |||
| buffer = NULL; | |||
| capacity = 0; | |||
| len = 0; | |||
| flags = 0; | |||
| } | |||
| unsigned char String::reserve(unsigned int size) | |||
| { | |||
| if (capacity >= size) return 1; | |||
| if (changeBuffer(size)) { | |||
| if (len == 0) buffer[0] = 0; | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| unsigned char String::changeBuffer(unsigned int maxStrLen) | |||
| { | |||
| char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); | |||
| if (newbuffer) { | |||
| buffer = newbuffer; | |||
| capacity = maxStrLen; | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Copy and Move */ | |||
| /*********************************************/ | |||
| String & String::copy(const char *cstr, unsigned int length) | |||
| { | |||
| if (length == 0) { | |||
| if (buffer) buffer[0] = 0; | |||
| len = 0; | |||
| return *this; | |||
| } | |||
| if (!reserve(length)) { | |||
| if (buffer) { | |||
| free(buffer); | |||
| buffer = NULL; | |||
| } | |||
| len = capacity = 0; | |||
| return *this; | |||
| } | |||
| len = length; | |||
| strcpy(buffer, cstr); | |||
| return *this; | |||
| } | |||
| String & String::copy(const __FlashStringHelper *pgmstr) | |||
| { | |||
| unsigned int length = strlen_P((const char PROGMEM *)pgmstr); | |||
| if (!reserve(length)) { | |||
| if (buffer) { | |||
| free(buffer); | |||
| buffer = NULL; | |||
| } | |||
| len = capacity = 0; | |||
| return *this; | |||
| } | |||
| len = length; | |||
| strcpy_P(buffer, (const char PROGMEM *)pgmstr); | |||
| return *this; | |||
| } | |||
| void String::move(String &rhs) | |||
| { | |||
| if (buffer) { | |||
| if (capacity >= rhs.len) { | |||
| strcpy(buffer, rhs.buffer); | |||
| len = rhs.len; | |||
| rhs.len = 0; | |||
| return; | |||
| } else { | |||
| free(buffer); | |||
| } | |||
| } | |||
| buffer = rhs.buffer; | |||
| capacity = rhs.capacity; | |||
| len = rhs.len; | |||
| rhs.buffer = NULL; | |||
| rhs.capacity = 0; | |||
| rhs.len = 0; | |||
| } | |||
| String & String::operator = (const String &rhs) | |||
| { | |||
| if (this == &rhs) return *this; | |||
| return copy(rhs.buffer, rhs.len); | |||
| } | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String & String::operator = (String &&rval) | |||
| { | |||
| if (this != &rval) move(rval); | |||
| return *this; | |||
| } | |||
| String & String::operator = (StringSumHelper &&rval) | |||
| { | |||
| if (this != &rval) move(rval); | |||
| return *this; | |||
| } | |||
| #endif | |||
| String & String::operator = (const char *cstr) | |||
| { | |||
| if (cstr) { | |||
| copy(cstr, strlen(cstr)); | |||
| } else { | |||
| len = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::operator = (const __FlashStringHelper *pgmstr) | |||
| { | |||
| copy(pgmstr); | |||
| return *this; | |||
| } | |||
| String & String::operator = (char c) | |||
| { | |||
| char buf[2]; | |||
| buf[0] = c; | |||
| buf[1] = 0; | |||
| return copy(buf, 1); | |||
| } | |||
| /*********************************************/ | |||
| /* Append */ | |||
| /*********************************************/ | |||
| String & String::append(const String &s) | |||
| { | |||
| return append(s.buffer, s.len); | |||
| } | |||
| String & String::append(const char *cstr, unsigned int length) | |||
| { | |||
| unsigned int newlen = len + length; | |||
| if (length == 0 || !reserve(newlen)) return *this; | |||
| strcpy(buffer + len, cstr); | |||
| len = newlen; | |||
| return *this; | |||
| } | |||
| String & String::append(const char *cstr) | |||
| { | |||
| if (cstr) append(cstr, strlen(cstr)); | |||
| return *this; | |||
| } | |||
| String & String::append(const __FlashStringHelper *pgmstr) | |||
| { | |||
| unsigned int length = strlen_P((const char PROGMEM *)pgmstr); | |||
| unsigned int newlen = len + length; | |||
| if (length == 0 || !reserve(newlen)) return *this; | |||
| strcpy_P(buffer + len, (const char PROGMEM *)pgmstr); | |||
| len = newlen; | |||
| return *this; | |||
| } | |||
| String & String::append(char c) | |||
| { | |||
| char buf[2]; | |||
| buf[0] = c; | |||
| buf[1] = 0; | |||
| append(buf, 1); | |||
| return *this; | |||
| } | |||
| String & String::append(int num) | |||
| { | |||
| char buf[7]; | |||
| itoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(unsigned int num) | |||
| { | |||
| char buf[6]; | |||
| utoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(long num) | |||
| { | |||
| char buf[12]; | |||
| ltoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(unsigned long num) | |||
| { | |||
| char buf[11]; | |||
| ultoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(float num) | |||
| { | |||
| char buf[30]; | |||
| dtostrf(num, 4, 2, buf); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| /*********************************************/ | |||
| /* Concatenate */ | |||
| /*********************************************/ | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(rhs.buffer, rhs.len); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| if (cstr) a.append(cstr, strlen(cstr)); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(pgmstr); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, char c) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(c); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(c); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, int num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, long num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, float num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, double num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| /*********************************************/ | |||
| /* Comparison */ | |||
| /*********************************************/ | |||
| int String::compareTo(const String &s) const | |||
| { | |||
| if (!buffer || !s.buffer) { | |||
| if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; | |||
| if (buffer && len > 0) return *(unsigned char *)buffer; | |||
| return 0; | |||
| } | |||
| return strcmp(buffer, s.buffer); | |||
| } | |||
| unsigned char String::equals(const String &s2) const | |||
| { | |||
| return (len == s2.len && compareTo(s2) == 0); | |||
| } | |||
| unsigned char String::equals(const char *cstr) const | |||
| { | |||
| if (len == 0) return (cstr == NULL || *cstr == 0); | |||
| if (cstr == NULL) return buffer[0] == 0; | |||
| return strcmp(buffer, cstr) == 0; | |||
| } | |||
| unsigned char String::equals(const __FlashStringHelper *pgmstr) const | |||
| { | |||
| if (len == 0) return pgm_read_byte(pgmstr) == 0; | |||
| return strcmp_P(buffer, (const char PROGMEM *)pgmstr) == 0; | |||
| } | |||
| unsigned char String::operator<(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) < 0; | |||
| } | |||
| unsigned char String::operator>(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) > 0; | |||
| } | |||
| unsigned char String::operator<=(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) <= 0; | |||
| } | |||
| unsigned char String::operator>=(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) >= 0; | |||
| } | |||
| unsigned char String::equalsIgnoreCase( const String &s2 ) const | |||
| { | |||
| if (this == &s2) return 1; | |||
| if (len != s2.len) return 0; | |||
| if (len == 0) return 1; | |||
| const char *p1 = buffer; | |||
| const char *p2 = s2.buffer; | |||
| while (*p1) { | |||
| if (tolower(*p1++) != tolower(*p2++)) return 0; | |||
| } | |||
| return 1; | |||
| } | |||
| unsigned char String::startsWith( const String &s2 ) const | |||
| { | |||
| if (len < s2.len) return 0; | |||
| return startsWith(s2, 0); | |||
| } | |||
| unsigned char String::startsWith( const String &s2, unsigned int offset ) const | |||
| { | |||
| if (offset > len - s2.len || !buffer || !s2.buffer) return 0; | |||
| return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; | |||
| } | |||
| unsigned char String::endsWith( const String &s2 ) const | |||
| { | |||
| if ( len < s2.len || !buffer || !s2.buffer) return 0; | |||
| return strcmp(&buffer[len - s2.len], s2.buffer) == 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Character Access */ | |||
| /*********************************************/ | |||
| char String::charAt(unsigned int loc) const | |||
| { | |||
| return operator[](loc); | |||
| } | |||
| void String::setCharAt(unsigned int loc, char c) | |||
| { | |||
| if (loc < len) buffer[loc] = c; | |||
| } | |||
| char & String::operator[](unsigned int index) | |||
| { | |||
| static char dummy_writable_char; | |||
| if (index >= len || !buffer) { | |||
| dummy_writable_char = 0; | |||
| return dummy_writable_char; | |||
| } | |||
| return buffer[index]; | |||
| } | |||
| char String::operator[]( unsigned int index ) const | |||
| { | |||
| if (index >= len || !buffer) return 0; | |||
| return buffer[index]; | |||
| } | |||
| void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const | |||
| { | |||
| if (!bufsize || !buf) return; | |||
| if (index >= len) { | |||
| buf[0] = 0; | |||
| return; | |||
| } | |||
| unsigned int n = bufsize - 1; | |||
| if (n > len - index) n = len - index; | |||
| strncpy((char *)buf, buffer + index, n); | |||
| buf[n] = 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Search */ | |||
| /*********************************************/ | |||
| int String::indexOf(char c) const | |||
| { | |||
| return indexOf(c, 0); | |||
| } | |||
| int String::indexOf( char ch, unsigned int fromIndex ) const | |||
| { | |||
| if (fromIndex >= len) return -1; | |||
| const char* temp = strchr(buffer + fromIndex, ch); | |||
| if (temp == NULL) return -1; | |||
| return temp - buffer; | |||
| } | |||
| int String::indexOf(const String &s2) const | |||
| { | |||
| return indexOf(s2, 0); | |||
| } | |||
| int String::indexOf(const String &s2, unsigned int fromIndex) const | |||
| { | |||
| if (fromIndex >= len) return -1; | |||
| const char *found = strstr(buffer + fromIndex, s2.buffer); | |||
| if (found == NULL) return -1; | |||
| return found - buffer; | |||
| } | |||
| int String::lastIndexOf( char theChar ) const | |||
| { | |||
| return lastIndexOf(theChar, len - 1); | |||
| } | |||
| int String::lastIndexOf(char ch, unsigned int fromIndex) const | |||
| { | |||
| if (fromIndex >= len || 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; | |||
| } | |||
| int String::lastIndexOf(const String &s2) const | |||
| { | |||
| return lastIndexOf(s2, len - s2.len); | |||
| } | |||
| int String::lastIndexOf(const String &s2, unsigned int fromIndex) const | |||
| { | |||
| if (s2.len == 0 || len == 0 || s2.len > len || 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 ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; | |||
| } | |||
| return found; | |||
| } | |||
| String String::substring( unsigned int left ) const | |||
| { | |||
| 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 */ | |||
| /*********************************************/ | |||
| String & String::replace(char find, char replace) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| if (*p == find) *p = replace; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::replace(const String& find, const String& replace) | |||
| { | |||
| if (len == 0 || find.len == 0) return *this; | |||
| 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 *this; | |||
| if (size > capacity && !changeBuffer(size)) return *this; | |||
| int index = len - 1; | |||
| while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { | |||
| readFrom = buffer + index + find.len; | |||
| memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); | |||
| len += diff; | |||
| buffer[len] = 0; | |||
| memcpy(buffer + index, replace.buffer, replace.len); | |||
| index--; | |||
| } | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::remove(unsigned int index) | |||
| { | |||
| if (index < len) { | |||
| len = index; | |||
| buffer[len] = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::remove(unsigned int index, unsigned int count) | |||
| { | |||
| if (index < len && count > 0) { | |||
| if (index + count > len) count = len - index; | |||
| len = len - count; | |||
| memmove(buffer + index, buffer + index + count, len - index); | |||
| buffer[len] = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::toLowerCase(void) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| *p = tolower(*p); | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::toUpperCase(void) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| *p = toupper(*p); | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::trim(void) | |||
| { | |||
| if (!buffer || len == 0) return *this; | |||
| 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; | |||
| return *this; | |||
| } | |||
| /*********************************************/ | |||
| /* Parsing / Conversion */ | |||
| /*********************************************/ | |||
| long String::toInt(void) const | |||
| { | |||
| if (buffer) return atol(buffer); | |||
| return 0; | |||
| } | |||
| float String::toFloat(void) const | |||
| { | |||
| if (buffer) return atof(buffer); | |||
| return 0.0; | |||
| } | |||
| @@ -0,0 +1,216 @@ | |||
| /* | |||
| WString.h - String library for Wiring & Arduino | |||
| ...mostly rewritten by Paul Stoffregen... | |||
| Copyright (c) 2009-10 Hernando Barragan. All right reserved. | |||
| Copyright 2011, Paul Stoffregen, paul@pjrc.com | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef String_class_h | |||
| #define String_class_h | |||
| #ifdef __cplusplus | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <ctype.h> | |||
| #include <avr/pgmspace.h> | |||
| // When compiling programs with this class, the following gcc parameters | |||
| // dramatically increase performance and memory (RAM) efficiency, typically | |||
| // with little or no increase in code size. | |||
| // -felide-constructors | |||
| // -std=c++0x | |||
| // Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010) | |||
| // modified by Mikal Hart for his FlashString library | |||
| class __FlashStringHelper; | |||
| #ifndef F | |||
| #define F(string_literal) ((const __FlashStringHelper *)(PSTR(string_literal))) | |||
| #endif | |||
| // 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 *cstr = NULL); | |||
| String(const __FlashStringHelper *pgmstr); | |||
| String(const String &str); | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String(String &&rval); | |||
| String(StringSumHelper &&rval); | |||
| #endif | |||
| String(char c); | |||
| String(unsigned char c); | |||
| String(int, unsigned char base=10); | |||
| String(unsigned int, unsigned char base=10); | |||
| String(long, unsigned char base=10); | |||
| String(unsigned long, unsigned char base=10); | |||
| String(float num, unsigned char digits=2); | |||
| String(double num, unsigned char digits=2); | |||
| ~String(void); | |||
| // memory management | |||
| unsigned char reserve(unsigned int size); | |||
| inline unsigned int length(void) const {return len;} | |||
| // copy and move | |||
| String & copy(const char *cstr, unsigned int length); | |||
| String & copy(const __FlashStringHelper *pgmstr); | |||
| void move(String &rhs); | |||
| String & operator = (const String &rhs); | |||
| String & operator = (const char *cstr); | |||
| String & operator = (const __FlashStringHelper *pgmstr); | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String & operator = (String &&rval); | |||
| String & operator = (StringSumHelper &&rval); | |||
| #endif | |||
| String & operator = (char c); | |||
| // append | |||
| String & append(const String &str); | |||
| String & append(const char *cstr); | |||
| String & append(const __FlashStringHelper *pgmstr); | |||
| String & append(char c); | |||
| String & append(unsigned char c) {return append((int)c);} | |||
| String & append(int num); | |||
| String & append(unsigned int num); | |||
| String & append(long num); | |||
| String & append(unsigned long num); | |||
| String & append(float num); | |||
| String & append(double num) {return append((float)num);} | |||
| String & operator += (const String &rhs) {return append(rhs);} | |||
| String & operator += (const char *cstr) {return append(cstr);} | |||
| String & operator += (const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||
| String & operator += (char c) {return append(c);} | |||
| String & operator += (unsigned char c) {return append((int)c);} | |||
| String & operator += (int num) {return append(num);} | |||
| String & operator += (unsigned int num) {return append(num);} | |||
| String & operator += (long num) {return append(num);} | |||
| String & operator += (unsigned long num) {return append(num);} | |||
| String & operator += (float num) {return append(num);} | |||
| String & operator += (double num) {return append(num);} | |||
| // concatenate | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); | |||
| String & concat(const String &str) {return append(str);} | |||
| String & concat(const char *cstr) {return append(cstr);} | |||
| String & concat(const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||
| String & concat(char c) {return append(c);} | |||
| String & concat(unsigned char c) {return append((int)c);} | |||
| String & concat(int num) {return append(num);} | |||
| String & concat(unsigned int num) {return append(num);} | |||
| String & concat(long num) {return append(num);} | |||
| String & concat(unsigned long num) {return append(num);} | |||
| String & concat(float num) {return append(num);} | |||
| String & concat(double num) {return append(num);} | |||
| // comparison | |||
| int compareTo(const String &s) const; | |||
| unsigned char equals(const String &s) const; | |||
| unsigned char equals(const char *cstr) const; | |||
| unsigned char equals(const __FlashStringHelper *pgmstr) 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 __FlashStringHelper *pgmstr) const {return equals(pgmstr);} | |||
| unsigned char operator != (const String &rhs) const {return !equals(rhs);} | |||
| unsigned char operator != (const char *cstr) const {return !equals(cstr);} | |||
| unsigned char operator != (const __FlashStringHelper *pgmstr) const {return !equals(pgmstr);} | |||
| unsigned char operator < (const String &rhs) const; | |||
| unsigned char operator > (const String &rhs) const; | |||
| unsigned char operator <= (const String &rhs) const; | |||
| unsigned char operator >= (const String &rhs) const; | |||
| unsigned char equalsIgnoreCase(const String &s) const; | |||
| unsigned char startsWith( const String &prefix) const; | |||
| unsigned char startsWith(const String &prefix, unsigned int offset) const; | |||
| unsigned char endsWith(const String &suffix) const; | |||
| // character acccess | |||
| char charAt(unsigned int index) const; | |||
| void setCharAt(unsigned int index, char c); | |||
| char operator [] (unsigned int index) const; | |||
| char& operator [] (unsigned int index); | |||
| void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; | |||
| void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const | |||
| {getBytes((unsigned char *)buf, bufsize, index);} | |||
| const char * c_str() const { return buffer; } | |||
| // search | |||
| int indexOf( char ch ) const; | |||
| int indexOf( char ch, unsigned int fromIndex ) const; | |||
| int indexOf( const String &str ) const; | |||
| int indexOf( const String &str, unsigned int fromIndex ) const; | |||
| int lastIndexOf( char ch ) const; | |||
| int lastIndexOf( char ch, unsigned int fromIndex ) const; | |||
| int lastIndexOf( const String &str ) const; | |||
| int lastIndexOf( const String &str, unsigned int fromIndex ) const; | |||
| String substring( unsigned int beginIndex ) const; | |||
| String substring( unsigned int beginIndex, unsigned int endIndex ) const; | |||
| // modification | |||
| String & replace(char find, char replace); | |||
| String & replace(const String& find, const String& replace); | |||
| String & remove(unsigned int index); | |||
| String & remove(unsigned int index, unsigned int count); | |||
| String & toLowerCase(void); | |||
| String & toUpperCase(void); | |||
| String & trim(void); | |||
| // parsing/conversion | |||
| long toInt(void) const; | |||
| float toFloat(void) const; | |||
| protected: | |||
| char *buffer; // the actual char array | |||
| unsigned int capacity; // the array length minus one (for the '\0') | |||
| unsigned int len; // the String length (not counting the '\0') | |||
| unsigned char flags; // unused, for future features | |||
| protected: | |||
| void init(void); | |||
| unsigned char changeBuffer(unsigned int maxStrLen); | |||
| String & append(const char *cstr, unsigned int length); | |||
| }; | |||
| class StringSumHelper : public String | |||
| { | |||
| public: | |||
| StringSumHelper(const String &s) : String(s) {} | |||
| StringSumHelper(const char *p) : String(p) {} | |||
| StringSumHelper(const __FlashStringHelper *pgmstr) : String(pgmstr) {} | |||
| StringSumHelper(char c) : String(c) {} | |||
| StringSumHelper(unsigned char c) : String(c) {} | |||
| StringSumHelper(int num) : String(num, 10) {} | |||
| StringSumHelper(unsigned int num) : String(num, 10) {} | |||
| StringSumHelper(long num) : String(num, 10) {} | |||
| StringSumHelper(unsigned long num) : String(num, 10) {} | |||
| }; | |||
| #endif // __cplusplus | |||
| #endif // String_class_h | |||
| @@ -0,0 +1,515 @@ | |||
| #ifndef Binary_h | |||
| #define Binary_h | |||
| #define B0 0 | |||
| #define B00 0 | |||
| #define B000 0 | |||
| #define B0000 0 | |||
| #define B00000 0 | |||
| #define B000000 0 | |||
| #define B0000000 0 | |||
| #define B00000000 0 | |||
| #define B1 1 | |||
| #define B01 1 | |||
| #define B001 1 | |||
| #define B0001 1 | |||
| #define B00001 1 | |||
| #define B000001 1 | |||
| #define B0000001 1 | |||
| #define B00000001 1 | |||
| #define B10 2 | |||
| #define B010 2 | |||
| #define B0010 2 | |||
| #define B00010 2 | |||
| #define B000010 2 | |||
| #define B0000010 2 | |||
| #define B00000010 2 | |||
| #define B11 3 | |||
| #define B011 3 | |||
| #define B0011 3 | |||
| #define B00011 3 | |||
| #define B000011 3 | |||
| #define B0000011 3 | |||
| #define B00000011 3 | |||
| #define B100 4 | |||
| #define B0100 4 | |||
| #define B00100 4 | |||
| #define B000100 4 | |||
| #define B0000100 4 | |||
| #define B00000100 4 | |||
| #define B101 5 | |||
| #define B0101 5 | |||
| #define B00101 5 | |||
| #define B000101 5 | |||
| #define B0000101 5 | |||
| #define B00000101 5 | |||
| #define B110 6 | |||
| #define B0110 6 | |||
| #define B00110 6 | |||
| #define B000110 6 | |||
| #define B0000110 6 | |||
| #define B00000110 6 | |||
| #define B111 7 | |||
| #define B0111 7 | |||
| #define B00111 7 | |||
| #define B000111 7 | |||
| #define B0000111 7 | |||
| #define B00000111 7 | |||
| #define B1000 8 | |||
| #define B01000 8 | |||
| #define B001000 8 | |||
| #define B0001000 8 | |||
| #define B00001000 8 | |||
| #define B1001 9 | |||
| #define B01001 9 | |||
| #define B001001 9 | |||
| #define B0001001 9 | |||
| #define B00001001 9 | |||
| #define B1010 10 | |||
| #define B01010 10 | |||
| #define B001010 10 | |||
| #define B0001010 10 | |||
| #define B00001010 10 | |||
| #define B1011 11 | |||
| #define B01011 11 | |||
| #define B001011 11 | |||
| #define B0001011 11 | |||
| #define B00001011 11 | |||
| #define B1100 12 | |||
| #define B01100 12 | |||
| #define B001100 12 | |||
| #define B0001100 12 | |||
| #define B00001100 12 | |||
| #define B1101 13 | |||
| #define B01101 13 | |||
| #define B001101 13 | |||
| #define B0001101 13 | |||
| #define B00001101 13 | |||
| #define B1110 14 | |||
| #define B01110 14 | |||
| #define B001110 14 | |||
| #define B0001110 14 | |||
| #define B00001110 14 | |||
| #define B1111 15 | |||
| #define B01111 15 | |||
| #define B001111 15 | |||
| #define B0001111 15 | |||
| #define B00001111 15 | |||
| #define B10000 16 | |||
| #define B010000 16 | |||
| #define B0010000 16 | |||
| #define B00010000 16 | |||
| #define B10001 17 | |||
| #define B010001 17 | |||
| #define B0010001 17 | |||
| #define B00010001 17 | |||
| #define B10010 18 | |||
| #define B010010 18 | |||
| #define B0010010 18 | |||
| #define B00010010 18 | |||
| #define B10011 19 | |||
| #define B010011 19 | |||
| #define B0010011 19 | |||
| #define B00010011 19 | |||
| #define B10100 20 | |||
| #define B010100 20 | |||
| #define B0010100 20 | |||
| #define B00010100 20 | |||
| #define B10101 21 | |||
| #define B010101 21 | |||
| #define B0010101 21 | |||
| #define B00010101 21 | |||
| #define B10110 22 | |||
| #define B010110 22 | |||
| #define B0010110 22 | |||
| #define B00010110 22 | |||
| #define B10111 23 | |||
| #define B010111 23 | |||
| #define B0010111 23 | |||
| #define B00010111 23 | |||
| #define B11000 24 | |||
| #define B011000 24 | |||
| #define B0011000 24 | |||
| #define B00011000 24 | |||
| #define B11001 25 | |||
| #define B011001 25 | |||
| #define B0011001 25 | |||
| #define B00011001 25 | |||
| #define B11010 26 | |||
| #define B011010 26 | |||
| #define B0011010 26 | |||
| #define B00011010 26 | |||
| #define B11011 27 | |||
| #define B011011 27 | |||
| #define B0011011 27 | |||
| #define B00011011 27 | |||
| #define B11100 28 | |||
| #define B011100 28 | |||
| #define B0011100 28 | |||
| #define B00011100 28 | |||
| #define B11101 29 | |||
| #define B011101 29 | |||
| #define B0011101 29 | |||
| #define B00011101 29 | |||
| #define B11110 30 | |||
| #define B011110 30 | |||
| #define B0011110 30 | |||
| #define B00011110 30 | |||
| #define B11111 31 | |||
| #define B011111 31 | |||
| #define B0011111 31 | |||
| #define B00011111 31 | |||
| #define B100000 32 | |||
| #define B0100000 32 | |||
| #define B00100000 32 | |||
| #define B100001 33 | |||
| #define B0100001 33 | |||
| #define B00100001 33 | |||
| #define B100010 34 | |||
| #define B0100010 34 | |||
| #define B00100010 34 | |||
| #define B100011 35 | |||
| #define B0100011 35 | |||
| #define B00100011 35 | |||
| #define B100100 36 | |||
| #define B0100100 36 | |||
| #define B00100100 36 | |||
| #define B100101 37 | |||
| #define B0100101 37 | |||
| #define B00100101 37 | |||
| #define B100110 38 | |||
| #define B0100110 38 | |||
| #define B00100110 38 | |||
| #define B100111 39 | |||
| #define B0100111 39 | |||
| #define B00100111 39 | |||
| #define B101000 40 | |||
| #define B0101000 40 | |||
| #define B00101000 40 | |||
| #define B101001 41 | |||
| #define B0101001 41 | |||
| #define B00101001 41 | |||
| #define B101010 42 | |||
| #define B0101010 42 | |||
| #define B00101010 42 | |||
| #define B101011 43 | |||
| #define B0101011 43 | |||
| #define B00101011 43 | |||
| #define B101100 44 | |||
| #define B0101100 44 | |||
| #define B00101100 44 | |||
| #define B101101 45 | |||
| #define B0101101 45 | |||
| #define B00101101 45 | |||
| #define B101110 46 | |||
| #define B0101110 46 | |||
| #define B00101110 46 | |||
| #define B101111 47 | |||
| #define B0101111 47 | |||
| #define B00101111 47 | |||
| #define B110000 48 | |||
| #define B0110000 48 | |||
| #define B00110000 48 | |||
| #define B110001 49 | |||
| #define B0110001 49 | |||
| #define B00110001 49 | |||
| #define B110010 50 | |||
| #define B0110010 50 | |||
| #define B00110010 50 | |||
| #define B110011 51 | |||
| #define B0110011 51 | |||
| #define B00110011 51 | |||
| #define B110100 52 | |||
| #define B0110100 52 | |||
| #define B00110100 52 | |||
| #define B110101 53 | |||
| #define B0110101 53 | |||
| #define B00110101 53 | |||
| #define B110110 54 | |||
| #define B0110110 54 | |||
| #define B00110110 54 | |||
| #define B110111 55 | |||
| #define B0110111 55 | |||
| #define B00110111 55 | |||
| #define B111000 56 | |||
| #define B0111000 56 | |||
| #define B00111000 56 | |||
| #define B111001 57 | |||
| #define B0111001 57 | |||
| #define B00111001 57 | |||
| #define B111010 58 | |||
| #define B0111010 58 | |||
| #define B00111010 58 | |||
| #define B111011 59 | |||
| #define B0111011 59 | |||
| #define B00111011 59 | |||
| #define B111100 60 | |||
| #define B0111100 60 | |||
| #define B00111100 60 | |||
| #define B111101 61 | |||
| #define B0111101 61 | |||
| #define B00111101 61 | |||
| #define B111110 62 | |||
| #define B0111110 62 | |||
| #define B00111110 62 | |||
| #define B111111 63 | |||
| #define B0111111 63 | |||
| #define B00111111 63 | |||
| #define B1000000 64 | |||
| #define B01000000 64 | |||
| #define B1000001 65 | |||
| #define B01000001 65 | |||
| #define B1000010 66 | |||
| #define B01000010 66 | |||
| #define B1000011 67 | |||
| #define B01000011 67 | |||
| #define B1000100 68 | |||
| #define B01000100 68 | |||
| #define B1000101 69 | |||
| #define B01000101 69 | |||
| #define B1000110 70 | |||
| #define B01000110 70 | |||
| #define B1000111 71 | |||
| #define B01000111 71 | |||
| #define B1001000 72 | |||
| #define B01001000 72 | |||
| #define B1001001 73 | |||
| #define B01001001 73 | |||
| #define B1001010 74 | |||
| #define B01001010 74 | |||
| #define B1001011 75 | |||
| #define B01001011 75 | |||
| #define B1001100 76 | |||
| #define B01001100 76 | |||
| #define B1001101 77 | |||
| #define B01001101 77 | |||
| #define B1001110 78 | |||
| #define B01001110 78 | |||
| #define B1001111 79 | |||
| #define B01001111 79 | |||
| #define B1010000 80 | |||
| #define B01010000 80 | |||
| #define B1010001 81 | |||
| #define B01010001 81 | |||
| #define B1010010 82 | |||
| #define B01010010 82 | |||
| #define B1010011 83 | |||
| #define B01010011 83 | |||
| #define B1010100 84 | |||
| #define B01010100 84 | |||
| #define B1010101 85 | |||
| #define B01010101 85 | |||
| #define B1010110 86 | |||
| #define B01010110 86 | |||
| #define B1010111 87 | |||
| #define B01010111 87 | |||
| #define B1011000 88 | |||
| #define B01011000 88 | |||
| #define B1011001 89 | |||
| #define B01011001 89 | |||
| #define B1011010 90 | |||
| #define B01011010 90 | |||
| #define B1011011 91 | |||
| #define B01011011 91 | |||
| #define B1011100 92 | |||
| #define B01011100 92 | |||
| #define B1011101 93 | |||
| #define B01011101 93 | |||
| #define B1011110 94 | |||
| #define B01011110 94 | |||
| #define B1011111 95 | |||
| #define B01011111 95 | |||
| #define B1100000 96 | |||
| #define B01100000 96 | |||
| #define B1100001 97 | |||
| #define B01100001 97 | |||
| #define B1100010 98 | |||
| #define B01100010 98 | |||
| #define B1100011 99 | |||
| #define B01100011 99 | |||
| #define B1100100 100 | |||
| #define B01100100 100 | |||
| #define B1100101 101 | |||
| #define B01100101 101 | |||
| #define B1100110 102 | |||
| #define B01100110 102 | |||
| #define B1100111 103 | |||
| #define B01100111 103 | |||
| #define B1101000 104 | |||
| #define B01101000 104 | |||
| #define B1101001 105 | |||
| #define B01101001 105 | |||
| #define B1101010 106 | |||
| #define B01101010 106 | |||
| #define B1101011 107 | |||
| #define B01101011 107 | |||
| #define B1101100 108 | |||
| #define B01101100 108 | |||
| #define B1101101 109 | |||
| #define B01101101 109 | |||
| #define B1101110 110 | |||
| #define B01101110 110 | |||
| #define B1101111 111 | |||
| #define B01101111 111 | |||
| #define B1110000 112 | |||
| #define B01110000 112 | |||
| #define B1110001 113 | |||
| #define B01110001 113 | |||
| #define B1110010 114 | |||
| #define B01110010 114 | |||
| #define B1110011 115 | |||
| #define B01110011 115 | |||
| #define B1110100 116 | |||
| #define B01110100 116 | |||
| #define B1110101 117 | |||
| #define B01110101 117 | |||
| #define B1110110 118 | |||
| #define B01110110 118 | |||
| #define B1110111 119 | |||
| #define B01110111 119 | |||
| #define B1111000 120 | |||
| #define B01111000 120 | |||
| #define B1111001 121 | |||
| #define B01111001 121 | |||
| #define B1111010 122 | |||
| #define B01111010 122 | |||
| #define B1111011 123 | |||
| #define B01111011 123 | |||
| #define B1111100 124 | |||
| #define B01111100 124 | |||
| #define B1111101 125 | |||
| #define B01111101 125 | |||
| #define B1111110 126 | |||
| #define B01111110 126 | |||
| #define B1111111 127 | |||
| #define B01111111 127 | |||
| #define B10000000 128 | |||
| #define B10000001 129 | |||
| #define B10000010 130 | |||
| #define B10000011 131 | |||
| #define B10000100 132 | |||
| #define B10000101 133 | |||
| #define B10000110 134 | |||
| #define B10000111 135 | |||
| #define B10001000 136 | |||
| #define B10001001 137 | |||
| #define B10001010 138 | |||
| #define B10001011 139 | |||
| #define B10001100 140 | |||
| #define B10001101 141 | |||
| #define B10001110 142 | |||
| #define B10001111 143 | |||
| #define B10010000 144 | |||
| #define B10010001 145 | |||
| #define B10010010 146 | |||
| #define B10010011 147 | |||
| #define B10010100 148 | |||
| #define B10010101 149 | |||
| #define B10010110 150 | |||
| #define B10010111 151 | |||
| #define B10011000 152 | |||
| #define B10011001 153 | |||
| #define B10011010 154 | |||
| #define B10011011 155 | |||
| #define B10011100 156 | |||
| #define B10011101 157 | |||
| #define B10011110 158 | |||
| #define B10011111 159 | |||
| #define B10100000 160 | |||
| #define B10100001 161 | |||
| #define B10100010 162 | |||
| #define B10100011 163 | |||
| #define B10100100 164 | |||
| #define B10100101 165 | |||
| #define B10100110 166 | |||
| #define B10100111 167 | |||
| #define B10101000 168 | |||
| #define B10101001 169 | |||
| #define B10101010 170 | |||
| #define B10101011 171 | |||
| #define B10101100 172 | |||
| #define B10101101 173 | |||
| #define B10101110 174 | |||
| #define B10101111 175 | |||
| #define B10110000 176 | |||
| #define B10110001 177 | |||
| #define B10110010 178 | |||
| #define B10110011 179 | |||
| #define B10110100 180 | |||
| #define B10110101 181 | |||
| #define B10110110 182 | |||
| #define B10110111 183 | |||
| #define B10111000 184 | |||
| #define B10111001 185 | |||
| #define B10111010 186 | |||
| #define B10111011 187 | |||
| #define B10111100 188 | |||
| #define B10111101 189 | |||
| #define B10111110 190 | |||
| #define B10111111 191 | |||
| #define B11000000 192 | |||
| #define B11000001 193 | |||
| #define B11000010 194 | |||
| #define B11000011 195 | |||
| #define B11000100 196 | |||
| #define B11000101 197 | |||
| #define B11000110 198 | |||
| #define B11000111 199 | |||
| #define B11001000 200 | |||
| #define B11001001 201 | |||
| #define B11001010 202 | |||
| #define B11001011 203 | |||
| #define B11001100 204 | |||
| #define B11001101 205 | |||
| #define B11001110 206 | |||
| #define B11001111 207 | |||
| #define B11010000 208 | |||
| #define B11010001 209 | |||
| #define B11010010 210 | |||
| #define B11010011 211 | |||
| #define B11010100 212 | |||
| #define B11010101 213 | |||
| #define B11010110 214 | |||
| #define B11010111 215 | |||
| #define B11011000 216 | |||
| #define B11011001 217 | |||
| #define B11011010 218 | |||
| #define B11011011 219 | |||
| #define B11011100 220 | |||
| #define B11011101 221 | |||
| #define B11011110 222 | |||
| #define B11011111 223 | |||
| #define B11100000 224 | |||
| #define B11100001 225 | |||
| #define B11100010 226 | |||
| #define B11100011 227 | |||
| #define B11100100 228 | |||
| #define B11100101 229 | |||
| #define B11100110 230 | |||
| #define B11100111 231 | |||
| #define B11101000 232 | |||
| #define B11101001 233 | |||
| #define B11101010 234 | |||
| #define B11101011 235 | |||
| #define B11101100 236 | |||
| #define B11101101 237 | |||
| #define B11101110 238 | |||
| #define B11101111 239 | |||
| #define B11110000 240 | |||
| #define B11110001 241 | |||
| #define B11110010 242 | |||
| #define B11110011 243 | |||
| #define B11110100 244 | |||
| #define B11110101 245 | |||
| #define B11110110 246 | |||
| #define B11110111 247 | |||
| #define B11111000 248 | |||
| #define B11111001 249 | |||
| #define B11111010 250 | |||
| #define B11111011 251 | |||
| #define B11111100 252 | |||
| #define B11111101 253 | |||
| #define B11111110 254 | |||
| #define B11111111 255 | |||
| #endif | |||
| @@ -0,0 +1,18 @@ | |||
| #ifndef CORE_TEENSY | |||
| #define CORE_TEENSY | |||
| #if defined(USB_SERIAL) | |||
| #include "../usb_serial/core_id.h" | |||
| #elif defined(USB_HID) | |||
| #include "../usb_hid/core_id.h" | |||
| #elif defined(USB_SERIAL_HID) | |||
| #include "../usb_serial_hid/core_id.h" | |||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||
| #include "../usb_disk/core_id.h" | |||
| #elif defined(USB_MIDI) | |||
| #include "../usb_midi/core_id.h" | |||
| #elif defined(USB_RAWHID) | |||
| #include "../usb_rawhid/core_id.h" | |||
| #elif defined(USB_FLIGHTSIM) | |||
| #include "../usb_flightsim/core_id.h" | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,81 @@ | |||
| /* Elapsed time types - for easy-to-use measurements of elapsed time | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2011 PJRC.COM, LLC | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| #ifndef elapsedMillis_h | |||
| #define elapsedMillis_h | |||
| #ifdef __cplusplus | |||
| #if ARDUINO >= 100 | |||
| #include "Arduino.h" | |||
| #else | |||
| #include "WProgram.h" | |||
| #endif | |||
| class elapsedMillis | |||
| { | |||
| private: | |||
| unsigned long ms; | |||
| public: | |||
| elapsedMillis(void) { ms = millis(); } | |||
| elapsedMillis(unsigned long val) { ms = millis() - val; } | |||
| elapsedMillis(const elapsedMillis &orig) { ms = orig.ms; } | |||
| operator unsigned long () const { return millis() - ms; } | |||
| elapsedMillis & operator = (const elapsedMillis &rhs) { ms = rhs.ms; return *this; } | |||
| elapsedMillis & operator = (unsigned long val) { ms = millis() - val; return *this; } | |||
| elapsedMillis & operator -= (unsigned long val) { ms += val ; return *this; } | |||
| elapsedMillis & operator += (unsigned long val) { ms -= val ; return *this; } | |||
| elapsedMillis operator - (int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (unsigned int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (unsigned long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator + (int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (unsigned int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| }; | |||
| class elapsedMicros | |||
| { | |||
| private: | |||
| unsigned long us; | |||
| public: | |||
| elapsedMicros(void) { us = micros(); } | |||
| elapsedMicros(unsigned long val) { us = micros() - val; } | |||
| elapsedMicros(const elapsedMicros &orig) { us = orig.us; } | |||
| operator unsigned long () const { return micros() - us; } | |||
| elapsedMicros & operator = (const elapsedMicros &rhs) { us = rhs.us; return *this; } | |||
| elapsedMicros & operator = (unsigned long val) { us = micros() - val; return *this; } | |||
| elapsedMicros & operator -= (unsigned long val) { us += val ; return *this; } | |||
| elapsedMicros & operator += (unsigned long val) { us -= val ; return *this; } | |||
| elapsedMicros operator - (int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (unsigned int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (unsigned long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator + (int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (unsigned int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (unsigned long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| }; | |||
| #endif // __cplusplus | |||
| #endif // elapsedMillis_h | |||
| @@ -0,0 +1,66 @@ | |||
| #include <avr/pgmspace.h> | |||
| #include <stdint.h> | |||
| #include "keylayouts.h" | |||
| #ifdef M | |||
| #undef M | |||
| #endif | |||
| #define M(n) ((n) & 0x3FFF) | |||
| const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { | |||
| M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), | |||
| M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), | |||
| M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), | |||
| M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), | |||
| M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), | |||
| M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), | |||
| M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), | |||
| M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), | |||
| M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), | |||
| M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), | |||
| M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), | |||
| M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), | |||
| M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), | |||
| M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), | |||
| M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), | |||
| M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), | |||
| M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), | |||
| M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), | |||
| M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), | |||
| M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), | |||
| M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), | |||
| M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), | |||
| M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), | |||
| M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) | |||
| }; | |||
| #ifdef ISO_8859_1_A0 | |||
| const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { | |||
| M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), | |||
| M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), | |||
| M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), | |||
| M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), | |||
| M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), | |||
| M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), | |||
| M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), | |||
| M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), | |||
| M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), | |||
| M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), | |||
| M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), | |||
| M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), | |||
| M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), | |||
| M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), | |||
| M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), | |||
| M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), | |||
| M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), | |||
| M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), | |||
| M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), | |||
| M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), | |||
| M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), | |||
| M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), | |||
| M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), | |||
| M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) | |||
| }; | |||
| #endif // ISO_8859_1_A0 | |||
| @@ -0,0 +1,14 @@ | |||
| #include <WProgram.h> | |||
| //int main(void) __attribute__((noreturn)); | |||
| int main(void) | |||
| { | |||
| _init_Teensyduino_internal_(); | |||
| setup(); | |||
| while (1) { | |||
| loop(); | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| // the main function is now built into core.a and linked into the final executable | |||
| @@ -0,0 +1,388 @@ | |||
| /* Copyright (c) 2002, 2004, 2010 Joerg Wunsch | |||
| Copyright (c) 2010 Gerben van den Broeke | |||
| All rights reserved. | |||
| malloc, free, realloc from avr-libc 1.7.0 | |||
| with minor modifications, by Paul Stoffregen | |||
| Redistribution and use in source and binary forms, with or without | |||
| modification, are permitted provided that the following conditions are met: | |||
| * Redistributions of source code must retain the above copyright | |||
| notice, this list of conditions and the following disclaimer. | |||
| * Redistributions in binary form must reproduce the above copyright | |||
| notice, this list of conditions and the following disclaimer in | |||
| the documentation and/or other materials provided with the | |||
| distribution. | |||
| * Neither the name of the copyright holders nor the names of | |||
| contributors may be used to endorse or promote products derived | |||
| from this software without specific prior written permission. | |||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
| POSSIBILITY OF SUCH DAMAGE. | |||
| */ | |||
| #include <stdlib.h> | |||
| #include <inttypes.h> | |||
| #include <string.h> | |||
| #include <avr/io.h> | |||
| extern char __heap_start; | |||
| extern char __heap_end; | |||
| #define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG) | |||
| struct __freelist { | |||
| size_t sz; | |||
| struct __freelist *nx; | |||
| }; | |||
| /* | |||
| * Exported interface: | |||
| * | |||
| * When extending the data segment, the allocator will not try to go | |||
| * beyond the current stack limit, decreased by __malloc_margin bytes. | |||
| * Thus, all possible stack frames of interrupt routines that could | |||
| * interrupt the current function, plus all further nested function | |||
| * calls must not require more stack space, or they'll risk to collide | |||
| * with the data segment. | |||
| */ | |||
| size_t __malloc_margin = 128; | |||
| char *__malloc_heap_start = &__heap_start; | |||
| char *__malloc_heap_end = &__heap_end; | |||
| char *__brkval = NULL; // first location not yet allocated | |||
| struct __freelist *__flp; // freelist pointer (head of freelist) | |||
| // this is useful for tracking the worst case memory allocation | |||
| //char *__brkval_maximum = 0; | |||
| void * | |||
| malloc(size_t len) | |||
| { | |||
| struct __freelist *fp1, *fp2, *sfp1, *sfp2; | |||
| char *cp; | |||
| size_t s, avail; | |||
| /* | |||
| * Our minimum chunk size is the size of a pointer (plus the | |||
| * size of the "sz" field, but we don't need to account for | |||
| * this), otherwise we could not possibly fit a freelist entry | |||
| * into the chunk later. | |||
| */ | |||
| if (len < sizeof(struct __freelist) - sizeof(size_t)) | |||
| len = sizeof(struct __freelist) - sizeof(size_t); | |||
| /* | |||
| * First, walk the free list and try finding a chunk that | |||
| * would match exactly. If we found one, we are done. While | |||
| * walking, note down the smallest chunk we found that would | |||
| * still fit the request -- we need it for step 2. | |||
| * | |||
| */ | |||
| for (s = 0, fp1 = __flp, fp2 = 0; | |||
| fp1; | |||
| fp2 = fp1, fp1 = fp1->nx) { | |||
| if (fp1->sz < len) | |||
| continue; | |||
| if (fp1->sz == len) { | |||
| /* | |||
| * Found it. Disconnect the chunk from the | |||
| * freelist, and return it. | |||
| */ | |||
| if (fp2) | |||
| fp2->nx = fp1->nx; | |||
| else | |||
| __flp = fp1->nx; | |||
| return &(fp1->nx); | |||
| } | |||
| else { | |||
| if (s == 0 || fp1->sz < s) { | |||
| /* this is the smallest chunk found so far */ | |||
| s = fp1->sz; | |||
| sfp1 = fp1; | |||
| sfp2 = fp2; | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| * Step 2: If we found a chunk on the freelist that would fit | |||
| * (but was too large), look it up again and use it, since it | |||
| * is our closest match now. Since the freelist entry needs | |||
| * to be split into two entries then, watch out that the | |||
| * difference between the requested size and the size of the | |||
| * chunk found is large enough for another freelist entry; if | |||
| * not, just enlarge the request size to what we have found, | |||
| * and use the entire chunk. | |||
| */ | |||
| if (s) { | |||
| if (s - len < sizeof(struct __freelist)) { | |||
| /* Disconnect it from freelist and return it. */ | |||
| if (sfp2) | |||
| sfp2->nx = sfp1->nx; | |||
| else | |||
| __flp = sfp1->nx; | |||
| return &(sfp1->nx); | |||
| } | |||
| /* | |||
| * Split them up. Note that we leave the first part | |||
| * as the new (smaller) freelist entry, and return the | |||
| * upper portion to the caller. This saves us the | |||
| * work to fix up the freelist chain; we just need to | |||
| * fixup the size of the current entry, and note down | |||
| * the size of the new chunk before returning it to | |||
| * the caller. | |||
| */ | |||
| cp = (char *)sfp1; | |||
| s -= len; | |||
| cp += s; | |||
| sfp2 = (struct __freelist *)cp; | |||
| sfp2->sz = len; | |||
| sfp1->sz = s - sizeof(size_t); | |||
| return &(sfp2->nx); | |||
| } | |||
| /* | |||
| * Step 3: If the request could not be satisfied from a | |||
| * freelist entry, just prepare a new chunk. This means we | |||
| * need to obtain more memory first. The largest address just | |||
| * not allocated so far is remembered in the brkval variable. | |||
| * Under Unix, the "break value" was the end of the data | |||
| * segment as dynamically requested from the operating system. | |||
| * Since we don't have an operating system, just make sure | |||
| * that we don't collide with the stack. | |||
| */ | |||
| if (__brkval == 0) | |||
| __brkval = __malloc_heap_start; | |||
| cp = __malloc_heap_end; | |||
| if (cp == 0) | |||
| cp = STACK_POINTER() - __malloc_margin; | |||
| if (cp <= __brkval) | |||
| /* | |||
| * Memory exhausted. | |||
| */ | |||
| return 0; | |||
| avail = cp - __brkval; | |||
| /* | |||
| * Both tests below are needed to catch the case len >= 0xfffe. | |||
| */ | |||
| if (avail >= len && avail >= len + sizeof(size_t)) { | |||
| fp1 = (struct __freelist *)__brkval; | |||
| __brkval += len + sizeof(size_t); | |||
| //__brkval_maximum = __brkval; | |||
| fp1->sz = len; | |||
| return &(fp1->nx); | |||
| } | |||
| /* | |||
| * Step 4: There's no help, just fail. :-/ | |||
| */ | |||
| return 0; | |||
| } | |||
| void | |||
| free(void *p) | |||
| { | |||
| struct __freelist *fp1, *fp2, *fpnew; | |||
| char *cp1, *cp2, *cpnew; | |||
| /* ISO C says free(NULL) must be a no-op */ | |||
| if (p == 0) | |||
| return; | |||
| cpnew = p; | |||
| cpnew -= sizeof(size_t); | |||
| fpnew = (struct __freelist *)cpnew; | |||
| fpnew->nx = 0; | |||
| /* | |||
| * Trivial case first: if there's no freelist yet, our entry | |||
| * will be the only one on it. If this is the last entry, we | |||
| * can reduce __brkval instead. | |||
| */ | |||
| if (__flp == 0) { | |||
| if ((char *)p + fpnew->sz == __brkval) | |||
| __brkval = cpnew; | |||
| else | |||
| __flp = fpnew; | |||
| return; | |||
| } | |||
| /* | |||
| * Now, find the position where our new entry belongs onto the | |||
| * freelist. Try to aggregate the chunk with adjacent chunks | |||
| * if possible. | |||
| */ | |||
| for (fp1 = __flp, fp2 = 0; | |||
| fp1; | |||
| fp2 = fp1, fp1 = fp1->nx) { | |||
| if (fp1 < fpnew) | |||
| continue; | |||
| cp1 = (char *)fp1; | |||
| fpnew->nx = fp1; | |||
| if ((char *)&(fpnew->nx) + fpnew->sz == cp1) { | |||
| /* upper chunk adjacent, assimilate it */ | |||
| fpnew->sz += fp1->sz + sizeof(size_t); | |||
| fpnew->nx = fp1->nx; | |||
| } | |||
| if (fp2 == 0) { | |||
| /* new head of freelist */ | |||
| __flp = fpnew; | |||
| return; | |||
| } | |||
| break; | |||
| } | |||
| /* | |||
| * Note that we get here either if we hit the "break" above, | |||
| * or if we fell off the end of the loop. The latter means | |||
| * we've got a new topmost chunk. Either way, try aggregating | |||
| * with the lower chunk if possible. | |||
| */ | |||
| fp2->nx = fpnew; | |||
| cp2 = (char *)&(fp2->nx); | |||
| if (cp2 + fp2->sz == cpnew) { | |||
| /* lower junk adjacent, merge */ | |||
| fp2->sz += fpnew->sz + sizeof(size_t); | |||
| fp2->nx = fpnew->nx; | |||
| } | |||
| /* | |||
| * If there's a new topmost chunk, lower __brkval instead. | |||
| */ | |||
| for (fp1 = __flp, fp2 = 0; | |||
| fp1->nx != 0; | |||
| fp2 = fp1, fp1 = fp1->nx) | |||
| /* advance to entry just before end of list */; | |||
| cp2 = (char *)&(fp1->nx); | |||
| if (cp2 + fp1->sz == __brkval) { | |||
| if (fp2 == NULL) | |||
| /* Freelist is empty now. */ | |||
| __flp = NULL; | |||
| else | |||
| fp2->nx = NULL; | |||
| __brkval = cp2 - sizeof(size_t); | |||
| } | |||
| } | |||
| void * | |||
| realloc(void *ptr, size_t len) | |||
| { | |||
| struct __freelist *fp1, *fp2, *fp3, *ofp3; | |||
| char *cp, *cp1; | |||
| void *memp; | |||
| size_t s, incr; | |||
| /* Trivial case, required by C standard. */ | |||
| if (ptr == 0) | |||
| return malloc(len); | |||
| cp1 = (char *)ptr; | |||
| cp1 -= sizeof(size_t); | |||
| fp1 = (struct __freelist *)cp1; | |||
| cp = (char *)ptr + len; /* new next pointer */ | |||
| if (cp < cp1) | |||
| /* Pointer wrapped across top of RAM, fail. */ | |||
| return 0; | |||
| /* | |||
| * See whether we are growing or shrinking. When shrinking, | |||
| * we split off a chunk for the released portion, and call | |||
| * free() on it. Therefore, we can only shrink if the new | |||
| * size is at least sizeof(struct __freelist) smaller than the | |||
| * previous size. | |||
| */ | |||
| if (len <= fp1->sz) { | |||
| /* The first test catches a possible unsigned int | |||
| * rollover condition. */ | |||
| if (fp1->sz <= sizeof(struct __freelist) || | |||
| len > fp1->sz - sizeof(struct __freelist)) | |||
| return ptr; | |||
| fp2 = (struct __freelist *)cp; | |||
| fp2->sz = fp1->sz - len - sizeof(size_t); | |||
| fp1->sz = len; | |||
| free(&(fp2->nx)); | |||
| return ptr; | |||
| } | |||
| /* | |||
| * If we get here, we are growing. First, see whether there | |||
| * is space in the free list on top of our current chunk. | |||
| */ | |||
| incr = len - fp1->sz; | |||
| cp = (char *)ptr + fp1->sz; | |||
| fp2 = (struct __freelist *)cp; | |||
| for (s = 0, ofp3 = 0, fp3 = __flp; | |||
| fp3; | |||
| ofp3 = fp3, fp3 = fp3->nx) { | |||
| if (fp3 == fp2 && fp3->sz + sizeof(size_t) >= incr) { | |||
| /* found something that fits */ | |||
| if (fp3->sz + sizeof(size_t) - incr > sizeof(struct __freelist)) { | |||
| /* split off a new freelist entry */ | |||
| cp = (char *)ptr + len; | |||
| fp2 = (struct __freelist *)cp; | |||
| fp2->nx = fp3->nx; | |||
| fp2->sz = fp3->sz - incr; | |||
| fp1->sz = len; | |||
| } else { | |||
| /* it just fits, so use it entirely */ | |||
| fp1->sz += fp3->sz + sizeof(size_t); | |||
| fp2 = fp3->nx; | |||
| } | |||
| if (ofp3) | |||
| ofp3->nx = fp2; | |||
| else | |||
| __flp = fp2; | |||
| return ptr; | |||
| } | |||
| /* | |||
| * Find the largest chunk on the freelist while | |||
| * walking it. | |||
| */ | |||
| if (fp3->sz > s) | |||
| s = fp3->sz; | |||
| } | |||
| /* | |||
| * If we are the topmost chunk in memory, and there was no | |||
| * large enough chunk on the freelist that could be re-used | |||
| * (by a call to malloc() below), quickly extend the | |||
| * allocation area if possible, without need to copy the old | |||
| * data. | |||
| */ | |||
| if (__brkval == (char *)ptr + fp1->sz && len > s) { | |||
| cp = (char *)ptr + len; | |||
| cp1 = STACK_POINTER() - __malloc_margin; | |||
| if (cp < cp1) { | |||
| __brkval = cp; | |||
| //__brkval_maximum = cp; | |||
| fp1->sz = len; | |||
| return ptr; | |||
| } | |||
| /* If that failed, we are out of luck. */ | |||
| return 0; | |||
| } | |||
| /* | |||
| * Call malloc() for a new chunk, then copy over the data, and | |||
| * release the old region. | |||
| */ | |||
| if ((memp = malloc(len)) == 0) | |||
| return 0; | |||
| memcpy(memp, ptr, fp1->sz); | |||
| free(ptr); | |||
| return memp; | |||
| } | |||
| @@ -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) {}; | |||
| @@ -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 | |||
| @@ -0,0 +1,147 @@ | |||
| #ifndef pins_macros_for_arduino_compatibility_h | |||
| #define pins_macros_for_arduino_compatibility_h | |||
| #include <avr/pgmspace.h> | |||
| #include "core_pins.h" | |||
| #if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
| const static uint8_t A0 = CORE_ANALOG0_PIN; | |||
| const static uint8_t A1 = CORE_ANALOG1_PIN; | |||
| const static uint8_t A2 = CORE_ANALOG2_PIN; | |||
| const static uint8_t A3 = CORE_ANALOG3_PIN; | |||
| const static uint8_t A4 = CORE_ANALOG4_PIN; | |||
| const static uint8_t A5 = CORE_ANALOG5_PIN; | |||
| const static uint8_t A6 = CORE_ANALOG6_PIN; | |||
| const static uint8_t A7 = CORE_ANALOG7_PIN; | |||
| #if defined(__AVR_ATmega32U4__) | |||
| const static uint8_t A8 = CORE_ANALOG8_PIN; | |||
| const static uint8_t A9 = CORE_ANALOG9_PIN; | |||
| const static uint8_t A10 = 10; | |||
| const static uint8_t A11 = CORE_ANALOG11_PIN; | |||
| #endif | |||
| #endif | |||
| const static uint8_t SS = CORE_SS0_PIN; | |||
| const static uint8_t MOSI = CORE_MOSI0_PIN; | |||
| const static uint8_t MISO = CORE_MISO0_PIN; | |||
| const static uint8_t SCK = CORE_SCLK0_PIN; | |||
| const static uint8_t LED_BUILTIN = CORE_LED0_PIN; | |||
| #if defined(CORE_SDA0_PIN) | |||
| const static uint8_t SDA = CORE_SDA0_PIN; | |||
| #endif | |||
| #if defined(CORE_SCL0_PIN) | |||
| const static uint8_t SCL = CORE_SCL0_PIN; | |||
| #endif | |||
| #define NUM_DIGITAL_PINS CORE_NUM_TOTAL_PINS | |||
| #define NUM_ANALOG_INPUTS CORE_NUM_ANALOG | |||
| // This allows CapSense to work. Do any libraries | |||
| // depend on these to be zero? | |||
| #define NOT_A_PORT 127 | |||
| #define NOT_A_PIN 127 | |||
| #define digitalPinToPort(P) (P) | |||
| #define portInputRegister(P) ((volatile uint8_t *)((int)pgm_read_byte(digital_pin_table_PGM+(P)*2+1))) | |||
| #define portModeRegister(P) (portInputRegister(P) + 1) | |||
| #define portOutputRegister(P) (portInputRegister(P) + 2) | |||
| #define digitalPinToBitMask(P) (pgm_read_byte(digital_pin_table_PGM+(P)*2)) | |||
| extern const uint8_t PROGMEM digital_pin_table_PGM[]; | |||
| #if defined(__AVR_AT90USB162__) | |||
| #define analogInputToDigitalPin(ch) (-1) | |||
| #define digitalPinHasPWM(p) ((p) == 0 || (p) == 15 || (p) == 17 || (p) == 18) | |||
| #elif defined(__AVR_ATmega32U4__) | |||
| #define analogInputToDigitalPin(ch) ((ch) <= 10 ? 21 - (ch) : ((ch) == 11 ? 22 : -1)) | |||
| #define digitalPinHasPWM(p) ((p) == 4 || (p) == 5 || (p) == 9 || (p) == 10 || (p) == 12 || (p) == 14 || (p) == 15) | |||
| #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
| #define analogInputToDigitalPin(ch) ((ch) <= 7 ? (ch) + 38 : -1) | |||
| #define digitalPinHasPWM(p) (((p) >= 14 && (p) <= 16) || ((p) >= 24 && (p) <= 27) || (p) == 0 || (p) == 1) | |||
| #endif | |||
| #if defined(__AVR_AT90USB162__) | |||
| #define digitalPinToPortReg(p) (((p) <= 7) ? &PORTD : (((p) <= 15) ? &PORTB : &PORTC)) | |||
| #define digitalPinToBit(p) \ | |||
| (((p) <= 7) ? (p) : (((p) <= 15) ? (p) - 8 : (((p) <= 19) ? 23 - (p) : 2))) | |||
| #define digitalPinToPCICR(p) \ | |||
| ((((p) >= 8 && (p) <= 15) || ((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCICR : NULL) | |||
| #define digitalPinToPCICRbit(p) (((p) >= 8 && (p) <= 15) ? 0 : 1) | |||
| #define digitalPinToPCIFR(p) \ | |||
| ((((p) >= 8 && (p) <= 15) || ((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCIFR : NULL) | |||
| #define digitalPinToPCIFRbit(p) (((p) >= 8 && (p) <= 15) ? 0 : 1) | |||
| #define digitalPinToPCMSK(p) \ | |||
| (((p) >= 8 && (p) <= 15) ? &PCMSK0 : ((((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCMSK1 : NULL)) | |||
| #define digitalPinToPCMSKbit(p) \ | |||
| (((p) >= 8 && (p) <= 15) ? (p) - 8 : (((p) >= 17 && (p) <= 20) ? (p) - 17 : 4)) | |||
| #elif defined(__AVR_ATmega32U4__) | |||
| #define digitalPinToPortReg(p) \ | |||
| (((p) <= 4) ? &PORTB : (((p) <= 8) ? &PORTD : (((p) <= 10) ? &PORTC : (((p) <= 12) ? &PORTD : \ | |||
| (((p) <= 15) ? &PORTB : (((p) <= 21) ? &PORTF : (((p) <= 23) ? &PORTD : &PORTE))))))) | |||
| #define digitalPinToBit(p) \ | |||
| (((p) <= 3) ? (p) : (((p) == 4) ? 7 : (((p) <= 8) ? (p) - 5 : (((p) <= 10) ? (p) - 3 : \ | |||
| (((p) <= 12) ? (p) - 5 : (((p) <= 15) ? (p) - 9 : (((p) <= 19) ? 23 - (p) : \ | |||
| (((p) <= 21) ? 21 - (p) : (((p) <= 23) ? (p) - 18 : 6))))))))) | |||
| #define digitalPinToPCICR(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCICR : NULL) | |||
| #define digitalPinToPCICRbit(p) (0) | |||
| #define digitalPinToPCIFR(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCIFR : NULL) | |||
| #define digitalPinToPCIFRbit(p) (0) | |||
| #define digitalPinToPCMSK(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCMSK0 : NULL) | |||
| #define digitalPinToPCMSKbit(p) \ | |||
| (((p) >= 0 && (p) <= 3) ? (p) : (((p) >= 13 && (p) <= 15) ? (p) - 9 : 7)) | |||
| #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
| #define digitalPinToPortReg(p) \ | |||
| (((p) >= 0 && (p) <= 7) ? &PORTD : (((p) >= 10 && (p) <= 17) ? &PORTC : \ | |||
| (((p) >= 20 && (p) <= 27) ? &PORTB : (((p) >= 28 && (p) <= 35) ? &PORTA : \ | |||
| (((p) >= 38 && (p) <= 45) ? &PORTF : &PORTE))))) | |||
| #define digitalPinToBit(p) \ | |||
| (((p) <= 7) ? (p) : (((p) <= 9) ? (p) - 8 : (((p) <= 17) ? (p) - 10 : \ | |||
| (((p) <= 19) ? (p) - 12 : (((p) <= 27) ? (p) - 20 : (((p) <= 35) ? (p) - 28 : \ | |||
| (((p) <= 37) ? (p) - 32 : (((p) <= 45) ? (p) - 38 : 2)))))))) | |||
| #define digitalPinToPCICR(p) (((p) >= 20 && (p) <= 27) ? &PCICR : NULL) | |||
| #define digitalPinToPCICRbit(p) (0) | |||
| #define digitalPinToPCIFR(p) (((p) >= 20 && (p) <= 27) ? &PCIFR : NULL) | |||
| #define digitalPinToPCIFRbit(p) (0) | |||
| #define digitalPinToPCMSK(p) (((p) >= 20 && (p) <= 27) ? &PCMSK0 : NULL) | |||
| #define digitalPinToPCMSKbit(p) (((p) - 20) & 7) | |||
| #endif | |||
| #define NOT_ON_TIMER 0 | |||
| static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused)); | |||
| static inline uint8_t digitalPinToTimer(uint8_t pin) | |||
| { | |||
| switch (pin) { | |||
| #ifdef CORE_PWM0_PIN | |||
| case CORE_PWM0_PIN: return 1; | |||
| #endif | |||
| #ifdef CORE_PWM1_PIN | |||
| case CORE_PWM1_PIN: return 2; | |||
| #endif | |||
| #ifdef CORE_PWM2_PIN | |||
| case CORE_PWM2_PIN: return 3; | |||
| #endif | |||
| #ifdef CORE_PWM3_PIN | |||
| case CORE_PWM3_PIN: return 4; | |||
| #endif | |||
| #ifdef CORE_PWM4_PIN | |||
| case CORE_PWM4_PIN: return 5; | |||
| #endif | |||
| #ifdef CORE_PWM5_PIN | |||
| case CORE_PWM5_PIN: return 6; | |||
| #endif | |||
| #ifdef CORE_PWM6_PIN | |||
| case CORE_PWM6_PIN: return 7; | |||
| #endif | |||
| #ifdef CORE_PWM7_PIN | |||
| case CORE_PWM7_PIN: return 8; | |||
| #endif | |||
| #ifdef CORE_PWM8_PIN | |||
| case CORE_PWM8_PIN: return 9; | |||
| #endif | |||
| default: return NOT_ON_TIMER; | |||
| } | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,15 @@ | |||
| #if defined(USB_SERIAL) | |||
| #include "../usb_serial/usb.c" | |||
| #elif defined(USB_HID) | |||
| #include "../usb_hid/usb.c" | |||
| #elif defined(USB_SERIAL_HID) | |||
| #include "../usb_serial_hid/usb.c" | |||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||
| #include "../usb_disk/usb.c" | |||
| #elif defined(USB_MIDI) | |||
| #include "../usb_midi/usb.c" | |||
| #elif defined(USB_RAWHID) | |||
| #include "../usb_rawhid/usb.c" | |||
| #elif defined(USB_FLIGHTSIM) | |||
| #include "../usb_flightsim/usb.c" | |||
| #endif | |||
| @@ -0,0 +1,15 @@ | |||
| #if defined(USB_SERIAL) | |||
| #include "../usb_serial/usb_api.cpp" | |||
| #elif defined(USB_HID) | |||
| #include "../usb_hid/usb_api.cpp" | |||
| #elif defined(USB_SERIAL_HID) | |||
| #include "../usb_serial_hid/usb_api.cpp" | |||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||
| #include "../usb_disk/usb_api.cpp" | |||
| #elif defined(USB_MIDI) | |||
| #include "../usb_midi/usb_api.cpp" | |||
| #elif defined(USB_RAWHID) | |||
| #include "../usb_rawhid/usb_api.cpp" | |||
| #elif defined(USB_FLIGHTSIM) | |||
| #include "../usb_flightsim/usb_api.cpp" | |||
| #endif | |||
| @@ -0,0 +1,15 @@ | |||
| #if defined(USB_SERIAL) | |||
| #include "../usb_serial/usb_api.h" | |||
| #elif defined(USB_HID) | |||
| #include "../usb_hid/usb_api.h" | |||
| #elif defined(USB_SERIAL_HID) | |||
| #include "../usb_serial_hid/usb_api.h" | |||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||
| #include "../usb_disk/usb_api.h" | |||
| #elif defined(USB_MIDI) | |||
| #include "../usb_midi/usb_api.h" | |||
| #elif defined(USB_RAWHID) | |||
| #include "../usb_rawhid/usb_api.h" | |||
| #elif defined(USB_FLIGHTSIM) | |||
| #include "../usb_flightsim/usb_api.h" | |||
| #endif | |||
| @@ -0,0 +1,153 @@ | |||
| #ifndef usb_common_h__ | |||
| #define usb_common_h__ | |||
| #include <stdint.h> | |||
| #include <avr/io.h> | |||
| #include <avr/pgmspace.h> | |||
| #include <avr/interrupt.h> | |||
| #ifdef __cplusplus | |||
| extern "C"{ | |||
| #endif | |||
| #define MAX_ENDPOINT 6 | |||
| #define LSB(n) (n & 255) | |||
| #define MSB(n) ((n >> 8) & 255) | |||
| // constants corresponding to the various serial parameters | |||
| #define USB_SERIAL_DTR 0x01 | |||
| #define USB_SERIAL_RTS 0x02 | |||
| #define USB_SERIAL_1_STOP 0 | |||
| #define USB_SERIAL_1_5_STOP 1 | |||
| #define USB_SERIAL_2_STOP 2 | |||
| #define USB_SERIAL_PARITY_NONE 0 | |||
| #define USB_SERIAL_PARITY_ODD 1 | |||
| #define USB_SERIAL_PARITY_EVEN 2 | |||
| #define USB_SERIAL_PARITY_MARK 3 | |||
| #define USB_SERIAL_PARITY_SPACE 4 | |||
| #define USB_SERIAL_DCD 0x01 | |||
| #define USB_SERIAL_DSR 0x02 | |||
| #define USB_SERIAL_BREAK 0x04 | |||
| #define USB_SERIAL_RI 0x08 | |||
| #define USB_SERIAL_FRAME_ERR 0x10 | |||
| #define USB_SERIAL_PARITY_ERR 0x20 | |||
| #define USB_SERIAL_OVERRUN_ERR 0x40 | |||
| #define EP_TYPE_CONTROL 0x00 | |||
| #define EP_TYPE_BULK_IN 0x81 | |||
| #define EP_TYPE_BULK_OUT 0x80 | |||
| #define EP_TYPE_INTERRUPT_IN 0xC1 | |||
| #define EP_TYPE_INTERRUPT_OUT 0xC0 | |||
| #define EP_TYPE_ISOCHRONOUS_IN 0x41 | |||
| #define EP_TYPE_ISOCHRONOUS_OUT 0x40 | |||
| #define EP_SINGLE_BUFFER 0x02 | |||
| #define EP_DOUBLE_BUFFER 0x06 | |||
| #define EP_SIZE(s) ((s) == 64 ? 0x30 : \ | |||
| ((s) == 32 ? 0x20 : \ | |||
| ((s) == 16 ? 0x10 : \ | |||
| 0x00))) | |||
| #if defined(__AVR_AT90USB162__) | |||
| #define HW_CONFIG() | |||
| #define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0))) | |||
| #define USB_CONFIG() (USBCON = (1<<USBE)) | |||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||
| #elif defined(__AVR_ATmega32U4__) | |||
| #define HW_CONFIG() (UHWCON = 0x01) | |||
| #define PLL_CONFIG() (PLLCSR = 0x12) | |||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||
| #elif defined(__AVR_AT90USB646__) | |||
| #define HW_CONFIG() (UHWCON = 0x81) | |||
| #define PLL_CONFIG() (PLLCSR = 0x1A) | |||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||
| #elif defined(__AVR_AT90USB1286__) | |||
| #define HW_CONFIG() (UHWCON = 0x81) | |||
| #define PLL_CONFIG() (PLLCSR = 0x16) | |||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||
| #endif | |||
| // standard control endpoint request types | |||
| #define GET_STATUS 0 | |||
| #define CLEAR_FEATURE 1 | |||
| #define SET_FEATURE 3 | |||
| #define SET_ADDRESS 5 | |||
| #define GET_DESCRIPTOR 6 | |||
| #define GET_CONFIGURATION 8 | |||
| #define SET_CONFIGURATION 9 | |||
| #define GET_INTERFACE 10 | |||
| #define SET_INTERFACE 11 | |||
| // CDC (communication class device) | |||
| #define CDC_SET_LINE_CODING 0x20 | |||
| #define CDC_GET_LINE_CODING 0x21 | |||
| #define CDC_SET_CONTROL_LINE_STATE 0x22 | |||
| #define CDC_SEND_BREAK 0x23 | |||
| // HID (human interface device) | |||
| #define HID_GET_REPORT 1 | |||
| #define HID_GET_IDLE 2 | |||
| #define HID_GET_PROTOCOL 3 | |||
| #define HID_SET_REPORT 9 | |||
| #define HID_SET_IDLE 10 | |||
| #define HID_SET_PROTOCOL 11 | |||
| // Mass Storage | |||
| #define MS_BULK_ONLY_RESET 0xFF | |||
| #define MS_GET_MAX_LUN 0xFE /* stall = 0 */ | |||
| #define pgm_read_byte_postinc(val, addr) \ | |||
| asm ("lpm %0, Z+\n" : "=r" (val), "+z" (addr) : ) | |||
| #define pgm_read_word_postinc(val, addr) \ | |||
| asm ("lpm %A0, Z+\n\tlpm %B0, Z+\n" : "=r" (val), "+z" (addr) : ) | |||
| #define read_word_lsbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "lds %A0, %1\n\tlds %B0, %1\n" \ | |||
| : "=r" (val) : "M" ((int)(®)) ) | |||
| #define read_word_msbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "lds %B0, %1\n\tlds %A0, %1\n" \ | |||
| : "=r" (val) : "M" ((int)(®)) ) | |||
| #define read_dword_lsbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "lds %A0, %1\n\tlds %B0, %1\n\t" \ | |||
| "lds %C0, %1\n\tlds %D0, %1\n" \ | |||
| : "=r" (val) : "M" ((int)(®)) ) | |||
| #define read_dword_msbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "lds %D0, %1\n\tlds %C0, %1\n\t" \ | |||
| "lds %B0, %1\n\tlds %A0, %1\n" \ | |||
| : "=r" (val) : "M" ((int)(®)) ) | |||
| #define write_word_lsbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "sts %1, %A0\n\tsts %1, %B0\n" \ | |||
| : : "r" (val) , "M" ((int)(®)) ) | |||
| #define write_word_msbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "sts %1, %B0\n\tsts %1, %A0\n" \ | |||
| : : "r" (val) , "M" ((int)(®)) ) | |||
| #define write_dword_lsbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "sts %1, %A0\n\tsts %1, %B0\n\t" \ | |||
| "sts %1, %C0\n\tsts %1, %D0\n" \ | |||
| : : "r" (val) , "M" ((int)(®)) ) | |||
| #define write_dword_msbfirst(val, reg) \ | |||
| asm volatile( \ | |||
| "sts %1, %D0\n\tsts %1, %C0\n\t" \ | |||
| "sts %1, %B0\n\tsts %1, %A0\n" \ | |||
| : : "r" (val) , "M" ((int)(®)) ) | |||
| #define USBSTATE __attribute__ ((section (".noinit"))) | |||
| extern void _reboot_Teensyduino_(void) __attribute__((noreturn)); | |||
| extern void _restart_Teensyduino_(void) __attribute__((noreturn)); | |||
| #ifdef __cplusplus | |||
| } // extern "C" | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,15 @@ | |||
| #if defined(USB_SERIAL) | |||
| #include "../usb_serial/usb_private.h" | |||
| #elif defined(USB_HID) | |||
| #include "../usb_hid/usb_private.h" | |||
| #elif defined(USB_SERIAL_HID) | |||
| #include "../usb_serial_hid/usb_private.h" | |||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||
| #include "../usb_disk/usb_private.h" | |||
| #elif defined(USB_MIDI) | |||
| #include "../usb_midi/usb_private.h" | |||
| #elif defined(USB_RAWHID) | |||
| #include "../usb_rawhid/usb_private.h" | |||
| #elif defined(USB_FLIGHTSIM) | |||
| #include "../usb_flightsim/usb_private.h" | |||
| #endif | |||
| @@ -0,0 +1,80 @@ | |||
| /* | |||
| wiring.c - Partial implementation of the Wiring API for the ATmega8. | |||
| Part of Arduino - http://www.arduino.cc/ | |||
| Copyright (c) 2005-2006 David A. Mellis | |||
| Modified for Teensyduino by Paul Stoffregen, paul@pjrc.com | |||
| http://www.pjrc.com/teensy/teensyduino.html | |||
| 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 | |||
| */ | |||
| #include "wiring_private.h" | |||
| #include "pins_arduino.h" | |||
| #include "core_pins.h" | |||
| #define PULSEIN_CYCLES_PER_LOOP 21 | |||
| #define PULSEIN_CYCLES_LATENCY 11 | |||
| /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH | |||
| * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds | |||
| * to 3 minutes in length, but must be called at least a few dozen microseconds | |||
| * before the start of the pulse. */ | |||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) | |||
| { | |||
| // cache the port and bit of the pin in order to speed up the | |||
| // pulse width measuring loop and achieve finer resolution. calling | |||
| // digitalRead() instead yields much coarser resolution. | |||
| uint8_t bit = digitalPinToBitMask(pin); | |||
| volatile uint8_t *reg = portInputRegister(digitalPinToPort(pin)); | |||
| uint8_t stateMask = (state ? bit : 0); | |||
| unsigned long width = 0; // keep initialization out of time critical area | |||
| // convert the timeout from microseconds to a number of times through | |||
| // the initial loop | |||
| unsigned long numloops = 0; | |||
| //unsigned long maxloops = microsecondsToClockCycles(timeout) / PULSEIN_CYCLES_PER_LOOP; | |||
| unsigned long maxloops = timeout * clockCyclesPerMicrosecond() / PULSEIN_CYCLES_PER_LOOP; | |||
| // wait for any previous pulse to end | |||
| while ((*reg & bit) == stateMask) | |||
| if (numloops++ == maxloops) | |||
| return 0; | |||
| // wait for the pulse to start | |||
| while ((*reg & bit) != stateMask) | |||
| if (numloops++ == maxloops) | |||
| return 0; | |||
| // wait for the pulse to stop | |||
| while ((*reg & bit) == stateMask) { | |||
| width++; | |||
| if (numloops++ == maxloops) | |||
| return 0; | |||
| } | |||
| // convert the reading to microseconds. The loop has been determined | |||
| // to be PULSEIN_CYCLES_LATENCY clock cycles long and have about | |||
| // PULSEIN_CYCLES_PER_LOOP clocks between the edge and the start of | |||
| // the loop. There will be some error introduced by the interrupt | |||
| // handlers. | |||
| //return clockCyclesToMicroseconds(PULSEIN_CYCLES_PER_LOOP * width + PULSEIN_CYCLES_LATENCY); | |||
| return (width * PULSEIN_CYCLES_PER_LOOP + PULSEIN_CYCLES_LATENCY + (clockCyclesPerMicrosecond() / 2)) / clockCyclesPerMicrosecond(); | |||
| } | |||
| @@ -0,0 +1,112 @@ | |||
| /* | |||
| 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: wiring.h 387 2008-03-08 21:30:00Z mellis $ | |||
| */ | |||
| #ifndef Wiring_h | |||
| #define Wiring_h | |||
| #include <avr/io.h> | |||
| #include <stdlib.h> | |||
| #include <math.h> | |||
| #include "binary.h" | |||
| #include "core_id.h" | |||
| #include "core_pins.h" | |||
| #ifdef ID | |||
| #undef ID // ID bit in USBSTA conflicts with user's code | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C"{ | |||
| #endif | |||
| #define true 1 | |||
| #define false 0 | |||
| #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 0 | |||
| #define DISPLAY 1 | |||
| #define CHANGE 1 | |||
| #define FALLING 2 | |||
| #define RISING 3 | |||
| #define INTERNAL 3 | |||
| #define INTERNAL2V56 3 | |||
| #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) / clockCyclesPerMicrosecond() ) | |||
| #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) | |||
| #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; | |||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); | |||
| void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val); | |||
| void attachInterrupt(uint8_t, void (*)(void), uint8_t mode); | |||
| void detachInterrupt(uint8_t); | |||
| void setup(void); | |||
| void loop(void); | |||
| #ifdef __cplusplus | |||
| } // extern "C" | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,72 @@ | |||
| /* | |||
| wiring_private.h - Internal header file. | |||
| 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: wiring.h 239 2007-01-12 17:58:39Z mellis $ | |||
| */ | |||
| #ifndef WiringPrivate_h | |||
| #define WiringPrivate_h | |||
| #include <avr/io.h> | |||
| #include <avr/interrupt.h> | |||
| #include <stdio.h> | |||
| #include <stdarg.h> | |||
| #include "wiring.h" | |||
| #if F_CPU == 16000000L | |||
| #define ADC_PRESCALER 0x07 | |||
| #define CPU_PRESCALER 0x00 | |||
| #elif F_CPU == 8000000L | |||
| #define ADC_PRESCALER 0x06 | |||
| #define CPU_PRESCALER 0x01 | |||
| #elif F_CPU == 4000000L | |||
| #define ADC_PRESCALER 0x05 | |||
| #define CPU_PRESCALER 0x02 | |||
| #elif F_CPU == 2000000L | |||
| #define ADC_PRESCALER 0x04 | |||
| #define CPU_PRESCALER 0x03 | |||
| #elif F_CPU == 1000000L | |||
| #define ADC_PRESCALER 0x03 | |||
| #define CPU_PRESCALER 0x04 | |||
| #else | |||
| #error "Teensyduino only supports 16, 8, 4, 2, 1 MHz. Please edit boards.txt" | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C"{ | |||
| #endif | |||
| #ifndef cbi | |||
| #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | |||
| #endif | |||
| #ifndef sbi | |||
| #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | |||
| #endif | |||
| typedef void (*voidFuncPtr)(void); | |||
| #ifdef __cplusplus | |||
| } // extern "C" | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,2 @@ | |||
| #include "WProgram.h" | |||
| #include "pins_arduino.h" | |||
| @@ -0,0 +1,213 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "AudioStream.h" | |||
| audio_block_t * AudioStream::memory_pool; | |||
| uint8_t AudioStream::memory_pool_size = 0; | |||
| uint32_t AudioStream::memory_pool_available_mask; | |||
| uint16_t AudioStream::cpu_cycles_total = 0; | |||
| uint16_t AudioStream::cpu_cycles_total_max = 0; | |||
| uint8_t AudioStream::memory_used = 0; | |||
| uint8_t AudioStream::memory_used_max = 0; | |||
| // Set up the pool of audio data blocks | |||
| // placing them all onto the free list | |||
| void AudioStream::initialize_memory(audio_block_t *data, unsigned int num) | |||
| { | |||
| //Serial.println("AudioStream initialize_memory"); | |||
| memory_pool = data; | |||
| if (num > 31) num = 31; | |||
| memory_pool_size = num; | |||
| memory_pool_available_mask = 0xFFFFFFFF; | |||
| for (unsigned int i=0; i < num; i++) { | |||
| data[i].memory_pool_index = i; | |||
| } | |||
| } | |||
| // Allocate 1 audio data block. If successful | |||
| // the caller is the only owner of this new block | |||
| audio_block_t * AudioStream::allocate(void) | |||
| { | |||
| uint32_t n, avail; | |||
| audio_block_t *block; | |||
| uint8_t used; | |||
| __disable_irq(); | |||
| avail = memory_pool_available_mask; | |||
| n = __builtin_clz(avail); | |||
| if (n >= memory_pool_size) { | |||
| __enable_irq(); | |||
| return NULL; | |||
| } | |||
| memory_pool_available_mask = avail & ~(0x80000000 >> n); | |||
| used = memory_used + 1; | |||
| memory_used = used; | |||
| __enable_irq(); | |||
| block = memory_pool + n; | |||
| block->ref_count = 1; | |||
| if (used > memory_used_max) memory_used_max = used; | |||
| return block; | |||
| } | |||
| // Release ownership of a data block. If no | |||
| // other streams have ownership, the block is | |||
| // returned to the free pool | |||
| void AudioStream::release(audio_block_t *block) | |||
| { | |||
| uint32_t mask = (0x80000000 >> block->memory_pool_index); | |||
| __disable_irq(); | |||
| if (block->ref_count > 1) { | |||
| block->ref_count--; | |||
| } else { | |||
| memory_pool_available_mask |= mask; | |||
| memory_used--; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| // Transmit an audio data block | |||
| // to all streams that connect to an output. The block | |||
| // becomes owned by all the recepients, but also is still | |||
| // owned by this object. Normally, a block is released | |||
| // after it's transmitted. | |||
| void AudioStream::transmit(audio_block_t *block, unsigned char index) | |||
| { | |||
| for (AudioConnection *c = destination_list; c != NULL; c = c->next_dest) { | |||
| if (c->src_index == index) { | |||
| if (c->dst.inputQueue[c->dest_index] == NULL) { | |||
| c->dst.inputQueue[c->dest_index] = block; | |||
| block->ref_count++; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // Receive block from an input. The block's data | |||
| // may be shared with other streams, so it must not be written | |||
| audio_block_t * AudioStream::receiveReadOnly(unsigned int index) | |||
| { | |||
| audio_block_t *in; | |||
| if (index >= num_inputs) return NULL; | |||
| in = inputQueue[index]; | |||
| inputQueue[index] = NULL; | |||
| return in; | |||
| } | |||
| // Receive block from an input. The block will not | |||
| // be shared, so its contents may be changed. | |||
| audio_block_t * AudioStream::receiveWritable(unsigned int index) | |||
| { | |||
| audio_block_t *in, *p; | |||
| if (index >= num_inputs) return NULL; | |||
| in = inputQueue[index]; | |||
| inputQueue[index] = NULL; | |||
| if (in && in->ref_count > 1) { | |||
| p = allocate(); | |||
| if (p) memcpy(p->data, in->data, sizeof(p->data)); | |||
| in->ref_count--; | |||
| in = p; | |||
| } | |||
| return in; | |||
| } | |||
| void AudioConnection::connect(void) | |||
| { | |||
| AudioConnection *p; | |||
| if (dest_index > dst.num_inputs) return; | |||
| __disable_irq(); | |||
| p = src.destination_list; | |||
| if (p == NULL) { | |||
| src.destination_list = this; | |||
| } else { | |||
| while (p->next_dest) p = p->next_dest; | |||
| p->next_dest = this; | |||
| } | |||
| src.active = true; | |||
| dst.active = true; | |||
| __enable_irq(); | |||
| } | |||
| // When an object has taken responsibility for calling update_all() | |||
| // at each block interval (approx 2.9ms), this variable is set to | |||
| // true. Objects that are capable of calling update_all(), typically | |||
| // input and output based on interrupts, must check this variable in | |||
| // their constructors. | |||
| bool AudioStream::update_scheduled = false; | |||
| bool AudioStream::update_setup(void) | |||
| { | |||
| if (update_scheduled) return false; | |||
| NVIC_SET_PRIORITY(IRQ_SOFTWARE, 0xFF); // 0xFF = lowest priority | |||
| NVIC_ENABLE_IRQ(IRQ_SOFTWARE); | |||
| update_scheduled = true; | |||
| return true; | |||
| } | |||
| AudioStream * AudioStream::first_update = NULL; | |||
| void software_isr(void) // AudioStream::update_all() | |||
| { | |||
| AudioStream *p; | |||
| ARM_DEMCR |= ARM_DEMCR_TRCENA; | |||
| ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; | |||
| uint32_t totalcycles = ARM_DWT_CYCCNT; | |||
| //digitalWriteFast(2, HIGH); | |||
| for (p = AudioStream::first_update; p; p = p->next_update) { | |||
| if (p->active) { | |||
| uint32_t cycles = ARM_DWT_CYCCNT; | |||
| p->update(); | |||
| // TODO: traverse inputQueueArray and release | |||
| // any input blocks that weren't consumed? | |||
| cycles = (ARM_DWT_CYCCNT - cycles) >> 4; | |||
| p->cpu_cycles = cycles; | |||
| if (cycles > p->cpu_cycles_max) p->cpu_cycles_max = cycles; | |||
| } | |||
| } | |||
| //digitalWriteFast(2, LOW); | |||
| totalcycles = (ARM_DWT_CYCCNT - totalcycles) >> 4;; | |||
| AudioStream::cpu_cycles_total = totalcycles; | |||
| if (totalcycles > AudioStream::cpu_cycles_total_max) | |||
| AudioStream::cpu_cycles_total_max = totalcycles; | |||
| } | |||
| @@ -0,0 +1,147 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef AudioStream_h | |||
| #define AudioStream_h | |||
| #include "Arduino.h" | |||
| #define AUDIO_BLOCK_SAMPLES 128 | |||
| #define AUDIO_SAMPLE_RATE 44100 | |||
| #define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256 | |||
| class AudioStream; | |||
| class AudioConnection; | |||
| typedef struct audio_block_struct { | |||
| unsigned char ref_count; | |||
| unsigned char memory_pool_index; | |||
| int16_t data[AUDIO_BLOCK_SAMPLES]; | |||
| } audio_block_t; | |||
| class AudioConnection | |||
| { | |||
| public: | |||
| AudioConnection(AudioStream &source, AudioStream &destination) : | |||
| src(source), dst(destination), src_index(0), dest_index(0), | |||
| next_dest(NULL) | |||
| { connect(); } | |||
| AudioConnection(AudioStream &source, unsigned char sourceOutput, | |||
| AudioStream &destination, unsigned char destinationInput) : | |||
| src(source), dst(destination), | |||
| src_index(sourceOutput), dest_index(destinationInput), | |||
| next_dest(NULL) | |||
| { connect(); } | |||
| friend class AudioStream; | |||
| protected: | |||
| void connect(void); | |||
| AudioStream &src; | |||
| AudioStream &dst; | |||
| unsigned char src_index; | |||
| unsigned char dest_index; | |||
| AudioConnection *next_dest; | |||
| }; | |||
| #define AudioMemory(num) ({ \ | |||
| static DMAMEM audio_block_t data[num]; \ | |||
| AudioStream::initialize_memory(data, num); \ | |||
| }) | |||
| #define CYCLE_COUNTER_APPROX_PERCENT(n) (((n) + (F_CPU / 32 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) / (F_CPU / 16 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) | |||
| #define AudioProcessorUsage() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total)) | |||
| #define AudioProcessorUsageMax() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total_max)) | |||
| #define AudioProcessorUsageMaxReset() (AudioStream::cpu_cycles_total_max = AudioStream::cpu_cycles_total) | |||
| #define AudioMemoryUsage() (AudioStream::memory_used) | |||
| #define AudioMemoryUsageMax() (AudioStream::memory_used_max) | |||
| #define AudioMemoryUsageMaxReset() (AudioStream::memory_used_max = AudioStream::memory_used) | |||
| class AudioStream | |||
| { | |||
| public: | |||
| AudioStream(unsigned char ninput, audio_block_t **iqueue) : | |||
| num_inputs(ninput), inputQueue(iqueue) { | |||
| active = false; | |||
| destination_list = NULL; | |||
| for (int i=0; i < num_inputs; i++) { | |||
| inputQueue[i] = NULL; | |||
| } | |||
| // add to a simple list, for update_all | |||
| // TODO: replace with a proper data flow analysis in update_all | |||
| if (first_update == NULL) { | |||
| first_update = this; | |||
| } else { | |||
| AudioStream *p; | |||
| for (p=first_update; p->next_update; p = p->next_update) ; | |||
| p->next_update = this; | |||
| } | |||
| next_update = NULL; | |||
| cpu_cycles = 0; | |||
| cpu_cycles_max = 0; | |||
| } | |||
| void connect(AudioStream &dest, unsigned char dest_index = 0, unsigned int src_index = 0); | |||
| void disconnect(void); | |||
| static void initialize_memory(audio_block_t *data, unsigned int num); | |||
| int processorUsage(void) { return CYCLE_COUNTER_APPROX_PERCENT(cpu_cycles); } | |||
| int processorUsageMax(void) { return CYCLE_COUNTER_APPROX_PERCENT(cpu_cycles_max); } | |||
| void processorUsageMaxReset(void) { cpu_cycles_max = cpu_cycles; } | |||
| uint16_t cpu_cycles; | |||
| uint16_t cpu_cycles_max; | |||
| static uint16_t cpu_cycles_total; | |||
| static uint16_t cpu_cycles_total_max; | |||
| static uint8_t memory_used; | |||
| static uint8_t memory_used_max; | |||
| protected: | |||
| bool active; | |||
| unsigned char num_inputs; | |||
| static audio_block_t * allocate(void); | |||
| static void release(audio_block_t * block); | |||
| void transmit(audio_block_t *block, unsigned char index = 0); | |||
| audio_block_t * receiveReadOnly(unsigned int index = 0); | |||
| audio_block_t * receiveWritable(unsigned int index = 0); | |||
| static bool update_setup(void); | |||
| static void update_all(void) { NVIC_SET_PENDING(IRQ_SOFTWARE); } | |||
| friend void software_isr(void); | |||
| friend class AudioConnection; | |||
| private: | |||
| AudioConnection *destination_list; | |||
| audio_block_t **inputQueue; | |||
| static bool update_scheduled; | |||
| virtual void update(void) = 0; | |||
| static AudioStream *first_update; // for update_all | |||
| AudioStream *next_update; // for update_all | |||
| static audio_block_t *memory_pool; | |||
| static uint8_t memory_pool_size; | |||
| static uint32_t memory_pool_available_mask; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,29 @@ | |||
| #if ARDUINO >= 100 | |||
| #ifndef client_h | |||
| #define client_h | |||
| #include "Print.h" | |||
| #include "Stream.h" | |||
| #include "IPAddress.h" | |||
| class Client : public Stream { | |||
| public: | |||
| virtual int connect(IPAddress ip, uint16_t port) =0; | |||
| virtual int connect(const char *host, uint16_t port) =0; | |||
| virtual size_t write(uint8_t) =0; | |||
| virtual size_t write(const uint8_t *buf, size_t size) =0; | |||
| virtual int available() = 0; | |||
| virtual int read() = 0; | |||
| virtual int read(uint8_t *buf, size_t size) = 0; | |||
| virtual int peek() = 0; | |||
| virtual void flush() = 0; | |||
| virtual void stop() = 0; | |||
| virtual uint8_t connected() = 0; | |||
| virtual operator bool() = 0; | |||
| protected: | |||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,158 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef HardwareSerial_h | |||
| #define HardwareSerial_h | |||
| #include "mk20dx128.h" | |||
| #include <inttypes.h> | |||
| #define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud)) | |||
| #define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud)) | |||
| // C language implementation | |||
| // | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void serial_begin(uint32_t divisor); | |||
| void serial_end(void); | |||
| void serial_putchar(uint8_t c); | |||
| void serial_write(const void *buf, unsigned int count); | |||
| void serial_flush(void); | |||
| int serial_available(void); | |||
| int serial_getchar(void); | |||
| int serial_peek(void); | |||
| void serial_clear(void); | |||
| void serial_print(const char *p); | |||
| void serial_phex(uint32_t n); | |||
| void serial_phex16(uint32_t n); | |||
| void serial_phex32(uint32_t n); | |||
| void serial2_begin(uint32_t divisor); | |||
| void serial2_end(void); | |||
| void serial2_putchar(uint8_t c); | |||
| void serial2_write(const void *buf, unsigned int count); | |||
| void serial2_flush(void); | |||
| int serial2_available(void); | |||
| int serial2_getchar(void); | |||
| int serial2_peek(void); | |||
| void serial2_clear(void); | |||
| void serial3_begin(uint32_t divisor); | |||
| void serial3_end(void); | |||
| void serial3_putchar(uint8_t c); | |||
| void serial3_write(const void *buf, unsigned int count); | |||
| void serial3_flush(void); | |||
| int serial3_available(void); | |||
| int serial3_getchar(void); | |||
| int serial3_peek(void); | |||
| void serial3_clear(void); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| // C++ interface | |||
| // | |||
| #ifdef __cplusplus | |||
| #include "Stream.h" | |||
| class HardwareSerial : public Stream | |||
| { | |||
| public: | |||
| void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); } | |||
| void end(void) { serial_end(); } | |||
| virtual int available(void) { return serial_available(); } | |||
| virtual int peek(void) { return serial_peek(); } | |||
| virtual int read(void) { return serial_getchar(); } | |||
| virtual void flush(void) { serial_flush(); } | |||
| void clear(void) { serial_clear(); } | |||
| virtual size_t write(uint8_t c) { serial_putchar(c); return 1; } | |||
| size_t write(unsigned long n) { return write((uint8_t)n); } | |||
| size_t write(long n) { return write((uint8_t)n); } | |||
| size_t write(unsigned int n) { return write((uint8_t)n); } | |||
| size_t write(int n) { return write((uint8_t)n); } | |||
| virtual size_t write(const uint8_t *buffer, size_t size) | |||
| { serial_write(buffer, size); return size; } | |||
| size_t write(const char *str) { size_t len = strlen(str); | |||
| serial_write((const uint8_t *)str, len); | |||
| return len; } | |||
| }; | |||
| extern HardwareSerial Serial1; | |||
| class HardwareSerial2 : public HardwareSerial | |||
| { | |||
| public: | |||
| void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); } | |||
| void end(void) { serial2_end(); } | |||
| virtual int available(void) { return serial2_available(); } | |||
| virtual int peek(void) { return serial2_peek(); } | |||
| virtual int read(void) { return serial2_getchar(); } | |||
| virtual void flush(void) { serial2_flush(); } | |||
| void clear(void) { serial2_clear(); } | |||
| virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; } | |||
| size_t write(unsigned long n) { return write((uint8_t)n); } | |||
| size_t write(long n) { return write((uint8_t)n); } | |||
| size_t write(unsigned int n) { return write((uint8_t)n); } | |||
| size_t write(int n) { return write((uint8_t)n); } | |||
| virtual size_t write(const uint8_t *buffer, size_t size) | |||
| { serial2_write(buffer, size); return size; } | |||
| size_t write(const char *str) { size_t len = strlen(str); | |||
| serial2_write((const uint8_t *)str, len); | |||
| return len; } | |||
| }; | |||
| extern HardwareSerial2 Serial2; | |||
| class HardwareSerial3 : public HardwareSerial | |||
| { | |||
| public: | |||
| void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); } | |||
| void end(void) { serial3_end(); } | |||
| virtual int available(void) { return serial3_available(); } | |||
| virtual int peek(void) { return serial3_peek(); } | |||
| virtual int read(void) { return serial3_getchar(); } | |||
| virtual void flush(void) { serial3_flush(); } | |||
| void clear(void) { serial3_clear(); } | |||
| virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; } | |||
| size_t write(unsigned long n) { return write((uint8_t)n); } | |||
| size_t write(long n) { return write((uint8_t)n); } | |||
| size_t write(unsigned int n) { return write((uint8_t)n); } | |||
| size_t write(int n) { return write((uint8_t)n); } | |||
| virtual size_t write(const uint8_t *buffer, size_t size) | |||
| { serial3_write(buffer, size); return size; } | |||
| size_t write(const char *str) { size_t len = strlen(str); | |||
| serial3_write((const uint8_t *)str, len); | |||
| return len; } | |||
| }; | |||
| extern HardwareSerial3 Serial3; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,4 @@ | |||
| #include "HardwareSerial.h" | |||
| HardwareSerial Serial1; | |||
| @@ -0,0 +1,4 @@ | |||
| #include "HardwareSerial.h" | |||
| HardwareSerial2 Serial2; | |||
| @@ -0,0 +1,4 @@ | |||
| #include "HardwareSerial.h" | |||
| HardwareSerial3 Serial3; | |||
| @@ -0,0 +1,57 @@ | |||
| #if ARDUINO >= 100 | |||
| #include "Arduino.h" | |||
| #include "IPAddress.h" | |||
| IPAddress::IPAddress() | |||
| { | |||
| memset(_address, 0, sizeof(_address)); | |||
| } | |||
| IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) | |||
| { | |||
| _address[0] = first_octet; | |||
| _address[1] = second_octet; | |||
| _address[2] = third_octet; | |||
| _address[3] = fourth_octet; | |||
| } | |||
| IPAddress::IPAddress(uint32_t address) | |||
| { | |||
| memcpy(_address, &address, sizeof(_address)); | |||
| } | |||
| IPAddress::IPAddress(const uint8_t *address) | |||
| { | |||
| memcpy(_address, address, sizeof(_address)); | |||
| } | |||
| IPAddress& IPAddress::operator=(const uint8_t *address) | |||
| { | |||
| memcpy(_address, address, sizeof(_address)); | |||
| return *this; | |||
| } | |||
| IPAddress& IPAddress::operator=(uint32_t address) | |||
| { | |||
| memcpy(_address, (const uint8_t *)&address, sizeof(_address)); | |||
| return *this; | |||
| } | |||
| bool IPAddress::operator==(const uint8_t* addr) | |||
| { | |||
| return memcmp(addr, _address, sizeof(_address)) == 0; | |||
| } | |||
| size_t IPAddress::printTo(Print& p) const | |||
| { | |||
| size_t n = 0; | |||
| for (int i =0; i < 3; i++) | |||
| { | |||
| n += p.print(_address[i], DEC); | |||
| n += p.print('.'); | |||
| } | |||
| n += p.print(_address[3], DEC); | |||
| return n; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,82 @@ | |||
| /* | |||
| * | |||
| * MIT License: | |||
| * Copyright (c) 2011 Adrian McEwen | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| * | |||
| * adrianm@mcqn.com 1/1/2011 | |||
| */ | |||
| #if ARDUINO >= 100 | |||
| #ifndef IPAddress_h | |||
| #define IPAddress_h | |||
| #include <Printable.h> | |||
| // A class to make it easier to handle and pass around IP addresses | |||
| class IPAddress : public Printable { | |||
| private: | |||
| uint8_t _address[4]; // IPv4 address | |||
| // Access the raw byte array containing the address. Because this returns a pointer | |||
| // to the internal structure rather than a copy of the address this function should only | |||
| // be used when you know that the usage of the returned uint8_t* will be transient and not | |||
| // stored. | |||
| uint8_t* raw_address() { return _address; }; | |||
| public: | |||
| // Constructors | |||
| IPAddress(); | |||
| IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); | |||
| IPAddress(uint32_t address); | |||
| IPAddress(const uint8_t *address); | |||
| // Overloaded cast operator to allow IPAddress objects to be used where a pointer | |||
| // to a four-byte uint8_t array is expected | |||
| operator uint32_t () { return _address[0] | (_address[1] << 8) | |||
| | (_address[2] << 16) | (_address[3] << 24); } | |||
| bool operator==(const IPAddress& addr) { return _address[0] == addr._address[0] | |||
| && _address[1] == addr._address[1] | |||
| && _address[2] == addr._address[2] | |||
| && _address[3] == addr._address[3]; } | |||
| bool operator==(const uint8_t* addr); | |||
| // Overloaded index operator to allow getting and setting individual octets of the address | |||
| uint8_t operator[](int index) const { return _address[index]; }; | |||
| uint8_t& operator[](int index) { return _address[index]; }; | |||
| // Overloaded copy operators to allow initialisation of IPAddress objects from other types | |||
| IPAddress& operator=(const uint8_t *address); | |||
| IPAddress& operator=(uint32_t address); | |||
| virtual size_t printTo(Print& p) const; | |||
| friend class EthernetClass; | |||
| friend class UDP; | |||
| friend class Client; | |||
| friend class Server; | |||
| friend class DhcpClass; | |||
| friend class DNSClient; | |||
| }; | |||
| const IPAddress INADDR_NONE(0,0,0,0); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,185 @@ | |||
| /* Copyright (c) 2013 Daniel Gilbert, loglow@gmail.com | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | |||
| this software and associated documentation files (the "Software"), to deal in the | |||
| Software without restriction, including without limitation the rights to use, copy, | |||
| modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |||
| and to permit persons to whom the Software is furnished to do so, subject to the | |||
| following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |||
| INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ | |||
| #include "IntervalTimer.h" | |||
| // ------------------------------------------------------------ | |||
| // static class variables need to be reiterated here before use | |||
| // ------------------------------------------------------------ | |||
| bool IntervalTimer::PIT_enabled; | |||
| bool IntervalTimer::PIT_used[]; | |||
| IntervalTimer::ISR IntervalTimer::PIT_ISR[]; | |||
| // ------------------------------------------------------------ | |||
| // these are the ISRs (Interrupt Service Routines) that get | |||
| // called by each PIT timer when it fires. they're defined here | |||
| // so that they can auto-clear themselves and so the user can | |||
| // specify a custom ISR and reassign it as needed | |||
| // ------------------------------------------------------------ | |||
| void pit0_isr() { PIT_TFLG0 = 1; IntervalTimer::PIT_ISR[0](); } | |||
| void pit1_isr() { PIT_TFLG1 = 1; IntervalTimer::PIT_ISR[1](); } | |||
| void pit2_isr() { PIT_TFLG2 = 1; IntervalTimer::PIT_ISR[2](); } | |||
| void pit3_isr() { PIT_TFLG3 = 1; IntervalTimer::PIT_ISR[3](); } | |||
| // ------------------------------------------------------------ | |||
| // this function inits and starts the timer, using the specified | |||
| // function as a callback and the period provided. must be passed | |||
| // the name of a function taking no arguments and returning void. | |||
| // make sure this function can complete within the time allowed. | |||
| // attempts to allocate a timer using available resources, | |||
| // returning true on success or false in case of failure. | |||
| // period is specified as number of bus cycles | |||
| // ------------------------------------------------------------ | |||
| bool IntervalTimer::beginCycles(ISR newISR, uint32_t newValue) { | |||
| // if this interval timer is already running, stop it | |||
| if (status == TIMER_PIT) { | |||
| stop_PIT(); | |||
| status = TIMER_OFF; | |||
| } | |||
| // store callback pointer | |||
| myISR = newISR; | |||
| // attempt to allocate this timer | |||
| if (allocate_PIT(newValue)) status = TIMER_PIT; | |||
| else status = TIMER_OFF; | |||
| // check for success and return | |||
| if (status != TIMER_OFF) return true; | |||
| return false; | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // stop the timer if it's currently running, using its status | |||
| // to determine what hardware resources the timer may be using | |||
| // ------------------------------------------------------------ | |||
| void IntervalTimer::end() { | |||
| if (status == TIMER_PIT) stop_PIT(); | |||
| status = TIMER_OFF; | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // enables the PIT clock bit, the master PIT reg, and sets flag | |||
| // ------------------------------------------------------------ | |||
| void IntervalTimer::enable_PIT() { | |||
| SIM_SCGC6 |= SIM_SCGC6_PIT; | |||
| PIT_MCR = 0; | |||
| PIT_enabled = true; | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // disables the master PIT reg, the PIT clock bit, and unsets flag | |||
| // ------------------------------------------------------------ | |||
| void IntervalTimer::disable_PIT() { | |||
| PIT_MCR = 1; | |||
| SIM_SCGC6 &= ~SIM_SCGC6_PIT; | |||
| PIT_enabled = false; | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // enables the PIT clock if not already enabled, then checks to | |||
| // see if any PITs are available for use. if one is available, | |||
| // it's initialized and started with the specified value, and | |||
| // the function returns true, otherwise it returns false | |||
| // ------------------------------------------------------------ | |||
| bool IntervalTimer::allocate_PIT(uint32_t newValue) { | |||
| // enable clock to the PIT module if necessary | |||
| if (!PIT_enabled) enable_PIT(); | |||
| // check for an available PIT, and if so, start it | |||
| for (uint8_t id = 0; id < NUM_PIT; id++) { | |||
| if (!PIT_used[id]) { | |||
| PIT_id = id; | |||
| start_PIT(newValue); | |||
| PIT_used[id] = true; | |||
| return true; | |||
| } | |||
| } | |||
| // no PIT available | |||
| return false; | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // configuters a PIT's registers, function pointer, and enables | |||
| // interrupts, effectively starting the timer upon completion | |||
| // ------------------------------------------------------------ | |||
| void IntervalTimer::start_PIT(uint32_t newValue) { | |||
| // point to the correct registers | |||
| PIT_LDVAL = &PIT_LDVAL0 + PIT_id * 4; | |||
| PIT_TCTRL = &PIT_TCTRL0 + PIT_id * 4; | |||
| IRQ_PIT_CH = IRQ_PIT_CH0 + PIT_id; | |||
| // point to the correct PIT ISR | |||
| PIT_ISR[PIT_id] = myISR; | |||
| // write value to register and enable interrupt | |||
| *PIT_TCTRL = 0; | |||
| *PIT_LDVAL = newValue; | |||
| *PIT_TCTRL = 3; | |||
| NVIC_ENABLE_IRQ(IRQ_PIT_CH); | |||
| } | |||
| // ------------------------------------------------------------ | |||
| // stops an active PIT by disabling its interrupt, writing to | |||
| // its control register, and freeing up its state for future use. | |||
| // also, if no PITs remain in use, disables the core PIT clock | |||
| // ------------------------------------------------------------ | |||
| void IntervalTimer::stop_PIT() { | |||
| // disable interrupt and PIT | |||
| NVIC_DISABLE_IRQ(IRQ_PIT_CH); | |||
| *PIT_TCTRL = 0; | |||
| // free PIT for future use | |||
| PIT_used[PIT_id] = false; | |||
| // check if we're still using any PIT | |||
| for (uint8_t id = 0; id < NUM_PIT; id++) { | |||
| if (PIT_used[id]) return; | |||
| } | |||
| // none used, disable PIT clock | |||
| disable_PIT(); | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| /* Copyright (c) 2013 Daniel Gilbert, loglow@gmail.com | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | |||
| this software and associated documentation files (the "Software"), to deal in the | |||
| Software without restriction, including without limitation the rights to use, copy, | |||
| modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |||
| and to permit persons to whom the Software is furnished to do so, subject to the | |||
| following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |||
| INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ | |||
| #ifndef __INTERVALTIMER_H__ | |||
| #define __INTERVALTIMER_H__ | |||
| #include <stdint.h> | |||
| #include "mk20dx128.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| class IntervalTimer { | |||
| private: | |||
| typedef void (*ISR)(); | |||
| typedef volatile uint32_t* reg; | |||
| enum {TIMER_OFF, TIMER_PIT}; | |||
| static const uint8_t NUM_PIT = 4; | |||
| static const uint32_t MAX_PERIOD = UINT32_MAX / (F_BUS / 1000000.0); | |||
| static void enable_PIT(); | |||
| static void disable_PIT(); | |||
| static bool PIT_enabled; | |||
| static bool PIT_used[NUM_PIT]; | |||
| bool allocate_PIT(uint32_t newValue); | |||
| void start_PIT(uint32_t newValue); | |||
| void stop_PIT(); | |||
| bool status; | |||
| uint8_t PIT_id; | |||
| reg PIT_LDVAL; | |||
| reg PIT_TCTRL; | |||
| uint8_t IRQ_PIT_CH; | |||
| ISR myISR; | |||
| bool beginCycles(ISR newISR, uint32_t cycles); | |||
| public: | |||
| IntervalTimer() { status = TIMER_OFF; } | |||
| ~IntervalTimer() { end(); } | |||
| bool begin(ISR newISR, unsigned int newPeriod) { | |||
| if (newPeriod == 0 || newPeriod > MAX_PERIOD) return false; | |||
| uint32_t newValue = (F_BUS / 1000000) * newPeriod - 1; | |||
| return beginCycles(newISR, newValue); | |||
| } | |||
| bool begin(ISR newISR, int newPeriod) { | |||
| if (newPeriod < 0) return false; | |||
| return begin(newISR, (unsigned int)newPeriod); | |||
| } | |||
| bool begin(ISR newISR, unsigned long newPeriod) { | |||
| return begin(newISR, (unsigned int)newPeriod); | |||
| } | |||
| bool begin(ISR newISR, long newPeriod) { | |||
| return begin(newISR, (int)newPeriod); | |||
| } | |||
| bool begin(ISR newISR, float newPeriod) { | |||
| if (newPeriod <= 0 || newPeriod > MAX_PERIOD) return false; | |||
| uint32_t newValue = (float)(F_BUS / 1000000) * newPeriod + 0.5; | |||
| if (newValue < 40) return false; | |||
| return beginCycles(newISR, newValue); | |||
| } | |||
| bool begin(ISR newISR, double newPeriod) { | |||
| return begin(newISR, (float)newPeriod); | |||
| } | |||
| void end(); | |||
| static ISR PIT_ISR[NUM_PIT]; | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,81 @@ | |||
| # The name of your project (used to name the compiled .hex file) | |||
| TARGET = main | |||
| # configurable options | |||
| OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH | |||
| # options needed by many Arduino libraries to configure for Teensy 3.0 | |||
| OPTIONS += -D__MK20DX128__ -DARDUIO=104 | |||
| #************************************************************************ | |||
| # Location of Teensyduino utilities, Toolchain, and Arduino Libraries. | |||
| # To use this makefile without Arduino, copy the resources from these | |||
| # locations and edit the pathnames. The rest of Arduino is not needed. | |||
| #************************************************************************ | |||
| # path location for Teensy Loader, teensy_post_compile and teensy_reboot | |||
| TOOLSPATH = ../../../tools # on Linux | |||
| #TOOLSPATH = ../../../tools/avr/bin # on Mac or Windows | |||
| # path location for Arduino libraries (currently not used) | |||
| LIBRARYPATH = ../../../../libraries | |||
| # path location for the arm-none-eabi compiler | |||
| COMPILERPATH = ../../../tools/arm-none-eabi/bin | |||
| #************************************************************************ | |||
| # Settings below this point usually do not need to be edited | |||
| #************************************************************************ | |||
| # CPPFLAGS = compiler options for C and C++ | |||
| CPPFLAGS = -Wall -g -Os -mcpu=cortex-m4 -mthumb -nostdlib -MMD $(OPTIONS) -I. | |||
| # compiler options for C++ only | |||
| CXXFLAGS = -std=gnu++0x -felide-constructors -fno-exceptions -fno-rtti | |||
| # compiler options for C only | |||
| CFLAGS = | |||
| # linker options | |||
| LDFLAGS = -Os -Wl,--gc-sections -mcpu=cortex-m4 -mthumb -Tmk20dx128.ld | |||
| # additional libraries to link | |||
| LIBS = -lm | |||
| # names for the compiler programs | |||
| CC = $(abspath $(COMPILERPATH))/arm-none-eabi-gcc | |||
| CXX = $(abspath $(COMPILERPATH))/arm-none-eabi-g++ | |||
| OBJCOPY = $(abspath $(COMPILERPATH))/arm-none-eabi-objcopy | |||
| SIZE = $(abspath $(COMPILERPATH))/arm-none-eabi-size | |||
| # automatically create lists of the sources and objects | |||
| # TODO: this does not handle Arduino libraries yet... | |||
| C_FILES := $(wildcard *.c) | |||
| CPP_FILES := $(wildcard *.cpp) | |||
| OBJS := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o) | |||
| # the actual makefile rules (all .o files built by GNU make's default implicit rules) | |||
| all: $(TARGET).hex | |||
| $(TARGET).elf: $(OBJS) mk20dx128.ld | |||
| $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) | |||
| %.hex: %.elf | |||
| $(SIZE) $< | |||
| $(OBJCOPY) -O ihex -R .eeprom $< $@ | |||
| $(abspath $(TOOLSPATH))/teensy_post_compile -file=$(basename $@) -path=$(shell pwd) -tools=$(abspath $(TOOLSPATH)) | |||
| -$(abspath $(TOOLSPATH))/teensy_reboot | |||
| # compiler generated dependency info | |||
| -include $(OBJS:.o=.d) | |||
| clean: | |||
| rm -f *.o *.d $(TARGET).elf $(TARGET).hex | |||
| @@ -0,0 +1,157 @@ | |||
| /* | |||
| Print.cpp - Base class that provides print() and println() | |||
| Copyright (c) 2008 David A. Mellis. All right reserved. | |||
| many modifications, by Paul Stoffregen <paul@pjrc.com> | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| Modified 23 November 2006 by David A. Mellis | |||
| */ | |||
| //#include <stdio.h> | |||
| //#include <string.h> | |||
| #include <inttypes.h> | |||
| //#include <math.h> | |||
| //#include <avr/pgmspace.h> | |||
| //#include "wiring.h" | |||
| #include "Print.h" | |||
| size_t Print::write(const uint8_t *buffer, size_t size) | |||
| { | |||
| size_t count = 0; | |||
| while (size--) count += write(*buffer++); | |||
| return count; | |||
| } | |||
| size_t Print::print(const String &s) | |||
| { | |||
| uint8_t buffer[33]; | |||
| size_t count = 0; | |||
| unsigned int index = 0; | |||
| unsigned int len = s.length(); | |||
| while (len > 0) { | |||
| s.getBytes(buffer, sizeof(buffer), index); | |||
| unsigned int nbytes = len; | |||
| if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1; | |||
| index += nbytes; | |||
| len -= nbytes; | |||
| count += write(buffer, nbytes); | |||
| } | |||
| return count; | |||
| } | |||
| size_t Print::print(long n) | |||
| { | |||
| uint8_t sign=0; | |||
| if (n < 0) { | |||
| sign = '-'; | |||
| n = -n; | |||
| } | |||
| return printNumber(n, 10, sign); | |||
| } | |||
| size_t Print::println(void) | |||
| { | |||
| uint8_t buf[2]={'\r', '\n'}; | |||
| return write(buf, 2); | |||
| } | |||
| size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign) | |||
| { | |||
| uint8_t buf[34]; | |||
| uint8_t digit, i; | |||
| // TODO: make these checks as inline, since base is | |||
| // almost always a constant. base = 0 (BYTE) should | |||
| // inline as a call directly to write() | |||
| if (base == 0) { | |||
| return write((uint8_t)n); | |||
| } else if (base == 1) { | |||
| base = 10; | |||
| } | |||
| if (n == 0) { | |||
| buf[sizeof(buf) - 1] = '0'; | |||
| i = sizeof(buf) - 1; | |||
| } else { | |||
| i = sizeof(buf) - 1; | |||
| while (1) { | |||
| digit = n % base; | |||
| buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); | |||
| n /= base; | |||
| if (n == 0) break; | |||
| i--; | |||
| } | |||
| } | |||
| if (sign) { | |||
| i--; | |||
| buf[i] = '-'; | |||
| } | |||
| return write(buf + i, sizeof(buf) - i); | |||
| } | |||
| size_t Print::printFloat(double number, uint8_t digits) | |||
| { | |||
| uint8_t sign=0; | |||
| size_t count=0; | |||
| // Handle negative numbers | |||
| if (number < 0.0) { | |||
| sign = 1; | |||
| number = -number; | |||
| } | |||
| // Round correctly so that print(1.999, 2) prints as "2.00" | |||
| double rounding = 0.5; | |||
| for (uint8_t i=0; i<digits; ++i) { | |||
| rounding *= 0.1; | |||
| } | |||
| number += rounding; | |||
| // Extract the integer part of the number and print it | |||
| unsigned long int_part = (unsigned long)number; | |||
| double remainder = number - (double)int_part; | |||
| count += printNumber(int_part, 10, sign); | |||
| // Print the decimal point, but only if there are digits beyond | |||
| if (digits > 0) { | |||
| uint8_t n, buf[8], count=1; | |||
| buf[0] = '.'; | |||
| // Extract digits from the remainder one at a time | |||
| if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1; | |||
| while (digits-- > 0) { | |||
| remainder *= 10.0; | |||
| n = (uint8_t)(remainder); | |||
| buf[count++] = '0' + n; | |||
| remainder -= n; | |||
| } | |||
| count += write(buf, count); | |||
| } | |||
| return count; | |||
| } | |||
| @@ -0,0 +1,105 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef Print_h | |||
| #define Print_h | |||
| #include <inttypes.h> | |||
| #include <stdio.h> // for size_t - gives sprintf and other stuff to all sketches & libs | |||
| #include "core_id.h" | |||
| #include "WString.h" | |||
| #include "Printable.h" | |||
| #define DEC 10 | |||
| #define HEX 16 | |||
| #define OCT 8 | |||
| #define BIN 2 | |||
| #define BYTE 0 | |||
| class __FlashStringHelper; | |||
| class Print | |||
| { | |||
| public: | |||
| Print() : write_error(0) {} | |||
| virtual size_t write(uint8_t b) = 0; | |||
| size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } | |||
| virtual size_t write(const uint8_t *buffer, size_t size); | |||
| size_t print(const String &s); | |||
| size_t print(char c) { return write((uint8_t)c); } | |||
| size_t print(const char s[]) { return write(s); } | |||
| size_t print(const __FlashStringHelper *f) { return write((const char *)f); } | |||
| size_t print(uint8_t b) { return printNumber(b, 10, 0); } | |||
| size_t print(int n) { return print((long)n); } | |||
| size_t print(unsigned int n) { return printNumber(n, 10, 0); } | |||
| size_t print(long n); | |||
| size_t print(unsigned long n) { return printNumber(n, 10, 0); } | |||
| size_t print(unsigned char n, int base) { return printNumber(n, base, 0); } | |||
| size_t print(int n, int base) { return (base == 10) ? print(n) : printNumber(n, base, 0); } | |||
| size_t print(unsigned int n, int base) { return printNumber(n, base, 0); } | |||
| size_t print(long n, int base) { return (base == 10) ? print(n) : printNumber(n, base, 0); } | |||
| size_t print(unsigned long n, int base) { return printNumber(n, base, 0); } | |||
| size_t print(double n, int digits = 2) { return printFloat(n, digits); } | |||
| size_t print(const Printable &obj) { return obj.printTo(*this); } | |||
| size_t println(void); | |||
| size_t println(const String &s) { return print(s) + println(); } | |||
| size_t println(char c) { return print(c) + println(); } | |||
| size_t println(const char s[]) { return print(s) + println(); } | |||
| size_t println(const __FlashStringHelper *f) { return print(f) + println(); } | |||
| size_t println(uint8_t b) { return print(b) + println(); } | |||
| size_t println(int n) { return print(n) + println(); } | |||
| size_t println(unsigned int n) { return print(n) + println(); } | |||
| size_t println(long n) { return print(n) + println(); } | |||
| size_t println(unsigned long n) { return print(n) + println(); } | |||
| size_t println(unsigned char n, int base) { return print(n, base) + println(); } | |||
| size_t println(int n, int base) { return print(n, base) + println(); } | |||
| size_t println(unsigned int n, int base) { return print(n, base) + println(); } | |||
| size_t println(long n, int base) { return print(n, base) + println(); } | |||
| size_t println(unsigned long n, int base) { return print(n, base) + println(); } | |||
| size_t println(double n, int digits = 2) { return print(n, digits) + println(); } | |||
| size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } | |||
| int getWriteError() { return write_error; } | |||
| void clearWriteError() { setWriteError(0); } | |||
| size_t printNumber(unsigned long n, uint8_t base, uint8_t sign); | |||
| protected: | |||
| void setWriteError(int err = 1) { write_error = err; } | |||
| private: | |||
| char write_error; | |||
| size_t printFloat(double n, uint8_t digits); | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,55 @@ | |||
| /* | |||
| 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 | |||
| #ifdef __cplusplus | |||
| #include <stdlib.h> | |||
| inline void * operator new(unsigned int size) __attribute__((always_inline, unused)); | |||
| inline void * operator new(unsigned int size) | |||
| { | |||
| return malloc(size); | |||
| } | |||
| inline void operator delete(void * ptr) __attribute__((always_inline, unused)); | |||
| inline void operator delete(void * ptr) | |||
| { | |||
| free(ptr); | |||
| } | |||
| 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 | |||
| #endif | |||
| @@ -0,0 +1,12 @@ | |||
| #if ARDUINO >= 100 | |||
| #ifndef server_h | |||
| #define server_h | |||
| class Server : public Print { | |||
| public: | |||
| virtual void begin() =0; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,312 @@ | |||
| /* | |||
| Stream.cpp - adds parsing methods to Stream class | |||
| Copyright (c) 2008 David A. Mellis. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| Created July 2011 | |||
| parsing functions based on TextFinder library by Michael Margolis | |||
| */ | |||
| #include "Arduino.h" | |||
| #include "Stream.h" | |||
| #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait | |||
| #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field | |||
| // private method to read stream with timeout | |||
| int Stream::timedRead() | |||
| { | |||
| int c; | |||
| unsigned long startMillis = millis(); | |||
| do { | |||
| c = read(); | |||
| if (c >= 0) return c; | |||
| yield(); | |||
| } while(millis() - startMillis < _timeout); | |||
| return -1; // -1 indicates timeout | |||
| } | |||
| // private method to peek stream with timeout | |||
| int Stream::timedPeek() | |||
| { | |||
| int c; | |||
| unsigned long startMillis = millis(); | |||
| do { | |||
| c = peek(); | |||
| if (c >= 0) return c; | |||
| yield(); | |||
| } while(millis() - startMillis < _timeout); | |||
| return -1; // -1 indicates timeout | |||
| } | |||
| // returns peek of the next digit in the stream or -1 if timeout | |||
| // discards non-numeric characters | |||
| int Stream::peekNextDigit() | |||
| { | |||
| int c; | |||
| while (1) { | |||
| c = timedPeek(); | |||
| if (c < 0) return c; // timeout | |||
| if (c == '-') return c; | |||
| if (c >= '0' && c <= '9') return c; | |||
| read(); // discard non-numeric | |||
| } | |||
| } | |||
| // Public Methods | |||
| ////////////////////////////////////////////////////////////// | |||
| void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait | |||
| { | |||
| _timeout = timeout; | |||
| } | |||
| // find returns true if the target string is found | |||
| bool Stream::find(char *target) | |||
| { | |||
| return findUntil(target, NULL); | |||
| } | |||
| // reads data from the stream until the target string of given length is found | |||
| // returns true if target string is found, false if timed out | |||
| bool Stream::find(char *target, size_t length) | |||
| { | |||
| return findUntil(target, length, NULL, 0); | |||
| } | |||
| // as find but search ends if the terminator string is found | |||
| bool Stream::findUntil(char *target, char *terminator) | |||
| { | |||
| return findUntil(target, strlen(target), terminator, strlen(terminator)); | |||
| } | |||
| // reads data from the stream until the target string of the given length is found | |||
| // search terminated if the terminator string is found | |||
| // returns true if target string is found, false if terminated or timed out | |||
| bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) | |||
| { | |||
| size_t index = 0; // maximum target string length is 64k bytes! | |||
| size_t termIndex = 0; | |||
| int c; | |||
| if( *target == 0) | |||
| return true; // return true if target is a null string | |||
| while( (c = timedRead()) > 0){ | |||
| if( c == target[index]){ | |||
| //////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 = peekNextDigit(); | |||
| // ignore non numeric leading characters | |||
| if(c < 0) | |||
| return 0; // zero returned if timeout | |||
| do{ | |||
| if(c == skipChar) | |||
| ; // ignore this charactor | |||
| else if(c == '-') | |||
| isNegative = true; | |||
| else if(c >= '0' && c <= '9') // is c a digit? | |||
| value = value * 10 + c - '0'; | |||
| read(); // consume the character we got with peek | |||
| c = timedPeek(); | |||
| } | |||
| while( (c >= '0' && c <= '9') || c == skipChar ); | |||
| if(isNegative) | |||
| value = -value; | |||
| return value; | |||
| } | |||
| // as parseInt but returns a floating point value | |||
| float Stream::parseFloat() | |||
| { | |||
| return parseFloat(NO_SKIP_CHAR); | |||
| } | |||
| // as above but the given skipChar is ignored | |||
| // this allows format characters (typically commas) in values to be ignored | |||
| float Stream::parseFloat(char skipChar){ | |||
| boolean isNegative = false; | |||
| boolean isFraction = false; | |||
| long value = 0; | |||
| char c; | |||
| float fraction = 1.0; | |||
| c = peekNextDigit(); | |||
| // ignore non numeric leading characters | |||
| if(c < 0) | |||
| return 0; // zero returned if timeout | |||
| do{ | |||
| if(c == skipChar) | |||
| ; // ignore | |||
| else if(c == '-') | |||
| isNegative = true; | |||
| else if (c == '.') | |||
| isFraction = true; | |||
| else if(c >= '0' && c <= '9') { // is c a digit? | |||
| value = value * 10 + c - '0'; | |||
| if(isFraction) | |||
| fraction *= 0.1; | |||
| } | |||
| read(); // consume the character we got with peek | |||
| c = timedPeek(); | |||
| } | |||
| while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); | |||
| if(isNegative) | |||
| value = -value; | |||
| if(isFraction) | |||
| return value * fraction; | |||
| else | |||
| return value; | |||
| } | |||
| // read characters from stream into buffer | |||
| // terminates if length characters have been read, or timeout (see setTimeout) | |||
| // returns the number of characters placed in the buffer | |||
| // the buffer is NOT null terminated. | |||
| // | |||
| size_t Stream::readBytes(char *buffer, size_t length) | |||
| { | |||
| size_t count = 0; | |||
| while (count < length) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; | |||
| } | |||
| *buffer++ = (char)c; | |||
| count++; | |||
| } | |||
| return count; | |||
| } | |||
| // as readBytes with terminator character | |||
| // terminates if length characters have been read, timeout, or if the terminator character detected | |||
| // returns the number of characters placed in the buffer (0 means no valid data found) | |||
| size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) | |||
| { | |||
| if (length < 1) return 0; | |||
| length--; | |||
| size_t index = 0; | |||
| while (index < length) { | |||
| int c = timedRead(); | |||
| if (c == terminator) break; | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; | |||
| } | |||
| *buffer++ = (char)c; | |||
| index++; | |||
| } | |||
| *buffer = 0; | |||
| return index; // return number of characters, not including null terminator | |||
| } | |||
| String Stream::readString(size_t max) | |||
| { | |||
| String str; | |||
| size_t length = str.length(); | |||
| while (length < max) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; // timeout | |||
| } | |||
| if (c == 0) break; | |||
| str += (char)c; | |||
| } | |||
| return str; | |||
| } | |||
| String Stream::readStringUntil(char terminator, size_t max) | |||
| { | |||
| String str; | |||
| size_t length = str.length(); | |||
| while (length < max) { | |||
| int c = timedRead(); | |||
| if (c < 0) { | |||
| setReadError(); | |||
| break; // timeout | |||
| } | |||
| if (c == 0 || c == terminator) break; | |||
| str += (char)c; | |||
| } | |||
| return str; | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| Stream.h - base class for character-based streams. | |||
| Copyright (c) 2010 David A. Mellis. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef Stream_h | |||
| #define Stream_h | |||
| #include <inttypes.h> | |||
| #include "Print.h" | |||
| class Stream : public Print | |||
| { | |||
| public: | |||
| Stream() : _timeout(1000), read_error(0) {} | |||
| virtual int available() = 0; | |||
| virtual int read() = 0; | |||
| virtual int peek() = 0; | |||
| virtual void flush() = 0; | |||
| void setTimeout(unsigned long timeout); | |||
| bool find(char *target); | |||
| bool find(char *target, size_t length); | |||
| bool findUntil(char *target, char *terminator); | |||
| bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); | |||
| long parseInt(); | |||
| long parseInt(char skipChar); | |||
| float parseFloat(); | |||
| float parseFloat(char skipChar); | |||
| size_t readBytes(char *buffer, size_t length); | |||
| size_t readBytesUntil(char terminator, char *buffer, size_t length); | |||
| String readString(size_t max = 120); | |||
| String readStringUntil(char terminator, size_t max = 120); | |||
| int getReadError() { return read_error; } | |||
| void clearReadError() { setReadError(0); } | |||
| protected: | |||
| void setReadError(int err = 1) { read_error = err; } | |||
| unsigned long _timeout; | |||
| private: | |||
| char read_error; | |||
| int timedRead(); | |||
| int timedPeek(); | |||
| int peekNextDigit(); | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,214 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "core_pins.h" | |||
| #include "pins_arduino.h" | |||
| #include "HardwareSerial.h" | |||
| #include "IntervalTimer.h" | |||
| #if 1 | |||
| // IntervalTimer based tone. This allows tone() to share the timers with other | |||
| // libraries, rather than permanently hogging one PIT timer even for projects | |||
| // which never use tone(). Someday this single-tone implementation might be | |||
| // changed to allow multiple simultaneous tones. | |||
| static uint32_t tone_toggle_count; | |||
| static volatile uint8_t *tone_reg; | |||
| static uint8_t tone_pin=255; | |||
| static uint16_t tone_frequency=0; | |||
| IntervalTimer tone_timer; | |||
| void tone_interrupt(void); | |||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration) | |||
| { | |||
| uint32_t count; | |||
| volatile uint32_t *config; | |||
| float usec; | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| if (duration) { | |||
| count = (frequency * duration / 1000) * 2; | |||
| } else { | |||
| count = 0xFFFFFFFF; | |||
| } | |||
| usec = (float)500000.0 / (float)frequency; | |||
| config = portConfigRegister(pin); | |||
| // TODO: IntervalTimer really needs an API to disable and enable | |||
| // the interrupt on a single timer. | |||
| __disable_irq(); | |||
| if (pin == tone_pin) { | |||
| if (frequency == tone_frequency) { | |||
| // same pin, same frequency, so just update the | |||
| // duration. Users will call repetitively call | |||
| // tone() with the same setting, expecting a | |||
| // continuous output with no glitches or phase | |||
| // changes or jitter at each call. | |||
| tone_toggle_count = count; | |||
| } else { | |||
| // same pin, but a new frequency. | |||
| tone_reg[0] = 1; // clear pin | |||
| tone_timer.begin(tone_interrupt, usec); | |||
| } | |||
| } else { | |||
| if (tone_pin < CORE_NUM_DIGITAL) { | |||
| tone_reg[0] = 1; // clear pin | |||
| } | |||
| tone_pin = pin; | |||
| tone_reg = portClearRegister(pin); | |||
| tone_reg[0] = 1; // clear pin | |||
| tone_reg[384] = 1; // output mode; | |||
| *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
| tone_toggle_count = count; | |||
| tone_timer.begin(tone_interrupt, usec); | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| void tone_interrupt(void) | |||
| { | |||
| if (tone_toggle_count) { | |||
| tone_reg[128] = 1; // toggle | |||
| if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--; | |||
| } else { | |||
| tone_timer.end(); | |||
| tone_reg[0] = 0; // clear | |||
| tone_pin = 255; | |||
| tone_frequency = 0; | |||
| } | |||
| } | |||
| void noTone(uint8_t pin) | |||
| { | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| __disable_irq(); | |||
| if (pin == tone_pin) { | |||
| tone_timer.end(); | |||
| tone_reg[0] = 0; // clear | |||
| tone_pin = 255; | |||
| tone_frequency = 0; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| #if 0 | |||
| // Old PIT timer based tone(). This implementation is slightly more efficient, | |||
| // but it consumes one of the PIT timers, even for projects which never use tone(). | |||
| static uint32_t tone_toggle_count; | |||
| static volatile uint8_t *tone_reg; | |||
| static uint8_t tone_pin; | |||
| void init_tone(void) | |||
| { | |||
| if (SIM_SCGC6 & SIM_SCGC6_PIT) return; | |||
| SIM_SCGC6 |= SIM_SCGC6_PIT; // TODO: use bitband for atomic read-mod-write | |||
| PIT_MCR = 0; | |||
| PIT_TCTRL3 = 0; // disabled | |||
| tone_pin = 255; | |||
| NVIC_ENABLE_IRQ(IRQ_PIT_CH3); | |||
| } | |||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration) | |||
| { | |||
| uint32_t count, load; | |||
| volatile uint32_t *config; | |||
| init_tone(); | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| if (duration) { | |||
| count = (frequency * duration / 1000) * 2; | |||
| } else { | |||
| count = 0xFFFFFFFF; | |||
| } | |||
| load = (F_BUS / 2) / frequency; | |||
| config = portConfigRegister(pin); | |||
| __disable_irq(); | |||
| if (pin != tone_pin) { | |||
| if (tone_pin < CORE_NUM_DIGITAL) { | |||
| tone_reg[0] = 1; // clear pin | |||
| } | |||
| tone_pin = pin; | |||
| tone_reg = portClearRegister(pin); | |||
| tone_reg[0] = 1; // clear pin | |||
| tone_reg[384] = 1; // output mode; | |||
| *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
| } | |||
| tone_toggle_count = count; | |||
| if (PIT_LDVAL3 != load) { | |||
| PIT_TCTRL3 = 0; | |||
| PIT_LDVAL3 = load; | |||
| PIT_TCTRL3 = 3; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| void pit3_isr(void) | |||
| { | |||
| PIT_TFLG3 = 1; | |||
| if (tone_toggle_count) { | |||
| tone_reg[128] = 1; // toggle | |||
| if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--; | |||
| } else { | |||
| PIT_TCTRL3 = 0; | |||
| PIT_LDVAL3 = 0; | |||
| tone_reg[0] = 0; // clear | |||
| tone_pin = 255; | |||
| } | |||
| } | |||
| void noTone(uint8_t pin) | |||
| { | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| __disable_irq(); | |||
| if (pin == tone_pin) { | |||
| PIT_TCTRL3 = 0; | |||
| PIT_LDVAL3 = 0; | |||
| tone_reg[0] = 0; // clear | |||
| tone_pin = 255; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,91 @@ | |||
| /* | |||
| * Udp.cpp: Library to send/receive UDP packets. | |||
| * | |||
| * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) | |||
| * 1) UDP does not guarantee the order in which assembled UDP packets are received. This | |||
| * might not happen often in practice, but in larger network topologies, a UDP | |||
| * packet can be received out of sequence. | |||
| * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being | |||
| * aware of it. Again, this may not be a concern in practice on small local networks. | |||
| * For more information, see http://www.cafeaulait.org/course/week12/35.html | |||
| * | |||
| * MIT License: | |||
| * Copyright (c) 2008 Bjoern Hartmann | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| * | |||
| * bjoern@cs.stanford.edu 12/30/2008 | |||
| */ | |||
| #if ARDUINO >= 100 | |||
| #ifndef udp_h | |||
| #define udp_h | |||
| #include <Stream.h> | |||
| #include <IPAddress.h> | |||
| class UDP : public Stream { | |||
| public: | |||
| virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use | |||
| virtual void stop() =0; // Finish with the UDP socket | |||
| // Sending UDP packets | |||
| // Start building up a packet to send to the remote host specific in ip and port | |||
| // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port | |||
| virtual int beginPacket(IPAddress ip, uint16_t port) =0; | |||
| // Start building up a packet to send to the remote host specific in host and port | |||
| // Returns 1 if successful, 0 if there was a problem resolving the hostname or port | |||
| virtual int beginPacket(const char *host, uint16_t port) =0; | |||
| // Finish off this packet and send it | |||
| // Returns 1 if the packet was sent successfully, 0 if there was an error | |||
| virtual int endPacket() =0; | |||
| // Write a single byte into the packet | |||
| virtual size_t write(uint8_t) =0; | |||
| // Write size bytes from buffer into the packet | |||
| virtual size_t write(const uint8_t *buffer, size_t size) =0; | |||
| // Start processing the next available incoming packet | |||
| // Returns the size of the packet in bytes, or 0 if no packets are available | |||
| virtual int parsePacket() =0; | |||
| // Number of bytes remaining in the current packet | |||
| virtual int available() =0; | |||
| // Read a single byte from the current packet | |||
| virtual int read() =0; | |||
| // Read up to len bytes from the current packet and place them into buffer | |||
| // Returns the number of bytes read, or 0 if none are available | |||
| virtual int read(unsigned char* buffer, size_t len) =0; | |||
| // Read up to len characters from the current packet and place them into buffer | |||
| // Returns the number of characters read, or 0 if none are available | |||
| virtual int read(char* buffer, size_t len) =0; | |||
| // Return the next byte from the current packet without moving on to the next byte | |||
| virtual int peek() =0; | |||
| virtual void flush() =0; // Finish reading the current packet | |||
| // Return the IP address of the host who sent the current incoming packet | |||
| virtual IPAddress remoteIP() =0; | |||
| // Return the port of the host who sent the current incoming packet | |||
| virtual uint16_t remotePort() =0; | |||
| protected: | |||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||
| }; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,168 @@ | |||
| /* | |||
| WCharacter.h - Character utility functions for Wiring & Arduino | |||
| Copyright (c) 2010 Hernando Barragan. All right reserved. | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef Character_h | |||
| #define Character_h | |||
| #include <ctype.h> | |||
| // WCharacter.h prototypes | |||
| inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); | |||
| inline boolean isAlpha(int c) __attribute__((always_inline)); | |||
| inline boolean isAscii(int c) __attribute__((always_inline)); | |||
| inline boolean isWhitespace(int c) __attribute__((always_inline)); | |||
| inline boolean isControl(int c) __attribute__((always_inline)); | |||
| inline boolean isDigit(int c) __attribute__((always_inline)); | |||
| inline boolean isGraph(int c) __attribute__((always_inline)); | |||
| inline boolean isLowerCase(int c) __attribute__((always_inline)); | |||
| inline boolean isPrintable(int c) __attribute__((always_inline)); | |||
| inline boolean isPunct(int c) __attribute__((always_inline)); | |||
| inline boolean isSpace(int c) __attribute__((always_inline)); | |||
| inline boolean isUpperCase(int c) __attribute__((always_inline)); | |||
| inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); | |||
| inline int toAscii(int c) __attribute__((always_inline)); | |||
| inline int toLowerCase(int c) __attribute__((always_inline)); | |||
| inline int toUpperCase(int c)__attribute__((always_inline)); | |||
| // Checks for an alphanumeric character. | |||
| // It is equivalent to (isalpha(c) || isdigit(c)). | |||
| inline boolean isAlphaNumeric(int c) | |||
| { | |||
| return ( isalnum(c) == 0 ? false : true); | |||
| } | |||
| // Checks for an alphabetic character. | |||
| // It is equivalent to (isupper(c) || islower(c)). | |||
| inline boolean isAlpha(int c) | |||
| { | |||
| return ( isalpha(c) == 0 ? false : true); | |||
| } | |||
| // Checks whether c is a 7-bit unsigned char value | |||
| // that fits into the ASCII character set. | |||
| inline boolean isAscii(int c) | |||
| { | |||
| return ( isascii (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a blank character, that is, a space or a tab. | |||
| inline boolean isWhitespace(int c) | |||
| { | |||
| return ( isblank (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a control character. | |||
| inline boolean isControl(int c) | |||
| { | |||
| return ( iscntrl (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a digit (0 through 9). | |||
| inline boolean isDigit(int c) | |||
| { | |||
| return ( isdigit (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character except space. | |||
| inline boolean isGraph(int c) | |||
| { | |||
| return ( isgraph (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a lower-case character. | |||
| inline boolean isLowerCase(int c) | |||
| { | |||
| return (islower (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character including space. | |||
| inline boolean isPrintable(int c) | |||
| { | |||
| return ( isprint (c) == 0 ? false : true); | |||
| } | |||
| // Checks for any printable character which is not a space | |||
| // or an alphanumeric character. | |||
| inline boolean isPunct(int c) | |||
| { | |||
| return ( ispunct (c) == 0 ? false : true); | |||
| } | |||
| // Checks for white-space characters. For the avr-libc library, | |||
| // these are: space, formfeed ('\f'), newline ('\n'), carriage | |||
| // return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). | |||
| inline boolean isSpace(int c) | |||
| { | |||
| return ( isspace (c) == 0 ? false : true); | |||
| } | |||
| // Checks for an uppercase letter. | |||
| inline boolean isUpperCase(int c) | |||
| { | |||
| return ( isupper (c) == 0 ? false : true); | |||
| } | |||
| // Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 | |||
| // 8 9 a b c d e f A B C D E F. | |||
| inline boolean isHexadecimalDigit(int c) | |||
| { | |||
| return ( isxdigit (c) == 0 ? false : true); | |||
| } | |||
| // Converts c to a 7-bit unsigned char value that fits into the | |||
| // ASCII character set, by clearing the high-order bits. | |||
| inline int toAscii(int c) | |||
| { | |||
| return toascii (c); | |||
| } | |||
| // Warning: | |||
| // Many people will be unhappy if you use this function. | |||
| // This function will convert accented letters into random | |||
| // characters. | |||
| // Converts the letter c to lower case, if possible. | |||
| inline int toLowerCase(int c) | |||
| { | |||
| return tolower (c); | |||
| } | |||
| // Converts the letter c to upper case, if possible. | |||
| inline int toUpperCase(int c) | |||
| { | |||
| return toupper (c); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1 @@ | |||
| #include "wiring.h" | |||
| @@ -0,0 +1,50 @@ | |||
| #include <stdint.h> | |||
| static uint32_t seed; | |||
| void randomSeed(uint32_t newseed) | |||
| { | |||
| if (newseed > 0) seed = newseed; | |||
| } | |||
| void srandom(uint32_t newseed) | |||
| { | |||
| seed = newseed; | |||
| } | |||
| uint32_t random(void) | |||
| { | |||
| int32_t hi, lo, x; | |||
| // the algorithm used in avr-libc 1.6.4 | |||
| x = seed; | |||
| if (x == 0) x = 123459876; | |||
| hi = x / 127773; | |||
| lo = x % 127773; | |||
| x = 16807 * lo - 2836 * hi; | |||
| if (x < 0) x += 0x7FFFFFFF; | |||
| seed = x; | |||
| return x; | |||
| } | |||
| uint32_t random(uint32_t howbig) | |||
| { | |||
| if (howbig == 0) return 0; | |||
| return random() % howbig; | |||
| } | |||
| int32_t random(int32_t howsmall, int32_t howbig) | |||
| { | |||
| if (howsmall >= howbig) return howsmall; | |||
| int32_t diff = howbig - howsmall; | |||
| return random(diff) + howsmall; | |||
| } | |||
| long map(long x, long in_min, long in_max, long out_min, long out_max) | |||
| { | |||
| return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | |||
| } | |||
| unsigned int makeWord(unsigned int w) { return w; } | |||
| unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } | |||
| @@ -0,0 +1,59 @@ | |||
| #ifndef WProgram_h | |||
| #define WProgram_h | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| // some libraries and sketches depend on this | |||
| // AVR stuff, assuming Arduino.h or WProgram.h | |||
| // automatically includes it... | |||
| #include <avr/pgmspace.h> | |||
| #include <avr/interrupt.h> | |||
| #include "avr_functions.h" | |||
| #include "wiring.h" | |||
| #include "HardwareSerial.h" | |||
| #define DMAMEM __attribute__ ((section(".dmabuffers"), used)) | |||
| #ifdef __cplusplus | |||
| #include "avr_emulation.h" | |||
| #include "usb_serial.h" | |||
| #include "usb_seremu.h" | |||
| #include "usb_keyboard.h" | |||
| #include "usb_mouse.h" | |||
| #include "usb_joystick.h" | |||
| #include "usb_midi.h" | |||
| #include "usb_rawhid.h" | |||
| #include "usb_flightsim.h" | |||
| //#include "WCharacter.h" | |||
| #include "WString.h" | |||
| #include "elapsedMillis.h" | |||
| #include "IntervalTimer.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, uint16_t frequency, uint32_t duration = 0); | |||
| void noTone(uint8_t pin); | |||
| // WMath prototypes | |||
| uint32_t random(void); | |||
| uint32_t random(uint32_t howbig); | |||
| int32_t random(int32_t howsmall, int32_t howbig); | |||
| void randomSeed(uint32_t newseed); | |||
| void srandom(uint32_t newseed); | |||
| long map(long, long, long, long, long); | |||
| #include "pins_arduino.h" | |||
| #endif // __cplusplus | |||
| #endif // WProgram_h | |||
| @@ -0,0 +1,725 @@ | |||
| /* | |||
| WString.cpp - String library for Wiring & Arduino | |||
| ...mostly rewritten by Paul Stoffregen... | |||
| Copyright (c) 2009-10 Hernando Barragan. All rights reserved. | |||
| Copyright 2011, Paul Stoffregen, paul@pjrc.com | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "WString.h" | |||
| /*********************************************/ | |||
| /* Constructors */ | |||
| /*********************************************/ | |||
| String::String(const char *cstr) | |||
| { | |||
| init(); | |||
| if (cstr) copy(cstr, strlen(cstr)); | |||
| } | |||
| String::String(const __FlashStringHelper *pgmstr) | |||
| { | |||
| init(); | |||
| *this = pgmstr; | |||
| } | |||
| String::String(const String &value) | |||
| { | |||
| init(); | |||
| *this = value; | |||
| } | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String::String(String &&rval) | |||
| { | |||
| init(); | |||
| move(rval); | |||
| } | |||
| String::String(StringSumHelper &&rval) | |||
| { | |||
| init(); | |||
| move(rval); | |||
| } | |||
| #endif | |||
| String::String(char c) | |||
| { | |||
| init(); | |||
| *this = c; | |||
| } | |||
| String::String(unsigned char c) | |||
| { | |||
| init(); | |||
| char buf[4]; | |||
| utoa(c, buf, 10); | |||
| *this = buf; | |||
| } | |||
| String::String(const int value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[18]; | |||
| itoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(unsigned int value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[17]; | |||
| utoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(long value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[34]; | |||
| ltoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(unsigned long value, unsigned char base) | |||
| { | |||
| init(); | |||
| char buf[33]; | |||
| ultoa(value, buf, base); | |||
| *this = buf; | |||
| } | |||
| String::String(float num, unsigned char digits) | |||
| { | |||
| init(); | |||
| char buf[40]; | |||
| *this = dtostrf(num, digits + 2, digits, buf); | |||
| } | |||
| String::~String() | |||
| { | |||
| free(buffer); | |||
| } | |||
| /*********************************************/ | |||
| /* Memory Management */ | |||
| /*********************************************/ | |||
| inline void String::init(void) | |||
| { | |||
| buffer = NULL; | |||
| capacity = 0; | |||
| len = 0; | |||
| flags = 0; | |||
| } | |||
| unsigned char String::reserve(unsigned int size) | |||
| { | |||
| if (capacity >= size) return 1; | |||
| if (changeBuffer(size)) { | |||
| if (len == 0) buffer[0] = 0; | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| unsigned char String::changeBuffer(unsigned int maxStrLen) | |||
| { | |||
| char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); | |||
| if (newbuffer) { | |||
| buffer = newbuffer; | |||
| capacity = maxStrLen; | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Copy and Move */ | |||
| /*********************************************/ | |||
| String & String::copy(const char *cstr, unsigned int length) | |||
| { | |||
| if (length == 0) { | |||
| if (buffer) buffer[0] = 0; | |||
| len = 0; | |||
| return *this; | |||
| } | |||
| if (!reserve(length)) { | |||
| if (buffer) { | |||
| free(buffer); | |||
| buffer = NULL; | |||
| } | |||
| len = capacity = 0; | |||
| return *this; | |||
| } | |||
| len = length; | |||
| strcpy(buffer, cstr); | |||
| return *this; | |||
| } | |||
| void String::move(String &rhs) | |||
| { | |||
| if (buffer) { | |||
| if (capacity >= rhs.len) { | |||
| strcpy(buffer, rhs.buffer); | |||
| len = rhs.len; | |||
| rhs.len = 0; | |||
| return; | |||
| } else { | |||
| free(buffer); | |||
| } | |||
| } | |||
| buffer = rhs.buffer; | |||
| capacity = rhs.capacity; | |||
| len = rhs.len; | |||
| rhs.buffer = NULL; | |||
| rhs.capacity = 0; | |||
| rhs.len = 0; | |||
| } | |||
| String & String::operator = (const String &rhs) | |||
| { | |||
| if (this == &rhs) return *this; | |||
| return copy(rhs.buffer, rhs.len); | |||
| } | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String & String::operator = (String &&rval) | |||
| { | |||
| if (this != &rval) move(rval); | |||
| return *this; | |||
| } | |||
| String & String::operator = (StringSumHelper &&rval) | |||
| { | |||
| if (this != &rval) move(rval); | |||
| return *this; | |||
| } | |||
| #endif | |||
| String & String::operator = (const char *cstr) | |||
| { | |||
| if (cstr) { | |||
| copy(cstr, strlen(cstr)); | |||
| } else { | |||
| len = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::operator = (const __FlashStringHelper *pgmstr) | |||
| { | |||
| copy(pgmstr); | |||
| return *this; | |||
| } | |||
| String & String::operator = (char c) | |||
| { | |||
| char buf[2]; | |||
| buf[0] = c; | |||
| buf[1] = 0; | |||
| return copy(buf, 1); | |||
| } | |||
| /*********************************************/ | |||
| /* Append */ | |||
| /*********************************************/ | |||
| String & String::append(const String &s) | |||
| { | |||
| return append(s.buffer, s.len); | |||
| } | |||
| String & String::append(const char *cstr, unsigned int length) | |||
| { | |||
| unsigned int newlen = len + length; | |||
| if (length == 0 || !reserve(newlen)) return *this; | |||
| strcpy(buffer + len, cstr); | |||
| len = newlen; | |||
| return *this; | |||
| } | |||
| String & String::append(const char *cstr) | |||
| { | |||
| if (cstr) append(cstr, strlen(cstr)); | |||
| return *this; | |||
| } | |||
| String & String::append(char c) | |||
| { | |||
| char buf[2]; | |||
| buf[0] = c; | |||
| buf[1] = 0; | |||
| append(buf, 1); | |||
| return *this; | |||
| } | |||
| String & String::append(int num) | |||
| { | |||
| char buf[12]; | |||
| ltoa((long)num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(unsigned int num) | |||
| { | |||
| char buf[11]; | |||
| ultoa((unsigned long)num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(long num) | |||
| { | |||
| char buf[12]; | |||
| ltoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(unsigned long num) | |||
| { | |||
| char buf[11]; | |||
| ultoa(num, buf, 10); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| String & String::append(float num) | |||
| { | |||
| char buf[30]; | |||
| dtostrf(num, 4, 2, buf); | |||
| append(buf, strlen(buf)); | |||
| return *this; | |||
| } | |||
| /*********************************************/ | |||
| /* Concatenate */ | |||
| /*********************************************/ | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(rhs.buffer, rhs.len); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| if (cstr) a.append(cstr, strlen(cstr)); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(pgmstr); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, char c) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(c); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(c); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, int num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append((long)num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append((unsigned long)num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, long num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, float num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| StringSumHelper & operator + (const StringSumHelper &lhs, double num) | |||
| { | |||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||
| a.append(num); | |||
| return a; | |||
| } | |||
| /*********************************************/ | |||
| /* Comparison */ | |||
| /*********************************************/ | |||
| int String::compareTo(const String &s) const | |||
| { | |||
| if (!buffer || !s.buffer) { | |||
| if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; | |||
| if (buffer && len > 0) return *(unsigned char *)buffer; | |||
| return 0; | |||
| } | |||
| return strcmp(buffer, s.buffer); | |||
| } | |||
| unsigned char String::equals(const String &s2) const | |||
| { | |||
| return (len == s2.len && compareTo(s2) == 0); | |||
| } | |||
| unsigned char String::equals(const char *cstr) const | |||
| { | |||
| if (len == 0) return (cstr == NULL || *cstr == 0); | |||
| if (cstr == NULL) return buffer[0] == 0; | |||
| return strcmp(buffer, cstr) == 0; | |||
| } | |||
| unsigned char String::operator<(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) < 0; | |||
| } | |||
| unsigned char String::operator>(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) > 0; | |||
| } | |||
| unsigned char String::operator<=(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) <= 0; | |||
| } | |||
| unsigned char String::operator>=(const String &rhs) const | |||
| { | |||
| return compareTo(rhs) >= 0; | |||
| } | |||
| unsigned char String::equalsIgnoreCase( const String &s2 ) const | |||
| { | |||
| if (this == &s2) return 1; | |||
| if (len != s2.len) return 0; | |||
| if (len == 0) return 1; | |||
| const char *p1 = buffer; | |||
| const char *p2 = s2.buffer; | |||
| while (*p1) { | |||
| if (tolower(*p1++) != tolower(*p2++)) return 0; | |||
| } | |||
| return 1; | |||
| } | |||
| unsigned char String::startsWith( const String &s2 ) const | |||
| { | |||
| if (len < s2.len) return 0; | |||
| return startsWith(s2, 0); | |||
| } | |||
| unsigned char String::startsWith( const String &s2, unsigned int offset ) const | |||
| { | |||
| if (offset > len - s2.len || !buffer || !s2.buffer) return 0; | |||
| return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; | |||
| } | |||
| unsigned char String::endsWith( const String &s2 ) const | |||
| { | |||
| if ( len < s2.len || !buffer || !s2.buffer) return 0; | |||
| return strcmp(&buffer[len - s2.len], s2.buffer) == 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Character Access */ | |||
| /*********************************************/ | |||
| char String::charAt(unsigned int loc) const | |||
| { | |||
| return operator[](loc); | |||
| } | |||
| void String::setCharAt(unsigned int loc, char c) | |||
| { | |||
| if (loc < len) buffer[loc] = c; | |||
| } | |||
| char & String::operator[](unsigned int index) | |||
| { | |||
| static char dummy_writable_char; | |||
| if (index >= len || !buffer) { | |||
| dummy_writable_char = 0; | |||
| return dummy_writable_char; | |||
| } | |||
| return buffer[index]; | |||
| } | |||
| char String::operator[]( unsigned int index ) const | |||
| { | |||
| if (index >= len || !buffer) return 0; | |||
| return buffer[index]; | |||
| } | |||
| void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const | |||
| { | |||
| if (!bufsize || !buf) return; | |||
| if (index >= len) { | |||
| buf[0] = 0; | |||
| return; | |||
| } | |||
| unsigned int n = bufsize - 1; | |||
| if (n > len - index) n = len - index; | |||
| strncpy((char *)buf, buffer + index, n); | |||
| buf[n] = 0; | |||
| } | |||
| /*********************************************/ | |||
| /* Search */ | |||
| /*********************************************/ | |||
| int String::indexOf(char c) const | |||
| { | |||
| return indexOf(c, 0); | |||
| } | |||
| int String::indexOf( char ch, unsigned int fromIndex ) const | |||
| { | |||
| if (fromIndex >= len) return -1; | |||
| const char* temp = strchr(buffer + fromIndex, ch); | |||
| if (temp == NULL) return -1; | |||
| return temp - buffer; | |||
| } | |||
| int String::indexOf(const String &s2) const | |||
| { | |||
| return indexOf(s2, 0); | |||
| } | |||
| int String::indexOf(const String &s2, unsigned int fromIndex) const | |||
| { | |||
| if (fromIndex >= len) return -1; | |||
| const char *found = strstr(buffer + fromIndex, s2.buffer); | |||
| if (found == NULL) return -1; | |||
| return found - buffer; | |||
| } | |||
| int String::lastIndexOf( char theChar ) const | |||
| { | |||
| return lastIndexOf(theChar, len - 1); | |||
| } | |||
| int String::lastIndexOf(char ch, unsigned int fromIndex) const | |||
| { | |||
| if (fromIndex >= len || 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; | |||
| } | |||
| int String::lastIndexOf(const String &s2) const | |||
| { | |||
| return lastIndexOf(s2, len - s2.len); | |||
| } | |||
| int String::lastIndexOf(const String &s2, unsigned int fromIndex) const | |||
| { | |||
| if (s2.len == 0 || len == 0 || s2.len > len || 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 ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; | |||
| } | |||
| return found; | |||
| } | |||
| String String::substring( unsigned int left ) const | |||
| { | |||
| 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 */ | |||
| /*********************************************/ | |||
| String & String::replace(char find, char replace) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| if (*p == find) *p = replace; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::replace(const String& find, const String& replace) | |||
| { | |||
| if (len == 0 || find.len == 0) return *this; | |||
| 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 *this; | |||
| if (size > capacity && !changeBuffer(size)) return *this; | |||
| int index = len - 1; | |||
| while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { | |||
| readFrom = buffer + index + find.len; | |||
| memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); | |||
| len += diff; | |||
| buffer[len] = 0; | |||
| memcpy(buffer + index, replace.buffer, replace.len); | |||
| index--; | |||
| } | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::remove(unsigned int index) | |||
| { | |||
| if (index < len) { | |||
| len = index; | |||
| buffer[len] = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::remove(unsigned int index, unsigned int count) | |||
| { | |||
| if (index < len && count > 0) { | |||
| if (index + count > len) count = len - index; | |||
| len = len - count; | |||
| memmove(buffer + index, buffer + index + count, len - index); | |||
| buffer[len] = 0; | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::toLowerCase(void) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| *p = tolower(*p); | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::toUpperCase(void) | |||
| { | |||
| if (!buffer) return *this; | |||
| for (char *p = buffer; *p; p++) { | |||
| *p = toupper(*p); | |||
| } | |||
| return *this; | |||
| } | |||
| String & String::trim(void) | |||
| { | |||
| if (!buffer || len == 0) return *this; | |||
| 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; | |||
| return *this; | |||
| } | |||
| /*********************************************/ | |||
| /* Parsing / Conversion */ | |||
| /*********************************************/ | |||
| long String::toInt(void) const | |||
| { | |||
| if (buffer) return atol(buffer); | |||
| return 0; | |||
| } | |||
| float String::toFloat(void) const | |||
| { | |||
| if (buffer) return strtof(buffer, (char **)NULL); | |||
| return 0.0; | |||
| } | |||
| @@ -0,0 +1,216 @@ | |||
| /* | |||
| WString.h - String library for Wiring & Arduino | |||
| ...mostly rewritten by Paul Stoffregen... | |||
| Copyright (c) 2009-10 Hernando Barragan. All right reserved. | |||
| Copyright 2011, Paul Stoffregen, paul@pjrc.com | |||
| This library is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU Lesser General Public | |||
| License as published by the Free Software Foundation; either | |||
| version 2.1 of the License, or (at your option) any later version. | |||
| This library is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public | |||
| License along with this library; if not, write to the Free Software | |||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef String_class_h | |||
| #define String_class_h | |||
| #ifdef __cplusplus | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <ctype.h> | |||
| #include "avr_functions.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 | |||
| // Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010) | |||
| // modified by Mikal Hart for his FlashString library | |||
| class __FlashStringHelper; | |||
| #ifndef F | |||
| #define F(string_literal) ((const __FlashStringHelper *)(string_literal)) | |||
| #endif | |||
| // 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 *cstr = (const char *)NULL); | |||
| String(const __FlashStringHelper *pgmstr); | |||
| String(const String &str); | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String(String &&rval); | |||
| String(StringSumHelper &&rval); | |||
| #endif | |||
| String(char c); | |||
| String(unsigned char c); | |||
| String(int, unsigned char base=10); | |||
| String(unsigned int, unsigned char base=10); | |||
| String(long, unsigned char base=10); | |||
| String(unsigned long, unsigned char base=10); | |||
| String(float num, unsigned char digits=2); | |||
| String(double num, unsigned char digits=2) : String((float)num, digits) {} | |||
| ~String(void); | |||
| // memory management | |||
| unsigned char reserve(unsigned int size); | |||
| inline unsigned int length(void) const {return len;} | |||
| // copy and move | |||
| String & copy(const char *cstr, unsigned int length); | |||
| String & copy(const __FlashStringHelper *s) { return copy((const char *)s, strlen((const char *)s)); } | |||
| void move(String &rhs); | |||
| String & operator = (const String &rhs); | |||
| String & operator = (const char *cstr); | |||
| String & operator = (const __FlashStringHelper *pgmstr); | |||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||
| String & operator = (String &&rval); | |||
| String & operator = (StringSumHelper &&rval); | |||
| #endif | |||
| String & operator = (char c); | |||
| // append | |||
| String & append(const String &str); | |||
| String & append(const char *cstr); | |||
| String & append(const __FlashStringHelper *s) {return append((const char *)s, strlen((const char *)s)); } | |||
| String & append(char c); | |||
| String & append(unsigned char c) {return append((int)c);} | |||
| String & append(int num); | |||
| String & append(unsigned int num); | |||
| String & append(long num); | |||
| String & append(unsigned long num); | |||
| String & append(float num); | |||
| String & append(double num) {return append((float)num);} | |||
| String & operator += (const String &rhs) {return append(rhs);} | |||
| String & operator += (const char *cstr) {return append(cstr);} | |||
| String & operator += (const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||
| String & operator += (char c) {return append(c);} | |||
| String & operator += (unsigned char c) {return append((int)c);} | |||
| String & operator += (int num) {return append(num);} | |||
| String & operator += (unsigned int num) {return append(num);} | |||
| String & operator += (long num) {return append(num);} | |||
| String & operator += (unsigned long num) {return append(num);} | |||
| String & operator += (float num) {return append(num);} | |||
| String & operator += (double num) {return append(num);} | |||
| // concatenate | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); | |||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); | |||
| String & concat(const String &str) {return append(str);} | |||
| String & concat(const char *cstr) {return append(cstr);} | |||
| String & concat(const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||
| String & concat(char c) {return append(c);} | |||
| String & concat(unsigned char c) {return append((int)c);} | |||
| String & concat(int num) {return append(num);} | |||
| String & concat(unsigned int num) {return append(num);} | |||
| String & concat(long num) {return append(num);} | |||
| String & concat(unsigned long num) {return append(num);} | |||
| String & concat(float num) {return append(num);} | |||
| String & concat(double num) {return append(num);} | |||
| // comparison | |||
| int compareTo(const String &s) const; | |||
| unsigned char equals(const String &s) const; | |||
| unsigned char equals(const char *cstr) const; | |||
| //unsigned char equals(const __FlashStringHelper *pgmstr) 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 __FlashStringHelper *s) const {return equals((const char *)s);} | |||
| unsigned char operator != (const String &rhs) const {return !equals(rhs);} | |||
| unsigned char operator != (const char *cstr) const {return !equals(cstr);} | |||
| unsigned char operator != (const __FlashStringHelper *s) const {return !equals(s);} | |||
| unsigned char operator < (const String &rhs) const; | |||
| unsigned char operator > (const String &rhs) const; | |||
| unsigned char operator <= (const String &rhs) const; | |||
| unsigned char operator >= (const String &rhs) const; | |||
| unsigned char equalsIgnoreCase(const String &s) const; | |||
| unsigned char startsWith( const String &prefix) const; | |||
| unsigned char startsWith(const String &prefix, unsigned int offset) const; | |||
| unsigned char endsWith(const String &suffix) const; | |||
| // character acccess | |||
| char charAt(unsigned int index) const; | |||
| void setCharAt(unsigned int index, char c); | |||
| char operator [] (unsigned int index) const; | |||
| char& operator [] (unsigned int index); | |||
| void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; | |||
| void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const | |||
| {getBytes((unsigned char *)buf, bufsize, index);} | |||
| const char * c_str() const { return buffer; } | |||
| // search | |||
| int indexOf( char ch ) const; | |||
| int indexOf( char ch, unsigned int fromIndex ) const; | |||
| int indexOf( const String &str ) const; | |||
| int indexOf( const String &str, unsigned int fromIndex ) const; | |||
| int lastIndexOf( char ch ) const; | |||
| int lastIndexOf( char ch, unsigned int fromIndex ) const; | |||
| int lastIndexOf( const String &str ) const; | |||
| int lastIndexOf( const String &str, unsigned int fromIndex ) const; | |||
| String substring( unsigned int beginIndex ) const; | |||
| String substring( unsigned int beginIndex, unsigned int endIndex ) const; | |||
| // modification | |||
| String & replace(char find, char replace); | |||
| String & replace(const String& find, const String& replace); | |||
| String & remove(unsigned int index); | |||
| String & remove(unsigned int index, unsigned int count); | |||
| String & toLowerCase(void); | |||
| String & toUpperCase(void); | |||
| String & trim(void); | |||
| // parsing/conversion | |||
| long toInt(void) const; | |||
| float toFloat(void) const; | |||
| protected: | |||
| char *buffer; // the actual char array | |||
| unsigned int capacity; // the array length minus one (for the '\0') | |||
| unsigned int len; // the String length (not counting the '\0') | |||
| unsigned char flags; // unused, for future features | |||
| protected: | |||
| void init(void); | |||
| unsigned char changeBuffer(unsigned int maxStrLen); | |||
| String & append(const char *cstr, unsigned int length); | |||
| }; | |||
| class StringSumHelper : public String | |||
| { | |||
| public: | |||
| StringSumHelper(const String &s) : String(s) {} | |||
| StringSumHelper(const char *p) : String(p) {} | |||
| StringSumHelper(const __FlashStringHelper *pgmstr) : String(pgmstr) {} | |||
| StringSumHelper(char c) : String(c) {} | |||
| StringSumHelper(unsigned char c) : String(c) {} | |||
| StringSumHelper(int num) : String(num, 10) {} | |||
| StringSumHelper(unsigned int num) : String(num, 10) {} | |||
| StringSumHelper(long num) : String(num, 10) {} | |||
| StringSumHelper(unsigned long num) : String(num, 10) {} | |||
| }; | |||
| #endif // __cplusplus | |||
| #endif // String_class_h | |||
| @@ -0,0 +1,287 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "core_pins.h" | |||
| //#include "HardwareSerial.h" | |||
| static uint8_t calibrating; | |||
| static uint8_t analog_right_shift = 0; | |||
| static uint8_t analog_config_bits = 10; | |||
| static uint8_t analog_num_average = 4; | |||
| static uint8_t analog_reference_internal = 0; | |||
| // the alternate clock is connected to OSCERCLK (16 MHz). | |||
| // datasheet says ADC clock should be 2 to 12 MHz for 16 bit mode | |||
| // datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode | |||
| #if F_BUS == 48000000 | |||
| #define ADC0_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) | |||
| #define ADC0_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) | |||
| #define ADC0_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) | |||
| #elif F_BUS == 24000000 | |||
| #define ADC0_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(0) | |||
| #define ADC0_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) | |||
| #define ADC0_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) | |||
| #else | |||
| #error | |||
| #endif | |||
| void analog_init(void) | |||
| { | |||
| uint32_t num; | |||
| VREF_TRM = 0x60; | |||
| VREF_SC = 0xE1; // enable 1.2 volt ref | |||
| if (analog_config_bits == 8) { | |||
| ADC0_CFG1 = ADC0_CFG1_24MHZ + ADC_CFG1_MODE(0); | |||
| ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | |||
| } else if (analog_config_bits == 10) { | |||
| ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; | |||
| ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | |||
| } else if (analog_config_bits == 12) { | |||
| ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; | |||
| ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | |||
| } else { | |||
| ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; | |||
| ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | |||
| } | |||
| if (analog_reference_internal) { | |||
| ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref | |||
| } else { | |||
| ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref | |||
| } | |||
| num = analog_num_average; | |||
| if (num <= 1) { | |||
| ADC0_SC3 = ADC_SC3_CAL; // begin cal | |||
| } else if (num <= 4) { | |||
| ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); | |||
| } else if (num <= 8) { | |||
| ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); | |||
| } else if (num <= 16) { | |||
| ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); | |||
| } else { | |||
| ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); | |||
| } | |||
| calibrating = 1; | |||
| } | |||
| static void wait_for_cal(void) | |||
| { | |||
| uint16_t sum; | |||
| //serial_print("wait_for_cal\n"); | |||
| while (ADC0_SC3 & ADC_SC3_CAL) { | |||
| // wait | |||
| //serial_print("."); | |||
| } | |||
| __disable_irq(); | |||
| if (calibrating) { | |||
| //serial_print("\n"); | |||
| sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; | |||
| sum = (sum / 2) | 0x8000; | |||
| ADC0_PG = sum; | |||
| //serial_print("ADC0_PG = "); | |||
| //serial_phex16(sum); | |||
| //serial_print("\n"); | |||
| sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; | |||
| sum = (sum / 2) | 0x8000; | |||
| ADC0_MG = sum; | |||
| //serial_print("ADC0_MG = "); | |||
| //serial_phex16(sum); | |||
| //serial_print("\n"); | |||
| calibrating = 0; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| // ADCx_SC2[REFSEL] bit selects the voltage reference sources for ADC. | |||
| // VREFH/VREFL - connected as the primary reference option | |||
| // 1.2 V VREF_OUT - connected as the VALT reference option | |||
| #define DEFAULT 0 | |||
| #define INTERNAL 2 | |||
| #define INTERNAL1V2 2 | |||
| #define INTERNAL1V1 2 | |||
| #define EXTERNAL 0 | |||
| void analogReference(uint8_t type) | |||
| { | |||
| if (type) { | |||
| // internal reference requested | |||
| if (!analog_reference_internal) { | |||
| analog_reference_internal = 1; | |||
| if (calibrating) ADC0_SC3 = 0; // cancel cal | |||
| analog_init(); | |||
| } | |||
| } else { | |||
| // vcc or external reference requested | |||
| if (analog_reference_internal) { | |||
| analog_reference_internal = 0; | |||
| if (calibrating) ADC0_SC3 = 0; // cancel cal | |||
| analog_init(); | |||
| } | |||
| } | |||
| } | |||
| void analogReadRes(unsigned int bits) | |||
| { | |||
| unsigned int config; | |||
| if (bits >= 13) { | |||
| if (bits > 16) bits = 16; | |||
| config = 16; | |||
| } else if (bits >= 11) { | |||
| config = 12; | |||
| } else if (bits >= 9) { | |||
| config = 10; | |||
| } else { | |||
| config = 8; | |||
| } | |||
| analog_right_shift = config - bits; | |||
| if (config != analog_config_bits) { | |||
| analog_config_bits = config; | |||
| if (calibrating) ADC0_SC3 = 0; // cancel cal | |||
| analog_init(); | |||
| } | |||
| } | |||
| void analogReadAveraging(unsigned int num) | |||
| { | |||
| if (calibrating) wait_for_cal(); | |||
| if (num <= 1) { | |||
| num = 0; | |||
| ADC0_SC3 = 0; | |||
| } else if (num <= 4) { | |||
| num = 4; | |||
| ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); | |||
| } else if (num <= 8) { | |||
| num = 8; | |||
| ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); | |||
| } else if (num <= 16) { | |||
| num = 16; | |||
| ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2); | |||
| } else { | |||
| num = 32; | |||
| ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3); | |||
| } | |||
| analog_num_average = num; | |||
| } | |||
| // The SC1A register is used for both software and hardware trigger modes of operation. | |||
| static const uint8_t channel2sc1a[] = { | |||
| 5, 14, 8, 9, 13, 12, 6, 7, 15, 4, | |||
| 0, 19, 3, 21, 26, 22 | |||
| }; | |||
| // TODO: perhaps this should store the NVIC priority, so it works recursively? | |||
| static volatile uint8_t analogReadBusy = 0; | |||
| int analogRead(uint8_t pin) | |||
| { | |||
| int result; | |||
| if (pin >= 14) { | |||
| if (pin <= 23) { | |||
| pin -= 14; // 14-23 are A0-A9 | |||
| } else if (pin >= 34 && pin <= 39) { | |||
| pin -= 24; // 34-37 are A10-A13, 38 is temp sensor, 39 is vref | |||
| } else { | |||
| return 0; // all others are invalid | |||
| } | |||
| } | |||
| //serial_print("analogRead"); | |||
| //return 0; | |||
| if (calibrating) wait_for_cal(); | |||
| //pin = 5; // PTD1/SE5b, pin 14, analog 0 | |||
| __disable_irq(); | |||
| start: ADC0_SC1A = channel2sc1a[pin]; | |||
| analogReadBusy = 1; | |||
| __enable_irq(); | |||
| while (1) { | |||
| __disable_irq(); | |||
| if ((ADC0_SC1A & ADC_SC1_COCO)) { | |||
| result = ADC0_RA; | |||
| analogReadBusy = 0; | |||
| __enable_irq(); | |||
| result >>= analog_right_shift; | |||
| return result; | |||
| } | |||
| // detect if analogRead was used from an interrupt | |||
| // if so, our analogRead got canceled, so it must | |||
| // be restarted. | |||
| if (!analogReadBusy) goto start; | |||
| __enable_irq(); | |||
| yield(); | |||
| } | |||
| #if 0 | |||
| ADC0_SC1A = channel2sc1a[pin]; | |||
| while ((ADC0_SC1A & ADC_SC1_COCO) == 0) { | |||
| yield(); | |||
| // wait | |||
| //serial_print("."); | |||
| } | |||
| //serial_print("\n"); | |||
| result = ADC0_RA >> analog_right_shift; | |||
| //serial_phex16(result >> 3); | |||
| //serial_print("\n"); | |||
| return result; | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| /* ---------------------------------------------------------------------- | |||
| * Copyright (C) 2010 ARM Limited. All rights reserved. | |||
| * | |||
| * $Date: 11. November 2010 | |||
| * $Revision: V1.0.2 | |||
| * | |||
| * Project: CMSIS DSP Library | |||
| * Title: arm_common_tables.h | |||
| * | |||
| * Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions | |||
| * | |||
| * Target Processor: Cortex-M4/Cortex-M3 | |||
| * | |||
| * Version 1.0.2 2010/11/11 | |||
| * Documentation updated. | |||
| * | |||
| * Version 1.0.1 2010/10/05 | |||
| * Production release and review comments incorporated. | |||
| * | |||
| * Version 1.0.0 2010/09/20 | |||
| * Production release and review comments incorporated. | |||
| * -------------------------------------------------------------------- */ | |||
| #ifndef _ARM_COMMON_TABLES_H | |||
| #define _ARM_COMMON_TABLES_H | |||
| #include "arm_math.h" | |||
| extern const uint16_t armBitRevTable[1024]; | |||
| extern const q15_t armRecipTableQ15[64]; | |||
| extern const q31_t armRecipTableQ31[64]; | |||
| extern const q31_t realCoefAQ31[1024]; | |||
| extern const q31_t realCoefBQ31[1024]; | |||
| extern const float32_t twiddleCoef[6144]; | |||
| extern const q31_t twiddleCoefQ31[6144]; | |||
| extern const q15_t twiddleCoefQ15[6144]; | |||
| #endif /* ARM_COMMON_TABLES_H */ | |||
| @@ -0,0 +1,9 @@ | |||
| #ifndef _AVR_EEPROM_H_ | |||
| #define _AVR_EEPROM_H_ 1 | |||
| #include <stddef.h> | |||
| #include <stdint.h> | |||
| #define E2END 0x80 | |||
| #endif | |||
| @@ -0,0 +1 @@ | |||
| #include "../avr_emulation.h" | |||
| @@ -0,0 +1,46 @@ | |||
| #ifndef __PGMSPACE_H_ | |||
| #define __PGMSPACE_H_ 1 | |||
| #include <inttypes.h> | |||
| #define PROGMEM | |||
| #define PGM_P const char * | |||
| #define PSTR(str) (str) | |||
| #define _SFR_BYTE(n) (n) | |||
| typedef void prog_void; | |||
| typedef char prog_char; | |||
| typedef unsigned char prog_uchar; | |||
| typedef int8_t prog_int8_t; | |||
| typedef uint8_t prog_uint8_t; | |||
| typedef int16_t prog_int16_t; | |||
| typedef uint16_t prog_uint16_t; | |||
| typedef int32_t prog_int32_t; | |||
| typedef uint32_t prog_uint32_t; | |||
| #define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) | |||
| #define strcpy_P(dest, src) strcpy((dest), (src)) | |||
| #define strcat_P(dest, src) strcat((dest), (src)) | |||
| #define strcmp_P(a, b) strcmp((a), (b)) | |||
| #define strstr_P(a, b) strstr((a), (b)) | |||
| #define strlen_P(s) strlen((const char *)(s)) | |||
| #define strncmp_P(a, b, n) strncmp((a), (b), (n)) | |||
| #define strncpy_P(a, b, n) strncmp((a), (b), (n)) | |||
| #define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) | |||
| #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) | |||
| #define pgm_read_word(addr) (*(const unsigned short *)(addr)) | |||
| #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) | |||
| #define pgm_read_float(addr) (*(const float *)(addr)) | |||
| #define pgm_read_byte_near(addr) pgm_read_byte(addr) | |||
| #define pgm_read_word_near(addr) pgm_read_word(addr) | |||
| #define pgm_read_dword_near(addr) pgm_read_dword(addr) | |||
| #define pgm_read_float_near(addr) pgm_read_float(addr) | |||
| #define pgm_read_byte_far(addr) pgm_read_byte(addr) | |||
| #define pgm_read_word_far(addr) pgm_read_word(addr) | |||
| #define pgm_read_dword_far(addr) pgm_read_dword(addr) | |||
| #define pgm_read_float_far(addr) pgm_read_float(addr) | |||
| #endif | |||
| @@ -0,0 +1,34 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "avr_emulation.h" | |||
| uint8_t SPCRemulation::pinout = 0; | |||
| @@ -0,0 +1,105 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef _avr_functions_h_ | |||
| #define _avr_functions_h_ | |||
| #include <inttypes.h> | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void eeprom_initialize(void); | |||
| uint8_t eeprom_read_byte(const uint8_t *addr) __attribute__ ((pure)); | |||
| uint16_t eeprom_read_word(const uint16_t *addr) __attribute__ ((pure)); | |||
| uint32_t eeprom_read_dword(const uint32_t *addr) __attribute__ ((pure)); | |||
| void eeprom_read_block(void *buf, const void *addr, uint32_t len); | |||
| void eeprom_write_byte(uint8_t *addr, uint8_t value); | |||
| void eeprom_write_word(uint16_t *addr, uint16_t value); | |||
| void eeprom_write_dword(uint32_t *addr, uint32_t value); | |||
| void eeprom_write_block(const void *buf, void *addr, uint32_t len); | |||
| static inline float eeprom_read_float(const float *addr) __attribute__((pure, always_inline, unused)); | |||
| static inline float eeprom_read_float(const float *addr) | |||
| { | |||
| union {float f; uint32_t u32;} u; | |||
| u.u32 = eeprom_read_dword((const uint32_t *)addr); | |||
| return u.f; | |||
| } | |||
| static inline void eeprom_write_float(float *addr, float value) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_write_float(float *addr, float value) | |||
| { | |||
| union {float f; uint32_t u32;} u; | |||
| u.f = value; | |||
| eeprom_write_dword((uint32_t *)addr, u.u32); | |||
| } | |||
| static inline void eeprom_update_byte(uint8_t *addr, uint8_t value) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_update_byte(uint8_t *addr, uint8_t value) | |||
| { | |||
| eeprom_write_byte(addr, value); | |||
| } | |||
| static inline void eeprom_update_word(uint16_t *addr, uint16_t value) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_update_word(uint16_t *addr, uint16_t value) | |||
| { | |||
| eeprom_write_word(addr, value); | |||
| } | |||
| static inline void eeprom_update_dword(uint32_t *addr, uint32_t value) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_update_dword(uint32_t *addr, uint32_t value) | |||
| { | |||
| eeprom_write_dword(addr, value); | |||
| } | |||
| static inline void eeprom_update_float(float *addr, float value) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_update_float(float *addr, float value) | |||
| { | |||
| union {float f; uint32_t u32;} u; | |||
| u.f = value; | |||
| eeprom_write_dword((uint32_t *)addr, u.u32); | |||
| } | |||
| static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len) __attribute__((always_inline, unused)); | |||
| static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len) | |||
| { | |||
| eeprom_write_block(buf, addr, len); | |||
| } | |||
| char * ultoa(unsigned long val, char *buf, int radix); | |||
| char * ltoa(long val, char *buf, int radix); | |||
| static inline char * utoa(unsigned int val, char *buf, int radix) __attribute__((always_inline, unused)); | |||
| static inline char * utoa(unsigned int val, char *buf, int radix) { return ultoa(val, buf, radix); } | |||
| static inline char * itoa(int val, char *buf, int radix) __attribute__((always_inline, unused)); | |||
| static inline char * itoa(int val, char *buf, int radix) { return ltoa(val, buf, radix); } | |||
| char * dtostrf(float val, int width, unsigned int precision, char *buf); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,515 @@ | |||
| #ifndef Binary_h | |||
| #define Binary_h | |||
| #define B0 0 | |||
| #define B00 0 | |||
| #define B000 0 | |||
| #define B0000 0 | |||
| #define B00000 0 | |||
| #define B000000 0 | |||
| #define B0000000 0 | |||
| #define B00000000 0 | |||
| #define B1 1 | |||
| #define B01 1 | |||
| #define B001 1 | |||
| #define B0001 1 | |||
| #define B00001 1 | |||
| #define B000001 1 | |||
| #define B0000001 1 | |||
| #define B00000001 1 | |||
| #define B10 2 | |||
| #define B010 2 | |||
| #define B0010 2 | |||
| #define B00010 2 | |||
| #define B000010 2 | |||
| #define B0000010 2 | |||
| #define B00000010 2 | |||
| #define B11 3 | |||
| #define B011 3 | |||
| #define B0011 3 | |||
| #define B00011 3 | |||
| #define B000011 3 | |||
| #define B0000011 3 | |||
| #define B00000011 3 | |||
| #define B100 4 | |||
| #define B0100 4 | |||
| #define B00100 4 | |||
| #define B000100 4 | |||
| #define B0000100 4 | |||
| #define B00000100 4 | |||
| #define B101 5 | |||
| #define B0101 5 | |||
| #define B00101 5 | |||
| #define B000101 5 | |||
| #define B0000101 5 | |||
| #define B00000101 5 | |||
| #define B110 6 | |||
| #define B0110 6 | |||
| #define B00110 6 | |||
| #define B000110 6 | |||
| #define B0000110 6 | |||
| #define B00000110 6 | |||
| #define B111 7 | |||
| #define B0111 7 | |||
| #define B00111 7 | |||
| #define B000111 7 | |||
| #define B0000111 7 | |||
| #define B00000111 7 | |||
| #define B1000 8 | |||
| #define B01000 8 | |||
| #define B001000 8 | |||
| #define B0001000 8 | |||
| #define B00001000 8 | |||
| #define B1001 9 | |||
| #define B01001 9 | |||
| #define B001001 9 | |||
| #define B0001001 9 | |||
| #define B00001001 9 | |||
| #define B1010 10 | |||
| #define B01010 10 | |||
| #define B001010 10 | |||
| #define B0001010 10 | |||
| #define B00001010 10 | |||
| #define B1011 11 | |||
| #define B01011 11 | |||
| #define B001011 11 | |||
| #define B0001011 11 | |||
| #define B00001011 11 | |||
| #define B1100 12 | |||
| #define B01100 12 | |||
| #define B001100 12 | |||
| #define B0001100 12 | |||
| #define B00001100 12 | |||
| #define B1101 13 | |||
| #define B01101 13 | |||
| #define B001101 13 | |||
| #define B0001101 13 | |||
| #define B00001101 13 | |||
| #define B1110 14 | |||
| #define B01110 14 | |||
| #define B001110 14 | |||
| #define B0001110 14 | |||
| #define B00001110 14 | |||
| #define B1111 15 | |||
| #define B01111 15 | |||
| #define B001111 15 | |||
| #define B0001111 15 | |||
| #define B00001111 15 | |||
| #define B10000 16 | |||
| #define B010000 16 | |||
| #define B0010000 16 | |||
| #define B00010000 16 | |||
| #define B10001 17 | |||
| #define B010001 17 | |||
| #define B0010001 17 | |||
| #define B00010001 17 | |||
| #define B10010 18 | |||
| #define B010010 18 | |||
| #define B0010010 18 | |||
| #define B00010010 18 | |||
| #define B10011 19 | |||
| #define B010011 19 | |||
| #define B0010011 19 | |||
| #define B00010011 19 | |||
| #define B10100 20 | |||
| #define B010100 20 | |||
| #define B0010100 20 | |||
| #define B00010100 20 | |||
| #define B10101 21 | |||
| #define B010101 21 | |||
| #define B0010101 21 | |||
| #define B00010101 21 | |||
| #define B10110 22 | |||
| #define B010110 22 | |||
| #define B0010110 22 | |||
| #define B00010110 22 | |||
| #define B10111 23 | |||
| #define B010111 23 | |||
| #define B0010111 23 | |||
| #define B00010111 23 | |||
| #define B11000 24 | |||
| #define B011000 24 | |||
| #define B0011000 24 | |||
| #define B00011000 24 | |||
| #define B11001 25 | |||
| #define B011001 25 | |||
| #define B0011001 25 | |||
| #define B00011001 25 | |||
| #define B11010 26 | |||
| #define B011010 26 | |||
| #define B0011010 26 | |||
| #define B00011010 26 | |||
| #define B11011 27 | |||
| #define B011011 27 | |||
| #define B0011011 27 | |||
| #define B00011011 27 | |||
| #define B11100 28 | |||
| #define B011100 28 | |||
| #define B0011100 28 | |||
| #define B00011100 28 | |||
| #define B11101 29 | |||
| #define B011101 29 | |||
| #define B0011101 29 | |||
| #define B00011101 29 | |||
| #define B11110 30 | |||
| #define B011110 30 | |||
| #define B0011110 30 | |||
| #define B00011110 30 | |||
| #define B11111 31 | |||
| #define B011111 31 | |||
| #define B0011111 31 | |||
| #define B00011111 31 | |||
| #define B100000 32 | |||
| #define B0100000 32 | |||
| #define B00100000 32 | |||
| #define B100001 33 | |||
| #define B0100001 33 | |||
| #define B00100001 33 | |||
| #define B100010 34 | |||
| #define B0100010 34 | |||
| #define B00100010 34 | |||
| #define B100011 35 | |||
| #define B0100011 35 | |||
| #define B00100011 35 | |||
| #define B100100 36 | |||
| #define B0100100 36 | |||
| #define B00100100 36 | |||
| #define B100101 37 | |||
| #define B0100101 37 | |||
| #define B00100101 37 | |||
| #define B100110 38 | |||
| #define B0100110 38 | |||
| #define B00100110 38 | |||
| #define B100111 39 | |||
| #define B0100111 39 | |||
| #define B00100111 39 | |||
| #define B101000 40 | |||
| #define B0101000 40 | |||
| #define B00101000 40 | |||
| #define B101001 41 | |||
| #define B0101001 41 | |||
| #define B00101001 41 | |||
| #define B101010 42 | |||
| #define B0101010 42 | |||
| #define B00101010 42 | |||
| #define B101011 43 | |||
| #define B0101011 43 | |||
| #define B00101011 43 | |||
| #define B101100 44 | |||
| #define B0101100 44 | |||
| #define B00101100 44 | |||
| #define B101101 45 | |||
| #define B0101101 45 | |||
| #define B00101101 45 | |||
| #define B101110 46 | |||
| #define B0101110 46 | |||
| #define B00101110 46 | |||
| #define B101111 47 | |||
| #define B0101111 47 | |||
| #define B00101111 47 | |||
| #define B110000 48 | |||
| #define B0110000 48 | |||
| #define B00110000 48 | |||
| #define B110001 49 | |||
| #define B0110001 49 | |||
| #define B00110001 49 | |||
| #define B110010 50 | |||
| #define B0110010 50 | |||
| #define B00110010 50 | |||
| #define B110011 51 | |||
| #define B0110011 51 | |||
| #define B00110011 51 | |||
| #define B110100 52 | |||
| #define B0110100 52 | |||
| #define B00110100 52 | |||
| #define B110101 53 | |||
| #define B0110101 53 | |||
| #define B00110101 53 | |||
| #define B110110 54 | |||
| #define B0110110 54 | |||
| #define B00110110 54 | |||
| #define B110111 55 | |||
| #define B0110111 55 | |||
| #define B00110111 55 | |||
| #define B111000 56 | |||
| #define B0111000 56 | |||
| #define B00111000 56 | |||
| #define B111001 57 | |||
| #define B0111001 57 | |||
| #define B00111001 57 | |||
| #define B111010 58 | |||
| #define B0111010 58 | |||
| #define B00111010 58 | |||
| #define B111011 59 | |||
| #define B0111011 59 | |||
| #define B00111011 59 | |||
| #define B111100 60 | |||
| #define B0111100 60 | |||
| #define B00111100 60 | |||
| #define B111101 61 | |||
| #define B0111101 61 | |||
| #define B00111101 61 | |||
| #define B111110 62 | |||
| #define B0111110 62 | |||
| #define B00111110 62 | |||
| #define B111111 63 | |||
| #define B0111111 63 | |||
| #define B00111111 63 | |||
| #define B1000000 64 | |||
| #define B01000000 64 | |||
| #define B1000001 65 | |||
| #define B01000001 65 | |||
| #define B1000010 66 | |||
| #define B01000010 66 | |||
| #define B1000011 67 | |||
| #define B01000011 67 | |||
| #define B1000100 68 | |||
| #define B01000100 68 | |||
| #define B1000101 69 | |||
| #define B01000101 69 | |||
| #define B1000110 70 | |||
| #define B01000110 70 | |||
| #define B1000111 71 | |||
| #define B01000111 71 | |||
| #define B1001000 72 | |||
| #define B01001000 72 | |||
| #define B1001001 73 | |||
| #define B01001001 73 | |||
| #define B1001010 74 | |||
| #define B01001010 74 | |||
| #define B1001011 75 | |||
| #define B01001011 75 | |||
| #define B1001100 76 | |||
| #define B01001100 76 | |||
| #define B1001101 77 | |||
| #define B01001101 77 | |||
| #define B1001110 78 | |||
| #define B01001110 78 | |||
| #define B1001111 79 | |||
| #define B01001111 79 | |||
| #define B1010000 80 | |||
| #define B01010000 80 | |||
| #define B1010001 81 | |||
| #define B01010001 81 | |||
| #define B1010010 82 | |||
| #define B01010010 82 | |||
| #define B1010011 83 | |||
| #define B01010011 83 | |||
| #define B1010100 84 | |||
| #define B01010100 84 | |||
| #define B1010101 85 | |||
| #define B01010101 85 | |||
| #define B1010110 86 | |||
| #define B01010110 86 | |||
| #define B1010111 87 | |||
| #define B01010111 87 | |||
| #define B1011000 88 | |||
| #define B01011000 88 | |||
| #define B1011001 89 | |||
| #define B01011001 89 | |||
| #define B1011010 90 | |||
| #define B01011010 90 | |||
| #define B1011011 91 | |||
| #define B01011011 91 | |||
| #define B1011100 92 | |||
| #define B01011100 92 | |||
| #define B1011101 93 | |||
| #define B01011101 93 | |||
| #define B1011110 94 | |||
| #define B01011110 94 | |||
| #define B1011111 95 | |||
| #define B01011111 95 | |||
| #define B1100000 96 | |||
| #define B01100000 96 | |||
| #define B1100001 97 | |||
| #define B01100001 97 | |||
| #define B1100010 98 | |||
| #define B01100010 98 | |||
| #define B1100011 99 | |||
| #define B01100011 99 | |||
| #define B1100100 100 | |||
| #define B01100100 100 | |||
| #define B1100101 101 | |||
| #define B01100101 101 | |||
| #define B1100110 102 | |||
| #define B01100110 102 | |||
| #define B1100111 103 | |||
| #define B01100111 103 | |||
| #define B1101000 104 | |||
| #define B01101000 104 | |||
| #define B1101001 105 | |||
| #define B01101001 105 | |||
| #define B1101010 106 | |||
| #define B01101010 106 | |||
| #define B1101011 107 | |||
| #define B01101011 107 | |||
| #define B1101100 108 | |||
| #define B01101100 108 | |||
| #define B1101101 109 | |||
| #define B01101101 109 | |||
| #define B1101110 110 | |||
| #define B01101110 110 | |||
| #define B1101111 111 | |||
| #define B01101111 111 | |||
| #define B1110000 112 | |||
| #define B01110000 112 | |||
| #define B1110001 113 | |||
| #define B01110001 113 | |||
| #define B1110010 114 | |||
| #define B01110010 114 | |||
| #define B1110011 115 | |||
| #define B01110011 115 | |||
| #define B1110100 116 | |||
| #define B01110100 116 | |||
| #define B1110101 117 | |||
| #define B01110101 117 | |||
| #define B1110110 118 | |||
| #define B01110110 118 | |||
| #define B1110111 119 | |||
| #define B01110111 119 | |||
| #define B1111000 120 | |||
| #define B01111000 120 | |||
| #define B1111001 121 | |||
| #define B01111001 121 | |||
| #define B1111010 122 | |||
| #define B01111010 122 | |||
| #define B1111011 123 | |||
| #define B01111011 123 | |||
| #define B1111100 124 | |||
| #define B01111100 124 | |||
| #define B1111101 125 | |||
| #define B01111101 125 | |||
| #define B1111110 126 | |||
| #define B01111110 126 | |||
| #define B1111111 127 | |||
| #define B01111111 127 | |||
| #define B10000000 128 | |||
| #define B10000001 129 | |||
| #define B10000010 130 | |||
| #define B10000011 131 | |||
| #define B10000100 132 | |||
| #define B10000101 133 | |||
| #define B10000110 134 | |||
| #define B10000111 135 | |||
| #define B10001000 136 | |||
| #define B10001001 137 | |||
| #define B10001010 138 | |||
| #define B10001011 139 | |||
| #define B10001100 140 | |||
| #define B10001101 141 | |||
| #define B10001110 142 | |||
| #define B10001111 143 | |||
| #define B10010000 144 | |||
| #define B10010001 145 | |||
| #define B10010010 146 | |||
| #define B10010011 147 | |||
| #define B10010100 148 | |||
| #define B10010101 149 | |||
| #define B10010110 150 | |||
| #define B10010111 151 | |||
| #define B10011000 152 | |||
| #define B10011001 153 | |||
| #define B10011010 154 | |||
| #define B10011011 155 | |||
| #define B10011100 156 | |||
| #define B10011101 157 | |||
| #define B10011110 158 | |||
| #define B10011111 159 | |||
| #define B10100000 160 | |||
| #define B10100001 161 | |||
| #define B10100010 162 | |||
| #define B10100011 163 | |||
| #define B10100100 164 | |||
| #define B10100101 165 | |||
| #define B10100110 166 | |||
| #define B10100111 167 | |||
| #define B10101000 168 | |||
| #define B10101001 169 | |||
| #define B10101010 170 | |||
| #define B10101011 171 | |||
| #define B10101100 172 | |||
| #define B10101101 173 | |||
| #define B10101110 174 | |||
| #define B10101111 175 | |||
| #define B10110000 176 | |||
| #define B10110001 177 | |||
| #define B10110010 178 | |||
| #define B10110011 179 | |||
| #define B10110100 180 | |||
| #define B10110101 181 | |||
| #define B10110110 182 | |||
| #define B10110111 183 | |||
| #define B10111000 184 | |||
| #define B10111001 185 | |||
| #define B10111010 186 | |||
| #define B10111011 187 | |||
| #define B10111100 188 | |||
| #define B10111101 189 | |||
| #define B10111110 190 | |||
| #define B10111111 191 | |||
| #define B11000000 192 | |||
| #define B11000001 193 | |||
| #define B11000010 194 | |||
| #define B11000011 195 | |||
| #define B11000100 196 | |||
| #define B11000101 197 | |||
| #define B11000110 198 | |||
| #define B11000111 199 | |||
| #define B11001000 200 | |||
| #define B11001001 201 | |||
| #define B11001010 202 | |||
| #define B11001011 203 | |||
| #define B11001100 204 | |||
| #define B11001101 205 | |||
| #define B11001110 206 | |||
| #define B11001111 207 | |||
| #define B11010000 208 | |||
| #define B11010001 209 | |||
| #define B11010010 210 | |||
| #define B11010011 211 | |||
| #define B11010100 212 | |||
| #define B11010101 213 | |||
| #define B11010110 214 | |||
| #define B11010111 215 | |||
| #define B11011000 216 | |||
| #define B11011001 217 | |||
| #define B11011010 218 | |||
| #define B11011011 219 | |||
| #define B11011100 220 | |||
| #define B11011101 221 | |||
| #define B11011110 222 | |||
| #define B11011111 223 | |||
| #define B11100000 224 | |||
| #define B11100001 225 | |||
| #define B11100010 226 | |||
| #define B11100011 227 | |||
| #define B11100100 228 | |||
| #define B11100101 229 | |||
| #define B11100110 230 | |||
| #define B11100111 231 | |||
| #define B11101000 232 | |||
| #define B11101001 233 | |||
| #define B11101010 234 | |||
| #define B11101011 235 | |||
| #define B11101100 236 | |||
| #define B11101101 237 | |||
| #define B11101110 238 | |||
| #define B11101111 239 | |||
| #define B11110000 240 | |||
| #define B11110001 241 | |||
| #define B11110010 242 | |||
| #define B11110011 243 | |||
| #define B11110100 244 | |||
| #define B11110101 245 | |||
| #define B11110110 246 | |||
| #define B11110111 247 | |||
| #define B11111000 248 | |||
| #define B11111001 249 | |||
| #define B11111010 250 | |||
| #define B11111011 251 | |||
| #define B11111100 252 | |||
| #define B11111101 253 | |||
| #define B11111110 254 | |||
| #define B11111111 255 | |||
| #endif | |||
| @@ -0,0 +1,541 @@ | |||
| /**************************************************************************//** | |||
| * @file core_cm4_simd.h | |||
| * @brief CMSIS Cortex-M4 SIMD Header File | |||
| * @version V3.01 | |||
| * @date 06. March 2012 | |||
| * | |||
| * @note | |||
| * Copyright (C) 2010-2012 ARM Limited. All rights reserved. | |||
| * | |||
| * @par | |||
| * ARM Limited (ARM) is supplying this software for use with Cortex-M | |||
| * processor based microcontrollers. This file can be freely distributed | |||
| * within development tools that are supporting such ARM based processors. | |||
| * | |||
| * @par | |||
| * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED | |||
| * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF | |||
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. | |||
| * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR | |||
| * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. | |||
| * | |||
| ******************************************************************************/ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #ifndef __CORE_CM4_SIMD_H | |||
| #define __CORE_CM4_SIMD_H | |||
| /******************************************************************************* | |||
| * Hardware Abstraction Layer | |||
| ******************************************************************************/ | |||
| /* ################### Compiler specific Intrinsics ########################### */ | |||
| /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics | |||
| Access to dedicated SIMD instructions | |||
| @{ | |||
| */ | |||
| #if defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ | |||
| /* GNU gcc specific functions */ | |||
| /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); | |||
| return(result); | |||
| } | |||
| #define __SSAT16(ARG1,ARG2) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1); \ | |||
| __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ | |||
| __RES; \ | |||
| }) | |||
| #define __USAT16(ARG1,ARG2) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1); \ | |||
| __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ | |||
| __RES; \ | |||
| }) | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); | |||
| return(result); | |||
| } | |||
| #define __SMLALD(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ | |||
| __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ | |||
| (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ | |||
| }) | |||
| #define __SMLALDX(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ | |||
| __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ | |||
| (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ | |||
| }) | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); | |||
| return(result); | |||
| } | |||
| #define __SMLSLD(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ | |||
| __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ | |||
| (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ | |||
| }) | |||
| #define __SMLSLDX(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ | |||
| __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ | |||
| (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ | |||
| }) | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); | |||
| return(result); | |||
| } | |||
| #define __PKHBT(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ | |||
| __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ | |||
| __RES; \ | |||
| }) | |||
| #define __PKHTB(ARG1,ARG2,ARG3) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ | |||
| if (ARG3 == 0) \ | |||
| __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ | |||
| else \ | |||
| __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ | |||
| __RES; \ | |||
| }) | |||
| /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ | |||
| #endif /* __GNUC__ */ | |||
| #endif /* __CORE_CM4_SIMD_H */ | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,374 @@ | |||
| /**************************************************************************//** | |||
| * @file core_cmInstr.h | |||
| * @brief CMSIS Cortex-M Core Instruction Access Header File | |||
| * @version V3.01 | |||
| * @date 06. March 2012 | |||
| * | |||
| * @note | |||
| * Copyright (C) 2009-2012 ARM Limited. All rights reserved. | |||
| * | |||
| * @par | |||
| * ARM Limited (ARM) is supplying this software for use with Cortex-M | |||
| * processor based microcontrollers. This file can be freely distributed | |||
| * within development tools that are supporting such ARM based processors. | |||
| * | |||
| * @par | |||
| * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED | |||
| * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF | |||
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. | |||
| * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR | |||
| * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. | |||
| * | |||
| ******************************************************************************/ | |||
| #ifndef __CORE_CMINSTR_H | |||
| #define __CORE_CMINSTR_H | |||
| /* ########################## Core Instruction Access ######################### */ | |||
| /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface | |||
| Access to dedicated instructions | |||
| @{ | |||
| */ | |||
| #if defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ | |||
| /* GNU gcc specific functions */ | |||
| /** \brief No Operation | |||
| No Operation does nothing. This instruction can be used for code alignment purposes. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) | |||
| { | |||
| __ASM volatile ("nop"); | |||
| } | |||
| /** \brief Wait For Interrupt | |||
| Wait For Interrupt is a hint instruction that suspends execution | |||
| until one of a number of events occurs. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) | |||
| { | |||
| __ASM volatile ("wfi"); | |||
| } | |||
| /** \brief Wait For Event | |||
| Wait For Event is a hint instruction that permits the processor to enter | |||
| a low-power state until one of a number of events occurs. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) | |||
| { | |||
| __ASM volatile ("wfe"); | |||
| } | |||
| /** \brief Send Event | |||
| Send Event is a hint instruction. It causes an event to be signaled to the CPU. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) | |||
| { | |||
| __ASM volatile ("sev"); | |||
| } | |||
| /** \brief Instruction Synchronization Barrier | |||
| Instruction Synchronization Barrier flushes the pipeline in the processor, | |||
| so that all instructions following the ISB are fetched from cache or | |||
| memory, after the instruction has been completed. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) | |||
| { | |||
| __ASM volatile ("isb"); | |||
| } | |||
| /** \brief Data Synchronization Barrier | |||
| This function acts as a special kind of Data Memory Barrier. | |||
| It completes when all explicit memory accesses before this instruction complete. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) | |||
| { | |||
| __ASM volatile ("dsb"); | |||
| } | |||
| /** \brief Data Memory Barrier | |||
| This function ensures the apparent order of the explicit memory operations before | |||
| and after the instruction, without ensuring their completion. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) | |||
| { | |||
| __ASM volatile ("dmb"); | |||
| } | |||
| /** \brief Reverse byte order (32 bit) | |||
| This function reverses the byte order in integer value. | |||
| \param [in] value Value to reverse | |||
| \return Reversed value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief Reverse byte order (16 bit) | |||
| This function reverses the byte order in two unsigned short values. | |||
| \param [in] value Value to reverse | |||
| \return Reversed value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief Reverse byte order in signed short value | |||
| This function reverses the byte order in a signed short value with sign extension to integer. | |||
| \param [in] value Value to reverse | |||
| \return Reversed value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief Rotate Right in unsigned value (32 bit) | |||
| This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. | |||
| \param [in] value Value to rotate | |||
| \param [in] value Number of Bits to rotate | |||
| \return Rotated value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) | |||
| { | |||
| __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); | |||
| return(op1); | |||
| } | |||
| #if (__CORTEX_M >= 0x03) | |||
| /** \brief Reverse bit order of value | |||
| This function reverses the bit order of the given value. | |||
| \param [in] value Value to reverse | |||
| \return Reversed value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief LDR Exclusive (8 bit) | |||
| This function performs a exclusive LDR command for 8 bit value. | |||
| \param [in] ptr Pointer to data | |||
| \return value of type uint8_t at (*ptr) | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) | |||
| { | |||
| uint8_t result; | |||
| __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); | |||
| return(result); | |||
| } | |||
| /** \brief LDR Exclusive (16 bit) | |||
| This function performs a exclusive LDR command for 16 bit values. | |||
| \param [in] ptr Pointer to data | |||
| \return value of type uint16_t at (*ptr) | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) | |||
| { | |||
| uint16_t result; | |||
| __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); | |||
| return(result); | |||
| } | |||
| /** \brief LDR Exclusive (32 bit) | |||
| This function performs a exclusive LDR command for 32 bit values. | |||
| \param [in] ptr Pointer to data | |||
| \return value of type uint32_t at (*ptr) | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); | |||
| return(result); | |||
| } | |||
| /** \brief STR Exclusive (8 bit) | |||
| This function performs a exclusive STR command for 8 bit values. | |||
| \param [in] value Value to store | |||
| \param [in] ptr Pointer to location | |||
| \return 0 Function succeeded | |||
| \return 1 Function failed | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief STR Exclusive (16 bit) | |||
| This function performs a exclusive STR command for 16 bit values. | |||
| \param [in] value Value to store | |||
| \param [in] ptr Pointer to location | |||
| \return 0 Function succeeded | |||
| \return 1 Function failed | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief STR Exclusive (32 bit) | |||
| This function performs a exclusive STR command for 32 bit values. | |||
| \param [in] value Value to store | |||
| \param [in] ptr Pointer to location | |||
| \return 0 Function succeeded | |||
| \return 1 Function failed | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) | |||
| { | |||
| uint32_t result; | |||
| __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); | |||
| return(result); | |||
| } | |||
| /** \brief Remove the exclusive lock | |||
| This function removes the exclusive lock which is created by LDREX. | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) | |||
| { | |||
| __ASM volatile ("clrex"); | |||
| } | |||
| /** \brief Signed Saturate | |||
| This function saturates a signed value. | |||
| \param [in] value Value to be saturated | |||
| \param [in] sat Bit position to saturate to (1..32) | |||
| \return Saturated value | |||
| */ | |||
| #define __SSAT(ARG1,ARG2) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1); \ | |||
| __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ | |||
| __RES; \ | |||
| }) | |||
| /** \brief Unsigned Saturate | |||
| This function saturates an unsigned value. | |||
| \param [in] value Value to be saturated | |||
| \param [in] sat Bit position to saturate to (0..31) | |||
| \return Saturated value | |||
| */ | |||
| #define __USAT(ARG1,ARG2) \ | |||
| ({ \ | |||
| uint32_t __RES, __ARG1 = (ARG1); \ | |||
| __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ | |||
| __RES; \ | |||
| }) | |||
| /** \brief Count leading zeros | |||
| This function counts the number of leading zeros of a data value. | |||
| \param [in] value Value to count the leading zeros | |||
| \return number of leading zeros in value | |||
| */ | |||
| __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) | |||
| { | |||
| uint8_t result; | |||
| __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); | |||
| return(result); | |||
| } | |||
| #endif /* (__CORTEX_M >= 0x03) */ | |||
| #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ | |||
| /* TASKING carm specific functions */ | |||
| /* | |||
| * The CMSIS functions have been implemented as intrinsics in the compiler. | |||
| * Please use "carm -?i" to get an up to date list of all intrinsics, | |||
| * Including the CMSIS ones. | |||
| */ | |||
| #endif | |||
| /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ | |||
| #endif /* __CORE_CMINSTR_H */ | |||
| @@ -0,0 +1,3 @@ | |||
| #ifndef CORE_TEENSY | |||
| #define CORE_TEENSY | |||
| #endif | |||
| @@ -0,0 +1,815 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef _core_pins_h_ | |||
| #define _core_pins_h_ | |||
| #include "mk20dx128.h" | |||
| #include "pins_arduino.h" | |||
| #define HIGH 1 | |||
| #define LOW 0 | |||
| #define INPUT 0 | |||
| #define OUTPUT 1 | |||
| #define INPUT_PULLUP 2 | |||
| #define LSBFIRST 0 | |||
| #define MSBFIRST 1 | |||
| #define _BV(n) (1<<(n)) | |||
| #define CHANGE 4 | |||
| #define FALLING 2 | |||
| #define RISING 3 | |||
| // Pin Arduino | |||
| // 0 B16 RXD | |||
| // 1 B17 TXD | |||
| // 2 D0 | |||
| // 3 A12 FTM1_CH0 | |||
| // 4 A13 FTM1_CH1 | |||
| // 5 D7 FTM0_CH7 OC0B/T1 | |||
| // 6 D4 FTM0_CH4 OC0A | |||
| // 7 D2 | |||
| // 8 D3 ICP1 | |||
| // 9 C3 FTM0_CH2 OC1A | |||
| // 10 C4 FTM0_CH3 SS/OC1B | |||
| // 11 C6 MOSI/OC2A | |||
| // 12 C7 MISO | |||
| // 13 C5 SCK | |||
| // 14 D1 | |||
| // 15 C0 | |||
| // 16 B0 (FTM1_CH0) | |||
| // 17 B1 (FTM1_CH1) | |||
| // 18 B3 SDA | |||
| // 19 B2 SCL | |||
| // 20 D5 FTM0_CH5 | |||
| // 21 D6 FTM0_CH6 | |||
| // 22 C1 FTM0_CH0 | |||
| // 23 C2 FTM0_CH1 | |||
| // 24 A5 (FTM0_CH2) | |||
| // 25 B19 | |||
| // 26 E1 | |||
| // 27 C9 | |||
| // 28 C8 | |||
| // 29 C10 | |||
| // 30 C11 | |||
| // 31 E0 | |||
| // 32 B18 | |||
| // 33 A4 (FTM0_CH1) | |||
| // (34) analog only | |||
| // (35) analog only | |||
| // (36) analog only | |||
| // (37) analog only | |||
| // not available to user: | |||
| // A0 FTM0_CH5 SWD Clock | |||
| // A1 FTM0_CH6 USB ID | |||
| // A2 FTM0_CH7 SWD Trace | |||
| // A3 FTM0_CH0 SWD Data | |||
| #define CORE_NUM_TOTAL_PINS 34 | |||
| #define CORE_NUM_DIGITAL 34 | |||
| #define CORE_NUM_ANALOG 14 | |||
| #define CORE_NUM_PWM 10 | |||
| #define CORE_NUM_INTERRUPT 34 | |||
| #define CORE_PIN0_BIT 16 | |||
| #define CORE_PIN1_BIT 17 | |||
| #define CORE_PIN2_BIT 0 | |||
| #define CORE_PIN3_BIT 12 | |||
| #define CORE_PIN4_BIT 13 | |||
| #define CORE_PIN5_BIT 7 | |||
| #define CORE_PIN6_BIT 4 | |||
| #define CORE_PIN7_BIT 2 | |||
| #define CORE_PIN8_BIT 3 | |||
| #define CORE_PIN9_BIT 3 | |||
| #define CORE_PIN10_BIT 4 | |||
| #define CORE_PIN11_BIT 6 | |||
| #define CORE_PIN12_BIT 7 | |||
| #define CORE_PIN13_BIT 5 | |||
| #define CORE_PIN14_BIT 1 | |||
| #define CORE_PIN15_BIT 0 | |||
| #define CORE_PIN16_BIT 0 | |||
| #define CORE_PIN17_BIT 1 | |||
| #define CORE_PIN18_BIT 3 | |||
| #define CORE_PIN19_BIT 2 | |||
| #define CORE_PIN20_BIT 5 | |||
| #define CORE_PIN21_BIT 6 | |||
| #define CORE_PIN22_BIT 1 | |||
| #define CORE_PIN23_BIT 2 | |||
| #define CORE_PIN24_BIT 5 | |||
| #define CORE_PIN25_BIT 19 | |||
| #define CORE_PIN26_BIT 1 | |||
| #define CORE_PIN27_BIT 9 | |||
| #define CORE_PIN28_BIT 8 | |||
| #define CORE_PIN29_BIT 10 | |||
| #define CORE_PIN30_BIT 11 | |||
| #define CORE_PIN31_BIT 0 | |||
| #define CORE_PIN32_BIT 18 | |||
| #define CORE_PIN33_BIT 4 | |||
| #define CORE_PIN0_BITMASK (1<<(CORE_PIN0_BIT)) | |||
| #define CORE_PIN1_BITMASK (1<<(CORE_PIN1_BIT)) | |||
| #define CORE_PIN2_BITMASK (1<<(CORE_PIN2_BIT)) | |||
| #define CORE_PIN3_BITMASK (1<<(CORE_PIN3_BIT)) | |||
| #define CORE_PIN4_BITMASK (1<<(CORE_PIN4_BIT)) | |||
| #define CORE_PIN5_BITMASK (1<<(CORE_PIN5_BIT)) | |||
| #define CORE_PIN6_BITMASK (1<<(CORE_PIN6_BIT)) | |||
| #define CORE_PIN7_BITMASK (1<<(CORE_PIN7_BIT)) | |||
| #define CORE_PIN8_BITMASK (1<<(CORE_PIN8_BIT)) | |||
| #define CORE_PIN9_BITMASK (1<<(CORE_PIN9_BIT)) | |||
| #define CORE_PIN10_BITMASK (1<<(CORE_PIN10_BIT)) | |||
| #define CORE_PIN11_BITMASK (1<<(CORE_PIN11_BIT)) | |||
| #define CORE_PIN12_BITMASK (1<<(CORE_PIN12_BIT)) | |||
| #define CORE_PIN13_BITMASK (1<<(CORE_PIN13_BIT)) | |||
| #define CORE_PIN14_BITMASK (1<<(CORE_PIN14_BIT)) | |||
| #define CORE_PIN15_BITMASK (1<<(CORE_PIN15_BIT)) | |||
| #define CORE_PIN16_BITMASK (1<<(CORE_PIN16_BIT)) | |||
| #define CORE_PIN17_BITMASK (1<<(CORE_PIN17_BIT)) | |||
| #define CORE_PIN18_BITMASK (1<<(CORE_PIN18_BIT)) | |||
| #define CORE_PIN19_BITMASK (1<<(CORE_PIN19_BIT)) | |||
| #define CORE_PIN20_BITMASK (1<<(CORE_PIN20_BIT)) | |||
| #define CORE_PIN21_BITMASK (1<<(CORE_PIN21_BIT)) | |||
| #define CORE_PIN22_BITMASK (1<<(CORE_PIN22_BIT)) | |||
| #define CORE_PIN23_BITMASK (1<<(CORE_PIN23_BIT)) | |||
| #define CORE_PIN24_BITMASK (1<<(CORE_PIN24_BIT)) | |||
| #define CORE_PIN25_BITMASK (1<<(CORE_PIN25_BIT)) | |||
| #define CORE_PIN26_BITMASK (1<<(CORE_PIN26_BIT)) | |||
| #define CORE_PIN27_BITMASK (1<<(CORE_PIN27_BIT)) | |||
| #define CORE_PIN28_BITMASK (1<<(CORE_PIN28_BIT)) | |||
| #define CORE_PIN29_BITMASK (1<<(CORE_PIN29_BIT)) | |||
| #define CORE_PIN30_BITMASK (1<<(CORE_PIN30_BIT)) | |||
| #define CORE_PIN31_BITMASK (1<<(CORE_PIN31_BIT)) | |||
| #define CORE_PIN32_BITMASK (1<<(CORE_PIN32_BIT)) | |||
| #define CORE_PIN33_BITMASK (1<<(CORE_PIN33_BIT)) | |||
| #define CORE_PIN0_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN1_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN2_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN3_PORTREG GPIOA_PDOR | |||
| #define CORE_PIN4_PORTREG GPIOA_PDOR | |||
| #define CORE_PIN5_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN6_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN7_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN8_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN9_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN10_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN11_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN12_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN13_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN14_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN15_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN16_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN17_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN18_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN19_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN20_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN21_PORTREG GPIOD_PDOR | |||
| #define CORE_PIN22_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN23_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN24_PORTREG GPIOA_PDOR | |||
| #define CORE_PIN25_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN26_PORTREG GPIOE_PDOR | |||
| #define CORE_PIN27_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN28_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN29_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN30_PORTREG GPIOC_PDOR | |||
| #define CORE_PIN31_PORTREG GPIOE_PDOR | |||
| #define CORE_PIN32_PORTREG GPIOB_PDOR | |||
| #define CORE_PIN33_PORTREG GPIOA_PDOR | |||
| #define CORE_PIN0_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN1_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN2_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN3_PORTSET GPIOA_PSOR | |||
| #define CORE_PIN4_PORTSET GPIOA_PSOR | |||
| #define CORE_PIN5_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN6_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN7_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN8_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN9_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN10_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN11_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN12_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN13_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN14_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN15_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN16_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN17_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN18_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN19_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN20_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN21_PORTSET GPIOD_PSOR | |||
| #define CORE_PIN22_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN23_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN24_PORTSET GPIOA_PSOR | |||
| #define CORE_PIN25_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN26_PORTSET GPIOE_PSOR | |||
| #define CORE_PIN27_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN28_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN29_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN30_PORTSET GPIOC_PSOR | |||
| #define CORE_PIN31_PORTSET GPIOE_PSOR | |||
| #define CORE_PIN32_PORTSET GPIOB_PSOR | |||
| #define CORE_PIN33_PORTSET GPIOA_PSOR | |||
| #define CORE_PIN0_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN1_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN2_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN3_PORTCLEAR GPIOA_PCOR | |||
| #define CORE_PIN4_PORTCLEAR GPIOA_PCOR | |||
| #define CORE_PIN5_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN6_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN7_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN8_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN9_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN10_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN11_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN12_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN13_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN14_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN15_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN16_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN17_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN18_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN19_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN20_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN21_PORTCLEAR GPIOD_PCOR | |||
| #define CORE_PIN22_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN23_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN24_PORTCLEAR GPIOA_PCOR | |||
| #define CORE_PIN25_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN26_PORTCLEAR GPIOE_PCOR | |||
| #define CORE_PIN27_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN28_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN29_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN30_PORTCLEAR GPIOC_PCOR | |||
| #define CORE_PIN31_PORTCLEAR GPIOE_PCOR | |||
| #define CORE_PIN32_PORTCLEAR GPIOB_PCOR | |||
| #define CORE_PIN33_PORTCLEAR GPIOA_PCOR | |||
| #define CORE_PIN0_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN1_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN2_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN3_DDRREG GPIOA_PDDR | |||
| #define CORE_PIN4_DDRREG GPIOA_PDDR | |||
| #define CORE_PIN5_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN6_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN7_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN8_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN9_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN10_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN11_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN12_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN13_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN14_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN15_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN16_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN17_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN18_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN19_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN20_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN21_DDRREG GPIOD_PDDR | |||
| #define CORE_PIN22_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN23_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN24_DDRREG GPIOA_PDDR | |||
| #define CORE_PIN25_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN26_DDRREG GPIOE_PDDR | |||
| #define CORE_PIN27_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN28_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN29_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN30_DDRREG GPIOC_PDDR | |||
| #define CORE_PIN31_DDRREG GPIOE_PDDR | |||
| #define CORE_PIN32_DDRREG GPIOB_PDDR | |||
| #define CORE_PIN33_DDRREG GPIOA_PDDR | |||
| #define CORE_PIN0_PINREG GPIOB_PDIR | |||
| #define CORE_PIN1_PINREG GPIOB_PDIR | |||
| #define CORE_PIN2_PINREG GPIOD_PDIR | |||
| #define CORE_PIN3_PINREG GPIOA_PDIR | |||
| #define CORE_PIN4_PINREG GPIOA_PDIR | |||
| #define CORE_PIN5_PINREG GPIOD_PDIR | |||
| #define CORE_PIN6_PINREG GPIOD_PDIR | |||
| #define CORE_PIN7_PINREG GPIOD_PDIR | |||
| #define CORE_PIN8_PINREG GPIOD_PDIR | |||
| #define CORE_PIN9_PINREG GPIOC_PDIR | |||
| #define CORE_PIN10_PINREG GPIOC_PDIR | |||
| #define CORE_PIN11_PINREG GPIOC_PDIR | |||
| #define CORE_PIN12_PINREG GPIOC_PDIR | |||
| #define CORE_PIN13_PINREG GPIOC_PDIR | |||
| #define CORE_PIN14_PINREG GPIOD_PDIR | |||
| #define CORE_PIN15_PINREG GPIOC_PDIR | |||
| #define CORE_PIN16_PINREG GPIOB_PDIR | |||
| #define CORE_PIN17_PINREG GPIOB_PDIR | |||
| #define CORE_PIN18_PINREG GPIOB_PDIR | |||
| #define CORE_PIN19_PINREG GPIOB_PDIR | |||
| #define CORE_PIN20_PINREG GPIOD_PDIR | |||
| #define CORE_PIN21_PINREG GPIOD_PDIR | |||
| #define CORE_PIN22_PINREG GPIOC_PDIR | |||
| #define CORE_PIN23_PINREG GPIOC_PDIR | |||
| #define CORE_PIN24_PINREG GPIOA_PDIR | |||
| #define CORE_PIN25_PINREG GPIOB_PDIR | |||
| #define CORE_PIN26_PINREG GPIOE_PDIR | |||
| #define CORE_PIN27_PINREG GPIOC_PDIR | |||
| #define CORE_PIN28_PINREG GPIOC_PDIR | |||
| #define CORE_PIN29_PINREG GPIOC_PDIR | |||
| #define CORE_PIN30_PINREG GPIOC_PDIR | |||
| #define CORE_PIN31_PINREG GPIOE_PDIR | |||
| #define CORE_PIN32_PINREG GPIOB_PDIR | |||
| #define CORE_PIN33_PINREG GPIOA_PDIR | |||
| #define CORE_PIN0_CONFIG PORTB_PCR16 | |||
| #define CORE_PIN1_CONFIG PORTB_PCR17 | |||
| #define CORE_PIN2_CONFIG PORTD_PCR0 | |||
| #define CORE_PIN3_CONFIG PORTA_PCR12 | |||
| #define CORE_PIN4_CONFIG PORTA_PCR13 | |||
| #define CORE_PIN5_CONFIG PORTD_PCR7 | |||
| #define CORE_PIN6_CONFIG PORTD_PCR4 | |||
| #define CORE_PIN7_CONFIG PORTD_PCR2 | |||
| #define CORE_PIN8_CONFIG PORTD_PCR3 | |||
| #define CORE_PIN9_CONFIG PORTC_PCR3 | |||
| #define CORE_PIN10_CONFIG PORTC_PCR4 | |||
| #define CORE_PIN11_CONFIG PORTC_PCR6 | |||
| #define CORE_PIN12_CONFIG PORTC_PCR7 | |||
| #define CORE_PIN13_CONFIG PORTC_PCR5 | |||
| #define CORE_PIN14_CONFIG PORTD_PCR1 | |||
| #define CORE_PIN15_CONFIG PORTC_PCR0 | |||
| #define CORE_PIN16_CONFIG PORTB_PCR0 | |||
| #define CORE_PIN17_CONFIG PORTB_PCR1 | |||
| #define CORE_PIN18_CONFIG PORTB_PCR3 | |||
| #define CORE_PIN19_CONFIG PORTB_PCR2 | |||
| #define CORE_PIN20_CONFIG PORTD_PCR5 | |||
| #define CORE_PIN21_CONFIG PORTD_PCR6 | |||
| #define CORE_PIN22_CONFIG PORTC_PCR1 | |||
| #define CORE_PIN23_CONFIG PORTC_PCR2 | |||
| #define CORE_PIN24_CONFIG PORTA_PCR5 | |||
| #define CORE_PIN25_CONFIG PORTB_PCR19 | |||
| #define CORE_PIN26_CONFIG PORTE_PCR1 | |||
| #define CORE_PIN27_CONFIG PORTC_PCR9 | |||
| #define CORE_PIN28_CONFIG PORTC_PCR8 | |||
| #define CORE_PIN29_CONFIG PORTC_PCR10 | |||
| #define CORE_PIN30_CONFIG PORTC_PCR11 | |||
| #define CORE_PIN31_CONFIG PORTE_PCR0 | |||
| #define CORE_PIN32_CONFIG PORTB_PCR18 | |||
| #define CORE_PIN33_CONFIG PORTA_PCR4 | |||
| #define CORE_ADC0_PIN 14 | |||
| #define CORE_ADC1_PIN 15 | |||
| #define CORE_ADC2_PIN 16 | |||
| #define CORE_ADC3_PIN 17 | |||
| #define CORE_ADC4_PIN 18 | |||
| #define CORE_ADC5_PIN 19 | |||
| #define CORE_ADC6_PIN 20 | |||
| #define CORE_ADC7_PIN 21 | |||
| #define CORE_ADC8_PIN 22 | |||
| #define CORE_ADC9_PIN 23 | |||
| #define CORE_ADC10_PIN 34 | |||
| #define CORE_ADC11_PIN 35 | |||
| #define CORE_ADC12_PIN 36 | |||
| #define CORE_ADC13_PIN 37 | |||
| #define CORE_RXD0_PIN 0 | |||
| #define CORE_TXD0_PIN 1 | |||
| #define CORE_RXD1_PIN 9 | |||
| #define CORE_TXD1_PIN 10 | |||
| #define CORE_RXD2_PIN 7 | |||
| #define CORE_TXD2_PIN 8 | |||
| #define CORE_INT0_PIN 0 | |||
| #define CORE_INT1_PIN 1 | |||
| #define CORE_INT2_PIN 2 | |||
| #define CORE_INT3_PIN 3 | |||
| #define CORE_INT4_PIN 4 | |||
| #define CORE_INT5_PIN 5 | |||
| #define CORE_INT6_PIN 6 | |||
| #define CORE_INT7_PIN 7 | |||
| #define CORE_INT8_PIN 8 | |||
| #define CORE_INT9_PIN 9 | |||
| #define CORE_INT10_PIN 10 | |||
| #define CORE_INT11_PIN 11 | |||
| #define CORE_INT12_PIN 12 | |||
| #define CORE_INT13_PIN 13 | |||
| #define CORE_INT14_PIN 14 | |||
| #define CORE_INT15_PIN 15 | |||
| #define CORE_INT16_PIN 16 | |||
| #define CORE_INT17_PIN 17 | |||
| #define CORE_INT18_PIN 18 | |||
| #define CORE_INT19_PIN 19 | |||
| #define CORE_INT20_PIN 20 | |||
| #define CORE_INT21_PIN 21 | |||
| #define CORE_INT22_PIN 22 | |||
| #define CORE_INT23_PIN 23 | |||
| #define CORE_INT24_PIN 24 | |||
| #define CORE_INT25_PIN 25 | |||
| #define CORE_INT26_PIN 26 | |||
| #define CORE_INT27_PIN 27 | |||
| #define CORE_INT28_PIN 28 | |||
| #define CORE_INT29_PIN 29 | |||
| #define CORE_INT30_PIN 30 | |||
| #define CORE_INT31_PIN 31 | |||
| #define CORE_INT32_PIN 32 | |||
| #define CORE_INT33_PIN 33 | |||
| #define CORE_INT_EVERY_PIN 1 | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void digitalWrite(uint8_t pin, uint8_t val); | |||
| static inline void digitalWriteFast(uint8_t pin, uint8_t val) __attribute__((always_inline, unused)); | |||
| static inline void digitalWriteFast(uint8_t pin, uint8_t val) | |||
| { | |||
| if (__builtin_constant_p(pin)) { | |||
| if (val) { | |||
| if (pin == 0) { | |||
| CORE_PIN0_PORTSET = CORE_PIN0_BITMASK; | |||
| } else if (pin == 1) { | |||
| CORE_PIN1_PORTSET = CORE_PIN1_BITMASK; | |||
| } else if (pin == 2) { | |||
| CORE_PIN2_PORTSET = CORE_PIN2_BITMASK; | |||
| } else if (pin == 3) { | |||
| CORE_PIN3_PORTSET = CORE_PIN3_BITMASK; | |||
| } else if (pin == 4) { | |||
| CORE_PIN4_PORTSET = CORE_PIN4_BITMASK; | |||
| } else if (pin == 5) { | |||
| CORE_PIN5_PORTSET = CORE_PIN5_BITMASK; | |||
| } else if (pin == 6) { | |||
| CORE_PIN6_PORTSET = CORE_PIN6_BITMASK; | |||
| } else if (pin == 7) { | |||
| CORE_PIN7_PORTSET = CORE_PIN7_BITMASK; | |||
| } else if (pin == 8) { | |||
| CORE_PIN8_PORTSET = CORE_PIN8_BITMASK; | |||
| } else if (pin == 9) { | |||
| CORE_PIN9_PORTSET = CORE_PIN9_BITMASK; | |||
| } else if (pin == 10) { | |||
| CORE_PIN10_PORTSET = CORE_PIN10_BITMASK; | |||
| } else if (pin == 11) { | |||
| CORE_PIN11_PORTSET = CORE_PIN11_BITMASK; | |||
| } else if (pin == 12) { | |||
| CORE_PIN12_PORTSET = CORE_PIN12_BITMASK; | |||
| } else if (pin == 13) { | |||
| CORE_PIN13_PORTSET = CORE_PIN13_BITMASK; | |||
| } else if (pin == 14) { | |||
| CORE_PIN14_PORTSET = CORE_PIN14_BITMASK; | |||
| } else if (pin == 15) { | |||
| CORE_PIN15_PORTSET = CORE_PIN15_BITMASK; | |||
| } else if (pin == 16) { | |||
| CORE_PIN16_PORTSET = CORE_PIN16_BITMASK; | |||
| } else if (pin == 17) { | |||
| CORE_PIN17_PORTSET = CORE_PIN17_BITMASK; | |||
| } else if (pin == 18) { | |||
| CORE_PIN18_PORTSET = CORE_PIN18_BITMASK; | |||
| } else if (pin == 19) { | |||
| CORE_PIN19_PORTSET = CORE_PIN19_BITMASK; | |||
| } else if (pin == 20) { | |||
| CORE_PIN20_PORTSET = CORE_PIN20_BITMASK; | |||
| } else if (pin == 21) { | |||
| CORE_PIN21_PORTSET = CORE_PIN21_BITMASK; | |||
| } else if (pin == 22) { | |||
| CORE_PIN22_PORTSET = CORE_PIN22_BITMASK; | |||
| } else if (pin == 23) { | |||
| CORE_PIN23_PORTSET = CORE_PIN23_BITMASK; | |||
| } else if (pin == 24) { | |||
| CORE_PIN24_PORTSET = CORE_PIN24_BITMASK; | |||
| } else if (pin == 25) { | |||
| CORE_PIN25_PORTSET = CORE_PIN25_BITMASK; | |||
| } else if (pin == 26) { | |||
| CORE_PIN26_PORTSET = CORE_PIN26_BITMASK; | |||
| } else if (pin == 27) { | |||
| CORE_PIN27_PORTSET = CORE_PIN27_BITMASK; | |||
| } else if (pin == 28) { | |||
| CORE_PIN28_PORTSET = CORE_PIN28_BITMASK; | |||
| } else if (pin == 29) { | |||
| CORE_PIN29_PORTSET = CORE_PIN29_BITMASK; | |||
| } else if (pin == 30) { | |||
| CORE_PIN30_PORTSET = CORE_PIN30_BITMASK; | |||
| } else if (pin == 31) { | |||
| CORE_PIN31_PORTSET = CORE_PIN31_BITMASK; | |||
| } else if (pin == 32) { | |||
| CORE_PIN32_PORTSET = CORE_PIN32_BITMASK; | |||
| } else if (pin == 33) { | |||
| CORE_PIN33_PORTSET = CORE_PIN33_BITMASK; | |||
| } | |||
| } else { | |||
| if (pin == 0) { | |||
| CORE_PIN0_PORTCLEAR = CORE_PIN0_BITMASK; | |||
| } else if (pin == 1) { | |||
| CORE_PIN1_PORTCLEAR = CORE_PIN1_BITMASK; | |||
| } else if (pin == 2) { | |||
| CORE_PIN2_PORTCLEAR = CORE_PIN2_BITMASK; | |||
| } else if (pin == 3) { | |||
| CORE_PIN3_PORTCLEAR = CORE_PIN3_BITMASK; | |||
| } else if (pin == 4) { | |||
| CORE_PIN4_PORTCLEAR = CORE_PIN4_BITMASK; | |||
| } else if (pin == 5) { | |||
| CORE_PIN5_PORTCLEAR = CORE_PIN5_BITMASK; | |||
| } else if (pin == 6) { | |||
| CORE_PIN6_PORTCLEAR = CORE_PIN6_BITMASK; | |||
| } else if (pin == 7) { | |||
| CORE_PIN7_PORTCLEAR = CORE_PIN7_BITMASK; | |||
| } else if (pin == 8) { | |||
| CORE_PIN8_PORTCLEAR = CORE_PIN8_BITMASK; | |||
| } else if (pin == 9) { | |||
| CORE_PIN9_PORTCLEAR = CORE_PIN9_BITMASK; | |||
| } else if (pin == 10) { | |||
| CORE_PIN10_PORTCLEAR = CORE_PIN10_BITMASK; | |||
| } else if (pin == 11) { | |||
| CORE_PIN11_PORTCLEAR = CORE_PIN11_BITMASK; | |||
| } else if (pin == 12) { | |||
| CORE_PIN12_PORTCLEAR = CORE_PIN12_BITMASK; | |||
| } else if (pin == 13) { | |||
| CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK; | |||
| } else if (pin == 14) { | |||
| CORE_PIN14_PORTCLEAR = CORE_PIN14_BITMASK; | |||
| } else if (pin == 15) { | |||
| CORE_PIN15_PORTCLEAR = CORE_PIN15_BITMASK; | |||
| } else if (pin == 16) { | |||
| CORE_PIN16_PORTCLEAR = CORE_PIN16_BITMASK; | |||
| } else if (pin == 17) { | |||
| CORE_PIN17_PORTCLEAR = CORE_PIN17_BITMASK; | |||
| } else if (pin == 18) { | |||
| CORE_PIN18_PORTCLEAR = CORE_PIN18_BITMASK; | |||
| } else if (pin == 19) { | |||
| CORE_PIN19_PORTCLEAR = CORE_PIN19_BITMASK; | |||
| } else if (pin == 20) { | |||
| CORE_PIN20_PORTCLEAR = CORE_PIN20_BITMASK; | |||
| } else if (pin == 21) { | |||
| CORE_PIN21_PORTCLEAR = CORE_PIN21_BITMASK; | |||
| } else if (pin == 22) { | |||
| CORE_PIN22_PORTCLEAR = CORE_PIN22_BITMASK; | |||
| } else if (pin == 23) { | |||
| CORE_PIN23_PORTCLEAR = CORE_PIN23_BITMASK; | |||
| } else if (pin == 24) { | |||
| CORE_PIN24_PORTCLEAR = CORE_PIN24_BITMASK; | |||
| } else if (pin == 25) { | |||
| CORE_PIN25_PORTCLEAR = CORE_PIN25_BITMASK; | |||
| } else if (pin == 26) { | |||
| CORE_PIN26_PORTCLEAR = CORE_PIN26_BITMASK; | |||
| } else if (pin == 27) { | |||
| CORE_PIN27_PORTCLEAR = CORE_PIN27_BITMASK; | |||
| } else if (pin == 28) { | |||
| CORE_PIN28_PORTCLEAR = CORE_PIN28_BITMASK; | |||
| } else if (pin == 29) { | |||
| CORE_PIN29_PORTCLEAR = CORE_PIN29_BITMASK; | |||
| } else if (pin == 30) { | |||
| CORE_PIN30_PORTCLEAR = CORE_PIN30_BITMASK; | |||
| } else if (pin == 31) { | |||
| CORE_PIN31_PORTCLEAR = CORE_PIN31_BITMASK; | |||
| } else if (pin == 32) { | |||
| CORE_PIN32_PORTCLEAR = CORE_PIN32_BITMASK; | |||
| } else if (pin == 33) { | |||
| CORE_PIN33_PORTCLEAR = CORE_PIN33_BITMASK; | |||
| } | |||
| } | |||
| } else { | |||
| if (val) { | |||
| *portSetRegister(pin) = 1; | |||
| } else { | |||
| *portClearRegister(pin) = 1; | |||
| } | |||
| } | |||
| } | |||
| uint8_t digitalRead(uint8_t pin); | |||
| static inline uint8_t digitalReadFast(uint8_t pin) __attribute__((always_inline, unused)); | |||
| static inline uint8_t digitalReadFast(uint8_t pin) | |||
| { | |||
| if (__builtin_constant_p(pin)) { | |||
| if (pin == 0) { | |||
| return (CORE_PIN0_PINREG & CORE_PIN0_BITMASK) ? 1 : 0; | |||
| } else if (pin == 1) { | |||
| return (CORE_PIN1_PINREG & CORE_PIN1_BITMASK) ? 1 : 0; | |||
| } else if (pin == 2) { | |||
| return (CORE_PIN2_PINREG & CORE_PIN2_BITMASK) ? 1 : 0; | |||
| } else if (pin == 3) { | |||
| return (CORE_PIN3_PINREG & CORE_PIN3_BITMASK) ? 1 : 0; | |||
| } else if (pin == 4) { | |||
| return (CORE_PIN4_PINREG & CORE_PIN4_BITMASK) ? 1 : 0; | |||
| } else if (pin == 5) { | |||
| return (CORE_PIN5_PINREG & CORE_PIN5_BITMASK) ? 1 : 0; | |||
| } else if (pin == 6) { | |||
| return (CORE_PIN6_PINREG & CORE_PIN6_BITMASK) ? 1 : 0; | |||
| } else if (pin == 7) { | |||
| return (CORE_PIN7_PINREG & CORE_PIN7_BITMASK) ? 1 : 0; | |||
| } else if (pin == 8) { | |||
| return (CORE_PIN8_PINREG & CORE_PIN8_BITMASK) ? 1 : 0; | |||
| } else if (pin == 9) { | |||
| return (CORE_PIN9_PINREG & CORE_PIN9_BITMASK) ? 1 : 0; | |||
| } else if (pin == 10) { | |||
| return (CORE_PIN10_PINREG & CORE_PIN10_BITMASK) ? 1 : 0; | |||
| } else if (pin == 11) { | |||
| return (CORE_PIN11_PINREG & CORE_PIN11_BITMASK) ? 1 : 0; | |||
| } else if (pin == 12) { | |||
| return (CORE_PIN12_PINREG & CORE_PIN12_BITMASK) ? 1 : 0; | |||
| } else if (pin == 13) { | |||
| return (CORE_PIN13_PINREG & CORE_PIN13_BITMASK) ? 1 : 0; | |||
| } else if (pin == 14) { | |||
| return (CORE_PIN14_PINREG & CORE_PIN14_BITMASK) ? 1 : 0; | |||
| } else if (pin == 15) { | |||
| return (CORE_PIN15_PINREG & CORE_PIN15_BITMASK) ? 1 : 0; | |||
| } else if (pin == 16) { | |||
| return (CORE_PIN16_PINREG & CORE_PIN16_BITMASK) ? 1 : 0; | |||
| } else if (pin == 17) { | |||
| return (CORE_PIN17_PINREG & CORE_PIN17_BITMASK) ? 1 : 0; | |||
| } else if (pin == 18) { | |||
| return (CORE_PIN18_PINREG & CORE_PIN18_BITMASK) ? 1 : 0; | |||
| } else if (pin == 19) { | |||
| return (CORE_PIN19_PINREG & CORE_PIN19_BITMASK) ? 1 : 0; | |||
| } else if (pin == 20) { | |||
| return (CORE_PIN20_PINREG & CORE_PIN20_BITMASK) ? 1 : 0; | |||
| } else if (pin == 21) { | |||
| return (CORE_PIN21_PINREG & CORE_PIN21_BITMASK) ? 1 : 0; | |||
| } else if (pin == 22) { | |||
| return (CORE_PIN22_PINREG & CORE_PIN22_BITMASK) ? 1 : 0; | |||
| } else if (pin == 23) { | |||
| return (CORE_PIN23_PINREG & CORE_PIN23_BITMASK) ? 1 : 0; | |||
| } else if (pin == 24) { | |||
| return (CORE_PIN24_PINREG & CORE_PIN24_BITMASK) ? 1 : 0; | |||
| } else if (pin == 25) { | |||
| return (CORE_PIN25_PINREG & CORE_PIN25_BITMASK) ? 1 : 0; | |||
| } else if (pin == 26) { | |||
| return (CORE_PIN26_PINREG & CORE_PIN26_BITMASK) ? 1 : 0; | |||
| } else if (pin == 27) { | |||
| return (CORE_PIN27_PINREG & CORE_PIN27_BITMASK) ? 1 : 0; | |||
| } else if (pin == 28) { | |||
| return (CORE_PIN28_PINREG & CORE_PIN28_BITMASK) ? 1 : 0; | |||
| } else if (pin == 29) { | |||
| return (CORE_PIN29_PINREG & CORE_PIN29_BITMASK) ? 1 : 0; | |||
| } else if (pin == 30) { | |||
| return (CORE_PIN30_PINREG & CORE_PIN30_BITMASK) ? 1 : 0; | |||
| } else if (pin == 31) { | |||
| return (CORE_PIN31_PINREG & CORE_PIN31_BITMASK) ? 1 : 0; | |||
| } else if (pin == 32) { | |||
| return (CORE_PIN32_PINREG & CORE_PIN32_BITMASK) ? 1 : 0; | |||
| } else if (pin == 33) { | |||
| return (CORE_PIN33_PINREG & CORE_PIN33_BITMASK) ? 1 : 0; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } else { | |||
| return *portInputRegister(pin); | |||
| } | |||
| } | |||
| void pinMode(uint8_t pin, uint8_t mode); | |||
| void init_pins(void); | |||
| void analogWrite(uint8_t pin, int val); | |||
| void analogWriteRes(uint32_t bits); | |||
| static inline void analogWriteResolution(uint32_t bits) { analogWriteRes(bits); } | |||
| void analogWriteFrequency(uint8_t pin, uint32_t frequency); | |||
| void attachInterrupt(uint8_t pin, void (*function)(void), int mode); | |||
| void detachInterrupt(uint8_t pin); | |||
| void _init_Teensyduino_internal_(void); | |||
| int analogRead(uint8_t pin); | |||
| void analogReference(uint8_t type); | |||
| void analogReadRes(unsigned int bits); | |||
| static inline void analogReadResolution(unsigned int bits) { analogReadRes(bits); } | |||
| void analogReadAveraging(unsigned int num); | |||
| void analog_init(void); | |||
| #define DEFAULT 0 | |||
| #define INTERNAL 2 | |||
| #define INTERNAL1V2 2 | |||
| #define INTERNAL1V1 2 | |||
| #define EXTERNAL 0 | |||
| int touchRead(uint8_t pin); | |||
| static inline void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t) __attribute__((always_inline, unused)); | |||
| extern void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) __attribute__((noinline)); | |||
| extern void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) __attribute__((noinline)); | |||
| extern void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) __attribute__((noinline)); | |||
| static inline void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) | |||
| { | |||
| if (__builtin_constant_p(bitOrder)) { | |||
| if (bitOrder == LSBFIRST) { | |||
| shiftOut_lsbFirst(dataPin, clockPin, value); | |||
| } else { | |||
| shiftOut_msbFirst(dataPin, clockPin, value); | |||
| } | |||
| } else { | |||
| _shiftOut(dataPin, clockPin, bitOrder, value); | |||
| } | |||
| } | |||
| static inline uint8_t shiftIn(uint8_t, uint8_t, uint8_t) __attribute__((always_inline, unused)); | |||
| extern uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) __attribute__((noinline)); | |||
| extern uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin) __attribute__((noinline)); | |||
| extern uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin) __attribute__((noinline)); | |||
| static inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) | |||
| { | |||
| if (__builtin_constant_p(bitOrder)) { | |||
| if (bitOrder == LSBFIRST) { | |||
| return shiftIn_lsbFirst(dataPin, clockPin); | |||
| } else { | |||
| return shiftIn_msbFirst(dataPin, clockPin); | |||
| } | |||
| } else { | |||
| return _shiftIn(dataPin, clockPin, bitOrder); | |||
| } | |||
| } | |||
| void _reboot_Teensyduino_(void) __attribute__((noreturn)); | |||
| void _restart_Teensyduino_(void) __attribute__((noreturn)); | |||
| void yield(void); | |||
| void delay(uint32_t msec); | |||
| extern volatile uint32_t systick_millis_count; | |||
| static inline uint32_t millis(void) __attribute__((always_inline, unused)); | |||
| static inline uint32_t millis(void) | |||
| { | |||
| volatile uint32_t ret = systick_millis_count; // single aligned 32 bit is atomic; | |||
| return ret; | |||
| } | |||
| uint32_t micros(void); | |||
| static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); | |||
| static inline void delayMicroseconds(uint32_t usec) | |||
| { | |||
| #if F_CPU == 96000000 | |||
| uint32_t n = usec << 5; | |||
| #elif F_CPU == 48000000 | |||
| uint32_t n = usec << 4; | |||
| #elif F_CPU == 24000000 | |||
| uint32_t n = usec << 3; | |||
| #endif | |||
| if (usec == 0) return; | |||
| asm volatile( | |||
| "L_%=_delayMicroseconds:" "\n\t" | |||
| "subs %0, #1" "\n\t" | |||
| "bne L_%=_delayMicroseconds" "\n" | |||
| : "+r" (n) : | |||
| ); | |||
| } | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| unsigned long rtc_get(void); | |||
| void rtc_set(unsigned long t); | |||
| void rtc_compensate(int adjust); | |||
| #ifdef __cplusplus | |||
| } | |||
| class teensy3_clock_class | |||
| { | |||
| public: | |||
| static unsigned long get(void) __attribute__((always_inline)) { return rtc_get(); } | |||
| static void set(unsigned long t) __attribute__((always_inline)) { rtc_set(t); } | |||
| static void compensate(int adj) __attribute__((always_inline)) { rtc_compensate(adj); } | |||
| }; | |||
| extern teensy3_clock_class Teensy3Clock; | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,294 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "mk20dx128.h" | |||
| #include <stdint.h> | |||
| //#include "HardwareSerial.h" | |||
| // The EEPROM is really RAM with a hardware-based backup system to | |||
| // flash memory. Selecting a smaller size EEPROM allows more wear | |||
| // leveling, for higher write endurance. If you edit this file, | |||
| // set this to the smallest size your application can use. Also, | |||
| // due to Freescale's implementation, writing 16 or 32 bit words | |||
| // (aligned to 2 or 4 byte boundaries) has twice the endurance | |||
| // compared to writing 8 bit bytes. | |||
| // | |||
| #define EEPROM_SIZE 2048 | |||
| // Writing unaligned 16 or 32 bit data is handled automatically when | |||
| // this is defined, but at a cost of extra code size. Without this, | |||
| // any unaligned write will cause a hard fault exception! If you're | |||
| // absolutely sure all 16 and 32 bit writes will be aligned, you can | |||
| // remove the extra unnecessary code. | |||
| // | |||
| #define HANDLE_UNALIGNED_WRITES | |||
| // Minimum EEPROM Endurance | |||
| // ------------------------ | |||
| #if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word | |||
| #define EEESIZE 0x33 | |||
| #elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word | |||
| #define EEESIZE 0x34 | |||
| #elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word | |||
| #define EEESIZE 0x35 | |||
| #elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word | |||
| #define EEESIZE 0x36 | |||
| #elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word | |||
| #define EEESIZE 0x37 | |||
| #elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word | |||
| #define EEESIZE 0x38 | |||
| #elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word | |||
| #define EEESIZE 0x39 | |||
| #endif | |||
| void eeprom_initialize(void) | |||
| { | |||
| uint32_t count=0; | |||
| uint16_t do_flash_cmd[] = { | |||
| 0xf06f, 0x037f, 0x7003, 0x7803, | |||
| 0xf013, 0x0f80, 0xd0fb, 0x4770}; | |||
| uint8_t status; | |||
| if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) { | |||
| // FlexRAM is configured as traditional RAM | |||
| // We need to reconfigure for EEPROM usage | |||
| FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command | |||
| FTFL_FCCOB4 = EEESIZE; // EEPROM Size | |||
| FTFL_FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup | |||
| __disable_irq(); | |||
| // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... | |||
| (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT); | |||
| __enable_irq(); | |||
| status = FTFL_FSTAT; | |||
| if (status & 0x70) { | |||
| FTFL_FSTAT = (status & 0x70); | |||
| return; // error | |||
| } | |||
| } | |||
| // wait for eeprom to become ready (is this really necessary?) | |||
| while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) { | |||
| if (++count > 20000) break; | |||
| } | |||
| } | |||
| #define FlexRAM ((uint8_t *)0x14000000) | |||
| uint8_t eeprom_read_byte(const uint8_t *addr) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE) return 0; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| return FlexRAM[offset]; | |||
| } | |||
| uint16_t eeprom_read_word(const uint16_t *addr) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE-1) return 0; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| return *(uint16_t *)(&FlexRAM[offset]); | |||
| } | |||
| uint32_t eeprom_read_dword(const uint32_t *addr) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE-3) return 0; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| return *(uint32_t *)(&FlexRAM[offset]); | |||
| } | |||
| void eeprom_read_block(void *buf, const void *addr, uint32_t len) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| uint8_t *dest = (uint8_t *)buf; | |||
| uint32_t end = offset + len; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| if (end > EEPROM_SIZE) end = EEPROM_SIZE; | |||
| while (offset < end) { | |||
| *dest++ = FlexRAM[offset++]; | |||
| } | |||
| } | |||
| static void flexram_wait(void) | |||
| { | |||
| while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) { | |||
| // TODO: timeout | |||
| } | |||
| } | |||
| void eeprom_write_byte(uint8_t *addr, uint8_t value) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE) return; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| if (FlexRAM[offset] != value) { | |||
| FlexRAM[offset] = value; | |||
| flexram_wait(); | |||
| } | |||
| } | |||
| void eeprom_write_word(uint16_t *addr, uint16_t value) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE-1) return; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| #ifdef HANDLE_UNALIGNED_WRITES | |||
| if ((offset & 1) == 0) { | |||
| #endif | |||
| if (*(uint16_t *)(&FlexRAM[offset]) != value) { | |||
| *(uint16_t *)(&FlexRAM[offset]) = value; | |||
| flexram_wait(); | |||
| } | |||
| #ifdef HANDLE_UNALIGNED_WRITES | |||
| } else { | |||
| if (FlexRAM[offset] != value) { | |||
| FlexRAM[offset] = value; | |||
| flexram_wait(); | |||
| } | |||
| if (FlexRAM[offset + 1] != (value >> 8)) { | |||
| FlexRAM[offset + 1] = value >> 8; | |||
| flexram_wait(); | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| void eeprom_write_dword(uint32_t *addr, uint32_t value) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| if (offset >= EEPROM_SIZE-3) return; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| #ifdef HANDLE_UNALIGNED_WRITES | |||
| switch (offset & 3) { | |||
| case 0: | |||
| #endif | |||
| if (*(uint32_t *)(&FlexRAM[offset]) != value) { | |||
| *(uint32_t *)(&FlexRAM[offset]) = value; | |||
| flexram_wait(); | |||
| } | |||
| return; | |||
| #ifdef HANDLE_UNALIGNED_WRITES | |||
| case 2: | |||
| if (*(uint16_t *)(&FlexRAM[offset]) != value) { | |||
| *(uint16_t *)(&FlexRAM[offset]) = value; | |||
| flexram_wait(); | |||
| } | |||
| if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { | |||
| *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; | |||
| flexram_wait(); | |||
| } | |||
| return; | |||
| default: | |||
| if (FlexRAM[offset] != value) { | |||
| FlexRAM[offset] = value; | |||
| flexram_wait(); | |||
| } | |||
| if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { | |||
| *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; | |||
| flexram_wait(); | |||
| } | |||
| if (FlexRAM[offset + 3] != (value >> 24)) { | |||
| FlexRAM[offset + 3] = value >> 24; | |||
| flexram_wait(); | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| void eeprom_write_block(const void *buf, void *addr, uint32_t len) | |||
| { | |||
| uint32_t offset = (uint32_t)addr; | |||
| const uint8_t *src = (const uint8_t *)buf; | |||
| if (offset >= EEPROM_SIZE) return; | |||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | |||
| if (len >= EEPROM_SIZE) len = EEPROM_SIZE; | |||
| if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; | |||
| while (len > 0) { | |||
| uint32_t lsb = offset & 3; | |||
| if (lsb == 0 && len >= 4) { | |||
| // write aligned 32 bits | |||
| uint32_t val32; | |||
| val32 = *src++; | |||
| val32 |= (*src++ << 8); | |||
| val32 |= (*src++ << 16); | |||
| val32 |= (*src++ << 24); | |||
| if (*(uint32_t *)(&FlexRAM[offset]) != val32) { | |||
| *(uint32_t *)(&FlexRAM[offset]) = val32; | |||
| flexram_wait(); | |||
| } | |||
| offset += 4; | |||
| len -= 4; | |||
| } else if ((lsb == 0 || lsb == 2) && len >= 2) { | |||
| // write aligned 16 bits | |||
| uint16_t val16; | |||
| val16 = *src++; | |||
| val16 |= (*src++ << 8); | |||
| if (*(uint16_t *)(&FlexRAM[offset]) != val16) { | |||
| *(uint16_t *)(&FlexRAM[offset]) = val16; | |||
| flexram_wait(); | |||
| } | |||
| offset += 2; | |||
| len -= 2; | |||
| } else { | |||
| // write 8 bits | |||
| uint8_t val8 = *src++; | |||
| if (FlexRAM[offset] != val8) { | |||
| FlexRAM[offset] = val8; | |||
| flexram_wait(); | |||
| } | |||
| offset++; | |||
| len--; | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| void do_flash_cmd(volatile uint8_t *fstat) | |||
| { | |||
| *fstat = 0x80; | |||
| while ((*fstat & 0x80) == 0) ; // wait | |||
| } | |||
| 00000000 <do_flash_cmd>: | |||
| 0: f06f 037f mvn.w r3, #127 ; 0x7f | |||
| 4: 7003 strb r3, [r0, #0] | |||
| 6: 7803 ldrb r3, [r0, #0] | |||
| 8: f013 0f80 tst.w r3, #128 ; 0x80 | |||
| c: d0fb beq.n 6 <do_flash_cmd+0x6> | |||
| e: 4770 bx lr | |||
| */ | |||
| @@ -0,0 +1,81 @@ | |||
| /* Elapsed time types - for easy-to-use measurements of elapsed time | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2011 PJRC.COM, LLC | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| #ifndef elapsedMillis_h | |||
| #define elapsedMillis_h | |||
| #ifdef __cplusplus | |||
| #if ARDUINO >= 100 | |||
| #include "Arduino.h" | |||
| #else | |||
| #include "WProgram.h" | |||
| #endif | |||
| class elapsedMillis | |||
| { | |||
| private: | |||
| unsigned long ms; | |||
| public: | |||
| elapsedMillis(void) { ms = millis(); } | |||
| elapsedMillis(unsigned long val) { ms = millis() - val; } | |||
| elapsedMillis(const elapsedMillis &orig) { ms = orig.ms; } | |||
| operator unsigned long () const { return millis() - ms; } | |||
| elapsedMillis & operator = (const elapsedMillis &rhs) { ms = rhs.ms; return *this; } | |||
| elapsedMillis & operator = (unsigned long val) { ms = millis() - val; return *this; } | |||
| elapsedMillis & operator -= (unsigned long val) { ms += val ; return *this; } | |||
| elapsedMillis & operator += (unsigned long val) { ms -= val ; return *this; } | |||
| elapsedMillis operator - (int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (unsigned int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator - (unsigned long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||
| elapsedMillis operator + (int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (unsigned int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||
| }; | |||
| class elapsedMicros | |||
| { | |||
| private: | |||
| unsigned long us; | |||
| public: | |||
| elapsedMicros(void) { us = micros(); } | |||
| elapsedMicros(unsigned long val) { us = micros() - val; } | |||
| elapsedMicros(const elapsedMicros &orig) { us = orig.us; } | |||
| operator unsigned long () const { return micros() - us; } | |||
| elapsedMicros & operator = (const elapsedMicros &rhs) { us = rhs.us; return *this; } | |||
| elapsedMicros & operator = (unsigned long val) { us = micros() - val; return *this; } | |||
| elapsedMicros & operator -= (unsigned long val) { us += val ; return *this; } | |||
| elapsedMicros & operator += (unsigned long val) { us -= val ; return *this; } | |||
| elapsedMicros operator - (int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (unsigned int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator - (unsigned long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||
| elapsedMicros operator + (int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (unsigned int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| elapsedMicros operator + (unsigned long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||
| }; | |||
| #endif // __cplusplus | |||
| #endif // elapsedMillis_h | |||
| @@ -0,0 +1,96 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include <avr/pgmspace.h> | |||
| #include <stdint.h> | |||
| #include "keylayouts.h" | |||
| #ifdef M | |||
| #undef M | |||
| #endif | |||
| #define M(n) ((n) & 0x3FFF) | |||
| const KEYCODE_TYPE keycodes_ascii[] = { | |||
| M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), | |||
| M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), | |||
| M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), | |||
| M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), | |||
| M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), | |||
| M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), | |||
| M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), | |||
| M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), | |||
| M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), | |||
| M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), | |||
| M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), | |||
| M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), | |||
| M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), | |||
| M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), | |||
| M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), | |||
| M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), | |||
| M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), | |||
| M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), | |||
| M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), | |||
| M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), | |||
| M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), | |||
| M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), | |||
| M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), | |||
| M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) | |||
| }; | |||
| #ifdef ISO_8859_1_A0 | |||
| const KEYCODE_TYPE keycodes_iso_8859_1[] = { | |||
| M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), | |||
| M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), | |||
| M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), | |||
| M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), | |||
| M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), | |||
| M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), | |||
| M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), | |||
| M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), | |||
| M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), | |||
| M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), | |||
| M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), | |||
| M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), | |||
| M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), | |||
| M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), | |||
| M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), | |||
| M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), | |||
| M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), | |||
| M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), | |||
| M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), | |||
| M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), | |||
| M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), | |||
| M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), | |||
| M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), | |||
| M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) | |||
| }; | |||
| #endif // ISO_8859_1_A0 | |||
| @@ -0,0 +1,28 @@ | |||
| #include "WProgram.h" | |||
| extern "C" int main(void) | |||
| { | |||
| #if !defined(ARDUINO) | |||
| // To use Teensy 3.0 without Arduino, simply put your code here. | |||
| // For example: | |||
| pinMode(13, OUTPUT); | |||
| while (1) { | |||
| digitalWriteFast(13, HIGH); | |||
| delay(500); | |||
| digitalWriteFast(13, LOW); | |||
| delay(500); | |||
| } | |||
| #else | |||
| // Arduino's main() function just calls setup() and loop().... | |||
| setup(); | |||
| while (1) { | |||
| loop(); | |||
| yield(); | |||
| } | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,447 @@ | |||
| /* ---------------------------------------------------------------------- | |||
| * Copyright (C) 2010 ARM Limited. All rights reserved. | |||
| * | |||
| * $Date: 29. November 2010 | |||
| * $Revision: V1.0.3 | |||
| * | |||
| * Project: CMSIS DSP Library | |||
| * | |||
| * Title: math_helper.c | |||
| * | |||
| * Description: Definition of all helper functions required. | |||
| * | |||
| * Target Processor: Cortex-M4/Cortex-M3 | |||
| * | |||
| * Version 1.0.3 2010/11/29 | |||
| * Re-organized the CMSIS folders and updated documentation. | |||
| * | |||
| * Version 1.0.2 2010/11/11 | |||
| * Documentation updated. | |||
| * | |||
| * Version 1.0.1 2010/10/05 | |||
| * Production release and review comments incorporated. | |||
| * | |||
| * Version 1.0.0 2010/09/20 | |||
| * Production release and review comments incorporated. | |||
| * | |||
| * Version 0.0.7 2010/06/10 | |||
| * Misra-C changes done | |||
| * -------------------------------------------------------------------- */ | |||
| /* ---------------------------------------------------------------------- | |||
| * Include standard header files | |||
| * -------------------------------------------------------------------- */ | |||
| #include<math.h> | |||
| /* ---------------------------------------------------------------------- | |||
| * Include project header files | |||
| * -------------------------------------------------------------------- */ | |||
| #include "math_helper.h" | |||
| /** | |||
| * @brief Caluclation of SNR | |||
| * @param float* Pointer to the reference buffer | |||
| * @param float* Pointer to the test buffer | |||
| * @param uint32_t total number of samples | |||
| * @return float SNR | |||
| * The function Caluclates signal to noise ratio for the reference output | |||
| * and test output | |||
| */ | |||
| float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize) | |||
| { | |||
| float EnergySignal = 0.0, EnergyError = 0.0; | |||
| uint32_t i; | |||
| float SNR; | |||
| int temp; | |||
| int *test; | |||
| for (i = 0; i < buffSize; i++) | |||
| { | |||
| /* Checking for a NAN value in pRef array */ | |||
| test = (int *)(&pRef[i]); | |||
| temp = *test; | |||
| if(temp == 0x7FC00000) | |||
| { | |||
| return(0); | |||
| } | |||
| /* Checking for a NAN value in pTest array */ | |||
| test = (int *)(&pTest[i]); | |||
| temp = *test; | |||
| if(temp == 0x7FC00000) | |||
| { | |||
| return(0); | |||
| } | |||
| EnergySignal += pRef[i] * pRef[i]; | |||
| EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]); | |||
| } | |||
| /* Checking for a NAN value in EnergyError */ | |||
| test = (int *)(&EnergyError); | |||
| temp = *test; | |||
| if(temp == 0x7FC00000) | |||
| { | |||
| return(0); | |||
| } | |||
| SNR = 10 * log10 (EnergySignal / EnergyError); | |||
| return (SNR); | |||
| } | |||
| /** | |||
| * @brief Provide guard bits for Input buffer | |||
| * @param q15_t* Pointer to input buffer | |||
| * @param uint32_t blockSize | |||
| * @param uint32_t guard_bits | |||
| * @return none | |||
| * The function Provides the guard bits for the buffer | |||
| * to avoid overflow | |||
| */ | |||
| void arm_provide_guard_bits_q15 (q15_t * input_buf, uint32_t blockSize, | |||
| uint32_t guard_bits) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < blockSize; i++) | |||
| { | |||
| input_buf[i] = input_buf[i] >> guard_bits; | |||
| } | |||
| } | |||
| /** | |||
| * @brief Converts float to fixed in q12.20 format | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point(q12.20) values | |||
| */ | |||
| void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| /* 1048576.0f corresponds to pow(2, 20) */ | |||
| pOut[i] = (q31_t) (pIn[i] * 1048576.0f); | |||
| pOut[i] += pIn[i] > 0 ? 0.5 : -0.5; | |||
| if (pIn[i] == (float) 1.0) | |||
| { | |||
| pOut[i] = 0x000FFFFF; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @brief Compare MATLAB Reference Output and ARM Test output | |||
| * @param q15_t* Pointer to Ref buffer | |||
| * @param q15_t* Pointer to Test buffer | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| */ | |||
| uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| int32_t diff, diffCrnt = 0; | |||
| uint32_t maxDiff = 0; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| diff = pIn[i] - pOut[i]; | |||
| diffCrnt = (diff > 0) ? diff : -diff; | |||
| if(diffCrnt > maxDiff) | |||
| { | |||
| maxDiff = diffCrnt; | |||
| } | |||
| } | |||
| return(maxDiff); | |||
| } | |||
| /** | |||
| * @brief Compare MATLAB Reference Output and ARM Test output | |||
| * @param q31_t* Pointer to Ref buffer | |||
| * @param q31_t* Pointer to Test buffer | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| */ | |||
| uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t * pOut, uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| int32_t diff, diffCrnt = 0; | |||
| uint32_t maxDiff = 0; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| diff = pIn[i] - pOut[i]; | |||
| diffCrnt = (diff > 0) ? diff : -diff; | |||
| if(diffCrnt > maxDiff) | |||
| { | |||
| maxDiff = diffCrnt; | |||
| } | |||
| } | |||
| return(maxDiff); | |||
| } | |||
| /** | |||
| * @brief Provide guard bits for Input buffer | |||
| * @param q31_t* Pointer to input buffer | |||
| * @param uint32_t blockSize | |||
| * @param uint32_t guard_bits | |||
| * @return none | |||
| * The function Provides the guard bits for the buffer | |||
| * to avoid overflow | |||
| */ | |||
| void arm_provide_guard_bits_q31 (q31_t * input_buf, | |||
| uint32_t blockSize, | |||
| uint32_t guard_bits) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < blockSize; i++) | |||
| { | |||
| input_buf[i] = input_buf[i] >> guard_bits; | |||
| } | |||
| } | |||
| /** | |||
| * @brief Provide guard bits for Input buffer | |||
| * @param q31_t* Pointer to input buffer | |||
| * @param uint32_t blockSize | |||
| * @param uint32_t guard_bits | |||
| * @return none | |||
| * The function Provides the guard bits for the buffer | |||
| * to avoid overflow | |||
| */ | |||
| void arm_provide_guard_bits_q7 (q7_t * input_buf, | |||
| uint32_t blockSize, | |||
| uint32_t guard_bits) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < blockSize; i++) | |||
| { | |||
| input_buf[i] = input_buf[i] >> guard_bits; | |||
| } | |||
| } | |||
| /** | |||
| * @brief Caluclates number of guard bits | |||
| * @param uint32_t number of additions | |||
| * @return none | |||
| * The function Caluclates the number of guard bits | |||
| * depending on the numtaps | |||
| */ | |||
| uint32_t arm_calc_guard_bits (uint32_t num_adds) | |||
| { | |||
| uint32_t i = 1, j = 0; | |||
| if (num_adds == 1) | |||
| { | |||
| return (0); | |||
| } | |||
| while (i < num_adds) | |||
| { | |||
| i = i * 2; | |||
| j++; | |||
| } | |||
| return (j); | |||
| } | |||
| /** | |||
| * @brief Converts Q15 to floating-point | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| */ | |||
| void arm_apply_guard_bits (float32_t * pIn, | |||
| uint32_t numSamples, | |||
| uint32_t guard_bits) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| pIn[i] = pIn[i] * arm_calc_2pow(guard_bits); | |||
| } | |||
| } | |||
| /** | |||
| * @brief Calculates pow(2, numShifts) | |||
| * @param uint32_t number of shifts | |||
| * @return pow(2, numShifts) | |||
| */ | |||
| uint32_t arm_calc_2pow(uint32_t numShifts) | |||
| { | |||
| uint32_t i, val = 1; | |||
| for (i = 0; i < numShifts; i++) | |||
| { | |||
| val = val * 2; | |||
| } | |||
| return(val); | |||
| } | |||
| /** | |||
| * @brief Converts float to fixed q14 | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point values | |||
| */ | |||
| void arm_float_to_q14 (float *pIn, q15_t * pOut, | |||
| uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| /* 16384.0f corresponds to pow(2, 14) */ | |||
| pOut[i] = (q15_t) (pIn[i] * 16384.0f); | |||
| pOut[i] += pIn[i] > 0 ? 0.5 : -0.5; | |||
| if (pIn[i] == (float) 2.0) | |||
| { | |||
| pOut[i] = 0x7FFF; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @brief Converts float to fixed q30 format | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point values | |||
| */ | |||
| void arm_float_to_q30 (float *pIn, q31_t * pOut, | |||
| uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| /* 1073741824.0f corresponds to pow(2, 30) */ | |||
| pOut[i] = (q31_t) (pIn[i] * 1073741824.0f); | |||
| pOut[i] += pIn[i] > 0 ? 0.5 : -0.5; | |||
| if (pIn[i] == (float) 2.0) | |||
| { | |||
| pOut[i] = 0x7FFFFFFF; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @brief Converts float to fixed q30 format | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point values | |||
| */ | |||
| void arm_float_to_q29 (float *pIn, q31_t * pOut, | |||
| uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| /* 1073741824.0f corresponds to pow(2, 30) */ | |||
| pOut[i] = (q31_t) (pIn[i] * 536870912.0f); | |||
| pOut[i] += pIn[i] > 0 ? 0.5 : -0.5; | |||
| if (pIn[i] == (float) 4.0) | |||
| { | |||
| pOut[i] = 0x7FFFFFFF; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @brief Converts float to fixed q28 format | |||
| * @param uint32_t number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point values | |||
| */ | |||
| void arm_float_to_q28 (float *pIn, q31_t * pOut, | |||
| uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| /* 268435456.0f corresponds to pow(2, 28) */ | |||
| pOut[i] = (q31_t) (pIn[i] * 268435456.0f); | |||
| pOut[i] += pIn[i] > 0 ? 0.5 : -0.5; | |||
| if (pIn[i] == (float) 8.0) | |||
| { | |||
| pOut[i] = 0x7FFFFFFF; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @brief Clip the float values to +/- 1 | |||
| * @param pIn input buffer | |||
| * @param numSamples number of samples in the buffer | |||
| * @return none | |||
| * The function converts floating point values to fixed point values | |||
| */ | |||
| void arm_clip_f32 (float *pIn, uint32_t numSamples) | |||
| { | |||
| uint32_t i; | |||
| for (i = 0; i < numSamples; i++) | |||
| { | |||
| if(pIn[i] > 1.0f) | |||
| { | |||
| pIn[i] = 1.0; | |||
| } | |||
| else if( pIn[i] < -1.0f) | |||
| { | |||
| pIn[i] = -1.0; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,63 @@ | |||
| /* ---------------------------------------------------------------------- | |||
| * Copyright (C) 2010 ARM Limited. All rights reserved. | |||
| * | |||
| * $Date: 29. November 2010 | |||
| * $Revision: V1.0.3 | |||
| * | |||
| * Project: CMSIS DSP Library | |||
| * | |||
| * Title: math_helper.h | |||
| * | |||
| * | |||
| * Description: Prototypes of all helper functions required. | |||
| * | |||
| * Target Processor: Cortex-M4/Cortex-M3 | |||
| * | |||
| * Version 1.0.3 2010/11/29 | |||
| * Re-organized the CMSIS folders and updated documentation. | |||
| * | |||
| * Version 1.0.2 2010/11/11 | |||
| * Documentation updated. | |||
| * | |||
| * Version 1.0.1 2010/10/05 | |||
| * Production release and review comments incorporated. | |||
| * | |||
| * Version 1.0.0 2010/09/20 | |||
| * Production release and review comments incorporated. | |||
| * | |||
| * Version 0.0.7 2010/06/10 | |||
| * Misra-C changes done | |||
| * -------------------------------------------------------------------- */ | |||
| #include "arm_math.h" | |||
| #ifndef MATH_HELPER_H | |||
| #define MATH_HELPER_H | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize); | |||
| void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples); | |||
| void arm_provide_guard_bits_q15(q15_t *input_buf, uint32_t blockSize, uint32_t guard_bits); | |||
| void arm_provide_guard_bits_q31(q31_t *input_buf, uint32_t blockSize, uint32_t guard_bits); | |||
| void arm_float_to_q14(float *pIn, q15_t *pOut, uint32_t numSamples); | |||
| void arm_float_to_q29(float *pIn, q31_t *pOut, uint32_t numSamples); | |||
| void arm_float_to_q28(float *pIn, q31_t *pOut, uint32_t numSamples); | |||
| void arm_float_to_q30(float *pIn, q31_t *pOut, uint32_t numSamples); | |||
| void arm_clip_f32(float *pIn, uint32_t numSamples); | |||
| uint32_t arm_calc_guard_bits(uint32_t num_adds); | |||
| void arm_apply_guard_bits (float32_t * pIn, uint32_t numSamples, uint32_t guard_bits); | |||
| uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples); | |||
| uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t *pOut, uint32_t numSamples); | |||
| uint32_t arm_calc_2pow(uint32_t guard_bits); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,382 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "mk20dx128.h" | |||
| extern unsigned long _stext; | |||
| extern unsigned long _etext; | |||
| extern unsigned long _sdata; | |||
| extern unsigned long _edata; | |||
| extern unsigned long _sbss; | |||
| extern unsigned long _ebss; | |||
| extern unsigned long _estack; | |||
| //extern void __init_array_start(void); | |||
| //extern void __init_array_end(void); | |||
| extern int main (void); | |||
| void ResetHandler(void); | |||
| void _init_Teensyduino_internal_(void); | |||
| void __libc_init_array(void); | |||
| void fault_isr(void) | |||
| { | |||
| while (1) { | |||
| // keep polling some communication while in fault | |||
| // mode, so we don't completely die. | |||
| if (SIM_SCGC4 & SIM_SCGC4_USBOTG) usb_isr(); | |||
| if (SIM_SCGC4 & SIM_SCGC4_UART0) uart0_status_isr(); | |||
| if (SIM_SCGC4 & SIM_SCGC4_UART1) uart1_status_isr(); | |||
| if (SIM_SCGC4 & SIM_SCGC4_UART2) uart2_status_isr(); | |||
| } | |||
| } | |||
| void unused_isr(void) | |||
| { | |||
| fault_isr(); | |||
| } | |||
| extern volatile uint32_t systick_millis_count; | |||
| void systick_default_isr(void) | |||
| { | |||
| systick_millis_count++; | |||
| } | |||
| void nmi_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void hard_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void memmanage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void bus_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void usage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void svcall_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void systick_isr(void) __attribute__ ((weak, alias("systick_default_isr"))); | |||
| void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void dma_ch2_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void dma_ch3_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void dma_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void flash_cmd_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void flash_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void low_voltage_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void wakeup_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void watchdog_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void i2c0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void spi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void i2s0_tx_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void i2s0_rx_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart0_lon_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart0_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart0_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart1_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart1_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart2_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void uart2_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void adc0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void cmp0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void cmp1_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void ftm0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void ftm1_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void cmt_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void rtc_alarm_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void rtc_seconds_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pit0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pit1_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pit2_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pit3_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void pdb_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void usb_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void usb_charge_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void tsi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void mcg_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void lptmr_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void porta_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void portb_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void portc_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void portd_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void porte_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| void software_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||
| // TODO: create AVR-stype ISR() macro, with default linkage to undefined handler | |||
| // | |||
| __attribute__ ((section(".vectors"), used)) | |||
| void (* const gVectors[])(void) = | |||
| { | |||
| (void (*)(void))((unsigned long)&_estack), // 0 ARM: Initial Stack Pointer | |||
| ResetHandler, // 1 ARM: Initial Program Counter | |||
| nmi_isr, // 2 ARM: Non-maskable Interrupt (NMI) | |||
| hard_fault_isr, // 3 ARM: Hard Fault | |||
| memmanage_fault_isr, // 4 ARM: MemManage Fault | |||
| bus_fault_isr, // 5 ARM: Bus Fault | |||
| usage_fault_isr, // 6 ARM: Usage Fault | |||
| fault_isr, // 7 -- | |||
| fault_isr, // 8 -- | |||
| fault_isr, // 9 -- | |||
| fault_isr, // 10 -- | |||
| svcall_isr, // 11 ARM: Supervisor call (SVCall) | |||
| debugmonitor_isr, // 12 ARM: Debug Monitor | |||
| fault_isr, // 13 -- | |||
| pendablesrvreq_isr, // 14 ARM: Pendable req serv(PendableSrvReq) | |||
| systick_isr, // 15 ARM: System tick timer (SysTick) | |||
| dma_ch0_isr, // 16 DMA channel 0 transfer complete | |||
| dma_ch1_isr, // 17 DMA channel 1 transfer complete | |||
| dma_ch2_isr, // 18 DMA channel 2 transfer complete | |||
| dma_ch3_isr, // 19 DMA channel 3 transfer complete | |||
| dma_error_isr, // 20 DMA error interrupt channel | |||
| unused_isr, // 21 DMA -- | |||
| flash_cmd_isr, // 22 Flash Memory Command complete | |||
| flash_error_isr, // 23 Flash Read collision | |||
| low_voltage_isr, // 24 Low-voltage detect/warning | |||
| wakeup_isr, // 25 Low Leakage Wakeup | |||
| watchdog_isr, // 26 Both EWM and WDOG interrupt | |||
| i2c0_isr, // 27 I2C0 | |||
| spi0_isr, // 28 SPI0 | |||
| i2s0_tx_isr, // 29 I2S0 Transmit | |||
| i2s0_rx_isr, // 30 I2S0 Receive | |||
| uart0_lon_isr, // 31 UART0 CEA709.1-B (LON) status | |||
| uart0_status_isr, // 32 UART0 status | |||
| uart0_error_isr, // 33 UART0 error | |||
| uart1_status_isr, // 34 UART1 status | |||
| uart1_error_isr, // 35 UART1 error | |||
| uart2_status_isr, // 36 UART2 status | |||
| uart2_error_isr, // 37 UART2 error | |||
| adc0_isr, // 38 ADC0 | |||
| cmp0_isr, // 39 CMP0 | |||
| cmp1_isr, // 40 CMP1 | |||
| ftm0_isr, // 41 FTM0 | |||
| ftm1_isr, // 42 FTM1 | |||
| cmt_isr, // 43 CMT | |||
| rtc_alarm_isr, // 44 RTC Alarm interrupt | |||
| rtc_seconds_isr, // 45 RTC Seconds interrupt | |||
| pit0_isr, // 46 PIT Channel 0 | |||
| pit1_isr, // 47 PIT Channel 1 | |||
| pit2_isr, // 48 PIT Channel 2 | |||
| pit3_isr, // 49 PIT Channel 3 | |||
| pdb_isr, // 50 PDB Programmable Delay Block | |||
| usb_isr, // 51 USB OTG | |||
| usb_charge_isr, // 52 USB Charger Detect | |||
| tsi0_isr, // 53 TSI0 | |||
| mcg_isr, // 54 MCG | |||
| lptmr_isr, // 55 Low Power Timer | |||
| porta_isr, // 56 Pin detect (Port A) | |||
| portb_isr, // 57 Pin detect (Port B) | |||
| portc_isr, // 58 Pin detect (Port C) | |||
| portd_isr, // 59 Pin detect (Port D) | |||
| porte_isr, // 60 Pin detect (Port E) | |||
| software_isr, // 61 Software interrupt | |||
| }; | |||
| //void usb_isr(void) | |||
| //{ | |||
| //} | |||
| __attribute__ ((section(".flashconfig"), used)) | |||
| const uint8_t flashconfigbytes[16] = { | |||
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF | |||
| }; | |||
| // Automatically initialize the RTC. When the build defines the compile | |||
| // time, and the user has added a crystal, the RTC will automatically | |||
| // begin at the time of the first upload. | |||
| #ifndef TIME_T | |||
| #define TIME_T 1349049600 // default 1 Oct 2012 (never used, Arduino sets this) | |||
| #endif | |||
| extern void rtc_set(unsigned long t); | |||
| static void startup_unused_hook(void) {} | |||
| void startup_early_hook(void) __attribute__ ((weak, alias("startup_unused_hook"))); | |||
| void startup_late_hook(void) __attribute__ ((weak, alias("startup_unused_hook"))); | |||
| __attribute__ ((section(".startup"))) | |||
| void ResetHandler(void) | |||
| { | |||
| uint32_t *src = &_etext; | |||
| uint32_t *dest = &_sdata; | |||
| unsigned int i; | |||
| WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; | |||
| WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; | |||
| WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; | |||
| startup_early_hook(); | |||
| // enable clocks to always-used peripherals | |||
| SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO | |||
| SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; | |||
| // if the RTC oscillator isn't enabled, get it started early | |||
| if (!(RTC_CR & RTC_CR_OSCE)) { | |||
| RTC_SR = 0; | |||
| RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; | |||
| } | |||
| // release I/O pins hold, if we woke up from VLLS mode | |||
| if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO; | |||
| // TODO: do this while the PLL is waiting to lock.... | |||
| while (dest < &_edata) *dest++ = *src++; | |||
| dest = &_sbss; | |||
| while (dest < &_ebss) *dest++ = 0; | |||
| SCB_VTOR = 0; // use vector table in flash | |||
| // default all interrupts to medium priority level | |||
| for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); | |||
| // start in FEI mode | |||
| // enable capacitors for crystal | |||
| OSC0_CR = OSC_SC8P | OSC_SC2P; | |||
| // enable osc, 8-32 MHz range, low power mode | |||
| MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS; | |||
| // switch to crystal as clock source, FLL input = 16 MHz / 512 | |||
| MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4); | |||
| // wait for crystal oscillator to begin | |||
| while ((MCG_S & MCG_S_OSCINIT0) == 0) ; | |||
| // wait for FLL to use oscillator | |||
| while ((MCG_S & MCG_S_IREFST) != 0) ; | |||
| // wait for MCGOUT to use oscillator | |||
| while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ; | |||
| // now we're in FBE mode | |||
| // config PLL input for 16 MHz Crystal / 4 = 4 MHz | |||
| MCG_C5 = MCG_C5_PRDIV0(3); | |||
| // config PLL for 96 MHz output | |||
| MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0); | |||
| // wait for PLL to start using xtal as its input | |||
| while (!(MCG_S & MCG_S_PLLST)) ; | |||
| // wait for PLL to lock | |||
| while (!(MCG_S & MCG_S_LOCK0)) ; | |||
| // now we're in PBE mode | |||
| #if F_CPU == 96000000 | |||
| // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash | |||
| SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); | |||
| #elif F_CPU == 48000000 | |||
| // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash | |||
| SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); | |||
| #elif F_CPU == 24000000 | |||
| // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash | |||
| SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); | |||
| #else | |||
| #error "Error, F_CPU must be 96000000, 48000000, or 24000000" | |||
| #endif | |||
| // switch to PLL as clock source, FLL input = 16 MHz / 512 | |||
| MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4); | |||
| // wait for PLL clock to be used | |||
| while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ; | |||
| // now we're in PEE mode | |||
| // configure USB for 48 MHz clock | |||
| SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // USB = 96 MHz PLL / 2 | |||
| // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0 | |||
| SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6); | |||
| // initialize the SysTick counter | |||
| SYST_RVR = (F_CPU / 1000) - 1; | |||
| SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE; | |||
| //init_pins(); | |||
| __enable_irq(); | |||
| _init_Teensyduino_internal_(); | |||
| if (RTC_SR & RTC_SR_TIF) rtc_set(TIME_T); | |||
| __libc_init_array(); | |||
| /* | |||
| for (ptr = &__init_array_start; ptr < &__init_array_end; ptr++) { | |||
| (*ptr)(); | |||
| } | |||
| */ | |||
| startup_late_hook(); | |||
| main(); | |||
| while (1) ; | |||
| } | |||
| // TODO: is this needed for c++ and where does it come from? | |||
| /* | |||
| void _init(void) | |||
| { | |||
| } | |||
| */ | |||
| char *__brkval = (char *)&_ebss; | |||
| void * _sbrk(int incr) | |||
| { | |||
| //static char *heap_end = (char *)&_ebss; | |||
| //char *prev = heap_end; | |||
| //heap_end += incr; | |||
| char *prev = __brkval; | |||
| __brkval += incr; | |||
| return prev; | |||
| } | |||
| int _read(int file, char *ptr, int len) | |||
| { | |||
| return 0; | |||
| } | |||
| int _write(int file, char *ptr, int len) | |||
| { | |||
| return 0; | |||
| } | |||
| int _close(int fd) | |||
| { | |||
| return -1; | |||
| } | |||
| int _lseek(int fd, long long offset, int whence) | |||
| { | |||
| return -1; | |||
| } | |||
| void _exit(int status) | |||
| { | |||
| while (1); | |||
| } | |||
| void __cxa_pure_virtual() | |||
| { | |||
| while (1); | |||
| } | |||
| int __cxa_guard_acquire (int *g) | |||
| { | |||
| return 1; | |||
| } | |||
| void __cxa_guard_release(int *g) | |||
| { | |||
| } | |||
| @@ -0,0 +1,109 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| MEMORY | |||
| { | |||
| FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K | |||
| RAM (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K | |||
| } | |||
| SECTIONS | |||
| { | |||
| .text : { | |||
| . = 0; | |||
| KEEP(*(.vectors)) | |||
| *(.startup*) | |||
| /* TODO: does linker detect startup overflow onto flashconfig? */ | |||
| . = 0x400; | |||
| KEEP(*(.flashconfig*)) | |||
| *(.text*) | |||
| *(.rodata*) | |||
| . = ALIGN(4); | |||
| KEEP(*(.init)) | |||
| . = ALIGN(4); | |||
| __preinit_array_start = .; | |||
| KEEP (*(.preinit_array)) | |||
| __preinit_array_end = .; | |||
| __init_array_start = .; | |||
| KEEP (*(SORT(.init_array.*))) | |||
| KEEP (*(.init_array)) | |||
| __init_array_end = .; | |||
| } > FLASH = 0xFF | |||
| .ARM.exidx : { | |||
| __exidx_start = .; | |||
| *(.ARM.exidx* .gnu.linkonce.armexidx.*) | |||
| __exidx_end = .; | |||
| } > FLASH | |||
| _etext = .; | |||
| .usbdescriptortable (NOLOAD) : { | |||
| /* . = ORIGIN(RAM); */ | |||
| . = ALIGN(512); | |||
| *(.usbdescriptortable*) | |||
| } > RAM | |||
| .dmabuffers (NOLOAD) : { | |||
| . = ALIGN(4); | |||
| *(.dmabuffers*) | |||
| } > RAM | |||
| .usbbuffers (NOLOAD) : { | |||
| . = ALIGN(4); | |||
| *(.usbbuffers*) | |||
| } > RAM | |||
| .data : AT (_etext) { | |||
| . = ALIGN(4); | |||
| _sdata = .; | |||
| *(.data*) | |||
| . = ALIGN(4); | |||
| _edata = .; | |||
| } > RAM | |||
| .noinit (NOLOAD) : { | |||
| *(.noinit*) | |||
| } > RAM | |||
| .bss : { | |||
| . = ALIGN(4); | |||
| _sbss = .; | |||
| *(.bss*) | |||
| *(COMMON) | |||
| . = ALIGN(4); | |||
| _ebss = .; | |||
| __bss_end = .; | |||
| } > RAM | |||
| _estack = ORIGIN(RAM) + LENGTH(RAM); | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "avr_functions.h" | |||
| #include <string.h> | |||
| #include <stdio.h> | |||
| size_t strlen(const char *s) | |||
| { | |||
| size_t n=0; | |||
| while (*s++) n++; | |||
| return n; | |||
| } | |||
| char * ultoa(unsigned long val, char *buf, int radix) | |||
| { | |||
| unsigned digit; | |||
| int i=0, j; | |||
| char t; | |||
| while (1) { | |||
| digit = val % radix; | |||
| buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); | |||
| val /= radix; | |||
| if (val == 0) break; | |||
| i++; | |||
| } | |||
| buf[i + 1] = 0; | |||
| for (j=0; j < i; j++, i--) { | |||
| t = buf[j]; | |||
| buf[j] = buf[i]; | |||
| buf[i] = t; | |||
| } | |||
| return buf; | |||
| } | |||
| char * ltoa(long val, char *buf, int radix) | |||
| { | |||
| if (val >= 0) { | |||
| return ultoa(val, buf, radix); | |||
| } else { | |||
| buf[0] = '-'; | |||
| ultoa(-val, buf + 1, radix); | |||
| return buf; | |||
| } | |||
| } | |||
| // TODO: actually write an efficient dtostrf().... | |||
| char * dtostrf(float val, int width, unsigned int precision, char *buf) | |||
| { | |||
| char format[20]; | |||
| sprintf(format, "%%%d.%df", width, precision); | |||
| sprintf(buf, format, val); | |||
| return buf; | |||
| } | |||
| @@ -0,0 +1,102 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #ifndef pins_macros_for_arduino_compatibility_h | |||
| #define pins_macros_for_arduino_compatibility_h | |||
| #include <stdint.h> | |||
| 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; | |||
| const static uint8_t A8 = 22; | |||
| const static uint8_t A9 = 23; | |||
| const static uint8_t A10 = 34; | |||
| const static uint8_t A11 = 35; | |||
| const static uint8_t A12 = 36; | |||
| const static uint8_t A13 = 37; | |||
| const static uint8_t SS = 10; | |||
| const static uint8_t MOSI = 11; | |||
| const static uint8_t MISO = 12; | |||
| const static uint8_t SCK = 13; | |||
| const static uint8_t LED_BUILTIN = 13; | |||
| const static uint8_t SDA = 18; | |||
| const static uint8_t SCL = 19; | |||
| #define NUM_DIGITAL_PINS 34 | |||
| #define NUM_ANALOG_INPUTS 14 | |||
| #define analogInputToDigitalPin(p) (((p) < 10) ? (p) + 14 : -1) | |||
| #define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23)) | |||
| struct digital_pin_bitband_and_config_table_struct { | |||
| volatile uint32_t *reg; | |||
| volatile uint32_t *config; | |||
| }; | |||
| extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[]; | |||
| // compatibility macros | |||
| #define digitalPinToPort(pin) (pin) | |||
| #define digitalPinToBitMask(pin) (1) | |||
| #define portOutputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 0)) | |||
| #define portSetRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 32)) | |||
| #define portClearRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 64)) | |||
| #define portToggleRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 96)) | |||
| #define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128)) | |||
| #define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160)) | |||
| #define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config)) | |||
| #define digitalPinToPortReg(pin) (portOutputRegister(pin)) | |||
| #define digitalPinToBit(pin) (1) | |||
| #define NOT_ON_TIMER 0 | |||
| static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused)); | |||
| static inline uint8_t digitalPinToTimer(uint8_t pin) | |||
| { | |||
| if (pin >= 3 && pin <= 6) return pin - 2; | |||
| if (pin >= 9 && pin <= 10) return pin - 4; | |||
| if (pin >= 20 && pin <= 23) return pin - 13; | |||
| return NOT_ON_TIMER; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,746 @@ | |||
| /* Teensyduino Core Library | |||
| * http://www.pjrc.com/teensy/ | |||
| * Copyright (c) 2013 PJRC.COM, LLC. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * 1. The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * 2. If the Software is incorporated into a build system that allows | |||
| * selection among a list of target devices, then similar target | |||
| * devices manufactured by PJRC.COM must be included in the list of | |||
| * target devices and selectable in the same manner. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "core_pins.h" | |||
| #include "pins_arduino.h" | |||
| #include "HardwareSerial.h" | |||
| #if 0 | |||
| // moved to pins_arduino.h | |||
| struct digital_pin_bitband_and_config_table_struct { | |||
| volatile uint32_t *reg; | |||
| volatile uint32_t *config; | |||
| }; | |||
| const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[]; | |||
| // compatibility macros | |||
| #define digitalPinToPort(pin) (pin) | |||
| #define digitalPinToBitMask(pin) (1) | |||
| #define portOutputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 0)) | |||
| #define portSetRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 32)) | |||
| #define portClearRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 64)) | |||
| #define portToggleRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 96)) | |||
| #define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128)) | |||
| #define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160)) | |||
| #define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config)) | |||
| #endif | |||
| //#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) | |||
| //#define analogInPinToBit(P) (P) | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| //#define GPIO_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1) | |||
| //#define GPIO_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0) | |||
| const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = { | |||
| {GPIO_BITBAND_PTR(CORE_PIN0_PORTREG, CORE_PIN0_BIT), &CORE_PIN0_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN1_PORTREG, CORE_PIN1_BIT), &CORE_PIN1_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN2_PORTREG, CORE_PIN2_BIT), &CORE_PIN2_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN3_PORTREG, CORE_PIN3_BIT), &CORE_PIN3_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN4_PORTREG, CORE_PIN4_BIT), &CORE_PIN4_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN5_PORTREG, CORE_PIN5_BIT), &CORE_PIN5_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN6_PORTREG, CORE_PIN6_BIT), &CORE_PIN6_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN7_PORTREG, CORE_PIN7_BIT), &CORE_PIN7_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN8_PORTREG, CORE_PIN8_BIT), &CORE_PIN8_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN9_PORTREG, CORE_PIN9_BIT), &CORE_PIN9_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN10_PORTREG, CORE_PIN10_BIT), &CORE_PIN10_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN11_PORTREG, CORE_PIN11_BIT), &CORE_PIN11_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN12_PORTREG, CORE_PIN12_BIT), &CORE_PIN12_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN13_PORTREG, CORE_PIN13_BIT), &CORE_PIN13_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN14_PORTREG, CORE_PIN14_BIT), &CORE_PIN14_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN15_PORTREG, CORE_PIN15_BIT), &CORE_PIN15_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN16_PORTREG, CORE_PIN16_BIT), &CORE_PIN16_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN17_PORTREG, CORE_PIN17_BIT), &CORE_PIN17_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN18_PORTREG, CORE_PIN18_BIT), &CORE_PIN18_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN19_PORTREG, CORE_PIN19_BIT), &CORE_PIN19_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN20_PORTREG, CORE_PIN20_BIT), &CORE_PIN20_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN21_PORTREG, CORE_PIN21_BIT), &CORE_PIN21_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN22_PORTREG, CORE_PIN22_BIT), &CORE_PIN22_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN23_PORTREG, CORE_PIN23_BIT), &CORE_PIN23_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN24_PORTREG, CORE_PIN24_BIT), &CORE_PIN24_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN25_PORTREG, CORE_PIN25_BIT), &CORE_PIN25_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN26_PORTREG, CORE_PIN26_BIT), &CORE_PIN26_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN27_PORTREG, CORE_PIN27_BIT), &CORE_PIN27_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN28_PORTREG, CORE_PIN28_BIT), &CORE_PIN28_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN29_PORTREG, CORE_PIN29_BIT), &CORE_PIN29_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN30_PORTREG, CORE_PIN30_BIT), &CORE_PIN30_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN31_PORTREG, CORE_PIN31_BIT), &CORE_PIN31_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN32_PORTREG, CORE_PIN32_BIT), &CORE_PIN32_CONFIG}, | |||
| {GPIO_BITBAND_PTR(CORE_PIN33_PORTREG, CORE_PIN33_BIT), &CORE_PIN33_CONFIG} | |||
| }; | |||
| typedef void (*voidFuncPtr)(void); | |||
| volatile static voidFuncPtr intFunc[CORE_NUM_DIGITAL]; | |||
| void init_pin_interrupts(void) | |||
| { | |||
| //SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO | |||
| NVIC_ENABLE_IRQ(IRQ_PORTA); | |||
| NVIC_ENABLE_IRQ(IRQ_PORTB); | |||
| NVIC_ENABLE_IRQ(IRQ_PORTC); | |||
| NVIC_ENABLE_IRQ(IRQ_PORTD); | |||
| NVIC_ENABLE_IRQ(IRQ_PORTE); | |||
| // TODO: maybe these should be set to a lower priority | |||
| // so if the user puts lots of slow code on attachInterrupt | |||
| // fast interrupts will still be serviced quickly? | |||
| } | |||
| void attachInterrupt(uint8_t pin, void (*function)(void), int mode) | |||
| { | |||
| volatile uint32_t *config; | |||
| uint32_t cfg, mask; | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| switch (mode) { | |||
| case CHANGE: mask = 0x0B; break; | |||
| case RISING: mask = 0x09; break; | |||
| case FALLING: mask = 0x0A; break; | |||
| case LOW: mask = 0x08; break; | |||
| case HIGH: mask = 0x0C; break; | |||
| default: return; | |||
| } | |||
| mask = (mask << 16) | 0x01000000; | |||
| config = portConfigRegister(pin); | |||
| __disable_irq(); | |||
| cfg = *config; | |||
| cfg &= ~0x000F0000; // disable any previous interrupt | |||
| *config = cfg; | |||
| intFunc[pin] = function; // set the function pointer | |||
| cfg |= mask; | |||
| *config = cfg; // enable the new interrupt | |||
| __enable_irq(); | |||
| } | |||
| void detachInterrupt(uint8_t pin) | |||
| { | |||
| volatile uint32_t *config; | |||
| config = portConfigRegister(pin); | |||
| __disable_irq(); | |||
| *config = ((*config & ~0x000F0000) | 0x01000000); | |||
| intFunc[pin] = NULL; | |||
| __enable_irq(); | |||
| } | |||
| void porta_isr(void) | |||
| { | |||
| uint32_t isfr = PORTA_ISFR; | |||
| PORTA_ISFR = isfr; | |||
| if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3](); | |||
| if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4](); | |||
| if ((isfr & CORE_PIN24_BITMASK) && intFunc[24]) intFunc[24](); | |||
| if ((isfr & CORE_PIN33_BITMASK) && intFunc[33]) intFunc[33](); | |||
| } | |||
| void portb_isr(void) | |||
| { | |||
| uint32_t isfr = PORTB_ISFR; | |||
| PORTB_ISFR = isfr; | |||
| if ((isfr & CORE_PIN0_BITMASK) && intFunc[0]) intFunc[0](); | |||
| if ((isfr & CORE_PIN1_BITMASK) && intFunc[1]) intFunc[1](); | |||
| if ((isfr & CORE_PIN16_BITMASK) && intFunc[16]) intFunc[16](); | |||
| if ((isfr & CORE_PIN17_BITMASK) && intFunc[17]) intFunc[17](); | |||
| if ((isfr & CORE_PIN18_BITMASK) && intFunc[18]) intFunc[18](); | |||
| if ((isfr & CORE_PIN19_BITMASK) && intFunc[19]) intFunc[19](); | |||
| if ((isfr & CORE_PIN25_BITMASK) && intFunc[25]) intFunc[25](); | |||
| if ((isfr & CORE_PIN32_BITMASK) && intFunc[32]) intFunc[32](); | |||
| } | |||
| void portc_isr(void) | |||
| { | |||
| // TODO: these are inefficent. Use CLZ somehow.... | |||
| uint32_t isfr = PORTC_ISFR; | |||
| PORTC_ISFR = isfr; | |||
| if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9](); | |||
| if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10](); | |||
| if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11](); | |||
| if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12](); | |||
| if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13](); | |||
| if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15](); | |||
| if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22](); | |||
| if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23](); | |||
| if ((isfr & CORE_PIN27_BITMASK) && intFunc[27]) intFunc[27](); | |||
| if ((isfr & CORE_PIN28_BITMASK) && intFunc[28]) intFunc[28](); | |||
| if ((isfr & CORE_PIN29_BITMASK) && intFunc[29]) intFunc[29](); | |||
| if ((isfr & CORE_PIN30_BITMASK) && intFunc[30]) intFunc[30](); | |||
| } | |||
| void portd_isr(void) | |||
| { | |||
| uint32_t isfr = PORTD_ISFR; | |||
| PORTD_ISFR = isfr; | |||
| if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2](); | |||
| if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5](); | |||
| if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6](); | |||
| if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7](); | |||
| if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8](); | |||
| if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14](); | |||
| if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20](); | |||
| if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21](); | |||
| } | |||
| void porte_isr(void) | |||
| { | |||
| uint32_t isfr = PORTE_ISFR; | |||
| PORTE_ISFR = isfr; | |||
| if ((isfr & CORE_PIN26_BITMASK) && intFunc[26]) intFunc[26](); | |||
| if ((isfr & CORE_PIN31_BITMASK) && intFunc[31]) intFunc[31](); | |||
| } | |||
| unsigned long rtc_get(void) | |||
| { | |||
| return RTC_TSR; | |||
| } | |||
| void rtc_set(unsigned long t) | |||
| { | |||
| RTC_SR = 0; | |||
| RTC_TPR = 0; | |||
| RTC_TSR = t; | |||
| RTC_SR = RTC_SR_TCE; | |||
| } | |||
| // adjust is the amount of crystal error to compensate, 1 = 0.1192 ppm | |||
| // For example, adjust = -100 is slows the clock by 11.92 ppm | |||
| // | |||
| void rtc_compensate(int adjust) | |||
| { | |||
| uint32_t comp, interval, tcr; | |||
| // This simple approach tries to maximize the interval. | |||
| // Perhaps minimizing TCR would be better, so the | |||
| // compensation is distributed more evenly across | |||
| // many seconds, rather than saving it all up and then | |||
| // altering one second up to +/- 0.38% | |||
| if (adjust >= 0) { | |||
| comp = adjust; | |||
| interval = 256; | |||
| while (1) { | |||
| tcr = comp * interval; | |||
| if (tcr < 128*256) break; | |||
| if (--interval == 1) break; | |||
| } | |||
| tcr = tcr >> 8; | |||
| } else { | |||
| comp = -adjust; | |||
| interval = 256; | |||
| while (1) { | |||
| tcr = comp * interval; | |||
| if (tcr < 129*256) break; | |||
| if (--interval == 1) break; | |||
| } | |||
| tcr = tcr >> 8; | |||
| tcr = 256 - tcr; | |||
| } | |||
| RTC_TCR = ((interval - 1) << 8) | tcr; | |||
| } | |||
| #if 0 | |||
| // TODO: build system should define this | |||
| // so RTC is automatically initialized to approx correct time | |||
| // at least when the program begins running right after upload | |||
| #ifndef TIME_T | |||
| #define TIME_T 1350160272 | |||
| #endif | |||
| void init_rtc(void) | |||
| { | |||
| serial_print("init_rtc\n"); | |||
| //SIM_SCGC6 |= SIM_SCGC6_RTC; | |||
| // enable the RTC crystal oscillator, for approx 12pf crystal | |||
| if (!(RTC_CR & RTC_CR_OSCE)) { | |||
| serial_print("start RTC oscillator\n"); | |||
| RTC_SR = 0; | |||
| RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; | |||
| } | |||
| // should wait for crystal to stabilize..... | |||
| serial_print("SR="); | |||
| serial_phex32(RTC_SR); | |||
| serial_print("\n"); | |||
| serial_print("CR="); | |||
| serial_phex32(RTC_CR); | |||
| serial_print("\n"); | |||
| serial_print("TSR="); | |||
| serial_phex32(RTC_TSR); | |||
| serial_print("\n"); | |||
| serial_print("TCR="); | |||
| serial_phex32(RTC_TCR); | |||
| serial_print("\n"); | |||
| if (RTC_SR & RTC_SR_TIF) { | |||
| // enable the RTC | |||
| RTC_SR = 0; | |||
| RTC_TPR = 0; | |||
| RTC_TSR = TIME_T; | |||
| RTC_SR = RTC_SR_TCE; | |||
| } | |||
| } | |||
| #endif | |||
| extern void usb_init(void); | |||
| // create a default PWM at the same 488.28 Hz as Arduino Uno | |||
| #if F_BUS == 48000000 | |||
| #define DEFAULT_FTM_MOD (49152 - 1) | |||
| #define DEFAULT_FTM_PRESCALE 1 | |||
| #else | |||
| #define DEFAULT_FTM_MOD (49152 - 1) | |||
| #define DEFAULT_FTM_PRESCALE 0 | |||
| #endif | |||
| //void init_pins(void) | |||
| void _init_Teensyduino_internal_(void) | |||
| { | |||
| init_pin_interrupts(); | |||
| //SIM_SCGC6 |= SIM_SCGC6_FTM0; // TODO: use bitband for atomic read-mod-write | |||
| //SIM_SCGC6 |= SIM_SCGC6_FTM1; | |||
| FTM0_CNT = 0; | |||
| FTM0_MOD = DEFAULT_FTM_MOD; | |||
| FTM0_C0SC = 0x28; // MSnB:MSnA = 10, ELSnB:ELSnA = 10 | |||
| FTM0_C1SC = 0x28; | |||
| FTM0_C2SC = 0x28; | |||
| FTM0_C3SC = 0x28; | |||
| FTM0_C4SC = 0x28; | |||
| FTM0_C5SC = 0x28; | |||
| FTM0_C6SC = 0x28; | |||
| FTM0_C7SC = 0x28; | |||
| FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE); | |||
| FTM1_CNT = 0; | |||
| FTM1_MOD = DEFAULT_FTM_MOD; | |||
| FTM1_C0SC = 0x28; | |||
| FTM1_C1SC = 0x28; | |||
| FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE); | |||
| analog_init(); | |||
| //delay(100); // TODO: this is not necessary, right? | |||
| usb_init(); | |||
| } | |||
| // SOPT4 is SIM select clocks? | |||
| // FTM is clocked by the bus clock, either 24 or 48 MHz | |||
| // input capture can be FTM1_CH0, CMP0 or CMP1 or USB start of frame | |||
| // 24 MHz with reload 49152 to match Arduino's speed = 488.28125 Hz | |||
| static uint8_t analog_write_res = 8; | |||
| void analogWrite(uint8_t pin, int val) | |||
| { | |||
| uint32_t cval, max; | |||
| max = 1 << analog_write_res; | |||
| if (val <= 0) { | |||
| digitalWrite(pin, LOW); | |||
| pinMode(pin, OUTPUT); // TODO: implement OUTPUT_LOW | |||
| return; | |||
| } else if (val >= max) { | |||
| digitalWrite(pin, HIGH); | |||
| pinMode(pin, OUTPUT); // TODO: implement OUTPUT_HIGH | |||
| return; | |||
| } | |||
| //serial_print("analogWrite\n"); | |||
| //serial_print("val = "); | |||
| //serial_phex32(val); | |||
| //serial_print("\n"); | |||
| //serial_print("analog_write_res = "); | |||
| //serial_phex(analog_write_res); | |||
| //serial_print("\n"); | |||
| if (pin == 3 || pin == 4) { | |||
| cval = ((uint32_t)val * (uint32_t)(FTM1_MOD + 1)) >> analog_write_res; | |||
| //serial_print("FTM1_MOD = "); | |||
| //serial_phex32(FTM1_MOD); | |||
| //serial_print("\n"); | |||
| } else { | |||
| cval = ((uint32_t)val * (uint32_t)(FTM0_MOD + 1)) >> analog_write_res; | |||
| //serial_print("FTM0_MOD = "); | |||
| //serial_phex32(FTM0_MOD); | |||
| //serial_print("\n"); | |||
| } | |||
| //serial_print("cval = "); | |||
| //serial_phex32(cval); | |||
| //serial_print("\n"); | |||
| switch (pin) { | |||
| case 3: // PTA12, FTM1_CH0 | |||
| FTM1_C0V = cval; | |||
| CORE_PIN3_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 4: // PTA13, FTM1_CH1 | |||
| FTM1_C1V = cval; | |||
| CORE_PIN4_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 5: // PTD7, FTM0_CH7 | |||
| FTM0_C7V = cval; | |||
| CORE_PIN5_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 6: // PTD4, FTM0_CH4 | |||
| FTM0_C4V = cval; | |||
| CORE_PIN6_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 9: // PTC3, FTM0_CH2 | |||
| FTM0_C2V = cval; | |||
| CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 10: // PTC4, FTM0_CH3 | |||
| FTM0_C3V = cval; | |||
| CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 20: // PTD5, FTM0_CH5 | |||
| FTM0_C5V = cval; | |||
| CORE_PIN20_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 21: // PTD6, FTM0_CH6 | |||
| FTM0_C6V = cval; | |||
| CORE_PIN21_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 22: // PTC1, FTM0_CH0 | |||
| FTM0_C0V = cval; | |||
| CORE_PIN22_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| case 23: // PTC2, FTM0_CH1 | |||
| FTM0_C1V = cval; | |||
| CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; | |||
| break; | |||
| default: | |||
| digitalWrite(pin, (val > 127) ? HIGH : LOW); | |||
| pinMode(pin, OUTPUT); | |||
| } | |||
| } | |||
| void analogWriteRes(uint32_t bits) | |||
| { | |||
| if (bits < 1) { | |||
| bits = 1; | |||
| } else if (bits > 16) { | |||
| bits = 16; | |||
| } | |||
| analog_write_res = bits; | |||
| } | |||
| void analogWriteFrequency(uint8_t pin, uint32_t frequency) | |||
| { | |||
| uint32_t minfreq, prescale, mod; | |||
| //serial_print("analogWriteFrequency: pin = "); | |||
| //serial_phex(pin); | |||
| //serial_print(", freq = "); | |||
| //serial_phex32(frequency); | |||
| //serial_print("\n"); | |||
| for (prescale = 0; prescale < 7; prescale++) { | |||
| minfreq = (F_BUS >> 16) >> prescale; | |||
| if (frequency > minfreq) break; | |||
| } | |||
| //serial_print("F_BUS = "); | |||
| //serial_phex32(F_BUS >> prescale); | |||
| //serial_print("\n"); | |||
| //serial_print("prescale = "); | |||
| //serial_phex(prescale); | |||
| //serial_print("\n"); | |||
| //mod = ((F_BUS >> prescale) / frequency) - 1; | |||
| mod = (((F_BUS >> prescale) + (frequency >> 1)) / frequency) - 1; | |||
| if (mod > 65535) mod = 65535; | |||
| //serial_print("mod = "); | |||
| //serial_phex32(mod); | |||
| //serial_print("\n"); | |||
| if (pin == 3 || pin == 4) { | |||
| FTM1_SC = 0; | |||
| FTM1_CNT = 0; | |||
| FTM1_MOD = mod; | |||
| FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale); | |||
| } else if (pin == 5 || pin == 6 || pin == 9 || pin == 10 || | |||
| (pin >= 20 && pin <= 23)) { | |||
| FTM0_SC = 0; | |||
| FTM0_CNT = 0; | |||
| FTM0_MOD = mod; | |||
| FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale); | |||
| } | |||
| } | |||
| // TODO: startup code needs to initialize all pins to GPIO mode, input by default | |||
| void digitalWrite(uint8_t pin, uint8_t val) | |||
| { | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| if (*portModeRegister(pin)) { | |||
| if (val) { | |||
| *portSetRegister(pin) = 1; | |||
| } else { | |||
| *portClearRegister(pin) = 1; | |||
| } | |||
| } else { | |||
| volatile uint32_t *config = portConfigRegister(pin); | |||
| if (val) { | |||
| // TODO use bitband for atomic read-mod-write | |||
| *config |= (PORT_PCR_PE | PORT_PCR_PS); | |||
| //*config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; | |||
| } else { | |||
| // TODO use bitband for atomic read-mod-write | |||
| *config &= ~(PORT_PCR_PE); | |||
| //*config = PORT_PCR_MUX(1); | |||
| } | |||
| } | |||
| } | |||
| uint8_t digitalRead(uint8_t pin) | |||
| { | |||
| if (pin >= CORE_NUM_DIGITAL) return 0; | |||
| return *portInputRegister(pin); | |||
| } | |||
| void pinMode(uint8_t pin, uint8_t mode) | |||
| { | |||
| volatile uint32_t *config; | |||
| if (pin >= CORE_NUM_DIGITAL) return; | |||
| config = portConfigRegister(pin); | |||
| if (mode == OUTPUT) { | |||
| *portModeRegister(pin) = 1; | |||
| *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
| } else { | |||
| *portModeRegister(pin) = 0; | |||
| if (mode == INPUT) { | |||
| *config = PORT_PCR_MUX(1); | |||
| } else { | |||
| *config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; // pullup | |||
| } | |||
| } | |||
| } | |||
| void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) | |||
| { | |||
| if (bitOrder == LSBFIRST) { | |||
| shiftOut_lsbFirst(dataPin, clockPin, value); | |||
| } else { | |||
| shiftOut_msbFirst(dataPin, clockPin, value); | |||
| } | |||
| } | |||
| void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) | |||
| { | |||
| uint8_t mask; | |||
| for (mask=0x01; mask; mask <<= 1) { | |||
| digitalWrite(dataPin, value & mask); | |||
| digitalWrite(clockPin, HIGH); | |||
| digitalWrite(clockPin, LOW); | |||
| } | |||
| } | |||
| void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) | |||
| { | |||
| uint8_t mask; | |||
| for (mask=0x80; mask; mask >>= 1) { | |||
| digitalWrite(dataPin, value & mask); | |||
| digitalWrite(clockPin, HIGH); | |||
| digitalWrite(clockPin, LOW); | |||
| } | |||
| } | |||
| uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) | |||
| { | |||
| if (bitOrder == LSBFIRST) { | |||
| return shiftIn_lsbFirst(dataPin, clockPin); | |||
| } else { | |||
| return shiftIn_msbFirst(dataPin, clockPin); | |||
| } | |||
| } | |||
| uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin) | |||
| { | |||
| uint8_t mask, value=0; | |||
| for (mask=0x01; mask; mask <<= 1) { | |||
| digitalWrite(clockPin, HIGH); | |||
| if (digitalRead(dataPin)) value |= mask; | |||
| digitalWrite(clockPin, LOW); | |||
| } | |||
| return value; | |||
| } | |||
| uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin) | |||
| { | |||
| uint8_t mask, value=0; | |||
| for (mask=0x80; mask; mask >>= 1) { | |||
| digitalWrite(clockPin, HIGH); | |||
| if (digitalRead(dataPin)) value |= mask; | |||
| digitalWrite(clockPin, LOW); | |||
| } | |||
| return value; | |||
| } | |||
| // the systick interrupt is supposed to increment this at 1 kHz rate | |||
| volatile uint32_t systick_millis_count = 0; | |||
| //uint32_t systick_current, systick_count, systick_istatus; // testing only | |||
| uint32_t micros(void) | |||
| { | |||
| uint32_t count, current, istatus; | |||
| __disable_irq(); | |||
| current = SYST_CVR; | |||
| count = systick_millis_count; | |||
| istatus = SCB_ICSR; // bit 26 indicates if systick exception pending | |||
| __enable_irq(); | |||
| //systick_current = current; | |||
| //systick_count = count; | |||
| //systick_istatus = istatus & SCB_ICSR_PENDSTSET ? 1 : 0; | |||
| if ((istatus & SCB_ICSR_PENDSTSET) && current > 50) count++; | |||
| current = ((F_CPU / 1000) - 1) - current; | |||
| return count * 1000 + current / (F_CPU / 1000000); | |||
| } | |||
| void delay(uint32_t ms) | |||
| { | |||
| uint32_t start = micros(); | |||
| if (ms > 0) { | |||
| while (1) { | |||
| if ((micros() - start) >= 1000) { | |||
| ms--; | |||
| if (ms == 0) return; | |||
| start += 1000; | |||
| } | |||
| yield(); | |||
| } | |||
| } | |||
| } | |||
| #if F_CPU == 96000000 | |||
| #define PULSEIN_LOOPS_PER_USEC 14 | |||
| #elif F_CPU == 48000000 | |||
| #define PULSEIN_LOOPS_PER_USEC 7 | |||
| #elif F_CPU == 24000000 | |||
| #define PULSEIN_LOOPS_PER_USEC 4 | |||
| #endif | |||
| uint32_t pulseIn_high(volatile uint8_t *reg, uint32_t timeout) | |||
| { | |||
| uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC; | |||
| uint32_t usec_start, usec_stop; | |||
| // wait for any previous pulse to end | |||
| while (*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| // wait for the pulse to start | |||
| while (!*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| usec_start = micros(); | |||
| // wait for the pulse to stop | |||
| while (*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| usec_stop = micros(); | |||
| return usec_stop - usec_start; | |||
| } | |||
| uint32_t pulseIn_low(volatile uint8_t *reg, uint32_t timeout) | |||
| { | |||
| uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC; | |||
| uint32_t usec_start, usec_stop; | |||
| // wait for any previous pulse to end | |||
| while (!*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| // wait for the pulse to start | |||
| while (*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| usec_start = micros(); | |||
| // wait for the pulse to stop | |||
| while (!*reg) { | |||
| if (--timeout_count == 0) return 0; | |||
| } | |||
| usec_stop = micros(); | |||
| return usec_stop - usec_start; | |||
| } | |||
| // TODO: an inline version should handle the common case where state is const | |||
| uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout) | |||
| { | |||
| if (pin >= CORE_NUM_DIGITAL) return 0; | |||
| if (state) return pulseIn_high(portInputRegister(pin), timeout); | |||
| return pulseIn_low(portInputRegister(pin), timeout);; | |||
| } | |||